Is it legal to use a const value captured in a lambda as a template argument?

Brian

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?

Columbo

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.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

Is it legal to use struct itself as template argument?

Is this legal template lambda syntax?

Is it legal for a lambda to odr-use this or a not captured entity with automatic storage duration in C++20?

Lambda loses captured value

Mockito. No argument value was captured

Sort a container with a lambda with captured value

Why is a const variable sometimes not required to be captured in a lambda?

Const keyword in template argument

"invalid use of incomplete type" for const function pointer type as template argument

Is it legal to use memset() function on `const` array?

Use a captured value as row identifier

Is it legal to use the #line directive in a macro argument?

In a lambda, how reference is being captured by value

Using lambda captured constexpr value as an array dimension

Template const/non-const argument cast

Template argument deduction from lambda

Template class with no use of template argument

C++ lambda capturing by copy of parent lambda's captured value

Is it legal to use template class name in derived class without template arguments?

Typescript generic argument to const value

How to use template template as template argument properly?

const array of const, to use its elements on array length definitions or give template parameters value

Initialize a static const member with a template argument

effects of a `const` as a template argument to a move constructor

Template argument deduction failing for const pointers

Why is reference template argument not deducing const?

Why type const double is not captured by lambda from reaching-scope, but const int is?

Why is a unique pointer not movable inside a lambda if it's a captured value?

Reset boost::shared_ptr captured by value from lambda