R Sahu
R Sahu

Reputation: 206737

Why isn't std::result_of<int(int)>::type valid?

I have read the following related questions:

  1. std::result_of simple function
  2. decltype, result_of, or typeof?

and the page on std::result_of at cppreference.com.

All of them seem to indicate that I should be able to use:

 std::result_of<int(int)>::type v1 = 10;

However, when I tried building the following program using g++ 4.9.2

#include <type_traits>

int foo()
{
   return 0;
}

int main()
{
    std::result_of<int(int)>::type v1 = 10;           // LINE A
    std::result_of<decltype(foo)>::type v2 = 20;      // LINE B
    return 0;
}

I get error messages for "LINE A" and "LINE B". The error messages are:

socc.cc: In function ‘int main()’:
socc.cc:10:5: error: ‘type’ is not a member of ‘std::result_of<int(int)>’
     std::result_of<int(int)>::type v1 = 10;
     ^
socc.cc:11:5: error: ‘type’ is not a member of ‘std::result_of<int()>’
     std::result_of<decltype(foo)>::type v2 = 20;
     ^

The command I used to compile:

g++ -std=c++11 -Wall    socc.cc   -o socc

FWIW, using

 typename std::result_of<int(int)>::type v1 = 10;
 typename std::result_of<decltype(foo)>::type v2 = 20;

didn't make a difference.

It seems that I am failing to understand how result_of is supposed to be used.

Can you explain why I am getting the compiler errors?

Upvotes: 12

Views: 2019

Answers (3)

David G
David G

Reputation: 96855

To use result_of, the type supplied must be a function type where the return type is the type of a Callable and the parameter list contains the types of the arguments to call it with. result_of<int(int)> therefore asks "what type will I get when I call declval<int>() with the argument declval<int>()". The answer is that there is no type, because int is not a function type.

Here's an excerpt from Table 57:

If the expression INVOKE(declval<Fn>(), declval<ArgTypes>()...) is well formed when treated as an unevaluated operand (Clause 5), the member typedef type shall name the type decltype(INVOKE (declval<Fn>(), declval<ArgTypes>()...)); otherwise, there shall be no member type

Given the function foo, you can use:

 std::result_of_t<decltype((foo))()> v1 = 10;
 std::result_of_t<decltype(&foo)()> v2 = 10;

Upvotes: 3

Mehrwolf
Mehrwolf

Reputation: 8537

As stated in the link you have already posted, the first part of the argument to result_of must be a callable type or a reference to a function.

Suppose you have a

struct Callable
{
    int operator()(double);
    void operator()(int);
};

then result_of helps you determining the return type, if you know the type of the arguments. For the example above:

result_of<Callable(int)>::type == void    ... per definition
result_of<Callable(double)>::type == int  ... per definition
result_of<Callable(char)>::type == void   ... the int-overload matches better
result_of<Callable(float)>::type == int   ... the double-overload matches better

In order to find the return type of the function foo you would have to go via a function reference:

result_of<decltype(foo)& ()>::type == int

But this seems a bit twisted as you could directly write

decltype(foo()) == int

Upvotes: 11

lisyarus
lisyarus

Reputation: 15586

You seem to assume std::result_of<R(Args...)>::type to be simply R - that is, the result type of a function having signature R(Args...). But std::result_of<F(Args...)>::type is the result of calling an instance of type F with arguments of types Args....

So, std::result_of<int(int)>::type does not make sense - int objects are not callable.

Please, read cppreference again :)

Upvotes: 12

Related Questions