2009-04-27 13 views
17

同じ型の関数へのポインタを返す関数を宣言したいと思います。Cの関数ポインタの再帰的宣言

私は以下のようなステートマシンを実装するためにそれを使用したいと思います:

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

しかし、これはリターンする:私は、次のような構造を使用してコンパイルにエラーを回避するために管理

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

より複雑な文章:

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

もっと良い方法があるのでしょうか? cの中のそのような関数ポインタ。

+1

も参照してください:[SO 816356](http://stackoverflow.com/questions/816356/how-can-i-typedef-a-function-pointer-that-takes-a-function-of-its-own - タイプ - として) –

答えて

7

Cでこれを行うことはできません。型宣言が再帰的に展開され、決して終了しないので、関数はそれ自身へのポインタを返すことができません。説明についてはこのページを参照してください。http://www.gotw.ca/gotw/057.htm

上記の回避策は、正確に型指定された関数ポインタの代わりにvoid (*)()を返すことを意味します。あなたの回避策は間違いなく少しきついです。

+0

まあ、良い点。 –

2

これは、Herb Sutterの本で詳しく説明されています。例外的なC++、アイテム32です。答えは(Cの場合)「キャストを使用しない」と思われます。 C++の場合、通常のクラスの導入で余計な間接指定を行うことは可能です。