Lambda failed to capture array element
The following C ++ code makes the GCC (6.3.0) and Clang (3.8.0) compiler insane.
for (auto v : vectors2d)
for_each (begin(ret), end(ret), [v[3]] (int &n) { n+= v[3];});
While the following is fine [/ p>
for (auto v : vectors2d) {
auto val = v[3];
for_each (begin(ret), end(ret), [val] (int &n) { n+= val;});
}
I know in C ++ 14 I can do something like
for (auto v : vectors2d)
for_each (begin(ret), end(ret), [val=v[3]] (int &n) { n+= val;});
GCC bug
expected identifier before '[' token
Klang says
expected ',' or ']' in lambda capture list
My question is, why is it illegal to [v[3]]
appear on the capture list?
source to share
My question is why is it banned for
[v[3]]
in the capture list?
As described in 5.1.2 / 1 [expr.prim.lambda] in N4141, the items in the capture list must be either a simple capture or init-capture.
The first is any of
- identifier
-
&
identifier -
this
,
the latter is either an identifier initializer or an identifier initializer &
.
v[3]
does not match any of the above and is thus correctly rejected by the compiler.
source to share
v[3]
is not a variable - it is a complex expression that expands to *(v + 3)
(unless operator[]
overloaded). Thus, capture is v[3]
very similar in meaning to capture x * x + y * y
- and it makes much less meaning. For example. the compiler must accept a x * x + y * y
lambda inside, but sometimes reject y * y + x * x
, because the overloaded operators are not supposed to be commutative.
Basically, you are asking the compiler, "if I use an expression equivalent to what I captured, that's fine, but if I mix the variables the other way around, you should give me a compiler error."
Suppose it v[3]
is legal. Then all of the following lambdas must compile correctly:
[v[3]]() { return v[3]; }
[v[3]]() { return v[2 * 2 - 1]; }
[v[3]](int x) { assert(x == 3); return v[x]; }
So, if we want the "invalid capture" to be a compiler error, the compiler must somehow "prove" that we will not access any element in v
except v[3]
. This is more difficult than the halting problem, so it is not possible.
We could, of course, make some less stringent restrictions: for example, allow only v[3]
but not, v[2 * 2 - 1]
or create some algorithm to detect such cases that work "well enough" but sometimes provide false negatives. I don't think it's worth the effort - you can always "cache" an expression inside a variable and capture it by value.
source to share