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.
Visual Studio 2017 version 15.3 and later (available in /std:c++17 mode and later): A lambda expression may be declared as constexpr or used in a constant expression when the initialization of each data member that it captures or introduces is allowed within a constant expression.
A constexpr function is a function that can be invoked within a constant expression. A constexpr function must satisfy the following conditions: It is not virtual. Its return type is a literal type.
A constexpr (which is short for “constant expression”) variable can only be a compile-time constant. If the initialization value of a constexpr variable is not a constant expression, the compiler will error.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With