Search code examples
c++c++20sfinaec++-conceptsnon-type-template-parameter

sfinae vs concepts with non type template parms


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?


Solution

  • 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>();
    }
    

    Live demo