#include <type_traits>
struct A{};
struct B{};
template <typename T>
struct Foo
{
typename std::enable_if<std::is_same<T, A>::value>::type
bar()
{}
typename std::enable_if<std::is_same<T, B>::value>::type
bar()
{}
};
Error message:
14:5: error: 'typename std::enable_if<std::is_same<T, B>::value>::type Foo<T>::bar()' cannot be overloaded 10:5:
error: with 'typename std::enable_if<std::is_same<T, A>::value>::type Foo<T>::bar()'
Source on cpp.sh. I thought both typename std::enable_if<std::is_same<T,?>::value>::type
could not be valid at the same time.
Edit
For posterity here is my edit based on @KerrekSB's answer -- SFINAE only works for deduced template arguments
#include <type_traits>
struct A{};
struct B{};
template<typename T>
struct Foo
{
template<typename U = T>
typename std::enable_if<std::is_same<U,A>::value>::type
bar()
{
}
template<typename U = T>
typename std::enable_if<std::is_same<U,B>::value>::type
bar()
{
}
};
int main()
{
};
SFINAE only works for deduced template arguments, i.e. for function templates. In your case, both templates are unconditionally instantiated, and the instantiation fails.
The following variant works:
Now
Foo()(x)
causes at most one of the overloads to be instantiated, since argument substitution fails in all the other ones.If you want to stick with your original structure, use explicit class template specialization: