Meta-sequence: Sequence of Types¶
In meta-programming, it is sometimes useful to process a list of types, in a way
that is similar to std::vector
. CLUE++ provides facilities to support such
operations in compile-time. Like other meta-programming tools, all these
facilities are also in the namespace clue::meta
.
Meta-sequence¶
In CLUE++, we use a variadic class template meta::seq_
, defined below, to
indicate a sequence of types.
// Within the namespace clue::meta:
template<typename... Elems> struct seq_;
We provide a series of meta-functions that emulate the std::vector
API to
work with such a sequence of types. Below is an example that illustrates the use
of seq_
and some of the meta-functions working with it.
using namespace clue::meta;
using meta::seq_;
using i1 = meta::int_<1>;
using i2 = meta::int_<2>;
using i3 = meta::int_<3>;
using i4 = meta::int_<4>;
// define a sequence of static values
using s = seq_<i1, i2, i3>;
constexpr size_t n = meta::size<s>::value // n = 3;
using xf = meta::front_t<s>; // xf is i1
using xb = meta::back_t<s>; // xb is i3
using x0 = meta::at_t<s, 0>; // x0 is i1
using x1 = meta::at_t<s, 1>; // x1 is i2
using r1 = meta::push_back_t<s, i4>;
// r1 is seq_<i1, i2, i3, i4>
using r2 = meta::push_front_t<s, i4>;
// r2 is seq_<i4, i1, i2, i3>
using r3 = meta::pop_front_t<s>;
// r3 is seq_<i2, i3>
using r4 = meta::pop_back_t<s>;
// r4 is seq_<i1, i2>
using rr = meta::reverse<s>;
// rr is seq_<i3, i2, i1>
using rt = meta::transform<meta::next, s>;
// rt is seq_<i2, i3, i4>
constexpr int v1 = meta::sum<s>::value; // v1 = 6;
constexpr int v2 = meta::max<s>::value; // v2 = 3;
constexpr int v3 = meta::min<s>::value; // v3 = 1;
Basic properties¶
-
class
meta::
size
¶ meta::size< seq_<elems...> >
has a member constantvalue
that equals to the number of element types.
-
class
meta::
empty
¶ meta::empty< seq_<elems...> >
has a member constantvalue
that istrue
when the number of element types is zero, orfalse
otherwise.
Element type access¶
-
class
meta::
front
¶ meta::front< seq_<elems...> >
has a member typedeftype
corresponding to the first element type.
-
class
meta::
back
¶ meta::back< seq_<elems...> >
has a member typedeftype
corresponding to the last element type in the sequence.
-
class
meta::
at
¶ meta::at< seq_<elems...>, I >
has a member typedeftype
corresponding to theI
-th element type of the sequence.
-
class
meta::
first
¶ meta::first< seq_<elems...> >
has a member typedeftype
corresponding to the first element type. (Equivalent to usingmeta::front
).
-
class
meta::
second
¶ meta::second< seq_<elems...> >
has a member typedeftype
corresponding to the second element type.
Helper aliases are provided for all these meta functions:
// Within the namespace clue::meta:
template<class Seq> using front_t = typename front<Seq>::type;
template<class Seq> using back_t = typename back<Seq>::type;
template<class Seq> using first_t = typename first<Seq>::type;
template<class Seq> using second_t = typename second<Seq>::type;
template<class Seq, size_t N>
using at_t = typename at<Seq, N>::type;
Modifiers¶
-
class
meta::
clear
¶ meta::clear< seq_<elems...> >
has a member typedeftype = meta::seq_<>
.
-
class
meta::
pop_front
¶ meta::pop_front< seq_<elems...> >
has a member typedeftype
which is a meta sequence with the first element type excluded.
-
class
meta::
pop_back
¶ meta::pop_back< seq_<elems...> >
has a member typedeftype
which is a meta sequence with the last element type excluded.
-
class
meta::
push_front
¶ meta::push_front< seq_<elems...>, X >
has a member typedeftype
which prepends a typeX
to the front of the input meta sequence.
-
class
meta::
push_back
¶ meta::push_back< seq_<elems...>, X >
has a member typedeftype
which appends a typeX
to the back of the input meta sequence.
Helper aliases are provided for all these meta functions:
// Within the namespace clue::meta:
template<class Seq> using clear_t = typename clear<Seq>::type;
template<class Seq> using pop_front_t = typename pop_front<Seq>::type;
template<class Seq> using pop_back_t = typename pop_back<Seq>::type;
template<class Seq, typename X>
using push_front_t = typename push_front<Seq, X>::type;
template<class Seq, typename X>
using push_back_t = typename push_back<Seq, X>::type;
Sequence reduction¶
All variadic reduction functions are specialized to perform reduction over a sequence, as
template<typename... Elems>
struct sum<seq_<Elems...>> : public sum<Elems...> {};
template<typename... Elems>
struct prod<seq_<Elems...>> : public prod<Elems...> {};
template<typename... Elems>
struct max<seq_<Elems...>> : public max<Elems...> {};
template<typename... Elems>
struct min<seq_<Elems...>> : public min<Elems...> {};
template<typename... Elems>
struct all<seq_<Elems...>> : public all<Elems...> {};
template<typename... Elems>
struct any<seq_<Elems...>> : public any<Elems...> {};
template<typename... Elems>
struct count_true<seq_<Elems...>> : public count_true<Elems...> {};
template<typename... Elems>
struct count_false<seq_<Elems...>> : public count_false<Elems...> {};
Algorithms¶
We also implement a collection of algorithms to work with meta sequences.
-
class
meta::
cat
¶ meta::cat<S1, S2>
has a member typedeftype
that is a concatenation of two meta sequencesS1
andS2
.
-
class
meta::
zip
¶ meta::zip<S1, S2>
has a member typedeftype
that zips two meta sequencesS1
andS2
of the same length.Example:
using namespace clue; using S1 = meta::seq_<char, int>; using S2 = meta::seq_<float, double>; using R = typename zip<S1, S2>::type; // meta::seq_< // meta::pair_<char, float>, // meta::pair_<int, double> // >
-
class
meta::
repeat
¶ meta::repeat<X, N>
has a member typedeftype
which is a meta sequence that repeats the typeX
forN
times.Example: meta::repeat<int, 3>::type
ismeta::seq_<int, int, int>
.
-
class
meta::
reverse
¶ meta::reverse<S>
has a member typedeftype
which is a reversed meta sequence.Example: meta::reverse<meta::seq_<char, short, int>>::type
ismeta::seq_<int, short, char>
.
-
class
meta::
transform
¶ meta::transform<F, S>
has a member typedeftype
which is the transformed sequence obtained by applying a meta-functionF
to each element type ofS
.
-
class
meta::
transform2
¶ meta::transform2<F, S1, S2>
has a member typedeftype
which is the transformed sequence obtained by applying a meta-functionF
to each element type ofS1
and that ofS2
.
Examples:
using namespace clue;
using meta::int_;
using meta::seq_;
using S1 = seq_<int_<1>, int_<2>, int_<3>>;
using S2 = seq_<int_<4>, int_<5>, int_<6>>;
using U = typename meta::transform<meta::next, S1>::type;
// U is seq_<int_<2>, int_<3>, int_<4>>
using V = typename meta::transform2<meta::plus, S1, S2>::type;
// V is seq_<int_<5>, int_<7>, int_<9>>
-
class
meta::
filter
¶ With a member typedef
type
which is the filtered sequence by retaining the element typesX
inS
for whichPred<X>::value
istrue
.
Examples:
using namespace clue;
using meta::int_;
using meta::seq_;
using S = seq_<int_<1>, int_<2>, int_<3>>;
template<class A>
struct is_odd : public bool_<(A::value % 2 == 1)> {};
using R = typename meta::filter<is_odd, S>::type;
// R is seq_<int_<1>, int_<3>>;
-
class
exists
¶ exists<X, S>
has a member constantvalue
that indicates whether the typeX
exists as an element type ofS
.
-
class
exists_if
¶ exists_if<Pred, S>
has a member constantvalue
which istrue
if there exist element typesX
ofS
such thatPred<X>::value
istrue
.
-
class
count
¶ count<X, S>
has a member constantvalue
which is equal to the number of occurrences of a typeX
in the sequenceS
.
-
class
count_if
¶ count_if<X, S>
has a member constantvalue
which is equal to the number of element typesX
inS
that satisfy the conditionPred<X>::value
istrue
.
Helper aliases are provided for all algorithms that transform types:
template<class S1, class S2> using cat_t = typename cat<S1, S2>::type;
template<class S1, class S2> using zip_t = typename zip<S1, S2>::type;
template<typename X, size_t N> using repeat_t = typename repeat<X, N>::type;
template<class Seq> using reverse_t = typename reverse<Seq>::type;
template<template<typename X> class F, class Seq>
using transform_t = typename transform<F, Seq>::type;
template<template<typename X, typename Y> class F, class S1, class S2>
using transform2_t = typename transform2<F, S1, S2>::type;
template<template<typename X> class Pred, class Seq>
using filter_t = typename filter<Pred, Seq>::type;