Considérez les typedefs suivants:
typedef int (*f1)(float);
typedef f1 (*f2)(double);
typedef f2 (*f3)(int);
f2
est une fonction qui renvoie un pointeur de fonction. De même f3
, mais le type de la fonction, le pointeur vers lequel f3
renvoie, est f2
. Comment puis-je définir f3
sans les typedefs? Je sais que les typedefs sont le moyen le plus propre et le plus facile à comprendre de définir f3
. Cependant, mon intention ici est de mieux comprendre la syntaxe C.
Commencez par votre déclaration pour f1
:
int (*f1)(float);
Tu veux f2
pour être un pointeur sur une fonction renvoyant f1
, donc remplacez f1
dans la déclaration ci-dessus avec la déclaration pour f2
:
int (* f1 )(float);
|
+-----+-----+
| |
v v
int (*(*f2)(double))(float);
La déclaration se lit comme suit:
f2 -- f2
*f2 -- is a pointer
(*f2)( ) -- to a function
(*f2)(double) -- taking a double parameter
*(*f2)(double) -- returning a pointer
(*(*f2)(double))( ) -- to a function
(*(*f2)(double))(float) -- taking a float parameter
int (*(*f2)(double))(float) -- returning int
Vous répétez le processus pour f3
:
int (*(* f2 )(double))(float);
|
+---+----+
| |
v v
int (*(*(*f3)(int))(double))(float);
qui se lit comme
f3 -- f3
*f3 -- is a pointer
(*f3)( ) -- to a function
(*f3)(int) -- taking an int parameter
*(*f3)(int) -- returning a pointer
(*(*f3)(int))( ) -- to a function
(*(*f3)(int))(double) -- taking a double parameter
*(*(*f3)(int))(double) -- returning a pointer
(*(*(*f3)(int))(double))( ) -- to a function
(*(*(*f3)(int))(double))(float) -- taking a float parameter
int (*(*(*f3)(int))(double))(float); -- returning int
En C++, le miracle des modèles peut rendre cela un peu plus facile.
#include <type_traits>
std::add_pointer<
std::add_pointer<
std::add_pointer<
int(float)
>::type(double)
>::type(int)
>::type wow;
Comme avec le typedef, vous seul placez votre définition de fonction à la place de son nom.
Voici comment f2
ressemblerait à:
typedef int (*(*f2)(double))(float);
Tu peux faire f3
comme exercice, car je suppose que ce sont des devoirs;)
Mais ne le fais pas. Cela peut être fait, mais ce sera très déroutant. Les typedefs sont là pour faciliter l'écriture et la lecture de ce short de code.
Une fonction f
qui ne prend aucun argument et retourne un pointeur de fonction int (*)(float)
serait probablement quelque chose comme (non testé):
int (*f())(float);
Ensuite, pour le reste, il vous suffit de continuer à ajouter des parenthèses jusqu'à ce qu'il ressemble à LISP.
Apprenez la la règle droite-gauche :
La règle "droite-gauche" est une règle tout à fait régulière pour déchiffrer les déclarations C. Il peut également être utile pour les créer.
Utilisation std::function
:
typedef std::function<int(float)> f1;
typedef std::function<f1(double)> f2;
typedef std::function<f2(int)> f3;
ou
typedef std::function<std::function<std::function<int(float)>(double)>(int)> f3;