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 modified in 2 ways:
- First, both versions of function
f()
have anint
as the first argument, so variablex
is not odr-used in any case. - Second, I removed (commented out) the capture-default in lambda
g2
.
Is this code Standard-compliant? Both clang and gcc compile successfully. However, in the original example lambda g2
had a capture-default ([=]
), so variable x
was implicitly captured because there was a dependent expression (and also because it could be odr-used in function f() #2_original
). Note that in the aforementioned paragraph of the Standard there are 2 conditions to implicitly capture variable x
(odr-use OR dependent expression). Now, without capture-default nor odr-use:
Shouldn't this be a compile-time error since there is a dependent expression and no capture-default? That is, variable
x
needs to be captured but it cannot be (assumeg2
calls with both kinds of arguments, i.e., ones yieldingsizeof(a)=1
and otherssizeof(a)>1
).Or does the condition of the dependent expression to implicitly capture a variable only apply when there is a capture-default? That would mean that, with no odr-use (i.e., without
const int&
in functionf() #2
) the program will work in the same way regardless of the capture-default. Therefore, wouldn't the second condition about the dependent expression be useless?
This is the C++14 Standard (ISO/IEC 14882:2014), Section 5.1.2, Paragraph 12 (emphasis mine):
A lambda-expression with an associated capture-default that does not explicitly capture this or a variable with automatic storage duration (this excludes any id-expression that has been found to refer to an init-capture’s associated non-static data member), is said to implicitly capture the entity (i.e., this or a variable) if the compound-statement:
- odr-uses (3.2) the entity, or
- names the entity in a potentially-evaluated expression (3.2) where the enclosing full-expression depends on a generic lambda parameter declared within the reaching scope of the lambda-expression.
Note: lambda g
does not capture variable x
because it is not odr-used in f(x)
(see C++14 Standard (ISO/IEC 14882:2014), Section 5.1.2, Paragraph 13)
Links: