2009-04-27 11 views
17

Me gustaría declarar una función que devuelve un puntero a una función del mismo tipo.Puntero de declaración recursiva de función en C

me gustaría utilizarlo para implementar máquinas de estado como la siguiente:

typedef event_handler_t (*event_handler_t)(event_t*); // compilation error 

event_handler_t state2(event_t* e); 
event_handler_t state1(event_t* e) { 
    switch(e->type) { 
    //... 
    case SOME_EVENT: 
     return state2; 
    //... 
    } 

} 
event_handler_t state2(event_t* e) { 
    switch(e->type) { 
    //... 
    case OTHER_EVENT: 
     return state1; 
    //... 
    } 
} 

//... 
event_handler_t event_handler; 
//... 
event_handler(&e); 
//... 

me las arreglo para evitar el error compliation utilizando estructuras de la siguiente manera:

typedef struct event_handler { 
    struct event_handler (*func)(event_t *); 
} event_handler_t; 

Pero esto hace que el retorno declaración más complicada:

event_handler_t state2(event_t* e) { 
{ 
    event_handler_t next_handler = {NULL}; 
    switch(e->type) { 
    //... 
    case OTHER_EVENT: 
     next_handler.func = state1; 
     break; 
    //... 
    } 
    return next_handler; 
} 

Me pregunto si hay una mejor manera de crear tales punteros de función en c.

+1

Ver también: [SO 816356] (http://stackoverflow.com/questions/816356/how-can-i-typedef-a-function-pointer-that-takes-a-function-of-its-own -type-as-an) –

Respuesta

7

No se puede hacer esto en C: una función no puede devolver un puntero a sí misma, ya que la declaración de tipo se expande recursivamente y nunca termina. Consulte esta página para obtener una explicación: http://www.gotw.ca/gotw/057.htm

La solución descrita en la página anterior significa devolver void (*)() en lugar del puntero de la función con el tipo correcto; su solución puede decirse que es un poco más ordenada.

+0

Er, buen punto. –

2

Esto se discute en el libro de Herb Sutter Más excepcional C++, artículo 32, donde la respuesta parece ser (para C) "no sin uso de moldes". Para C++ es posible con la introducción habitual de una clase proporcionar algo de indirección adicional.

Cuestiones relacionadas