Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Identifier with the same name in both expression and declaration of range-based for

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.

like image 930
Stephan Dollberg Avatar asked May 06 '13 21:05

Stephan Dollberg


2 Answers

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.

like image 187
Bill Lynch Avatar answered Oct 13 '22 10:10

Bill Lynch


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.

like image 30
Andy Prowl Avatar answered Oct 13 '22 11:10

Andy Prowl