Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

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 ?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
206 views
Welcome To Ask or Share your Answers For Others

1 Answer

I don't fully understand what exactly you'd like to achieve, but the following helpers might be useful, starting with bool_sequence:

#include <type_traits>

// Note: std::integer_sequence is C++14,
// but it's easy to use your own version (even stripped down)
// for the following purpose:
template< bool... Bs >
using bool_sequence = std::integer_sequence< bool, Bs... >;

// Alternatively, not using C++14:
template< bool... > struct bool_sequence {};

next, you can check if all or any boolean value or set with these:

template< bool... Bs >
using bool_and = std::is_same< bool_sequence< Bs... >,
                               bool_sequence< ( Bs || true )... > >;

template< bool... Bs >
using bool_or = std::integral_constant< bool, !bool_and< !Bs... >::value >;

they come in handy as building blocks for more advanced and specialized traits. For example, you could use them like this:

typename< typename R, bool... Bs > // note: R first, no default :(
using enable_if_any = std::enable_if< bool_or< Bs... >::value, R >;

typename< typename R, bool... Bs > // note: R first, no default :(
using enable_if_all = std::enable_if< bool_and< Bs... >::value, R >;

typename< typename T, typename... Ts >
using are_same = bool_and< std::is_same< T, Ts >::value... >;

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...