Comment puis-je taper un pointeur de fonction avec le C ++ 11 en utilisant la syntaxe?

171

J'aimerais écrire ceci

typedef void (*FunctionPtr)();

en utilisant using. Comment pourrais-je faire ça?

rubenvb
la source
2
très conf en usingeffet, en particulier parce que les identificateurs de pointeur de fonction résident généralement au milieu d'une typedefinstruction et se déplacent au premier plan en utilisant using. Au moins c'est là que je suis perdu.
starturtle

Réponses:

180

Il a une syntaxe similaire, sauf que vous supprimez l'identifiant du pointeur:

using FunctionPtr = void (*)();

Voici un exemple

Si vous voulez "enlever la laideur", essayez ce que Xeo a suggéré:

#include <type_traits>

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

Et voici une autre démo .

0x499602D2
la source
25
Dang, j'espérais que cela enlèverait la laideur:(
rubenvb
10
@rubenvb:; using FunctionPtr = AddPointer<void()>;)
Xeo
2
Il est possible d'utiliser des alias de type de modèle pour nettoyer davantage add_pointer<void()>::type: En utilisant la suggestion ici: groups.google.com/a/isocpp.org/d/msg/std-proposals/xDQR3y5uTZ0/ ... vous pouvez écrire pointer<function<void>>.
bames53
5
Ces alias de type changent la syntaxe de type d'une syntaxe obscure et à l'envers en une simple syntaxe de gauche à droite, ce qui élimine en grande partie le besoin de typedefs personnalisés pour des API spécifiques qui facilitent l'écriture des types composés de cette API.
bames53
10
En C ++ 14, vous pourrez écrire: en utilisant FunctionPtr = std :: add_pointer_t <void ()>;
Andrzej
46

La "laideur" peut également être supprimée si vous évitez de taper un pointeur:

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

http://ideone.com/e1XuYc

Vadim Goryunov
la source
C'est une approche intéressante, même si je crains peut-être d'oublier la *dernière et d'obtenir des erreurs déroutantes.
Apollys soutient Monica le
C'est certainement la plus belle version présentée ici. Je vous remercie. Et je préfère voir un pointeur, car c'est un pointeur de fonction après tout.
Pierre
13

Vous voulez un type-id, qui est essentiellement identique à une déclaration, sauf que vous supprimez le declarator-id. Le declarator-idest généralement un identifiant et le nom que vous déclarez dans la déclaration équivilante.

Par exemple:

int x

L' declarator-idest xdonc enlever juste:

int

Également:

int x[10]

Retirez le x:

int[10]

Pour votre exemple:

void (*FunctionPtr)()

Ici, declarator-idc'est FunctionPtr. alors supprimez-le simplement pour obtenir le type-id:

void (*)()

Cela fonctionne car, étant donné un, type-idvous pouvez toujours déterminer de manière unique où l'identifiant irait pour créer une déclaration. À partir de 8.1.1 dans la norme:

Il est possible d'identifier de manière unique l'emplacement dans le [type-id] où l'identifiant apparaîtrait si la construction était une [déclaration]. Le type nommé est alors le même que le type de l'identifiant hypothétique.

Andrew Tomazos
la source
9

Que diriez-vous de cette syntaxe pour plus de clarté? (Notez la double parenthèse)

void func();
using FunctionPtr = decltype((func));
Leo Goodstadt
la source
1
Que signifie la double parenthèse dans ce contexte? Une référence à un pointeur de fonction?
0x499602D2
5
Votre FunctionPtrn'est pas un pointeur de fonction, mais l' decltype(&f)est, voir ici .
rubenvb
@ 1234597890 FunctionPtr est une référence de valeur non const au type 'void ()'
Leo Goodstadt
@rubenvb: Vous avez raison. Ce n'est pas un pointeur de fonction mais une référence lvalue à la fonction (type). C'est pourquoi static_assert échoue ... <br/> Essayez d'utiliser FunctionPtr: using namespace std; #include <iostream> void do_f () {cerr << "quoi? \ n"; } void f (); en utilisant FunctionPtr = decltype ((f)); en utilisant FunctionPtr2 = decltype (& f); // Ne fonctionne pas // en utilisant FunctionPtr3 = decltype (f); int main () {FunctionPtr ff = do_f; ff (); FunctionPtr2 ff2 = do_f; ff2 (); }
Leo Goodstadt
1

Une autre approche pourrait utiliser le type de retour automatique avec le type de retour de fin.

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

Cela a l'avantage discutable de pouvoir dire que quelque chose est une fonction ptr lorsque l'alias commence par "auto (*)" et qu'il n'est pas obscurci par les noms d'identifiant.

Comparer

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

avec

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

Clause de non-responsabilité: J'ai pris ceci de la conférence "Easing into Modern C ++" de Bean Deane

Silvester
la source