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 constantvaluethat equals to the number of element types.
-
class
meta::empty¶ meta::empty< seq_<elems...> >has a member constantvaluethat istruewhen the number of element types is zero, orfalseotherwise.
Element type access¶
-
class
meta::front¶ meta::front< seq_<elems...> >has a member typedeftypecorresponding to the first element type.
-
class
meta::back¶ meta::back< seq_<elems...> >has a member typedeftypecorresponding to the last element type in the sequence.
-
class
meta::at¶ meta::at< seq_<elems...>, I >has a member typedeftypecorresponding to theI-th element type of the sequence.
-
class
meta::first¶ meta::first< seq_<elems...> >has a member typedeftypecorresponding to the first element type. (Equivalent to usingmeta::front).
-
class
meta::second¶ meta::second< seq_<elems...> >has a member typedeftypecorresponding 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 typedeftypewhich is a meta sequence with the first element type excluded.
-
class
meta::pop_back¶ meta::pop_back< seq_<elems...> >has a member typedeftypewhich is a meta sequence with the last element type excluded.
-
class
meta::push_front¶ meta::push_front< seq_<elems...>, X >has a member typedeftypewhich prepends a typeXto the front of the input meta sequence.
-
class
meta::push_back¶ meta::push_back< seq_<elems...>, X >has a member typedeftypewhich appends a typeXto 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 typedeftypethat is a concatenation of two meta sequencesS1andS2.
-
class
meta::zip¶ meta::zip<S1, S2>has a member typedeftypethat zips two meta sequencesS1andS2of 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 typedeftypewhich is a meta sequence that repeats the typeXforNtimes.Example: meta::repeat<int, 3>::typeismeta::seq_<int, int, int>.
-
class
meta::reverse¶ meta::reverse<S>has a member typedeftypewhich is a reversed meta sequence.Example: meta::reverse<meta::seq_<char, short, int>>::typeismeta::seq_<int, short, char>.
-
class
meta::transform¶ meta::transform<F, S>has a member typedeftypewhich is the transformed sequence obtained by applying a meta-functionFto each element type ofS.
-
class
meta::transform2¶ meta::transform2<F, S1, S2>has a member typedeftypewhich is the transformed sequence obtained by applying a meta-functionFto each element type ofS1and 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
typewhich is the filtered sequence by retaining the element typesXinSfor whichPred<X>::valueistrue.
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 constantvaluethat indicates whether the typeXexists as an element type ofS.
-
class
exists_if¶ exists_if<Pred, S>has a member constantvaluewhich istrueif there exist element typesXofSsuch thatPred<X>::valueistrue.
-
class
count¶ count<X, S>has a member constantvaluewhich is equal to the number of occurrences of a typeXin the sequenceS.
-
class
count_if¶ count_if<X, S>has a member constantvaluewhich is equal to the number of element typesXinSthat satisfy the conditionPred<X>::valueistrue.
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;