Troskyvs
Troskyvs

Reputation: 8087

C++11 result_of deducing my function type failed

I was trying a program below:

#include<type_traits>
using namespace std;
template <class F, class R = typename result_of<F()>::type>
R call(F& f) { return f(); }
int answer() { return 42; }

int main()
{
    call(answer); 
    return 0;
}

"call(answer)" fails to compile

VC says 'R call(F&)' could not deduce template argument for 'R'

GCC says |note: template argument deduction/substitution failed:|error: function returning a function

I'm not sure if a "function name" could be used for templates. Where did I get wrong, how to make my call(answer) work?

Upvotes: 1

Views: 77

Answers (3)

skypjack
skypjack

Reputation: 50568

You can use forwarding references in these cases:

#include<type_traits>
#include<utility>
#include<cassert>

using namespace std;

template <class F, class R = typename result_of<F()>::type>
R call(F&& f) { return std::forward<F>(f)(); }

int answer() { return 42; }

int main()
{
    assert(call(answer) == 42);
    return 0;
}

It usually avoids troubles.

That said, why your code doesn't work is nicely explained by @T.C. in his answer.
See also the comments to this question for further details.

Upvotes: 1

T.C.
T.C.

Reputation: 137394

You are calling f as an lvalue, so:

template <class F, class R = typename result_of<F&()>::type>
//                                               ^
R call(F& f) { return f(); }

Upvotes: 1

max66
max66

Reputation: 66230

I suppose you could avoid the second template argument and use a combination of auto and decltype().

Something like

#include<type_traits>

using namespace std;

template <class F>
auto call(F& f) -> decltype( f() )
 { return f(); } 

int answer()
 { return 42; }

int main()
{
    call(answer); 

    return 0;
}

If you (when you) can use C++14, you can use simply auto

template <class F>
auto call(F& f)
 { return f(); } 

p.s.: sorry for my bad English.

Upvotes: 0

Related Questions