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

Как вы объявляете указатель функции, который принимает себя по своим параметрам?typedef, который относится к самому себе

+1

Вы не можете, потому что это нескончаемый рекурсивное определение. –

+3

@SethCarnegie: ваш аргумент недействителен. 'struct X {X * a; }; 'концептуально одно и то же, но разрешено *. – ybungalobill

+1

@ybungalobill: Нет, это не так, тип функции содержит свои параметры, тип класса не содержит его членов. – Xeo

ответ

8

Косвенно:

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

Не то, чтобы я мог видеть любое использование в том, что, как вы можете видеть из моего примера.

+1

Это не совсем то, что было задано, но это, вероятно, насколько возможно. –

+0

Я могу воспользоваться этим, спасибо Xeo. – Tergiver

2

Вы не можете выразить это в системе типов. Хотя в этом нет ничего принципиально неправильного, это упрощает вещи, устраняя циклы в системе типов. Это сильно напоминает мне Axiom of Foundation.

Что вы можете сделать, это передать указатель недействительным и приведения его к вашему типу:

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

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

Вы не можете набрасывать указатели 'void *' в такие указатели на функции. POSIX рекомендует использовать что-то вроде 'void * ptr; FunctionPtrType fptr; * (void **) (& fptr) = ptr; ', чтобы избежать неопределенного поведения. –

+0

@ R.MartinhoFernandes: Вы правы, что это реализация определена. Но вы можете сделать это на любой разумной архитектуре фон Неймана, имеющей «void *» и указатели на функции одинакового размера. – ybungalobill

+2

Вы не можете переносить перенос между 'void *' и указателями на функции, независимо от того, сколько дополнительных уровней косвенности вы добавляете. Вместо этого используйте другой тип указателя функции. –

Смежные вопросы