简体   繁体   English

为什么我的constexpr函数不能返回lambda?

[英]Why can't my constexpr function return a lambda?

I found this piece of code doesn't work: 我发现这段代码不起作用:

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);
}

It gives me error 它给了我错误

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'

Why is that? 这是为什么? I'm not calling it here. 我不是在这里打电话。

Direct approach works: 直接进场工作:

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);
}

I'm using MinGW with g++ version 4.7.2. 我正在使用MinGW和g ++版本4.7.2。

Your function fp() does not return a literal type, therefore it cannot be a constexpr function : 你的函数fp()不返回文字类型,因此它不能是constexpr函数

From 7.1.5: "The definition of a constexpr function shall satisfy the following constraints: 从7.1.5开始:“constexpr函数的定义应满足以下约束条件:

  • it shall not be virtual (10.3); 它不应是虚拟的(10.3);
  • its return type shall be a literal type ; 其返回类型应为字面类型 ;
  • each of its parameter types shall be a literal type; 每个参数类型都应是文字类型;
  • its function-body shall be = delete, = default, or a compound-statement that contains only 它的函数体应为= delete,= default 或仅包含的复合语句
    • null statements, 空语句,
    • static_assert-declarations static_assert申述
    • typedef declarations and alias-declarations that do not define classes or enumerations, typedef声明和不定义类或枚举的别名声明,
    • using-declarations, 使用申述,
    • using-directives, using指令,
    • and exactly one return statement ;" 而且只有一个退货声明 ;“

I do not think there is any bug here, and especially nothing related to lambdas as mentioned in an earlier answer: variables simply cannot be declared inside of a constexpr function . 我不认为这里有任何错误,尤其是在前面的答案中提到的与lambdas无关:变量根本不能在constexpr函数内声明。

According to N3376 working draft of the standard section 5.19 [expr.const]: 根据N3376标准第5.19节[expr.const]的工作草案:

Certain contexts require expressions that satisfy additional requirements as detailed in this sub-clause; 某些上下文要求表达式满足本子条款中详述的其他要求; other contexts have different semantics depending on whether or not an expression satisfies these requirements. 其他语境具有不同的语义,取决于表达式是否满足这些要求。 Expressions that satisfy these requirements are called constant expressions. 满足这些要求的表达式称为常量表达式。 [ Note: Constant expressions can be evaluated during translation.— end note ] [注意:在翻译期间可以评估常量表达式.-结束注释]

It goes on to say: 它继续说:

A conditional-expression is a core constant expression unless it involves one of the following as a potentially evaluated subexpression (3.2), but subexpressions of logical AND (5.14), logical OR (5.15), and conditional (5.16) operations that are not evaluated are not considered [ Note: An overloaded operator invokes a function.— end note ]: 条件表达式是核心常量表达式,除非它涉及以下之一作为潜在评估的子表达式(3.2),但是未评估的逻辑AND(5.14),逻辑OR(5.15)和条件(5.16)操作的子表达式不考虑[注意:重载运算符调用函数.-结束注释]:

Which lists under it: 下面列出了哪些列表:

— a lambda-expression (5.1.2); - lambda表达式(5.1.2);

So while I don't know enough standardese, I believe this says that a constexpr shouldn't have a lambda expression inside. 因此,虽然我不知道足够的标准,但我相信这表明constexpr内部不应该有lambda表达式。

The error message gcc gave you was precise and correct: gcc给出的错误消息是准确无误的:

error: call to non-constexpr function 'addition():: 错误:调用非constexpr函数'addition()::
<lambda(int,int)>:: <拉姆达(INT,INT)> ::
operator int (*)(int, int)() const ' operator int(*)(int,int)()const '

I've reformatted it a bit and added emphasis. 我重新格式化了一点并加重了重点。 By coercing the lambda to a function pointer, you're implicitly calling the automatically-created conversion function from lambda to pointer to function of type "auto (int, int)->int" , which is not a constexpr function because the automatically-created conversion function is not declared constexpr (and the standard doesn't require it to be). 通过将lambda强制转换为函数指针,您隐式调用自动创建的转换函数从lambda pointer to function of type "auto (int, int)->int"函数,这不是constexpr函数,因为它是自动的 -创建的转换函数未声明为constexpr (并且标准不要求它)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM