Consider the following code, provided by a colleague:
#include <array>
#include <string>
int main() {
const int size = 4;
return [size]() {
std::array<std::string, size> a; // *
return a.size();
}();
}
It's accepted by Clang 5.0.0 but rejected by GCC 7.2 with the error message for the starred line being:
error: '__closure' is not a constant expression
Which compiler is right?
By default, variables are captured by const value . This means when the lambda is created, the lambda captures a constant copy of the outer scope variable, which means that the lambda is not allowed to modify them.
Lambda-expressions are not allowed in unevaluated expressions, template arguments, alias declarations, typedef declarations, and anywhere in a function (or function template) declaration except the function body and the function's default arguments.
Cons on lambda functions:Lambda functions can have only one expression. Lambda functions cannot have a docstring. Many times lambda functions make code difficult to read. For example, see the blocks of code given below.
A lambda function can take any number of arguments, but can only have one expression.
The rule is actually intuitive: any occurrence of a variable that doesn't necessitate a capture refers to the original variable. [expr.prim.lambda]/11:
Every id-expression within the compound-statement of a lambda-expression that is an odr-use of an entity captured by copy is transformed into an access to the corresponding unnamed data member of the closure type. [ Note: An id-expression that is not an odr-use refers to the original entity, never to a member of the closure type. […] — end note ]
Clearly, the declared size
variable can be used in constant expressions, hence Clang is right.
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