2016-06-15 3 views
6

Сегодня я помогаю с последующим неправильным куском коды (func был объявлено с int парами, но int* был принят в качестве второго паров для std::thread конструктора):Как интерпретировать этот тип C++?

#include <thread> 

void func(int); 
int* ptr; 

void start() 
{ 
    std::thread t = std::thread(func, ptr); 
} 

Когда я попытался скомпилировать это с GCC 5.3.0, напечатанное сообщение об ошибке с следующим типом:

class std::result_of<void (*(int*))(int)> 

Теперь интересно, как интерпретировать тип, передаваемый в качестве параметра class std::result_of<>. Он похож на указатель на функцию (в данном случае void(*)(int)), но с дополнительным (int*) после звезды в скобках. Как интерпретировать этот тип?

+0

Если 'func' требует' int', почему вы передаете 'int *'? – NathanOliver

+0

Это была ошибка в коде, который я видел сегодня - вероятно, это была опечатка. –

+2

Аналогичное утверждение дает [это согласно cdecl] (http://cdecl.ridiculousfish.com/?q=void+%28*f%28int*%29%29%28int%29). – ArchbishopOfBanterbury

ответ

5
void (*(int*))(int) 

Is:

функция, которая принимает один параметр типа int* как возвращения

указатель на функцию, которая принимает один параметр типа int и возвращает

void


Он аналогичен стандартной функции библиотеки signal на C/C++:

void (*signal(int sig, void (*func)(int)))(int); 

, которая возвращает указатель на предыдущий обработчик сигнала (который имеет тот же тип, что и параметр func).

EDIT: Как Pete Becker pointed out in comment, при использовании с std::result_of, так ли means something different, но тип выражения сама по себе еще тип я описал, std::result_of просто интерпретирует его по-разному.

+0

Спасибо, я вижу это сейчас. Я начал декодировать с неправильной точки и запутался. –

+1

Да, это то, что было бы в реальном мире. Но это ** не **, что это означает, когда это тип аргумента для 'std :: result_of', который захватывает это обозначение для представления вызываемого типа и его списка аргументов. –

+0

@PeteBecker Я думал, что OP был смущен этой декларацией. Я никогда не слышал о 'std :: result_of' (потому что я выучил C++ после выхода C++ 11, поэтому я использую просто' decltype' и новые функции), спасибо за ваше объяснение. Я отредактирую свой ответ. – PcAF

7

Это не так просто, как кажется. std::result_of злоупотребляет системой типов для контрабанды информации о вызове функции, чтобы он мог выяснить, каков будет тип возврата этого вызова функции.

Аргумента std::result_of имеет вид Fty(T1, T2, ...), где Fty является вызываемым типом и T1 и т.д. являются типами аргументов, что она вызывается с. Учитывая эту информацию, std::result_of имеет вложенный тип с именем type, который является синонимом возвращаемого типа вызова вызываемого типа с сигнатурой Fty с аргументами данных типов. Фу, это глоток.

Итак, в result_of<void (*(int*))(int)> есть две части аргумента шаблона. Первая часть - void (*(int*)), которая является вызываемым типом. В этом случае это указатель на функцию, которая принимает int* и возвращает void. Вторая часть - (int), которая является списком типов для предложенных аргументов.

Так что это то, что std::result_of создается при помощи функции, тип которой void (*(int*)) и список аргументов (int). И в этом проблема, как вы указали: вы не можете передать аргумент типа int функции, которая принимает аргумент типа int*.

Вы не рады, что спросили? (Кстати, это довольно низкоуровневый шаблонный хакер, который больше не нужен, decltype - это гораздо более простой способ выяснить тип возврата вызова функции).

+0

Да, это было путано с самого начала. Спасибо за объяснение. –