Intro
I'm looking for a pattern to convert C++ type traits into their variadic counterparts. A methodology to approach the problem would be appreciated and generative programming patterns to automate the task would be ideal.
Example
Take the following :
std::is_same<T, U>::value;
I want to write a trait that works like so :
std::are_same<T1, T2, T3, T4>::value;
Current approach
It's pretty straightforward to implement the are_same
; Seeking a general solution we can come up with a tool for any variadic trait implementing universal quantification :
template<template<class,class> class F, typename...Ts>
struct Univ;
template<template<class, class> class F, typename T, typename U, typename...Ts>
struct Univ<F, T, U, Ts...>
{
static const int value = F<T, U>::value && Univ<F, U, Ts...>::value;
};
template<template<class, class> class F, typename T>
struct Univ<F, T>
{
static const int value = 1;
};
so that eg are_same
could be written as
Univ<is_same,int, int, int>::value
and this could apply when creating traits like are_classes
, are_scalars
etc
Generalizing
Minor tweaks could give existential quantification out of the previous snippet (replacing &&
with ||
) so that we create traits like exist_same
in the following fashion :
Exist<is_same, int, double, float>::value
Question
The previous cover generalization on type traits related to
- Primary type categories
- Composite type categories
- Type properties
- Supported operations
How would I generalize for type traits like the following :
enable_if -> enable_if_any // enable if any clause is true
enable_if_all // enalbe if all clauses are true
enable_for // enable only for the type provided
The exist_same
example above is oversimplified. Any ideas for a correct implementation?
There are type_traits that "return" modified types. Any suggestion for scaling those to implementations for arbitrary number of types ?
Are there type_traits which are made not to scale to arbitrary number of type arguments ?
std::tuple< T1, T2, ... >
. – Bagtemplate
equivalent ofusing
--template<template<class,class>class F>using for_all=template<class...Ts>Univ<F,Ts...>;
, used likefor_all<std::is_same><int,int,int>
, and it would let you easily pass thetemplate<class...>
generated to other meta programming without ugliness. – HeliotherapyExist
– Debt