Home > Software engineering >  SFINAE does not work in a non-type template class
SFINAE does not work in a non-type template class

Time:03-01

I want to use SFINAE to select specific function to be compiled in a template class with non-type argument, here is how i do it:

#include<iostream>
#include<type_traits>
template <bool T>
struct is_right
{
    template <class Q = std::bool_constant<T>>
    typename std::enable_if<std::is_same<Q, std::bool_constant<true>>::value, bool>::type check()
    {
        return true;
    }

    template <class Q = std::bool_constant<!T>>
    typename std::enable_if<std::is_same<Q, std::bool_constant<false>>::value, bool>::type check()
    {
        return false;
    }
};

int main() {
    is_right<false> is_fs;
    is_right<true> is_ri;
    if(!is_fs.check() && is_ri.check()){
        std::cout << "It is right!" << std::endl;
    }
    return 0;
}

I compile it with g 8.1.0 using c 17 standard. But the compliler gives me a error said "no matching function for call to 'is_right::check()'".

However if I just substitue the non-type template argument with a type argument, it works:

#include<iostream>
#include<type_traits>
template <class T>
struct is_right
{
    template <class Q = T>
    typename std::enable_if<std::is_same<Q, std::bool_constant<true>>::value, bool>::type check()
    {
        return true;
    }

    template <class Q = T>
    typename std::enable_if<std::is_same<Q, std::bool_constant<false>>::value, bool>::type check()
    {
        return false;
    }
};

int main() {
    is_right<std::bool_constant<false>> is_fs;
    is_right<std::bool_constant<true>> is_ri;
    if(!is_fs.check() && is_ri.check()){
        std::cout << "It is right!" << std::endl;
    }
    return 0;
}

Is there any essential difference between them?

CodePudding user response:

The default template parameter for the second check function is wrong, it should be std::bool_constant<T> and not std::bool_constant<!T>.

The call is_fs.check() has no matching function, because you're testing is_same<bool_constant<false>, bool_constant<true>> in the first overload and is_same<bool_constant<true>, bool_constant<false>> in the second overload.


Also note that right now the call is_ri.check() is ambiguous, because both check functions are valid in is_right<true>.

  • Related