C++ 如何获取C++;lambda本身中的lambda函数?

C++ 如何获取C++;lambda本身中的lambda函数?,c++,c++11,lambda,c++14,c++17,C++,C++11,Lambda,C++14,C++17,我想弄清楚如何获取lambda函数本身的地址。下面是一个示例代码: []() { std::cout << "Address of this lambda function is => " << ???? }(); [](){ 解决这个问题的一种方法是用一个手写的函子类替换lambda,这也是lambda的本质所在 然后,您可以通过此获取地址,即使从未将函子分配给变量: #include <iostream> class Functor {

我想弄清楚如何获取lambda函数本身的地址。下面是一个示例代码:

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

解决这个问题的一种方法是用一个手写的函子类替换lambda,这也是lambda的本质所在

然后,您可以通过
获取地址,即使从未将函子分配给变量:

#include <iostream>

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

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

它的优点是100%可移植,并且非常容易推理和理解。

这不可能直接实现


但是,lambda捕获是类,并且对象的地址与其第一个成员的地址一致。因此,如果按值捕获一个对象作为第一个捕获,则第一个捕获的地址对应于lambda对象的地址:

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

0x7ffe8b80d820
0x7ffe8b80d820

或者,您可以创建一个lambda,将对lambda捕获的引用传递到其调用操作符:

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();
}
模板
自动装饰(F){
返回[f](自动&&…参数)可变{
f(f,std::forward(args)…);
};
}
int main(){
auto f=decoration([](auto&that){printf(“%p\n”,&that);});
f();
}

无法直接获取lambda中lambda对象的地址

现在,碰巧这是非常有用的。最常用的用法是为了递归

这些语言在定义之前无法谈论自己。它可以很容易地在以下语言中实现:

返回一个std函数


现在,这里,特别是,非常容易

auto-fib=[](auto&this-self,int-n){
如果(n<2)返回n;
返回自(n-1)+自(n-2);
};

(这个建议在标准会议上得到了广泛的支持)。

这是可能的,但在很大程度上取决于平台和编译器优化

在我所知道的大多数架构中,都有一个称为指令指针的寄存器。这个解决方案的目的是在函数内部提取它

在amd64上,以下代码应提供接近函数1的地址

#包括
void*foo(){
void*n;
asm易失性(“lea 0(%%rip),%%rax”
:“=a”(n));
返回n;
}
自动boo=[](){
void*n;
asm易失性(“lea 0(%%rip),%%rax”
:“=a”(n));
返回n;
};
int main(){
std::cout捕获lambda:

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

这仅仅是出于好奇,还是有一个潜在的问题需要解决?如果有潜在的问题,请直接问,而不是问一个单一的解决方案(对我们来说)未知问题…有效地确认XY问题。您可以使用手动编写的函子类替换lambda,然后使用
“获取lamba函数自身的地址”这是一个解决方案,一个你只关注的解决方案。可能还有其他的解决方案,可能更好。但我们无法帮助你,因为我们不知道真正的问题是什么。我们甚至不知道你将使用这个地址做什么。我只是想帮助你解决实际问题。@Someprogrammerdude这样说是明智的,我不认为问“X如何实现?”有什么问题。这里的X是“从内部获取lambda的地址”。你不知道该地址将用于什么用途并不重要,可能有“更好”也不重要解决方案,在其他人看来,在未知的代码库中(对我们来说)可能可行也可能不可行。更好的办法是只关注所陈述的问题。这要么可行,要么不可行。如果可行,那么如何解决?如果不可行,那么就说明它不可行,可以提出其他建议,IMHO。“对象的地址与其第一个成员的地址一致“是否在某个地方指定了捕获是有序的,或者没有不可见的成员?@n.”代词m。不,这是一个不可移植的解决方案。捕获实现可能会将成员从最大到最小排序,以最小化填充,标准明确允许。Re,“这是一个不可移植的解决方案。”这是未定义行为的另一个名称。@ruohola很难说。对象的地址与其第一个成员的地址一致对于标准布局类型也是如此。如果在不调用UB的情况下测试lambda的类型是否为标准布局,则可以在不产生UB的情况下执行此操作。生成的代码将具有依赖于实现的行为。但是,在不首先测试其合法性的情况下简单地执行此操作就是UB。我相信根据§8.1.5,它是未指定的。2,15:当计算lambda表达式时,通过copy捕获的实体用于直接初始化生成的闭包对象的每个对应的非静态数据成员,而与init捕获相对应的非静态数据成员则按照对应的初始值设定项(…)的指示进行初始化。(对于数组成员,数组元素是按递增的下标顺序直接初始化的。)这些初始化是按声明非静态数据成员的(未指定)顺序执行的。函子甚至可以像lambda一样声明:
struct{void operator()(){ STD::哇哦,Y组合器很难用动态类型语言(如Lisp/JavaScript /Python)来包装你的头。我从来没有想过我会在C++中看到一个。我感觉如果你在C++中这样做,你应该得到。arrested@MSalters不确定。如果
F
不是标准布局,那么
y\u combinator
就不是,所以sane guara不提供NTEE。@carto只有当lambda在作用域内,并且您不介意类型擦除开销时,上面的答案才有效。第三个答案是y组合器。第二个答案是手动y组合器。@kaz C++17功能。在11/14中,您将编写一个make函数,该函数将在1中扣除F
y_combinator{ [](auto& self)-> void {
  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)... );
  }
};
template<class R, class...Args>
auto Y = [] (auto f) {
  auto action = [=] (auto action) -> std::function<R(Args...)> {
    return [=] (Args&&... args)->R {
      return f( action(action), std::forward<Args>(args)... );
    };
  };
  return action(action);
};
auto fib = [](auto& this self, int n) {
  if (n < 2) return n;
  return self(n-1) + self(n-2);
};
std::function<void ()> fn = [&fn]() {
  std::cout << "My lambda is " << &fn << std::endl;
}