如何在编译时将this指针和类方法参数传递给局部constexpr lambda
报错原因
你给出的代码编译失败的核心原因是:当你用constexpr修饰lambda变量l时,要求该变量的初始化值必须是编译期常量。而你声明的lambda捕获了this和rhs两个运行期可变的参数(成员函数的入参、this指针都不属于编译期常量范畴),因此无法用于初始化constexpr修饰的变量。
可行解决方案
方案1:去掉lambda变量的constexpr修饰(推荐)
C++17及更高版本中,只要lambda的函数体符合constexpr要求,即使lambda变量本身没有被constexpr修饰,也可以在编译期上下文中正常调用。你只需要删除lambda变量前的constexpr关键字即可,整个operator+依然支持编译期计算:
struct A { int a; constexpr A(int a) : a(a) {} constexpr auto operator+(const A& rhs) const { // 不需要给变量l加constexpr修饰,lambda本身支持constexpr调用 auto l = [&]() constexpr { // C++20及以上可显式加constexpr说明符,C++17可省略 return A(this->a + rhs.a); }; return l(); } }; // 编译期调用验证 constexpr A res = A(1) + A(2); static_assert(res.a == 3); // 编译正常通过
方案2:无捕获constexpr lambda + 显式传参
如果你有强制要求必须将lambda变量声明为constexpr,可以将lambda改为无捕获形式,把this和rhs作为入参传递给lambda,无捕获的lambda本身就是编译期常量,可以用constexpr修饰:
struct A { int a; constexpr A(int a) : a(a) {} constexpr auto operator+(const A& rhs) const { // 无捕获lambda,可声明为constexpr constexpr auto l = [](const A* self, const A& other) { return A(self->a + other.a); }; // 调用时显式传入this和rhs return l(this, rhs); } }; // 编译期调用验证 constexpr A res = A(3) + A(4); static_assert(res.a == 7); // 编译正常通过
核心原理
constexpr修饰变量时,要求变量的初始化逻辑必须完全在编译期完成,所有依赖的取值都必须是编译期常量,带捕获的lambda依赖运行期的入参因此不符合要求。- 仅需要lambda支持编译期调用的场景下,不需要将lambda变量本身声明为
constexpr,只要lambda的执行逻辑符合constexpr要求即可正常在编译期上下文使用。
内容的提问来源于stack exchange,提问作者apopa
相关产品推荐
相关产品推荐

