Próbuję dowiedzieć się, jak uzyskać w sobie adres funkcji lambda. Oto przykładowy kod:
[]() {
std::cout << "Address of this lambda function is => " << ????
}();
Wiem, że potrafię uchwycić lambda w zmiennej i wydrukować adres, ale chcę to zrobić w miejscu, gdy wykonuje się ta anonimowa funkcja.
Czy istnieje prostszy sposób na zrobienie tego?
this
.Odpowiedzi:
Nie jest to bezpośrednio możliwe.
Jednak wartości lambda są klasami, a adres obiektu pokrywa się z adresem jego pierwszego elementu. Dlatego jeśli pierwszy obiekt zostanie przechwycony pod względem wartości, adres pierwszego przechwytywania odpowiada adresowi obiektu lambda:
Wyjścia:
Alternatywnie można utworzyć wzór dekoracyjny lambda, który przekazuje odwołanie do przechwytywania lambda do operatora wywołania:
źródło
Nie ma bezpośredniego sposobu uzyskania adresu obiektu lambda w lambda.
Tak się składa, że jest to często przydatne. Najczęstszym zastosowaniem jest powtórzenie.
y_combinator
Pochodzi z języków, w których nie można było mówić o sobie, aż was gdzie zdefiniowane. Można go dość łatwo zaimplementować w c ++ :teraz możesz to zrobić:
Odmiany tego mogą obejmować:
gdzie
self
przekazany można wywołać bez podawaniaself
jako pierwszego argumentu.Drugi odpowiada rzeczywistemu kombinatorowi y (czyli kombinatorowi punktu stałego). To, czego chcesz, zależy od tego, co rozumiesz przez „adres lambda”.
źródło
F
nie jest to standardowy układ,y_combinator
to nie jest, więc rozsądne gwarancje nie są zapewnione.Jednym ze sposobów rozwiązania tego problemu byłoby zastąpienie lambda ręcznie napisaną klasą funktora. Właśnie to lambda zasadniczo znajduje się pod maską.
Następnie możesz uzyskać adres
this
, nawet bez przypisywania funktora do zmiennej:Ma to tę zaletę, że jest w 100% przenośne i niezwykle łatwe do uzasadnienia i zrozumienia.
źródło
struct { void operator()() { std::cout << "Address of this functor is => " << this << '\n'; } } f;
Uchwyć lambda:
źródło
std::function
nie jest tu jednak potrzebna i wiąże się ze znacznymi kosztami. Kopiowanie / przenoszenie tego obiektu spowoduje jego uszkodzenie.Jest to możliwe, ale w dużym stopniu zależy od optymalizacji platformy i kompilatora.
W większości znanych mi architektur istnieje rejestr zwany wskaźnikiem instrukcji. Celem tego rozwiązania jest wyodrębnienie go, gdy jesteśmy w funkcji.
Na amd64 Poniższy kod powinien dać ci adresy zbliżone do funkcji 1.
Ale na przykład na gcc https://godbolt.org/z/dQXmHm z
-O3
funkcją poziomu optymalizacji może być wstawiony.źródło
thread_local
czasie trwania automatycznym lub przechowywania. To, co próbujesz uzyskać tutaj, to adres zwrotny funkcji, a nie obiekt. Ale nawet to nie zadziała, ponieważ prolog generowany przez kompilator przesuwa się na stos i dostosowuje wskaźnik stosu, aby zrobić miejsce dla zmiennych lokalnych.