Ich versuche herauszufinden, wie man die Adresse einer Lambda-Funktion in sich selbst erhält. Hier ist ein Beispielcode:
[]() {
std::cout << "Address of this lambda function is => " << ????
}();
Ich weiß, dass ich das Lambda in einer Variablen erfassen und die Adresse drucken kann, aber ich möchte es an Ort und Stelle tun, wenn diese anonyme Funktion ausgeführt wird.
Gibt es einen einfacheren Weg, dies zu tun?
this
.Antworten:
Es ist nicht direkt möglich.
Lambda-Captures sind jedoch Klassen, und die Adresse eines Objekts stimmt mit der Adresse seines ersten Mitglieds überein. Wenn Sie also ein Objekt als erste Erfassung nach Wert erfassen, entspricht die Adresse der ersten Erfassung der Adresse des Lambda-Objekts:
Ausgänge:
Alternativ können Sie ein Dekorationsmuster Lambda erstellen , das den Verweis auf die Lambda-Erfassung an seinen Anrufoperator übergibt:
quelle
Es gibt keine Möglichkeit, die Adresse eines Lambda-Objekts innerhalb eines Lambda direkt abzurufen.
Nun, wie es passiert, ist dies ziemlich oft nützlich. Die häufigste Verwendung ist, um zu rekursieren.
Das
y_combinator
kommt aus Sprachen, in denen Sie nicht über sich selbst sprechen konnten, bis Sie definiert wurden. Es kann ziemlich einfach in c ++ implementiert werden :Jetzt können Sie dies tun:
Eine Variation davon kann umfassen:
wobei das
self
übergebene aufgerufen werden kann, ohneself
als erstes Argument übergeben zu werden.Der zweite entspricht dem Real-Y-Kombinator (auch bekannt als Fixpunkt-Kombinator), glaube ich. Was Sie wollen, hängt davon ab, was Sie unter "Lambda-Adresse" verstehen.
quelle
F
es sich nicht um ein Standardlayout handelt,y_combinator
ist dies nicht der Fall, sodass keine vernünftigen Garantien gegeben werden.Eine Möglichkeit, dies zu lösen, besteht darin, das Lambda durch eine handgeschriebene Funktorklasse zu ersetzen. Es ist auch das, was das Lambda im Wesentlichen unter der Haube ist.
Dann können Sie die Adresse erhalten
this
, auch ohne den Funktor jemals einer Variablen zuzuweisen:Dies hat den Vorteil, dass dies zu 100% portabel ist und extrem einfach zu verstehen und zu verstehen ist.
quelle
struct { void operator()() { std::cout << "Address of this functor is => " << this << '\n'; } } f;
Nehmen Sie das Lambda auf:
quelle
std::function
wird hier jedoch nicht benötigt und ist mit erheblichen Kosten verbunden. Wenn Sie dieses Objekt kopieren / verschieben, wird es beschädigt.Dies ist möglich, hängt jedoch stark von der Plattform- und Compileroptimierung ab.
Auf den meisten mir bekannten Architekturen gibt es ein Register, das als Befehlszeiger bezeichnet wird. Der Sinn dieser Lösung besteht darin, sie zu extrahieren, wenn wir uns innerhalb der Funktion befinden.
Auf amd64 Der folgende Code sollte Ihnen Adressen in der Nähe der Funktion 1 geben.
Aber zum Beispiel auf gcc kann https://godbolt.org/z/dQXmHm mit
-O3
Optimierungsstufenfunktion inline sein.quelle
thread_local
Speicherdauer verwendet werden. Was Sie hier abrufen möchten, ist die Absenderadresse der Funktion, kein Objekt. Aber selbst das funktioniert nicht, da der vom Compiler generierte Funktionsprolog auf den Stapel verschoben und den Stapelzeiger angepasst wird, um Platz für lokale Variablen zu schaffen.