303
303

Reputation: 4732

Overload resolution of constrained functions

Is the call to f ambiguous? Since one of the functions is more constrained than the other, I wouldn't expect there to be any ambiguity. Yet, GCC 12.2 and Clang trunk reject the code, in contrast to Clang 15, MSVC 19.33, and MSVC trunk.

Code example:

template<typename...>
int f();

template<typename = void>
int f() requires true;

static_assert(sizeof(f()));

The error produced by GCC:

<source>:7:23: error: call of overloaded 'f()' is ambiguous
    7 | static_assert(sizeof(f()));
      |                      ~^~
<source>:2:5: note: candidate: 'int f() [with <template-parameter-1-1> = {}]'
    2 | int f();
      |     ^
<source>:5:5: note: candidate: 'int f() requires  true [with <template-parameter-1-1> = void]'
    5 | int f() requires true;
      |     ^

Upvotes: 5

Views: 186

Answers (1)

user17732522
user17732522

Reputation: 76678

Whether viable overloads from function templates are more constrained is considered only if the function templates are otherwise equivalent (except for potentially the return type). It is not sufficient that the call would otherwise be ambiguous.

In particular the corresponding template parameters must be equivalent, see [temp.func.order]/6.2.2. A template parameter that is a parameter pack (as in the first overload) is not equivalent to one that isn't (as in the second overload), see [temp.over.link]/6.2.

So the constraint doesn't matter for deciding which candidate is better. The call is ambiguous.

Upvotes: 2

Related Questions