Here is a piece of code that tries to provide a pointer to an overloaded function to another function that can accept a value of any type:
template <typename T>
void AcceptAnything(T&&);
void Foo();
template <typename T>
void Foo();
void Bar() {
AcceptAnything(&Foo);
}
This fails to compile, giving the following error under clang:
<source>:10:3: error: no matching function for call to 'AcceptAnything'
10 | AcceptAnything(&Foo);
| ^~~~~~~~~~~~~~
<source>:2:6: note: candidate template ignored: couldn't infer template argument 'T'
2 | void AcceptAnything(T&&);
| ^
I understand why you can't do this for an overloaded function in general. But in this particular case I'm surprised that &Foo doesn't have type void(*)(), given that no template arguments are provided. My mental model is:
The only function named
Foohere is the untemplated one, with the other one being a family of functions namedFoo<T>for any typeT.The expression
&Foorefers to the address of a particular function namedFoo.There is no such thing as the address of a family of functions.
So I would expect that &Foo unambiguously means "a pointer to the untemplated function Foo". But both gcc and clang disagree with me, so my mental model must be wrong.
Why is &Foo ambiguous in this case, and which part of the standard covers it?
This is CWG 2873 and current wording seems to make the program well-formed even though all compilers reject the code.
The non-template function is the only viable option here since template argument deduction fails here for function template
Fooand the phrase "if any" in over.over#3 seems to mean that template are ignored if deduction fails. So there is no specialization that can be added to the set and the set contains only one candidate which is the non-template function.Now as there is no target from the function template
Foo, the template argument deduction forFoofails so no specialization will be added to set and as per over.over#3 the template will be ignored:Note the emphasis on "if any" in the above quoted reference.
Since template argument deduction fails here, there is no specialization that is added to the set. And the only candidate in the set is the non-template function which will be used.