Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does this template argument deduction/overload resolution fail?

This code snippet fails to compile in MSVC, Clang and Gcc, (they give different error message):

int foo(int a, int b) {
    return a + b;
}

template <class Ret, class A, class B>
void foo(Ret (*)(A, B)) {

}

int main() {
    foo(foo);
    return 0;
}

Shouldn't this compile? I can't see why it fails in resolving the overloaded function or in deducing the template arguments. Any help is welcome, thanks.

PS: It compiles if the template is replaced with void foo(int (*)(int, int)), or if we rename one of foo to avoid overloading.

like image 723
felix Avatar asked Feb 20 '19 10:02

felix


People also ask

What is template argument deduction?

Template argument deduction is used when selecting user-defined conversion function template arguments. A is the type that is required as the result of the conversion. P is the return type of the conversion function template.

How template functions can be overloaded?

A template function can be overloaded either by a non-template function or using an ordinary function template.

What is type deduction c++?

Type inference or deduction refers to the automatic detection of the data type of an expression in a programming language. It is a feature present in some strongly statically typed languages. In C++, the auto keyword(added in C++ 11) is used for automatic type deduction.

What is 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.


1 Answers

For simplicity, let's call the first overload foo1 and call the second overload foo2.

With templates, the problem is that you cannot deduce the template arguments for the outer foo, according to [temp.deduct.call]/6:

If the argument is an overload set containing one or more function templates, the parameter is treated as a non-deduced context.

Without templates, the program considers all possibilities foo1(foo1), foo1(foo2), foo2(foo1), foo2(foo2) and chooses the only viable one foo2(foo1), according to [over.over]/6:

[ Note: If f() and g() are both overloaded functions, the cross product of possibilities must be considered to resolve f(&g), or the equivalent expression f(g). — end note ]

like image 181
xskxzr Avatar answered Sep 27 '22 20:09

xskxzr