2011-12-21 15 views
13
typedef bool (*Foo)(Foo a, Foo b); 

¿Cómo se declara un puntero de función que se acepta a sí mismo en sus parámetros?Un typedef que se refiere a sí mismo

+1

No se puede porque se trata de una definición recursiva sin fin. –

+3

@SethCarnegie: su argumento no es válido. 'struct X {X * a; }; 'conceptualmente es lo mismo, pero * está * permitido. – ybungalobill

+1

@ybungalobill: No, no lo es, un tipo de función contiene sus parámetros, un tipo de clase no contiene sus miembros. – Xeo

Respuesta

8

Indirectamente:

struct Foo{ 
    typedef bool (*FooPtr)(Foo a, Foo b); 
    Foo(FooPtr p) 
     : p(p) 
    {} 

    bool operator()(Foo a, Foo b) const{ 
    return p(a,b); 
    } 

    FooPtr p; 
}; 

struct Bar{ 
    Bar(Foo f) 
     : some_callback(f) 
    {} 

    Foo some_callback; 
}; 

bool a_callback(Foo a, Foo b){ 
    return false; 
} 

int main() { 
    Bar b(a_callback); 
    b.some_callback(Foo(a_callback), Foo(a_callback)); 
} 

No es que alguna vez podría ver cualquier uso en que, como se puede ver en mi ejemplo.

+1

Eso no es exactamente lo que se preguntó, pero es probable que sea todo lo que se pueda. –

+0

Puedo hacer uso de esto, gracias Xeo. – Tergiver

2

No puede expresar esto en el sistema de tipos. Aunque no hay nada fundamentalmente erróneo en esto, simplifica las cosas al eliminar los ciclos dentro del sistema de tipos. Me recuerda mucho al Axiom of Foundation.

Lo que puede hacer es pasar un puntero nulo y lo echó a su tipo:

typedef bool (*Foo)(void* a, void* b); 

bool f(void* a, void* b) 
{ 
    return ((Foo)a)(a,b); 
} 
+1

No puede convertir punteros 'void *' en punteros a funciones como esa. POSIX recomienda usar algo como 'void * ptr; FunctionPtrType fptr; * (void **) (& fptr) = ptr; ', para evitar un comportamiento indefinido. –

+0

@ R.MartinhoFernandes: Tiene razón en que su implementación está definida. Pero puede hacerlo en cualquier arquitectura de sane von Neumann que tenga 'void *' y punteros de función del mismo tamaño. – ybungalobill

+2

No se puede convertir de forma portátil entre 'void *' y los punteros de función, sin importar cuántos niveles adicionales de indirección agregue. Use otro tipo de puntero a función en su lugar. –

Cuestiones relacionadas