2013-03-11 11 views
6

Gibt es eine Möglichkeit, ein typedef so zu erstellen, dass das folgende (eine grundlegende "reine" Implementierung des y-Kombinator) kompilieren würde?Typedef für rekursives Lambda

typedef ??? f; 
[](f x){x(x);} ([](f x){x(x);}); 

Dies hat den Effekt eines „rekursive lambda“ erstellen, das heißt eine, die sich selbst aufruft, indem eine zweite Lambda unter Verwendung an sich selbst eine Referenz zu erhalten. x im ersten Lambda ist ein Verweis auf das zweite Lambda, so x(x) nennt das zweite Lambda mit einem Verweis auf sich. Danach rekursiert das zweite Lambda durch Aufruf x(x). Dieser Code sollte, wenn er ausgeführt wird, eine Endlosschleife erzeugen, bis er den Stapelüberlauf erreicht. Komplexere Implementierungen der zweiten Funktion können willkürliches rekursives Verhalten erzeugen.

Ich habe versucht typedef ing verschiedene Versionen von void(*)(...), aber ich glaube nicht, dass dies gelingen kann. Meine Template-Metaprogrammierung ist nicht stark genug, um mit so etwas fertig zu werden.

+0

Was bedeutet 'x (x);' zu tun (vorausgesetzt, es ist möglich)? Auch was bedeutet das Argument "([] (f x) {x (x);})" und tun? Gib uns eine Idee, was du tust. – Nawaz

+0

Nur recurse. Es ist ein Y-Kombinator. – nneonneo

+0

@nneonneo: OK, ich weiß nicht, was ein Y-Kombinator ist, also denke ich, meine Antwort sieht idiotisch aus. Sollte das nur eine unendliche Rekursion aufbauen, indem es sich selbst aufruft? Und darfst du eine neue Klasse 'X' definieren und dann' typedef X f'? –

Antwort

6

Wie wäre es mit diesem?

#include <functional> 
#include <iostream> 

struct X 
{ 
    template<typename F> 
    X(F f) : _f(f) 
    { } 

    void operator() (std::function<void(X)> f) 
    { 
     std::cout << "Calling myself..." << std::endl; 
     _f(f); 
    } 

    std::function<void(X)> _f; 
}; 

int main() 
{ 
    typedef X f; 
    [](f x){x(x);} ([](f x){x(x);}); 
} 
+0

Hm. Nun, es erfüllt den Buchstaben des Gesetzes, wenn nicht der Geist (das zweite Lambda ist im Grunde unbenutzt). – nneonneo

+0

@nneonneo: Du meinst die erste. – Xeo

+0

@ Xeo: Hm? Das erste Lambda konstruiert ein "f x" unter Verwendung des zweiten Lambda und ruft dann "x (x)" auf. Aber das zweite Lambda wird nach dem Bau weggeworfen. – nneonneo