The following C++ code makes the compiler GCC(6.3.0) and Clang (3.8.0) mad.
for (auto v : vectors2d)
for_each (begin(ret), end(ret), [v[3]] (int &n) { n+= v[3];});
While the following is fine
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;});
The error in GCC is
expected identifier before '[' token
Clang says
expected ',' or ']' in lambda capture list
My question is: Why it is illegal for [v[3]]
to appear in a capture list?
My question is why it is illegal for
[v[3]]
in capture list?
As described in 5.1.2/1 [expr.prim.lambda] in N4141, the items in a capture list shall be either a simple-capture or an init-capture.
The former is any of
&
identifier
this
,the latter either identifier initializer or &
identifier initializer.
v[3]
fits none of the above and is thus correctly rejected by the compiler.
v[3]
is not a variable - it's a complex expression which unfolds to *(v + 3)
(if operator[]
is not overloaded). So, capturing v[3]
is very similar in its spirit to capturing of x * x + y * y
- and that makes much less sense. E.g. the compiler would have to accept x * x + y * y
inside the lambda, but sometimes reject y * y + x * x
because overloaded operators do not have to be commutative.
Basically, you ask compiler: "if I use an expression equivalent to what I captured, it's ok, but if I mix variables the other way around, you should give me compiler error".
Suppose v[3]
was legal. Then all of the following lambdas should be compiled 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 "invalid capture" to be a compiler error, the compiler should be able to somehow "prove" that we're not going to access any element in v
other than v[3]
. This is harder than the halting problem, so it's impossible.
We could, of course, make some less strict limitations: e.g. allow only v[3]
, but not v[2 * 2 - 1]
or create some algorithm for detection of such cases that work "good enough", but sometimes provide false negatives. I don't think it's worth the effort - you can always "cache" the expression inside a variable and capture that by value.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With