21

我发现这段代码不起作用:

typedef int (*fp)(int a, int b);

constexpr fp addition()
{
    return [](int a, int b){ return a+b; };
}

#include <iostream>

int main()
{
    fp fun = addition();
    std::cout << fun(2,2);
}

它给了我错误

cexpr.cpp: In function 'constexpr int (* addition())(int, int)':
cexpr.cpp:5:43: error: call to non-constexpr function 'addition()::<lambda(int,
int)>::operator int (*)(int, int)() const'

这是为什么?我不是在这里称呼它。

直接方法有效:

typedef int (*fp)(int a, int b);

#include <iostream>

int main()
{
    fp fun = [](int a, int b){ return a+b; };
    std::cout << fun(2,2);
}

我将 MinGW 与 g++ 版本 4.7.2 一起使用。

4

3 回答 3

10

您的函数fp()不返回文字类型,因此它不能是constexpr 函数

从 7.1.5 开始:“constexpr 函数的定义应满足以下约束:

  • 它不应是虚拟的(10.3);
  • 它的返回类型应该是文字类型
  • 它的每个参数类型都应该是文字类型;
  • 其函数体应为 = delete、= default或仅包含
    • 空语句,
    • 静态断言声明
    • 不定义类或枚举的 typedef 声明和别名声明,
    • 使用声明,
    • 使用指令,
    • 并且只有一个返回声明;”

我认为这里没有任何错误,尤其是与前面答案中提到的 lambdas 无关:变量根本无法在constexpr function中声明。

于 2012-12-29T21:56:40.487 回答
7

根据标准第 5.19 节 [expr.const] 的 N3376 工作草案:

某些上下文需要满足本子条款中详述的附加要求的表达式;根据表达式是否满足这些要求,其他上下文具有不同的语义。满足这些要求的表达式称为常量表达式。[注:常量表达式可以在翻译过程中求值。——尾注]

它接着说:

条件表达式是核心常量表达式,除非它涉及以下之一作为潜在评估的子表达式 (3.2),但逻辑与 (5.14)、逻辑或 (5.15) 和条件 (5.16) 操作的子表达式不被评估不被考虑 [注意:重载的运算符调用函数。-结束注释]:

在它下面列出:

— 一个 lambda 表达式 (5.1.2);

所以虽然我不知道足够的标准,但我相信这说明 constexpr 内部不应该有 lambda 表达式。

于 2012-12-29T21:53:03.847 回答
6

gcc 给你的错误信息是准确和正确的:

错误:调用非 constexpr 函数 'addition()::
             <lambda(int,int)>::
             operator int (*)(int, int)() const '

我对其进行了一些重新格式化并增加了重点。通过将 lambda 强制转换为函数指针,您将隐式调用从 lambda to 自动创建的转换函数pointer to function of type "auto (int, int)->int",这不是 constexpr 函数,因为未声明自动创建的转换函数constexpr(并且标准不要求它是)。

于 2012-12-29T22:52:36.393 回答