【问题标题】:Static array of lambda functions (C++)lambda 函数的静态数组 (C++)
【发布时间】:2015-05-29 11:01:10
【问题描述】:

我想做这样的事情(在课堂上):

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的定义,但没有运气。

我在第一种情况下得到的错误是 "error: field initializer is not constant" 我并没有真正得到。如果我尝试使用std::function,它会变得更糟,因为它说:“在声明时不能由非常量表达式初始化”。

为什么 lambda 函数是非常量的?我错过了什么吗?

【问题讨论】:

  • constexpr 替换为const
  • lambda 表达式目前可能不会出现在常量表达式中,但该限制最终可能会被删除:isocpp.org/files/papers/N4487.pdf
  • 从 C++17 开始,请注意 lambdas 现在可以是 constexpr:stackoverflow.com/questions/6420085/…
  • 还请注意您的 lambda 通过引用捕获其范围内的所有内容。目前他们不使用任何东西,所以这不是问题,但捕获 lambda 不能转换为原始函数指针。

标签: c++ c++11 lambda


【解决方案1】:

当你构造constexpr对象时,你传入的所有东西都需要是一个核心常量表达式,[decl.constexpr]/9:

对象声明中使用的constexpr 说明符将对象声明为const。这样的对象应具有 文字类型,并应被初始化。如果它由构造函数调用初始化,该调用应为常量表达式(5.19)。

并且,来自 [expr.const] 的 lambda 不是常量表达式1

一个条件表达式 e是一个核心常量表达式,除非e的求值,遵循规则的 抽象机(1.9),将评估以下表达式之一:

  • [...]
  • 一个 lambda 表达式 (5.1.2);
  • [...]

但是,这仅适用于 constexpr 而不适用于 const,因此您可以简单地这样做:

static const MyStruct ops[6] = {
    {'+', [] (double a, double b) { return a+b; } },
    {'-', [] (double a, double b) { return a-b; } },
};

注意:您的 lambdas 不需要捕获任何内容,因此您只需清空捕获列表 []


1正如dyp 指出的那样,有一个改变这个的提议:N4487

【讨论】:

    【解决方案2】:

    捕获的 lambda 不能衰减到函数指针。

    并且从(非捕获)lambda返回函数指针的运算符不是constexpr

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-06-16
      • 2012-03-22
      • 1970-01-01
      • 2021-04-21
      • 2011-07-18
      • 2013-12-03
      相关资源
      最近更新 更多