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
C++11 [expr.prim.lambda]/12
and /17
So we don't even need to capture
Size
in the first example (where it is notstatic
), 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(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 capturingSize
explicitly (by copy) but not odr-using it: the use of the id-expressionSize
within the lambda accesses theconstexpr
variable declared inTest
, 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).