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>.
