2011-05-25 12 views
7

¿Cómo declaro un puntero de función que apunta a una función que toma el mismo puntero de función que el argumento?Puntero de función que apunta a una función que toma un puntero de función

he probado el siguiente sin éxito:

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

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

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

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

Es esto posible?

+1

No estoy seguro de si es posible, sería como tratar de crear plantillas de algo consigo mismo, que acaba de terminar con una declaración recursiva –

+0

Más bien creo que no se puede hacer. –

+2

¿Qué tal si solo utilizas una declaración genérica y un reparto explícito? – casablanca

Respuesta

13

Lo dudo mucho, pero puede obtener la recursión necesaria introduciendo una estructura.

struct Rec; 

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

struct Rec { 
    RecFun fun; 
}; 

Ejemplo de uso: (GotW #57 como en la hierba de Sutter) De acuerdo con las sugerencias de Chris, Vito, y Johannes, aquí hay algunas conversiones implícitas convenientes::

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

actualización

struct Rec; 

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

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

+1 Método elegante para gestionar el problema de recursión. – dusktreader

+1

Incluso podría anular 'operator()' para que se vea y se comporte como una función (un functor), si prefiere esa sintaxis –

+0

¡Respuesta perfecta! ¡Muchas gracias! : D –

0

La manera más fácil es simplemente tipear ambos. Un puntero de función es un parámetro al igual que cualquier otro tipo:

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

Editar: La gente ha señalado que quiere decir que ambos sean del mismo tipo. En ese caso, no es posible, ya que el tipo sería recursivo. Es imposible crear una especificación de tipo completa (el tipo de parámetro de la función nunca se especifica por completo, ergo ...)

+2

Creo que OP significa un argumento del mismo tipo. – casablanca

+0

El 'OuterFunctionPtr' tendría que tomar un 'OuterFunctionPtr' como argumento. –

+0

-1. Tipo incorrectodef! – Nawaz

0

Por desgracia, no se puede hacer. Sería bueno si pudieras usar typename para reenviar declarar un typedef; algo así como:

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

pero eso no funciona, porque typename se limita a unos pocos plantilla específica utiliza

0

es posible de esta manera:

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

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

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

También puede derrotar el tipo sistema simulando que la función toma algún otro tipo de puntero a función, y luego fundiéndolo cuando pasa algo a la función y dentro de la función para recuperar el tipo original.

No se recomienda, obviamente, pero solo ponerlo por ahí.

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); 
} 
Cuestiones relacionadas