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