The question you want to ask is probably a duplicate of this one: Why does std::result_of take an (unrelated) function type as a type argument?
Let's dissect:
std::result_of<F(Ts...)>::type
So, somewhere in namespace std
, we've got a class template result_of<>
. It takes one template type parameter; i.e., it looks basically like this:
template<typename Foo>
struct result_of
{
typedef FOOBARBAZ type;
};
Okay, so, we're instantiating this template with the parameter F(Ts...)
. That's unusual syntax! You presumably know that Ts
is a parameter pack, and therefore the Ts...
inside the parentheses will expand at compile time to a comma-separated list of types, for example int, double, bool
. So we've got F(int, double, bool)
. Okay, that's a function type.
Just as int(char)
means "function taking char
and returning int
", so does F(int, double, bool)
mean "function taking int, double, bool
and returning F
".
"But wait," you say. "I thought F
was already my function type!"
Yes. F
is your function type. But the type expected by std::result_of
is, really!, that function type wrapped up in another function type. To elaborate:
typedef int (*F)(char);
typedef F G(char);
static_assert(std::is_same< std::result_of<G>::type, int >::value);
static_assert(std::is_same< std::result_of<F(char)>::type, int >::value);
static_assert(std::is_same< std::result_of<int (*(char))(char)>::type, int >::value);
Each of the above lines is exactly equivalent: F(char)
is just a much more aesthetically pleasing way of writing int (*(char))(char)
. Of course, you can't always get away with it, because sometimes F
is a function type that can't be returned from a function:
typedef int F(char);
std::result_of<F(char)>; // fails to compile
As @Simple wrote in the comments, std::result_of<F(Ts...)>::type
can always be replaced with the less clever but also less confusing expression
decltype( std::declval<F>() ( std::declval<Ts>()... ) )
i.e., "the decltype
of the result of calling a value of type F
with arguments of types Ts...
. Here, there are no wacky higher-level function types; everything just works the way you'd naturally expect it to. Personally, I would probably use the decltype
approach in my own code, just because it's easier to understand; but I imagine that some people would prefer the std::result_of
approach because it looks superficially simpler and is blessed by the Standard. To each his own. :)