2011-05-25 8 views
7

Comment déclarer un pointeur de fonction pointant sur une fonction prenant le même pointeur de fonction que l'argument?Pointeur de fonction pointant sur une fonction qui prend un pointeur de fonction

J'ai essayé ce qui suit sans succès:

typedef void (*fnptr)(void (*)()); 

void func(fnptr) 
{ 
    /* ... */ 
} 

void func2(fnptr) 
{ 
    /* ... */ 
} 

void main() 
{ 
    fnptr fn = &func; 
    func2(fn); 
} 

Est-ce possible?

+1

Je ne suis pas sûr si vous le pouvez, ce serait comme essayer de quelque chose avec lui-même créer des modèles à, vous venez de finir avec une déclaration récursive –

+0

Je pense plutôt qu'il ne peut pas être fait. –

+2

Que diriez-vous d'utiliser une déclaration générique et une distribution explicite? – casablanca

Répondre

13

Je doute beaucoup, mais vous pouvez obtenir la récursivité nécessaire en introduisant une structure.

struct Rec; 

typedef void (*RecFun)(const Rec&); 

struct Rec { 
    RecFun fun; 
}; 

Exemple d'utilisation:

#include <iostream> 

void nothing(const Rec& rec) {} 
Rec recNothing = { nothing }; 

void f(const Rec& rec) 
{ 
    std::cout << "f\n"; 
    rec.fun(recNothing); 
} 
Rec recF = { f }; 

void g(const Rec& rec) 
{ 
    std::cout << "g\n"; 
    rec.fun(recNothing); 
} 
Rec recG = { g }; 

int main() 
{ 
    recF.fun(recG); 
} 

Mise à jour: Selon les suggestions de Chris, Vitus, et Johannes, voici quelques conversions implicites pratiques (comme dans Herb Sutter GotW #57):

struct Rec; 

typedef void (*RecFun)(const Rec&); 

struct Rec { 
    RecFun fun; 
    Rec(RecFun fun) : fun(fun) {} 
    operator RecFun() const { return fun; } 
}; 
+1

+1 Méthode élégante pour gérer le problème de récurrence. – dusktreader

+1

Vous pourriez même surcharger 'operator()' pour qu'il ressemble et se comporte comme une fonction (un foncteur), si vous préférez cette syntaxe –

+0

Réponse parfaite! Merci beaucoup! : D –

0

La manière la plus simple est de simplement typer les deux. Un pointeur de fonction est un paramètre comme tout autre type:

typedef (* InnerFunctionPtr)(void); 
typedef (* OuterFunctionPtr)(InnerFunctionPtr); 

Edit: Les gens ont signalé que vous voulez dire à la fois d'être du même type. Dans ce cas, ce n'est pas possible, car le type serait récursif. Il est impossible de créer une spécification de type complète (le type du paramètre de la fonction n'est jamais complètement spécifié, ergo ...)

+2

Je pense que l'OP signifie un argument du même type. – casablanca

+0

Le 'OuterFunctionPtr' devrait prendre un 'OuterFunctionPtr' comme argument. –

+0

-1. Mauvais typedef! – Nawaz

0

Hélas, cela ne peut pas être fait. Ce serait bien si vous pouviez utiliser typename pour transmettre un typedef; quelque chose comme:

typename fnptr; 
typedef (*fnptr)(fnptr); 

mais cela ne fonctionne pas, car typename est limitée à quelques modèles spécifiques utilise

0

il est possible de cette manière:

typedef void (*fnptr)(void (*)()); 

fnptr fn1,fn2; 
void func(fn1) 
{ 
/* ... */ 
} 

void func2(fn2) 
{ 
/* ... */ 
} 
void main() 
{ 
fnptr fn = &func; 
func2(fn); 
} 
0

Vous pouvez également vaincre le type système en prétendant que la fonction prend un autre type de pointeur de fonction, puis en le moulant lorsque vous passez quelque chose à la fonction et à l'intérieur de la fonction pour récupérer le type d'origine.

Non recommandé de toute évidence, mais il suffit de le mettre là.

typedef void (*fnptr)(void (*)()); 

void func(void (*x)()) 
{ 
    fnptr f = (fnptr)x; 
    /* ... */ 
} 

void func2(void (*x)()) 
{ 
    fnptr f = (fnptr)x; 
    /* ... */ 
} 

void main() 
{ 
    fnptr fn = &func; 
    func2((void (*)())fn); 
} 
Questions connexes