void f( int , const int (&)[2] = {}) { } // #1 void f( int , const int (&)[1] ) { } // #2 // void f(const int&, const int (&)[1] ) { } // #2_original void test() { const int x = 17; auto g = [](auto a) { f(x); // OK: calls #1, does not capture x }; auto g2 = [ /* = */ ](auto a) { int selector[ sizeof(a) == 1 ? 1 : 2 ]{}; f(x, selector); // OK: is a dependent expression, so captures x ??? }; }
This is an example from the C ++ 14 standard (ISO / IEC 14882: 2014), section 5.1.2, paragraph 12, which I changed in two ways:
- Firstly, both versions of the
f()
function have int
as their first argument, so the variable x
is not used odr in any case. - Secondly, I deleted (commented out) the default capture value in lambda
g2
.
Is this code standard? Both clang and gcc compile successfully. However, in the original example, lambda g2
had the default capture value ( [=]
), so the variable x
was implicitly captured because there was a dependent expression (and also because it could be used by odr in the f() #2_original
). Note that in the above paragraph of the Standard there are 2 conditions for implicit capture of the variable x
(ORR dependent expression). Now, without grabbing by default or using odr:
Is this not a compile-time error, since there is a dependent expression and there is no default value for capture? That is, the variable x
must be captured, but it cannot be (suppose g2
calls with both types of arguments, i.e., with obtaining sizeof(a)=1
and other sizeof(a)>1
).
Or does the condition of the dependent expression for implicit capture of a variable apply only when there is a default capture? This would mean that without using odr (i.e., without const int&
in the function f() #2
), the program would work the same regardless of the default capture value. Therefore, would the second condition regarding the dependent expression be useless?
This is C ++ 14 standard (ISO / IEC 14882: 2014), section 5.1.2, paragraph 12 (emphasis mine):
A default - bound lambda expression that does not explicitly commit this or a variable with automatic storage duration (this excludes any identification expression that has been found to refer to init captures a related non-static data element), it is said to implicitly capture an object (i.e., this or a variable) if the compound operator:
- odr-uses (3.2) an object, or
- names the object in the potentially computed expression (3.2), where the encompassing full expression depends on the general parameter of the lambda declared within the scope of the lambda expression.
Note: lambda g
does not capture the variable x
because it is not used in f(x)
(see C ++ 14 Standard (ISO / IEC 14882: 2014), section 5.1.2, paragraph 13)
References:
source share