Reputation: 385144
Consider this code:
#include <vector>
#include <iostream>
int main()
{
std::vector<int> v1 {1,2};
std::vector<int> v2 {4,5};
for (auto i : v1) {
for (auto j : v2) {
std::cout << i << ',' << j << '\n';
}
}
}
As expected, GCC 4.8 compiles it just fine, and the output is:
1,4
1,5
2,4
2,5
However, C++11 defines ranged-for thus:
{
auto && __range = range-init;
for ( auto __begin = begin-expr,
__end = end-expr;
__begin != __end;
++__begin ) {
for-range-declaration = *__begin;
statement
}
}
It does say:
__range
,__begin
, and__end
are variables defined for exposition only
but it doesn't clarify that each ranged-for statement should expand to code in which each of those variables is unique, and therefore does not hide the same variables in an enclosing ranged-for.
To that end, it seems to me that nested ranged-for statements are not guaranteed to work as one would expect.
Are we sure that this is not a defect?
Upvotes: 1
Views: 202
Reputation: 385144
Yes, it's perfectly and strictly legal.
The whole definition of ranged-for, despite being almost unique in the standard in its being given in terms of code, is not a simple expansion: this structure is designed to be expanded inside a compiler using intermediate representations of all the operations required.
In short, the use of the term "exposition" means this is all effectively pseudo-code anyway.
Besides, if you look closely at the scoping of those variables, there's no way they can conflict with the specified usage same variables declared in an enclosing ranged-for statement, and our own statement
cannot access them anyway. That is, there is no situation in which any hiding of those loop variables could cause unexpected behaviour.
Upvotes: 9