With the 3 following overloads
template <class T> auto foo() { return 1; }
template <class T> int foo() { return 2; }
template <class T> T foo() { return 3; }
Is the following ill formed ?
static_cast<int(*)()>(&foo<int>)();
Clang selects overload #2, whereas gcc fails to compile (Demo)
When removing overload #1, both agree to select overload #2 (Demo).
When removing overload #2, gcc selects overload #1 and clang fails to compile (Demo)
You may overload a function template either by a non-template function or by another function template. The function call f(1, 2) could match the argument types of both the template function and the non-template function.
Function overloading is used when multiple functions do similar operations; templates are used when multiple functions do identical operations. Templates provide an advantage when you want to perform the same action on types that can be different.
The process of selecting the most appropriate overloaded function or operator is called overload resolution. Suppose that f is an overloaded function name. When you call the overloaded function f() , the compiler creates a set of candidate functions.
Just as a reminder, overloading is what happens when you have two methods with the same name but different signatures. At compile time, the compiler works out which one it's going to call, based on the compile time types of the arguments and the target of the method call.
As per [over.over]/2, we perform template argument deduction. This will succeed for all three overloads: in the first one, keep [temp.deduct.funcaddr]/2 in mind:
A placeholder type (7.1.7.4) in the return type of a function template is a non-deduced context. If template argument deduction succeeds for such a function, the return type is determined from instantiation of the function body.
Since the deduction will succeed (given that all template parameters have explicitly supplied arguments), the return type is deduced as int
. In the second case, deduction succeeds since the argument is provided, and in the third, T
will be deduced. †
Going on to paragraph 4,
If more than one function is selected, [...] any given function template specialization
F1
is eliminated if the set contains a second function template specialization whose function template is more specialized than the function template ofF1
according to the partial ordering rules of 14.5.6.2. After such eliminations, if any, there shall remain exactly one selected function.
According to [temp.deduct.partial]/3, the function templates' function types are used for partial ordering. We can immediately see that #1 and #2's function types do not contain any template parameters that participate in deduction, hence via the addition to [temp.deduct.partial]/4 introduced by core issue 1391's resolution, their corresponding P
s are not used to determine the ordering. @bogdan explained here why that resolution is problematic; the bottom line is that ordering just yields an ambiguity for #1 and #2.
That is, according to current (probably defective) wording, the conversion is ill-formed in all cases. If partial ordering is fixed for pairs of non-dependent/deducing parameters,
†[temp.deduct.type]/8 element 9 (T()
), in case you were curious.
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