6

GCC and Clang do compile the following code:

void Test()
{
   constexpr int Size = 3;
   auto Lambda = [Size]{ int Dim[Size]; };
}

However, VisualStudio 2015 CTP 6 does not. Nevertheless, all 3 compilers are happy with this code:

void Test()
{
   static constexpr int Size = 3;
   auto Lambda = []{ int Dim[Size]; };
}

Which snippet is actually doing it in the correct way? What does the C++ standard say?

This question is related to Lambda capturing constexpr object

6
  • Does VS2015 accept [&]{ int Dim[Size]; }? Commented Feb 27, 2015 at 10:57
  • 1
    @dyo: nope, error C2057: expected constant expression. Commented Feb 27, 2015 at 10:59
  • Does VS2015 accept []{ int Dim[Size]; } when Size is not static? Commented Feb 27, 2015 at 10:59
  • @dyp: of course not, error C3493: 'Size' cannot be implicitly captured because no default capture mode has been specified Commented Feb 27, 2015 at 11:00
  • It is not obvious that it doesn't accept it: clang++ does. Commented Feb 27, 2015 at 11:01

1 Answer 1

7

C++11 [expr.prim.lambda]/12

If a lambda-expression odr-uses this or a variable with automatic storage duration from its reaching scope, that entity shall be captured by the lambda-expression.

and /17

Every id-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 ]

So we don't even need to capture Size in the first example (where it is not static), since reading from that variable is not an odr-use since it can appear in a constant expression and the lvalue-to-rvalue conversion is immediately applied to it, [basic.def.odr]/2

A variable whose name appears as a potentially-evaluated expression is odr-used unless it is an object that satisfies the requirements for appearing in a constant expression and the lvalue-to-rvalue conversion is immediately applied.

(It is not clear to me if the array bounds require an l-t-r conversion, though.)

The same applies when capturing Size by reference, or when capturing Size explicitly (by copy) but not odr-using it: the use of the id-expression Size within the lambda accesses the constexpr variable declared in Test, not any captured member (for capture-by-copy: IFF the access does not constitute an odr-use).

C++14 [expr.prim.lamda]/12 adds some wording for polymorphic lambdas that is irrelevant here, and moves /17 to /18. The rules for odr-use are more complicated, but I'd argue it's not an odr-use for the same underlying reason (reading a compile-time constant).

Sign up to request clarification or add additional context in comments.

2 Comments

Long story short. Is there a bug in VS 2015?
@SergeyK. I guess so. I'll try to look up the recent rules (C++14 and post-C++14) which will probably be a bit different. But I can't imagine them being more restrictive here.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.