Is there a way to conditional on a constant value parameter in a C ++ template specialization?

is there a way to constrain the integral parameter of the template as a specialization instead of the excess of this code?

// redundant code

template <int N>
struct A {};
template <>
struct A <0> {};
template <>
struct A <1> {};

// what i want is some thing like this

template <int N>
struct A {};

template <>
struct A <N < 2> {};

      

+3


source to share


2 answers


You can use SFINAE = "Substitution error is not an error". This can be done in several ways, for example

template<int N, typename E=void>
struct A { /* ... */ };     // general type

template<int N>
struct A<N, std::enable_if_t<(N<2)> >
{ /* ... */ };              // specialisation for N<2

      

Note that std::enable_if_t<>

is a C ++ 14 type, which is equivalent to

template<bool C, typename T=void>
using enable_if_t = typename std::enable_if<C,T>::type;

      



How it works? The definition is std::enable_if

similar to

template<bool C, typename T=void>
struct enable_if { using type=T; };

template<typename T>
struct enable_if<false,T> {};

      

In particular, there is no subtype enable_if::type

if the condition is C

false. So in the above specialization enable_if_t<(N<2)>

expands to a valid type ( void

) only for N<2

. For N>=2

we have a replacement failure as it enable_if<(N<2)>::type

does not exist. C ++ allows for such a failure, but simply ignores the resulting (invalid) code.

+4


source


You can add a second template parameter with a default value that selects the required specialization:

template <int N, bool = (N < 2)>
struct A {
    // code for N>=2 case
};

template <int N>
struct A<N, true> {
    // code for N<2 case
};

      



(You don't need to specify the second parameter, as you will never explicitly refer to it.)

+2


source







All Articles