Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

overload resolution of template function with auto

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)

like image 219
Jarod42 Avatar asked Dec 16 '16 01:12

Jarod42


People also ask

Can you overload a template function?

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.

What is difference between function template and overloaded?

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.

What is the overload resolution?

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.

What is overload resolution in C#?

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.


1 Answers

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 of F1 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 Ps 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,

  • case 1 and 3 are ambiguous, because for two non-dependent function types (the ones of #1 and #2), there is no ordering pair.
  • the accepting behavior in case 2 is correct (as expected).

[temp.deduct.type]/8 element 9 (T()), in case you were curious.

like image 183
Columbo Avatar answered Sep 28 '22 16:09

Columbo