Reputation: 15834
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.
Upvotes: 21
Views: 2727
Reputation: 241931
The error message gcc gave you was precise and correct:
error: call to non-constexpr function 'addition()::
<lambda(int,int)>::
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).
Upvotes: 5
Reputation: 126562
Your function fp()
does not return a literal type, therefore it cannot be a constexpr function:
From 7.1.5: "The definition of a constexpr function shall satisfy the following constraints:
- it shall not be virtual (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
- null statements,
- static_assert-declarations
- typedef declarations and alias-declarations that do not define classes or enumerations,
- using-declarations,
- using-directives,
- 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.
Upvotes: 9
Reputation: 21317
According to N3376 working draft of the standard section 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 ]:
Which lists under it:
— a lambda-expression (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.
Upvotes: 7