For academic reasons I want to implement an example which select a template if a non type template parameter fulfills a given criteria. As example I want to have a function which is only defined for odd integer numbers.
It can be done like:
template < int N, bool C = N%2>
struct is_odd: public std::false_type{};
template<int N >
struct is_odd< N,true >: std::true_type{};
template < int N>
constexpr bool is_odd_v = is_odd<N>::value;
template < int N, typename T=typename std::enable_if_t<is_odd_v<N>, int> >
void Check(){ std::cout << "odd number template specialization " << std::endl; };
int main()
{
Check<1>();
Check<2>(); // fails, as expected, ok
}
I think it is much code for doing such a simple thing. Quite clear, I directly can use the modulo operation inside the std::enable_if
but lets assume there will be a more complex check for the non type template parameter value.
Q: Can this be done without so many steps of indirection but still having some std::is_xxx
in use?
BTW: If concepts
can handle non type template parms, it can be done much simpler, but I know, not designed for it...
template < int N >
concept ODD = !(N % 2);
template < ODD N >
void Check() { std::cout << "odd number template specialization " << std::endl; }
Bonus: Maybe someone have an idea why concepts are not made for non type template parms?
After some more experimental work I found that concepts
can be used for non type template parms. I simply did not find anything about that in the docs I read.
template < int I >
concept ODD = !(I%2);
template< int N >
requires( ODD<N> )
void Check() { std::cout << "odd number template spezialisation " << std::endl; }
template< int N >
requires( !ODD<N> )
void Check() { std::cout << "even number template spezialisation " << std::endl; }
int main()
{
Check<2>();
Check<4>();
Check<3>();
}