Как мне определить указатель на функцию с C ++ 11, используя синтаксис?

171

Я хотел бы написать это

typedef void (*FunctionPtr)();

используя using. Как бы я это сделал?

rubenvb
источник
2
usingдействительно очень даже, особенно потому, что идентификаторы указателей на функции обычно находятся в середине typedefоператора и перемещаются вперед using. По крайней мере, там я потерян.
Starturtle

Ответы:

180

Он имеет аналогичный синтаксис, за исключением того, что вы удалите идентификатор из указателя:

using FunctionPtr = void (*)();

Вот пример

Если вы хотите «убрать безобразие», попробуйте то, что предложил Ксео:

#include <type_traits>

using FunctionPtr = std::add_pointer<void()>::type;

А вот еще одна демка .

0x499602D2
источник
25
Черт, я надеялся, что это :(
уберет
10
@rubenvb:; using FunctionPtr = AddPointer<void()>;)
Xeo
2
Для дальнейшей очистки можно использовать псевдонимы типов шаблонов add_pointer<void()>::type. Воспользуйтесь предложением здесь: groups.google.com/a/isocpp.org/d/msg/std-proposals/xDQR3y5uTZ0/… вы можете написать pointer<function<void>>.
bames53
5
Эти псевдонимы типов изменяют синтаксис типа с неясного, наизнаночного синтаксиса на простой синтаксис слева направо, что в значительной степени устраняет необходимость в пользовательских определениях типов для конкретных API, которые облегчают написание составных типов этого API.
bames53
10
В C ++ 14 вы сможете писать: using FunctionPtr = std :: add_pointer_t <void ()>;
Анджей
46

«Уродство» также можно убрать, если вы избегаете определения типа указателя:

void f() {}
using Function_t = void();    
Function_t* ptr = f;
ptr();

http://ideone.com/e1XuYc

Вадим Горюнов
источник
Это интересный подход, хотя я мог бы волноваться, что забуду *позже и получу запутанные ошибки.
Аполлис поддерживает Монику
Это определенно самая хорошая версия, представленная здесь. Спасибо. И я предпочитаю видеть указатель, так как в конце концов это указатель на функцию.
Пьер
13

Вы хотите a type-id, который по сути точно такой же, как объявление, за исключением того, что вы удалили declarator-id. declarator-id, Как правило , идентификатор, и имя , которое вы объявляете в equivilant декларации.

Например:

int x

declarator-idЭто xтак просто удалить его:

int

Точно так же:

int x[10]

Удалить x:

int[10]

Для вашего примера:

void (*FunctionPtr)()

Здесь declarator-idесть FunctionPtr. просто удалите его, чтобы получить type-id:

void (*)()

Это работает, потому что, учитывая, type-idвы всегда можете однозначно определить, куда будет идти идентификатор для создания объявления. С 8.1.1 в стандарте:

Можно однозначно определить местоположение в [type-id], где идентификатор появился бы, если бы конструкция была [декларацией]. Именованный тип тогда совпадает с типом гипотетического идентификатора.

Андрей Томазос
источник
9

Как насчет этого синтаксиса для ясности? (Обратите внимание на двойные скобки)

void func();
using FunctionPtr = decltype((func));
Лео Гудштадт
источник
1
Что означают двойные скобки в этом контексте? Ссылка на указатель на функцию?
0x499602D2
5
Вы FunctionPtrне указатель на функцию, но decltype(&f)смотрите здесь .
rubenvb
@ 1234597890 FunctionPtr - это неконстантная lvalue ссылка на тип 'void ()'
Лео Гудштадт
@rubenvb: Вы правы. Это не указатель на функцию, а ссылка на значение (тип). Вот почему static_assert завершается неудачно ... <br/> Попробуйте использовать FunctionPtr: using namespace std; #include <iostream> void do_f () {cerr << "что? \ n"; } void f (); используя FunctionPtr = decltype ((f)); используя FunctionPtr2 = decltype (& f); // не работает // используя FunctionPtr3 = decltype (f); int main () {FunctionPtr ff = do_f; и далее (); FunctionPtr2 ff2 = do_f; FF2 (); }
Лев Гудштадт
1

Другой подход может использовать автоматический тип возврата с конечным типом возврата.

using FunctionPtr = auto (*)(int*) -> void;

Это имеет спорное преимущество быть в состоянии сказать, что что-то функция PTR, когда псевдоним начинается с «авто (*)», и это не запутывается именами идентификаторов.

сравнить

typedef someStructureWithAWeirdName& (FunctionPtr*)(type1*, type2**, type3<type4&>);

с участием

using FunctionPtr = auto (*)(type1*, type2**, type3<type4&>) -> someStructureWithAWeirdName&;

Отказ от ответственности: я взял это из беседы Бина Дина "Легкость в современном C ++"

Сильвестр
источник