The Concept API
Contents
The Concept API
The following variables, functions and classes are all defined within the namespace HIPP.
The RawArray Concept
RawArrayTraits gives features for a raw-array-like type. User may add specializations to this generic class.
Given type T, if T is not RawArray, then the member
constexpr bool is_array = false.type
value_tis aliased toT.
Otherwise T is RawArray, satisfying
constexpr bool is_array = true.array_tis aliased to the corresponding raw array type with the same layout asT, andvalue_tis aliased to the type of the array element.constexpr size_t rank, sizegive the rank (no. of dimensions) and total number of elements, respectively.constexpr std::array<size_t, rank> extents, stridesgive extent of any dimension and the stride to the next element along this dimension.
For example:
RawArrayTraits<int [3][4]>::extents; // => std::array{3,4}.
RawArrayTraits< std::array<std::array<double, 4>, 3> >::extents; // => std::array{3,4}.
If an array has const value, or the array itself is const, the value_t,
i.e., type of the array element, is also const. e.g.:
RawArrayTraits<const int [3][4]>::value_t // => const int
RawArrayTraits<std::array<const int, 3> >::value_t // => const int
RawArrayTraits<const std::array<int, 3> >::value_t // => const int
RawArrayTraits<const std::array<int, 3> >::array_t // => const int [3]
RawArrayTraits
-
template<typename T, typename V = void>
class RawArrayTraits -
static constexpr bool is_array = false
-
static constexpr bool is_array = false
-
template<typename RawArrayT>
class RawArrayTraits<RawArrayT> Specialization for a raw array type.
-
typedef RawArrayT array_t
-
typedef std::remove_all_extents_t<array_t> value_t
The raw array type and its scalar type.
-
static constexpr bool is_array = true
-
static constexpr size_t rank = std::rank_v<array_t>
-
static constexpr size_t size = RawArrayHelper::size<array_t>()
-
static constexpr std::array<size_t, rank> extents = RawArrayHelper::extents<array_t>()
-
static constexpr std::array<size_t, rank> strides = RawArrayHelper::strides<array_t>()
is_arraytells whether or not the template parameter is an raw-array-like type. If true,rank,size,extents, andstridesgives its details.
-
typedef RawArrayT array_t
RawArrayHelper
-
class RawArrayHelper
Helpers for the raw array traits.
-
template<typename ArrayT>
static constexpr std::array<size_t, std::rank_v<ArrayT>> extents() Determines the extents of a raw array. For example:
extents<int [3][4]>(); // => std::array {3,4};
-
template<typename ArrayT>
static constexpr std::array<size_t, std::rank_v<ArrayT>> strides() Find the strides of a raw array. For example:
strides<int [2][3][4]>(); // => std::array {12, 4, 1}
-
template<typename ArrayT>
static constexpr size_t size() Determine the size, i.e., total number of elements in the raw array. For example:
size<int [3][4]>(); // => 12
-
template<typename ArrayT>
static ArrayT &get_elem(ArrayT &a) -
template<typename ArrayT, typename ...SizeTs>
static std::remove_all_extents_t<ArrayT> &get_elem(ArrayT &a, size_t id1, SizeTs&&... ids) Get an element from a raw array typed object. For scalar, return the reference to itself. For example:
int a[3][4]; get_elem(a, 0, 1); // => a[0][1], typed int & int b; get_elem(b); // => the reference to b itself
-
template<typename T, size_t... Ds>
class extents_to_array
-
template<typename T, size_t... Ds>
using extents_to_array_t = typename extents_to_array<T, Ds...>::type Get raw array type from from the extents list. Without any extent, return the type
Titself. For example:extents_to_array_t<int,3,4,5>; // => int[3][4][5] extents_to_array_t<int>; // => int
-
template<typename T, typename _V = void>
class is_std_array
-
template<typename T>
static constexpr bool is_std_array_v = is_std_array<T>::value Determine if
Tis astd::array. For example:is_std_array_v<std::array< std::array<int, 3>, 4 >>; // => true is_std_array_v<int [3]>; // => false
-
template<typename T, typename _V = void>
class std_array_to_raw
-
template<typename T>
using std_array_to_raw_t = typename std_array_to_raw<T>::type Find the raw array type corresponding to a
std::array. For example:std_array_to_raw_t< std::array< std::array<double, 4>, 3 > >; // => double [3][4]
If std::array is
const(in any nested depth), the raw array is also const. For example:std::array< std::array<const double, 4>, 3 > // => const double[3][4]. std::array<const std::array<double, 4>, 3 > // => const double[3][4]. const std::array<std::array<double, 4>, 3 > // => const double[3][4].
-
template<typename ArrayT>
The DynamicArray Concept
DynamicArray protocol: For any type T that does not satisfy this protocol,
member compile-time
bool is_array = false.member type
value_tis aliased asT.
Otherwise, the following conditions are required for the specialization of
DynamicArrayTraits on T:
member compile-time
bool is_array = true.member compile-time
size_t rankis set to the rank of the dynamic array.member type
array_tis aliased asT.member type
valueis aliased as the element type of the dynamic array.the traits can be constructed by passing
T &, with the public memberarray_t &arrayrefers to that passed instance.the call of methods
buff(),size(),extents(),strides()on the traits instance return the buffer starting address (typevalue_t *), number of element in the array (size_t), extent of the array at any dimension (std::array<size_t, rank>), and stride to the next element at any dimension (std::array<size_t, rank>).
Predefined DynamicArray-compliant type include std::vector and its const
const-qualified version. Traits for the later always has const-qualified
value_t.
-
template<typename T, typename V = void>
class DynamicArrayTraits -
static constexpr bool is_array = false
-
static constexpr bool is_array = false
-
template<typename ValueT, typename Allocator>
class DynamicArrayTraits<vector<ValueT, Allocator>>
The GeneralArray Concept
GeneralArray Protocol: Given type T, if it is not GeneralArray-compliant,
Compile-time attribute
bool is_array = false.Member type
value_tis aliased toT.
Otherwise, it is a GeneralArray type, satisfying
GeneralArrayTraits<T>can be constructed by passing a reference to theTinstance.Compile-time attribute
bool is_array = true.Compile-time attribute
bool is_consttells whether or not the element is a const-qualified type.Member type
array_tis aliased to a binary-compatible type asT, i.e., forRawArray, it is the corrpesponding raw array type, and forDynamicArray, it isTitself.Member type
value_tis aliased to the type of array element.Method
buff()returns the pointer to the first array element.Method
rank(),size(),extents(), andstridesreturns the details of the array - its number of dimensions, number of elements in total, number of elements at each dimension, and the stride to the next element at each dimension.
The traits object is copyable and movable and the results refer to the same array.
A special case is T = ValueT * or T = const ValueT * for any ValueT,
in this case the traits refers to a raw buffer.
Predefined GeneralArray types include any RawArray type and any DynamicArray type.
Examples:
Numerical scalars are not considered as GeneralArray:
// printed: int: is_array = 0
int scalar {};
pout << "int: is_array = ",
GeneralArrayTraits<decltype(scalar)>::is_array, "\n";
std::vector is DynamicArray, and therefore a General Array.
Detailed features are accessible from the traits instance:
// printed:
// vector<int>(4):
// is_array = 1, is_const = 0
// buff = 0x557a068552c0, size = 4
// extents = 4, strides = 1
vector<int> a1(4);
GeneralArrayTraits tr1{a1};
pout << "vector<int>(4):\n",
" is_array = ", tr1.is_array, ", is_const = ", tr1.is_const, "\n",
" buff = ", tr1.buff(), ", size = ", tr1.size(), "\n",
" extents = ", tr1.extents(), ", strides = ", tr1.strides(), "\n";
Raw array and std::array are RawArray types - also GeneralArray:
// printed:
// array<int,3>: buff = 0x7fffddb798bc, size = 3
// float[2]: buff = 0x7fffddb798b4, size = 2
array<int, 3> a2 {};
float a3[2];
GeneralArrayTraits tr2{a2};
GeneralArrayTraits tr3{a3};
pout << "array<int,3>: buff = ", tr2.buff(), ", size = ", tr2.size(), "\n";
pout << "float[2]: buff = ", tr3.buff(), ", size = ", tr3.size(), "\n";
Multi-dimensional arrays are also GeneralArray:
// printed:
// double[2][3]: extents = 2,3, strides = 3,1
// const array<array<int,3>,2>: is_const = 1, extents = 2,3
double a4[2][3] {};
const array<array<int, 3>, 2> a5{};
GeneralArrayTraits tr4{a4};
GeneralArrayTraits tr5{a5};
pout << "double[2][3]: extents = ", tr4.extents(),
", strides = ", tr4.strides(), "\n";
pout << "const array<array<int,3>,2>: is_const = ", tr5.is_const,
", extents = ", tr5.extents(), "\n";
-
template<typename T, typename V = void>
class GeneralArrayTraits -
static constexpr bool is_array = false
-
static constexpr bool is_array = false
-
template<typename ValueT>
class GeneralArrayTraits<const ValueT*> Specializations for pointer and const pointer.
-
template<typename ValueT>
class GeneralArrayTraits<ValueT*>
-
template<typename T>
class GeneralArrayTraits<T, std::enable_if_t<RawArrayTraits<T>::is_array>> Specializations for RawArray type.
-
typedef RawArrayTraits<T> _traits_t
-
static constexpr bool is_array = true;
-
typedef typename _traits_t::array_t array_t;
-
typedef typename _traits_t::value_t value_t;
-
typedef std::add_const_t<value_t> cvalue_t;
-
static constexpr bool is_const = GeneralArrayTraits<value_t*>::is_const
-
typedef RawArrayTraits<T> _traits_t
-
template<typename T>
class GeneralArrayTraits<T, std::enable_if_t<DynamicArrayTraits<T>::is_array>> Specializations for DynamicArray type.
-
typedef DynamicArrayTraits<T> _traits_t
-
static constexpr bool is_array = true;
-
typedef typename _traits_t::array_t array_t
-
typedef typename _traits_t::value_t value_t
-
typedef std::add_const_t<value_t> cvalue_t
-
static constexpr bool is_const = GeneralArrayTraits<value_t*>::is_const
-
typedef DynamicArrayTraits<T> _traits_t
The ContiguousBuffer Concept
ContiguousBufferTraits
ContiguousBuffer protocol.
For any type T that does not satisfying this protocol, member is_buffer is
false and buffer_t is T itself.
Otherwise, the following members must be defined for the specialization of
ContiguousBufferTraits:
is_buffer:true.is_const: whether or not the buffer is constant.value_tandcvalue_t: type of the element in the buffer, and itsconst counterpart. If
is_const,cvalue_tequals tovalue_t.
buffer_t: the type of the object that hosts the buffer.
Template argument V is not significant but reserved for type matching.
The traits type must be default-constructable, resulting in a size == 0
buffer.
The traits object can be constructed by passing a reference to the buffer-host object.
ContiguousBufferTraits is copy-constructable and copy-assignable, resulting in object that refers to the same buffer.
The traits object has methods get_buff(), get_cbuff() and get_size()
which returns the buffer pointer, const buffer pointer and size (i.e., number
of elements) of the buffer, respectively. Structured binding
cv-ref auto [buff, size] is allowed.
begin(), end(), cbegin(), cend() are defined to iterate over
the referred buffer. They all returns raw pointer typed value_t * or
cvalue_t.
A special case is T = ValueT * or T = const ValueT *, i.e., the
buffer-host type is a pointer. In this case, the specialization class is used.
Predefined contiguous-buffer-compliant types include any RawArray-compliant type (i.e., C-style raw array, std::array) and std::vector.
-
template<typename T, typename V = void>
class ContiguousBufferTraits -
static constexpr bool is_buffer = false
-
static constexpr bool is_buffer = false
-
template<typename ValueT>
class ContiguousBufferTraits<const ValueT*> Specialization for const raw pointer.
Template parameters:
ValueT: value of the element in the buffer.
Examples:
float a1[4]; const float a2[3]; ContiguousBufferTraits<const float *> cbt1 {a1, 4}, cbt21 {a2, 3}; ContiguousBufferTraits cbt22 {a2, 3}; // deduced <const float *>
-
constexpr ContiguousBufferTraits(value_t *p, size_t n) noexcept
-
constexpr ContiguousBufferTraits() noexcept
Constructors
p: pointer to the first element in the buffer.n: size of the buffer (i.e., number of elements).
Default constructor: equivalent to
p=nullptr; n=0.
-
constexpr value_t *get_buff() const noexcept
-
constexpr cvalue_t *get_cbuff() const noexcept
-
constexpr size_t get_size() const noexcept
-
constexpr value_t *begin() const noexcept
-
constexpr value_t *end() const noexcept
-
constexpr cvalue_t *cbegin() const noexcept
-
constexpr cvalue_t *cend() const noexcept
-
friend ostream &operator<<(ostream &os, const ContiguousBufferTraits &cbt)
-
template<typename ValueT>
class ContiguousBufferTraits<ValueT*> Specialization for raw pointer.
Template parameters:
ValueT: value of the element in the buffer.
Examples:
float a1[4]; const float a2[3]; ContiguousBufferTraits<float *> cbt11 {a1, 4}, // OK cbt2{a2, 4}; // ERROR, compile failure ContiguousBufferTraits cbt12 {a1, 4}; // deduced <float *>
-
constexpr ContiguousBufferTraits(value_t *p, size_t n) noexcept
-
constexpr ContiguousBufferTraits() noexcept
Constructors
p: pointer to the first element in the buffer.n: size of the buffer (i.e., number of elements).
Default constructor: equivalent to
p=nullptr; n=0.
-
constexpr value_t *get_buff() const noexcept
-
constexpr cvalue_t *get_cbuff() const noexcept
-
constexpr size_t get_size() const noexcept
-
constexpr value_t *begin() const noexcept
-
constexpr value_t *end() const noexcept
-
constexpr cvalue_t *cbegin() const noexcept
-
constexpr cvalue_t *cend() const noexcept
-
friend ostream &operator<<(ostream &os, const ContiguousBufferTraits &cbt)
-
template<typename RawArrayT>
class ContiguousBufferTraits<RawArrayT, std::enable_if_t<RawArrayTraits<RawArrayT>::is_array>> : ContiguousBufferTraits<typename RawArrayTraits<RawArrayT>::value_t*> Specialization for raw array concept (include C-style raw array, std::array, etc. ). In these case, they are treated as row-major storage 1D buffer.
For example:
std::array<std::array<double, 3>, 2> arr1 {}; const std::array<double, 3> arr2 {}; ContiguousBufferTraits<decltype(arr1)> cbt1{arr1}; // explicit set the template argument ContiguousBufferTraits cbr2{arr2}; // auto deduced
-
typedef RawArrayTraits<RawArrayT> _traits_t
-
typedef ContiguousBufferTraits<typename _traits_t::value_t*> _parent_t
-
typedef RawArrayT buffer_t
-
type _parent_t::value_t
-
typedef RawArrayTraits<RawArrayT> _traits_t
-
template<typename DynArrayT>
class ContiguousBufferTraits<DynArrayT, std::enable_if_t<DynamicArrayTraits<DynArrayT>::is_array>> : ContiguousBufferTraits<typename DynamicArrayTraits<DynArrayT>::value_t*> Specialization for DynamicArray protocol objects (e.g.,
std::vector). Any of these object is treated as row-major 1D buffer.For example:
const vector<int> a1{1,2,3}; vector<int> a2{1,2,3}; ContiguousBufferTraits<vector<int> > cbt1 {a1}; // explicit set the template argument ContiguousBufferTraits cbt2 {a2}; // auto deduced
-
typedef DynamicArrayTraits<DynArrayT> _traits_t
-
typedef ContiguousBufferTraits<typename _traits_t::value_t*> _parent_t
-
typedef DynArrayT buffer_t
-
typedef typename _parent_t::value_t value_t
-
typedef DynamicArrayTraits<DynArrayT> _traits_t
-
template<typename ValueT, typename Allocator>
class ContiguousBufferTraits<const vector<ValueT, Allocator>> : ContiguousBufferTraits<const ValueT*>
-
template<typename ValueT, typename Allocator>
class ContiguousBufferTraits<vector<ValueT, Allocator>> : ContiguousBufferTraits<ValueT*> Specialization for std::vector. For any vector v, v.data(), v.size() are used as buffer specification.
For example:
const vector<int> a1{1,2,3}; vector<int> a2{1,2,3}; ContiguousBufferTraits<vector<int> > cbt1 {a1}; // explicit set the template argument ContiguousBufferTraits cbt2 {a2}; // auto deduced
ContiguousBuffer
-
template<typename ValueT>
class ContiguousBuffer ContiguousBuffer object refers a buffer of element type
ValueT. Structured bindingcv-ref auto [buff, size]is allowed.ContiguousBuffer is copy-constructable and copy-assignable, resulting in object referring to the same buffer.
-
template<typename T>
using traits_t = ContiguousBufferTraits<T>
-
typedef ValueT value_t
-
typedef std::add_const_t<value_t> cvalue_t
Value type of the buffer element, and its const counterpart.
-
constexpr ContiguousBuffer()
-
template<typename T>
constexpr ContiguousBuffer(T *p, size_t n) noexcept -
template<typename T>
ContiguousBuffer(T &x) Constructors.
(1) Default constructor - an empty buffer as initialized with (2) by passing
p=nullptr, n=0.(2) by passing a pointer
pto the buffer starting address and a sizenindicating the number of elements.(3) by any other ContiguousBuffer protocol compliant object typed
T, i.e.,ContiguousBufferTraits<T>::is_buffer == true.Tcan also be a ContiguousBuffer with propervalue_t, e.g., copy-construct aContiguousBuffer<const int>fromContiguousBuffer<int>is allowed.
-
template<typename T>
constexpr ContiguousBuffer &operator=(const ContiguousBuffer<T> &cb) noexcept
-
constexpr value_t *get_buff() const noexcept
-
constexpr cvalue_t *get_cbuff() const noexcept
-
constexpr size_t get_size() const noexcept
Return the buffer starting pointer and the number of elements.
-
constexpr value_t *begin() const noexcept
-
constexpr value_t *end() const noexcept
-
constexpr cvalue_t *cbegin() const noexcept
-
constexpr cvalue_t *cend() const noexcept
Return the beginning and ending pointers to the buffer.
-
friend ostream &operator<<(ostream &os, const ContiguousBuffer &cb)
Print the detail of the buffer.
-
template<typename T>
Examples:
ContiguousBufferTraits defines the ContiguousBuffer concept. Example
classes that satisfy this protocol are std::vector, std::array, any RawArray concept
compliant class. A segment of raw memory buffer is also ContiguousBuffer. For example:
std::vector<int> a1(4);
const std::array<double, 4> a2 {};
float a3[4] {};
long *a4 = new long [4]; // raw memory buffer
ContiguousBuffer object represents a view of any of those object. To
create such a view, simply pass it to the constructor. For raw memory buffer,
a size argument should be provided. Class template parameters are deduced
automatically:
ContiguousBuffer<int> b11 {a1};
ContiguousBuffer<const int> b12{a1}; // cast to const buffer
ContiguousBuffer<const double> b21{a2};
ContiguousBuffer b22 {a2}; // auto deduced to <const double>
// ContiguousBuffer<double> b23 {a2}; // ERROR, compile failure - cannot cast const to non-const
ContiguousBuffer<float> b3 {a3};
ContiguousBuffer<long> b4 {a4, 4};
pout << "b11 = ", b11, "\nb12 = ", b12, "\nn21 = ", b21,
"\nb22 = ", b22, "\nb3 = ", b3, "\nb4 = ", b4, endl;
Output:
b11 = ContiguousBuffer{buff=0x56055fd1deb0, size=4}
b12 = ContiguousBuffer{buff=[const]0x56055fd1deb0, size=4}
n21 = ContiguousBuffer{buff=[const]0x7ffe5a50c520, size=4}
b22 = ContiguousBuffer{buff=[const]0x7ffe5a50c520, size=4}
b3 = ContiguousBuffer{buff=0x7ffe5a50c510, size=4}
b4 = ContiguousBuffer{buff=0x56055fd1ded0, size=4}
To get the info, i.e., buffer address and its size (number of elements),
use the structured binding, buff and size members, or
the iterators returned by begin() and end():
auto [p1, n1] = b11; // Get buffer address and size using structured binding,
const double *p2 = b21.buff; // or by visiting members.
size_t n2 = b21.size;
auto beg3 = b3.begin(), end3 = b3.end(); // Get iterators.
pout << "contents in a1 = {", pout(p1, p1+n1),
"}, a2 = {", pout(p2, p2+n2),
"}, a3 = {", pout(beg3, end3), "}\n";
Output:
contents in a1 = {0,0,0,0}, a2 = {0,0,0,0}, a3 = {0,0,0,0}