Home > OS >  SFINAE or enable_if to check if non-type template parameter is even or odd
SFINAE or enable_if to check if non-type template parameter is even or odd

Time:11-11

template <unsigned int n>
class myclass {};

Is there a way (preferably using SFINAE, that is std::enable_if) to get compilation error when n is odd? I need it to be even.

CodePudding user response:

If you want to do it with SFINAE, use partial template specialization and don't define the base class.

e.g.:

template <unsigned int n, typename _ = void>
class myclass;

template <unsigned int n>
class myclass<n,std::enable_if_t<n%2==0>> {};

then you'll get a compile-time error if you try to instantiate myclass with an odd number.
(example godbolt)


Another approach would be to just use a static_assert to check if the number is even, this has the additional benefit that you can specify a message instead of getting a cryptic SFINAE error:

template <unsigned int n>
class myclass {
    static_assert(n%2==0, "n must be even");
};

(example godbolt)


If you want you can also combine the two variants above, giving you an SFINAE solution with a nice error message:

template <unsigned int n, typename _ = void>
class myclass {
    static_assert(n!=n, "n must be even");
};

template <unsigned int n>
class myclass<n,std::enable_if_t<n%2==0>> {
    /* code */
};

(godbolt example)


In case you're using a c version before C 14 you'll need to replace

std::enable_if_t<?>

with

typename std::enable_if<?>::type

in the above examples.

CodePudding user response:

preferably using SFINAE

If you need SFINAE, I suggest creating a type trait:

template<unsigned n>
static constexpr bool is_even_v = n % 2 == 0;

template <unsigned int n, std::enable_if_t<is_even_v<n>, int> = 0>
class myclass {};

Demo

  • Related