Today I was helping with following incorrect code piece (func
was declared with int
param, but int*
was passed as second param to std::thread
constructor):
#include <thread>
void func(int);
int* ptr;
void start()
{
std::thread t = std::thread(func, ptr);
}
When I tried to compile this with gcc 5.3.0, it printed error message with following type:
class std::result_of<void (*(int*))(int)>
Now I wonder how to interpret type passed as parameter to class std::result_of<>
. It is similar to pointer to function (in this case void(*)(int)
), but with extra (int*)
after star in brackets. How to interpret this type?
This isn't as simple as it looks. std::result_of
abuses the type system to smuggle in information about a function call so that it can figure out what the return type of that function call would be.
The argument to std::result_of
has the form Fty(T1, T2, ...)
, where Fty
is a callable type and T1
etc. are the types of the arguments that it is being called with. Given that information, std::result_of
has a nested type named type
that is a synonym for the return type of calling a callable type with the signature Fty
with arguments of the given types. Phew, that's a mouthful.
So, in result_of<void (*(int*))(int)>
there are two parts to the template argument. The first part is void (*(int*))
, which is the callable type in question. In this case it's a pointer to function that takes int*
and returns void
. The second part is (int)
, which is the type list for the proposed arguments.
So what that is saying is that std::result_of
is being instantiated with a function whose type is void (*(int*))
and with an argument list of (int)
. And that's the problem, as you indicated: you can't pass an argument of type int
to a function that takes an argument of type int*
.
Aren't you glad you asked? (Incidentally, this is pretty low-level template hackery that's not needed any more; decltype
is a much cleaner way to figure out the return type of a function call).
void (*(int*))(int)
Is:
a function that takes a single parameter of type int*
as returns
a pointer to a function that takes a single parameter of type int
and returns
void
It is similar to the C/C++ standard library function signal:
void (*signal(int sig, void (*func)(int)))(int);
which returns a pointer to a previous signal handler (which is of the same type as the func
parameter).
EDIT: As Pete Becker pointed out in comment, when used with std::result_of
, it means something different, but type of expression itself is still the type I described, std::result_of
just interprets it differently.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With