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


171

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

typedef void (*FunctionPtr)();

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


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

Ответы:


180

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

using FunctionPtr = void (*)();

Вот пример

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

#include <type_traits>

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

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


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 ++"

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.