why sfinae overload is not resolved
Asked Answered
A

1

11

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?

Arc answered 6/6, 2018 at 8:47 Comment(2)
Default template parameter values are not part of function signatureMessenia
There is even a note about this common mistake in std::enable_if doc.Gluttonize
N
8

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.

Negro answered 6/6, 2018 at 8:59 Comment(2)
@Arc I fixed the statement. The point is different expression.Negro
Thanks! So I keep in mind that the expression itself makes the difference. It feels strange that this expression is something like part of the signature... but ok, it is like it is;)Arc

© 2022 - 2024 — McMap. All rights reserved.