Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to interpret this C++ type?

Tags:

c++

types

gcc

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?

like image 354
Daniel Frużyński Avatar asked Jun 15 '16 20:06

Daniel Frużyński


Video Answer


2 Answers

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

like image 187
Pete Becker Avatar answered Sep 28 '22 18:09

Pete Becker


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.

like image 36
PcAF Avatar answered Sep 28 '22 17:09

PcAF