Thursday 12 September 2013

Variadic variadic template templates, again

Variadic variadic template templates, again

I have seen e.g. a relevant question on the same issue, but I have a
different problem, which I think cannot be solved in any other way.
Here is function any that computes whether unary predicate F is true for
any of the elements in a template argument pack representation (list of
types) P:
template <template <typename...> class F, typename P>
struct any;
template <
template <typename...> class F,
template <typename...> class C, typename E, typename... En
>
struct any <F, C <E, En...> > :
public _if <F <E>{}, _true, any <F, C <En...> > > { };
template <template <typename...> class F, template <typename...> class C>
struct any <F, C <> > : public _false { };
where my _true/_false are equivalent to std::integral_constant <bool,
true/false>, and _if <C, T, E> is equivalent to typename std::conditional
<C, T, E>::type (details are irrelevant to the question, see below).
For instance, one may write
template <typename...> struct pack { };
template <typename T> using is_int = eq <int, T>;
any <is_int, pack <int, void, float, double> >(); // evaluates to true
any <is_int, pack <char, void, float, double> >(); // evaluates to false
where eq is equivalent to std::is_same.
An extension to binary predicates goes as follows:
template <template <typename...> class F, typename P, typename Q>
struct any2;
template <
template <typename...> class F,
template <typename...> class C, typename E, typename... En,
template <typename...> class D, typename H, typename... Hn
>
struct any2 <F, C <E, En...>, D <H, Hn...> > :
public _if <F <E, H>{}, _true, any2 <F, C <En...>, D <Hn...> > > { };
template <
template <typename...> class F,
template <typename...> class C, typename Q
>
struct any2 <F, C <>, Q> : public _false { };
where we may now write
typedef pack <int, void, float, double> A;
typedef pack <void, float, double, int> B;
typedef pack <void, float, double, double> C;
any2 <eq, A, B>(); // false
any2 <eq, A, C>(); // true
Here comes the question. Can we extend the approach to n-ary predicates,
operating on n input "packs" ?
This problem is different from the previous one, in that one element of
each input pack is needed at the same time for the evaluation of F <...>.
Here is a fictional attempt:
template <template <typename...> class F, typename... P>
struct any_n;
template <
template <typename...> class F,
template <typename...> class... C, typename... E, typename... En
>
struct any_n <F, C <E, En...>...> :
public _if <F <E...>{}, _true, any_n <F, C <En...>...> > { };
template <
template <typename...> class F,
template <typename...> class C, typename... P
>
struct any_n <F, C <>, P...> : public _false { };
which of course does not compile. So, can one write things like C <E,
En...>... ? What would be the types of C, E, En then?
I suspect the answer is no.
Such syntax would be extremely convenient, as e.g. in Scheme macros. I
have written a C++ template implementation of this syntax in the past
supporting up to two levels, using symbol dots or etc for .... But it
would be entirely different to have support from the compiler (especially
if you need to compile the thing on the same day).

No comments:

Post a Comment