Is it legal to declare a loop variable in a ranged-based for loop with the same name I use in the expression statement of the loop? I hope the example makes it clear.
#include <iostream>
#include <vector>
struct bar {
std::vector<int> nums;
};
int main()
{
bar b;
b.nums = {1, 2, 3};
for(int b : b.nums)
std::cout << b << std::endl;
}
gcc 4.8 gives an error while clang 3.2 allows it.
From my reading of C++2011 6.5.4, your code of:
bar b;
for(int b : b.nums)
std::cout << b << std::endl;
Should be converted to:
bar b;
{
auto && __range = b.nums;
for (auto __begin = __range.begin(), __end = __range.end(); __begin != __end; ++__begin ) {
int b = *__begin;
std::cout << b << std::endl;
}
}
This to me means that clang is correct.
Clang is right.
Paragraph 6.5.4/1 of the C++11 Standard defines the range-based for
statement as follows:
For a range-based for statement of the form
for ( for-range-declaration : expression ) statement
let range-init be equivalent to the expression surrounded by parentheses
( expression )
and for a range-based for statement of the form
for ( for-range-declaration : braced-init-list ) statement
let range-init be equivalent to the braced-init-list. In each case, a range-based for statement is equivalent
to
{
auto && __range = range-init;
for ( auto __begin = begin-expr,
__end = end-expr;
__begin != __end;
++__begin ) {
for-range-declaration = *__begin;
statement
}
}
From the above, it is visible that variable b
, which corresponds to the for-range-declaration
, is declared inside a nested block statement, while the initializer range-init
(which corresponds to b.nums
) appears in the parent scope, where b
should resolve to the object of type bar
.
For what it's worth, this bug has now been fixed on gcc trunk. :)