我想做这样的事情(在课堂内):
static constexpr MyStruct ops[6] = {
{'+', [&] (double a, double b) { return a+b; } },
{'-', [&] (double a, double b) { return a-b; } },
...
};
MyStruct
定义为:
typedef double (*binOp)(double, double);
struct MyStruct {
char c;
binOp fn;
};
我也尝试过:
std::function <double(double,double)> fn;
关于fn
的定义,但没有运气。
我在第一种情况下得到的错误是&#34;错误:字段初始化程序不是常数&#34; 我真的得不到。如果我尝试使用std::function
它会变得更糟,因为它说:&#34;在声明&#34;时无法通过非常量表达式初始化。
为什么lambda函数不是常数?我错过了什么吗?
答案 0 :(得分:8)
构造constexpr
对象时,传递给它的所有内容都需要是核心常量表达式,[decl.constexpr] / 9:
对象声明中使用的
constexpr
说明符将对象声明为const
。这样的对象应该有 字面类型,应初始化。如果它是由构造函数调用初始化的,那么该调用应该是一个常量表达式(5.19)。
并且,来自[expr.const]的lambdas不是常量表达式 1 :
条件表达式 e 是核心常量表达式,除非按照规则评估 e 的 抽象机器(1.9),将评估以下表达式之一:
- [...]
- lambda-expression(5.1.2);
- [...]
但是,这仅适用于constexpr
而不适用于const
,因此您可以这样做:
static const MyStruct ops[6] = {
{'+', [] (double a, double b) { return a+b; } },
{'-', [] (double a, double b) { return a-b; } },
};
注意:你的lambda不需要捕获任何东西,所以你应该只是空捕获列表[]
。
<小时/> 1 正如dyp所指出的那样,有一项建议要对此进行更改:N4487
答案 1 :(得分:0)
捕获lambda不能衰减到函数指针。
和从(非捕获)lambda返回函数指针的运算符不是constexpr
。