¿Cómo obtener la dirección de una función lambda de C++ dentro de la propia lambda?




c++11 c++14 (4)

Estoy tratando de descubrir cómo obtener la dirección de una función lambda dentro de sí misma. Aquí hay un código de muestra:

[]() {
    std::cout << "Address of this lambda function is => " << ????
}();

Sé que puedo capturar el lambda en una variable e imprimir la dirección, pero quiero hacerlo en el lugar cuando se ejecuta esta función anónima.

¿Hay una manera más simple de hacerlo?


Aquí hay un enfoque de versión prometedor:

#include <future>
#include <cstdio>

int main() {
    std::promise<void *> p;

    auto f = [ready_future = p.get_future()]() mutable {
             printf("%p\n", ready_future.get());
        };

    p.set_value(&f);

    f();
}

Captura la lambda:

std::function<void ()> fn = [&fn]() {
  std::cout << "My lambda is " << &fn << std::endl;
}

No es directamente posible.

Sin embargo, las capturas lambda son clases y la dirección de un objeto coincide con la dirección de su primer miembro. Por lo tanto, si captura un objeto por valor como la primera captura, la dirección de la primera captura corresponde a la dirección del objeto lambda:

int main() {
    int i = 0;
    auto f = [i]() { printf("%p\n", &i); };
    f();
    printf("%p\n", &f);
}

Salidas:

0x7ffe8b80d820
0x7ffe8b80d820

Alternativamente, puede crear un patrón de diseño de decorador lambda que pase la referencia a la captura lambda a su operador de llamada:

template<class F>
auto decorate(F f) {
    return [f](auto&&... args) mutable {
        f(f, std::forward<decltype(args)>(args)...);
    };
}

int main() {
    auto f = decorate([](auto& that) { printf("%p\n", &that); });
    f();
}

No hay forma de obtener directamente la dirección de un objeto lambda dentro de una lambda.

Ahora, como sucede, esto es bastante útil. El uso más común es para recurrir.

El y_combinator proviene de idiomas en los que no podría hablar sobre usted hasta que se lo definiera. Se puede implementar con bastante facilidad en c ++ :

template<class F>
struct y_combinator {
  F f;
  template<class...Args>
  decltype(auto) operator()(Args&&...args) const {
    return f( f, std::forward<Args>(args)... );
  }
  template<class...Args>
  decltype(auto) operator()(Args&&...args) {
    return f( f, std::forward<Args>(args)... );
  }
};

ahora puedes hacer esto:

y_combinator{ [](auto& self) {
  std::cout<<"Address of this lambda function is => "<< &self;
} }();

Una variación de esto puede incluir:

template<class F>
struct y_combinator {
  F f;
  template<class...Args>
  decltype(auto) operator()(Args&&...args) const {
    return f( *this, std::forward<Args>(args)... );
  }
  template<class...Args>
  decltype(auto) operator()(Args&&...args) {
    return f( *this, std::forward<Args>(args)... );
  }
};

donde el self pasado puede ser llamado sin pasar en self como primer argumento.

El segundo coincide con el combinador y real (también conocido como el combinador de punto fijo), creo. Lo que desea depende de lo que quiere decir con "dirección de lambda".





c++17