This version works fine:
template<typename T>
struct Foo
{
template<typename U = T>
typename std::enable_if<std::is_same<U,A>::value>::type
bar() { std::cout << "1" << std::endl; }
template<typename U = T>
typename std::enable_if<std::is_same<U,B>::value>::type
bar() { std::cout << "2" << std::endl; }
};
This version fails:
template<typename T>
struct Foo2
{
template<typename U = T, typename V = typename std::enable_if<std::is_same<U,A>::value>::type >
V bar() { std::cout << "1" << std::endl; }
template<typename U = T, typename V = typename std::enable_if<std::is_same<U,B>::value>::type >
V bar() { std::cout << "2" << std::endl; }
};
with:
error: 'template template V Foo2::bar()' cannot be overloaded with 'template template V Foo2::bar()'
The difference between both versions is in the first I use the expression directly, in the second one I create a template default parameter and use that one as return type.
What is the reason to fail in the second example?
Because in the case#2, the two bar
are considered to be equivalent. When consider whether two function templates are equivalent or not, the default template parameters are ignored; they're not the part of function template signature. So they're considered as
template<typename U, typename V>
V bar() { std::cout << "1" << std::endl; }
template<typename U, typename V>
V bar() { std::cout << "2" << std::endl; }
As you can see, they're equivalent in fact.
(emphasis mine)
Two function templates are considered equivalent if
- they are declared in the same scope
- they have the same name
- they have identical template parameter lists
- the expressions involving template parameters in their return types and parameter lists are equivalent
The case#1 works because the return type is dependent on the template parameter and used with different expression; then they're considered not equivalent.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With