Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot deduce template argument that is a function

Why cannot F be deduced for proxy()?

It should be possible because I am restricting it - only for functions that return an int.

#include <utility>
#include <iostream>
#include <type_traits>
using namespace std;

int foo(int bar) {
    cout << "int" << endl;
    return 2;
}

float foo(float bar) {
    cout << "float" << endl;
    return 1;
}

template <typename F, typename... Args>
typename enable_if<
    is_same<
        typename result_of<F(Args...)>::type,
        int
        >::value,
    typename result_of<F(Args...)>::type
    >::type
proxy(F func, Args&&... args) {
    return func(forward<Args>(args)...);
}

int main() {
    proxy(foo, 5);
}

Here is the error:

b.cpp:29:17: error: no matching function for call to 'proxy(<unresolved overloaded function type>, int)'
b.cpp:24:1: note:   template argument deduction/substitution failed:
b.cpp:29:17: note:   couldn't deduce template parameter 'F'
like image 810
onqtam Avatar asked Jun 03 '15 15:06

onqtam


People also ask

Can a template parameter be a function?

A template parameter is a special kind of parameter that can be used to pass a type as argument: just like regular function parameters can be used to pass values to a function, template parameters allow to pass also types to a function.

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 do you call a function template in C++?

Defining a Function TemplateA function template starts with the keyword template followed by template parameter(s) inside <> which is followed by the function definition. In the above code, T is a template argument that accepts different data types ( int , float , etc.), and typename is a keyword.

CAN default arguments be used with the template?

You cannot give default arguments to the same template parameters in different declarations in the same scope. The compiler will not allow the following example: template<class T = char> class X; template<class T = char> class X { };


1 Answers

The problem is this:

proxy(foo, 5);

The compiler tries to deduce the type of foo, but there are 2 overloads. Of course, it can deduce Args... from 5, but the type of foo is still non-deducible, since the compiler doesn't know which overload to pick when doing the type deduction.

Note that the compiler needs to know the type of F in the signature of the function, i.e. here, so SFINAE do its magic:

is_same<
    typename result_of<F(Args...)>::type,
    int
>::value,

There is absolutely no way for it to correctly deduce the type of F from the proxy(foo, 5) call, so SFINAE cannot kick in. As a side note, remark that C++ cannot overload based on the return type only. So you won't be able to differentiate two functions with the same name based on the return type alone. You'll need somehow to force a parameter matching which will SFINAE out the non-candidate overloads.

Somehow related: Deducing the return type of a standalone function

And a relevant quote from the standard, emphasize mine (thanks to @T.C. for pointing it out):

14.8.2.1 Deducing template arguments from a function call [temp.deduct.call]/(6.2)

(6) When P is a function type, pointer to function type, or pointer to member function type:

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

  • (6.2) If the argument is an overload set (not containing function templates), trial argument deduction is attempted using each of the members of the set. If deduction succeeds for only one of the overload set members, that member is used as the argument value for the deduction. If deduction succeeds for more than one member of the overload set the parameter is treated as a non-deduced context.

like image 121
vsoftco Avatar answered Oct 19 '22 14:10

vsoftco