12

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?

Community
  • 1
  • 1
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • 1
    Do you mean `result_of<(int(int))(int)>`? – Kerrek SB Jun 18 '15 at 15:21
  • note that `result_of` changed from C++11 to C++14, can you confirm you are asking about the C++11 version ? – M.M Jun 18 '15 at 15:25
  • @KerrekSB, No, I meant `result_of<(int(int))>`. That may be the the missing piece of my understanding of `result_of`. Would you elaborate on that? – R Sahu Jun 18 '15 at 15:25
  • @MattMcNabb, yes, I am using `C++11`. – R Sahu Jun 18 '15 at 15:26
  • I think you would want to mean that, but you cannot say the type of a function that returns a function. The next best thing is `result_of`. [Demo](http://ideone.com/KBJW7J). – Kerrek SB Jun 18 '15 at 15:27
  • 2
    @RSahu: Read again: `result_of::type` is the type of the result of calling a *callable of type `F`* with the `Args...`. In your demand, `int` is not callable! – Kerrek SB Jun 18 '15 at 15:27

3 Answers3

12

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 :)

lisyarus
  • 15,025
  • 3
  • 43
  • 68
11

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
Mehrwolf
  • 8,208
  • 2
  • 26
  • 38
3

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;
David G
  • 94,763
  • 41
  • 167
  • 253