类方法中将this与参数传入本地constexpr lambda并维持常量性
问题原因
- 核心错误来自
constexpr变量的初始化规则约束:C++要求constexpr变量的初始化表达式必须是编译期常量,而类成员函数中的this指针、函数参数rhs都是运行时才能确定实际取值的形参,哪怕整个成员函数声明为constexpr,也无法在函数内部强制用它们初始化constexpr变量——因为constexpr函数同时支持运行时调用,编译器无法保证该变量在所有调用场景下都满足编译期常量要求。 - 示例代码还存在两处语法问题:main函数中定义变量
a的行末尾错误使用逗号,以及类型推导指引和构造函数入参不匹配,也会引发编译错误。
修正方案
只需调整两处代码逻辑即可保留完整constexpr特性:
- 不需要给内部lambda声明
constexpr变量修饰:只要lambda的函数体符合constexpr语法要求,它本身就可以在constexpr上下文中正常调用。 - 移除
result变量的constexpr修饰:替换为普通的const或者直接用auto推导即可,constexpr函数内部的变量只要初始化逻辑合法,在编译期调用场景下会自动被编译器在编译期计算,不需要手动加constexpr强制约束。
修正后可运行代码
#include <array> template<typename T, std::size_t N> struct A { std::array<T, N> arr; constexpr A(std::array<T, N> arr) : arr(arr) {} constexpr auto operator+(A rhs) const { // 移除lambda的constexpr修饰 auto l = [](const auto& ta, const auto& ra) { std::array<T, N> result; result.fill(T{0}); for (std::size_t i = 0; i < N; i++) { result[i] = ta[i] + ra[i]; } return A(result); }; // 移除result的constexpr修饰 const auto result = l(arr, rhs.arr); /* 可调用其他constexpr方法/函数对result进行处理 */ return result; } }; // 修正推导指引匹配构造函数入参 template<typename T, std::size_t N> A(std::array<T, N>) -> A<T, N>; int main() { constexpr A a(std::array<int, 3>{1, 2, 3}); constexpr A b(std::array<int ,3>{4, 5, 6}); constexpr A c = a + b; // 验证编译期计算结果正确 static_assert(c.arr[0] == 5 && c.arr[1] ==7 && c.arr[2] ==9); return 0; }
修改后的代码在C++20及以上标准下可以正常编译,c的取值会在编译期完成计算,完全满足constexpr特性要求。
内容的提问来源于stack exchange,提问作者apopa
相关产品推荐
相关产品推荐

