如何在lambda本身中获取C++lambda函数的地址
How to get the address of a C++ lambda function within the lambda itself?
我正试图弄清楚如何在lambda函数本身中获取地址。这是一个示例代码:
[]() {
std::cout << "Address of this lambda function is => " << ????
}();
我知道我可以在一个变量中捕获lambda并打印地址,但我想在执行这个匿名函数时就地执行。
有没有更简单的方法?
在c++23之前的lambda中,无法直接获取lambda对象的地址。
现在,碰巧的是,这通常很有用。最常见的用法是为了递归。
y_combinator
来自于这样的语言:在你被定义之前,你不能谈论自己。它可以很容易地在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)... );
}
};
template<class F>
y_combinator(F)->y_combinator<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)... );
}
};
其中传递的CCD_ 2可以在不传递CCD_。
第二个匹配真实的y组合子(也就是不动点组合子(,我相信。你想要哪个取决于你所说的"lambda地址"是什么意思。
还有一个精辟的例子:
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);
};
返回std函数。
在c++23中,在lambda中访问this
变得更容易:
auto fib = [](this auto& self, int n) { if (n < 2) return n; return self(n-1) + self(n-2); };
您可以将第一个参数标记为this
,它就变成了自己。它甚至可以使用重载集技巧,其中self
是最推导的类型。
这不是直接可能的。
但是,lambda捕获是类,对象的地址与其第一个成员的地址一致。因此,如果按值捕获一个对象作为第一次捕获,则第一次捕获的地址对应于lambda对象的地址:
int main() {
int i = 0;
auto f = [i]() { printf("%pn", &i); };
f();
printf("%pn", &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("%pn", &that); });
f();
}
解决此问题的一种方法是用手工编写的函子类替换lambda。这也是lambda在发动机罩下的本质。
然后,您可以通过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%可移植的,并且非常容易推理和理解。
捕获lambda:
std::function<void ()> fn = [&fn]() {
std::cout << "My lambda is " << &fn << std::endl;
}
这是可能的,但在很大程度上取决于平台和编译器的优化。
在我所知道的大多数体系结构中,都有一个称为指令指针的寄存器。这个解决方案的要点是当我们在函数内部时提取它。
在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具有CCD_ 8的优化级别函数可以被内联。
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 获取具有静态局部变量的绑定/推断捕获 lambda 的函数指针
- 如何在lambda本身中获取C++lambda函数的地址
- 检测/获取捕获的 lambda 函数值
- 如何从 lambda 表达式中获取函数指针?
- 获取模板函数/泛型 lambda 的唯一返回类型
- 使用自动说明符获取 lambda 的参数类型
- 获取lambda的功能原型
- 如何在 c++/gcc 中获取 lambda 函数名称?
- 在编译时获取捕获 lambda 的类型
- 如何获取在 gcc 5+ 上不起作用的 lambda 函数
- 获取对 lambda 捕获值的引用
- 标准算法按值获取 lambda 是否有原因?
- "Error: expected a '{' introducing a lambda body"尝试从地图<字符,字符中获取字符时> C++
- 正在获取指向lambda的函数指针
- 如何获取 lambda 的返回类型,在 C++11 中归约函数
- 正在从带有参数的new_ptr的boost::lambda::bind中获取boost::函数
- 使用std::find_if时,从传递给lambda的元素中获取迭代器
- 如何使用捕获子句从lambda获取状态引用
- C++:使用提升 lambda 获取 std::tr1::unordered_map 中的最大值