Как получить адрес лямбда-функции C ++ внутри самой лямбды?

Я пытаюсь выяснить, как получить адрес лямбда-функции внутри себя. Вот пример кода:

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

Я знаю, что могу записать лямбда-переменную и напечатать адрес, но я хочу сделать это на месте, когда эта анонимная функция выполняется.

Есть ли более простой способ сделать это?

39
задан ruohola 7 November 2019 в 22:55
поделиться

6 ответов

Это не непосредственно возможно.

Однако получения лямбды являются классами, и адрес объекта совпадает с адресом своего первого участника. Следовательно при получении одного объекта значением как первое получение адрес первого получения соответствует адресу объекта лямбды:

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

Выводы:

0x7ffe8b80d820
0x7ffe8b80d820
<час>

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

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();
}
29
ответ дан 26 November 2019 в 18:47
поделиться

Нет никакого способа непосредственно получить адрес объекта лямбды в лямбде.

Теперь, как это происходит, это довольно часто полезно. Наиболее популярный способ использования в порядке для рекурсивного вызова.

y_combinator прибывает из языков, где Вы не могли говорить о себе до Вас, где определено. Это может быть реализовано довольно легко в :

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

теперь можно сделать это:

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

изменения А этого могут включать:

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

то, куда эти self передал, можно назвать, не передавая в self как первый аргумент.

вторые соответствия реальный y combinator (иначе комбинатор неподвижной точки) я верю. То, которое Вы хотите, зависит от того, что Вы подразумеваете 'под адресом лямбды'.

47
ответ дан 26 November 2019 в 18:47
поделиться

Это возможно, но высоко зависит от платформы и компиляторной оптимизации.

На большей части архитектуры я знаю, существует регистр, названный указателем команд. Точка этого решения должна извлечь его, когда мы в функции.

На amd64 После кода должен дать, Вы обращаетесь близко к функциональному.

#include <iostream>

void* foo() {
    void* n;
    asm volatile("lea 0(%%rip), %%rax"
      : "=a" (n));
    return n;
}

auto boo = [](){
    void* n;
    asm volatile("lea 0(%%rip), %%rax"
       : "=a" (n));
    return n;
};

int main() {
    std::cout<<"foo"<<'\n'<<((void*)&foo)<<'\n'<<foo()<<std::endl;  
    std::cout<<"boo"<<'\n'<<((void*)&boo)<<'\n'<<boo()<<std::endl;
}

, Но например на gcc https://godbolt.org/z/dQXmHm с -O3 функция уровня оптимизации могла бы быть встроена.

-6
ответ дан 26 November 2019 в 18:47
поделиться

Получите лямбду:

std::function<void ()> fn = [&fn]() {
  std::cout << "My lambda is " << &fn << std::endl;
}
-1
ответ дан 26 November 2019 в 18:47
поделиться

Вот подход версии обещания:

#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();
}
-2
ответ дан 26 November 2019 в 18:47
поделиться

Один способ решить это, должен был бы заменить лямбду рукописным классом функтора. Это также, что лямбда по существу находится под капотом.

Тогда можно получить адрес до this, даже никогда не присваивая функтор переменной:

#include <iostream>

class Functor
{
public:
    void operator()() {
        std::cout << "Address of this functor is => " << this;
    }
};

int main()
{
    Functor()();
    return 0;
}

Вывод:

Address of this functor is => 0x7ffd4cd3a4df

Это имеет преимущество, о котором это - 100%-е портативное устройство, и чрезвычайно легкий рассуждать и понять.

23
ответ дан 26 November 2019 в 18:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: