Як я можу набрати вказівник функції на C ++ 11 за допомогою синтаксису?


171

Я хотів би написати це

typedef void (*FunctionPtr)();

використовуючи using. Як би я це зробив?


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

Відповіді:


180

Він має подібний синтаксис, за винятком того, як ви видалите ідентифікатор з вказівника:

using FunctionPtr = void (*)();

Ось приклад

Якщо ви хочете "зняти потворність", спробуйте те, що запропонував Xeo:

#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
Ці псевдоніми типів змінюють синтаксис типу з неясного, синтаксису зсередини на простий синтаксис зліва направо, що значною мірою виключає потребу в користувальницьких typedefs для конкретних API, що полегшує записування цих типів сполук API.
bames53

10
У C ++ 14 ви зможете записати: використовуючи FunctionPtr = std :: add_pointer_t <void ()>;
Анджей

46

"Потворність" також може бути знята, якщо уникнути набору вказівника:

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

http://ideone.com/e1XuYc


Це цікавий підхід, хоча, можливо, я переживаю, що забуду *пізніше і помилково помиляюся.
Аполіс підтримує Моніку

Це, безумовно, найкраща версія, представлена ​​тут. Дякую. І я вважаю за краще бачити вказівник, оскільки це вказівник функції.
П’єр

13

Ви хочете 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 (*)()

Це працює, тому що, даючи a, type-idви завжди можете однозначно визначити, куди піде ідентифікатор для створення декларації. З 8.1.1 у стандарті:

Можна однозначно визначити розташування в [type-id], де ідентифікатор з'явиться, якби конструкція була [декларацією]. Тоді названий тип такий же, як і тип гіпотетичного ідентифікатора.


9

Як щодо цього синтаксису для наочності? (Зверніть увагу на подвійні дужки)

void func();
using FunctionPtr = decltype((func));

1
Що означають подвійні дужки в цьому контексті? Посилання на покажчик на функцію?
0x499602D2

5
Ваш FunctionPtrне є покажчиком функції, але decltype(&f)це, дивіться тут .
rubenvb

@ 1234597890 FunctionPtr - це нецікаве значення посилання на тип "void ()"
Лео Гудштадт

@rubenvb: Ти маєш рацію. Це не покажчик функції, а посилання на значення на функцію (тип). Ось чому static_assert не вдається ... <br/> Спробуйте використовувати FunctionPtr: використання простору імен 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; ff (); FunctionPtr2 ff2 = do_f; ff2 (); }
Лев Гудштадт

1

Інший підхід може використовувати тип автоматичного повернення із заднім типом повернення.

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

Це має суперечливу перевагу в тому, що можна сказати щось - це функція ptr, коли псевдонім починається з "auto (*)", і він не переплутаний іменами ідентифікатора.

Порівняйте

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.