web-dev-qa-db-fra.com

Syntaxe C pour les fonctions renvoyant des pointeurs de fonction

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.

35
keveman

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
124
John Bode

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;
14
Puppy

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;)

7
Blindy

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.

4
Maxim Egorushkin

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;
0
Inverse