Come posso digitare un puntatore a funzione con C ++ 11 usando la sintassi?


171

Mi piacerebbe scrivere questo

typedef void (*FunctionPtr)();

usando using. Come potrei farlo?


2
in usingeffetti molto conf , soprattutto perché gli identificatori di puntatori a funzione di solito risiedevano nel mezzo di typedefun'istruzione e si spostano in primo piano usando using. Almeno è lì che mi sono perso.
inizio

Risposte:


180

Ha una sintassi simile, tranne per la rimozione dell'identificatore dal puntatore:

using FunctionPtr = void (*)();

Ecco un esempio

Se vuoi "togliere la bruttezza", prova ciò che Xeo ha suggerito:

#include <type_traits>

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

Ed ecco un'altra demo .


25
Dang, speravo che :(
togliesse

10
@rubenvb:; using FunctionPtr = AddPointer<void()>;)
Xeo,

2
È possibile utilizzare gli alias del tipo di modello per ripulire ulteriormente add_pointer<void()>::type: Utilizzando il suggerimento qui: groups.google.com/a/isocpp.org/d/msg/std-proposals/xDQR3y5uTZ0/… è possibile scrivere pointer<function<void>>.
bames53

5
Questi alias di tipo cambiano la sintassi del tipo da sintassi oscura e capovolta a una semplice sintassi da sinistra a destra, che elimina in gran parte la necessità di typedef personalizzati per API specifiche che semplificano la scrittura dei tipi composti di quell'API.
bames53

10
In C ++ 14, sarai in grado di scrivere: usando FunctionPtr = std :: add_pointer_t <void ()>;
Andrzej,

46

La "bruttezza" può anche essere tolta se si evita di scrivere un puntatore:

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

http://ideone.com/e1XuYc


Questo è un approccio interessante, anche se potrei essere preoccupato, dimenticherò più *tardi e otterrò errori confusi.
Apollys sostiene Monica il

Questa è sicuramente la versione più bella presentata qui. Grazie. E preferisco vedere un puntatore, dopo tutto è un puntatore a funzione.
Pierre

13

Si desidera un type-id, che è sostanzialmente identico a una dichiarazione, tranne per il fatto che si elimina declarator-id. Di declarator-idsolito è un identificatore e il nome che si sta dichiarando nella dichiarazione equivalente.

Per esempio:

int x

Il declarator-idè xquindi basta rimuoverlo:

int

Allo stesso modo:

int x[10]

Rimuovi il x:

int[10]

Per il tuo esempio:

void (*FunctionPtr)()

Qui declarator-idè FunctionPtr. quindi rimuovilo per ottenere type-id:

void (*)()

Questo funziona perché, dato type-idche puoi sempre determinare in modo univoco dove andrebbe l'identificatore per creare una dichiarazione. Dall'8.1.1 nella norma:

È possibile identificare in modo univoco la posizione in [ID-tipo] in cui l'identificatore apparirebbe se la costruzione fosse una [dichiarazione]. Il tipo indicato è quindi uguale al tipo dell'ipotetico identificatore.


9

Che ne dici di questa sintassi per chiarezza? (Nota doppia parentesi)

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

1
Cosa significa la doppia parentesi in questo contesto? Un riferimento a un puntatore a funzione?
0x499602D2,

5
Il tuo FunctionPtrnon è un puntatore a funzione, ma lo decltype(&f)è, vedi qui .
rubenvb,

@ 1234597890 FunctionPtr è un riferimento al valore non costante al tipo 'void ()'
Leo Goodstadt

@rubenvb: hai ragione. Non è un puntatore a funzione ma un riferimento lvalue alla funzione (tipo). Ecco perché static_assert fallisce ... <br/> Prova a utilizzare FunctionPtr: usando namespace std; #include <iostream> void do_f () {cerr << "che cosa? \ n"; } void f (); utilizzando FunctionPtr = decltype ((f)); utilizzando FunctionPtr2 = decltype (& f); // Non funziona // utilizzando FunctionPtr3 = decltype (f); int main () {FunctionPtr ff = do_f; ff (); FunctionPtr2 ff2 = do_f; ff2 (); }
Leo Goodstadt,

1

Un altro approccio potrebbe utilizzare il tipo di ritorno automatico con tipo di ritorno finale.

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

Questo ha il vantaggio discutibile di poter dire che qualcosa è una funzione ptr quando l'alias inizia con "auto (*)" e non è offuscato dai nomi degli identificatori.

Confrontare

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

con

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

Disclaimer: ho preso questo dal discorso "Easing into Modern C ++" di Bean Deane

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.