2013-05-06 22 views
16

Có hợp pháp để khai báo biến vòng lặp trong một vòng lặp dựa trên vòng lặp có cùng tên mà tôi sử dụng trong câu lệnh biểu thức của vòng lặp không? Tôi hy vọng ví dụ này làm cho nó rõ ràng.Mã định danh có cùng tên trong cả biểu thức và khai báo dựa trên dải cho

#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 đưa ra lỗi trong khi clang 3.2 cho phép.

+5

[lỗi đã được báo cáo với gcc] (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54430). –

+0

@ JesseGood Cảm ơn bạn đã đào bới điều đó. Hóa ra tôi không tìm thấy bất cứ thứ gì trên bugzilla vì tôi đang tìm kiếm "ranged based for" thay vì "range based for". Không biết thuật ngữ đó được biểu hiện như thế nào trong đầu tôi, cùng một lỗi xảy ra trong tiêu đề. – inf

Trả lời

11

Từ đọc sách của tôi năm 2011 6.5.4 C++, mã của bạn về:

bar b; 

for(int b : b.nums) 
    std::cout << b << std::endl; 

nên được chuyển đổi sang:

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; 
    } 
} 

này đối với tôi có nghĩa là kêu vang là đúng.

+0

IMHO, tôi muốn nói rằng đây là lỗi trong tiêu chuẩn. Tầm nhìn của 'int b' phải từ': 'cho đến khi kết thúc câu lệnh for. – rodrigo

+0

@rodrigo: Tôi đồng ý cho đến khi tôi nghĩ về nó một số chi tiết. Điều này có nghĩa là gì: 'for (auto & x: x)'? –

+0

Điều đó sẽ vô nghĩa như khai báo đơn giản 'auto &x = x; 'và vì những lý do tương tự. – rodrigo

9

Clang là đúng.

Đoạn 6.5.4/1 của C++ 11 Tiêu chuẩn xác định for tuyên bố phạm vi dựa trên như sau:

Đối với một phạm vi dựa trên cho tuyên bố của mẫu

for (for-range-declaration : expression) statement 

để phạm vi-init tương đương với biểu thức được bao quanh bởi dấu ngoặc đơn

(expression) 

và trong một phạm vi dựa trên cho tuyên bố của mẫu

for (for-range-declaration : braced-init-list) statement 

hãy phạm vi-init tương đương với chuẩn bị tinh thần-init-list. Trong mỗi trường hợp, một loạt trụ sở cho tuyên bố là tương đương để

{ 
    auto && __range = range-init; 
    for (auto __begin = begin-expr, 
      __end = end-expr; 
      __begin != __end; 
      ++__begin) { 
     for-range-declaration = *__begin; 
     statement 
    } 
} 

Từ trên, nó có thể nhìn thấy rằng biến b, tương ứng với for-range-declaration, được khai báo bên trong một tuyên bố khối lồng nhau, trong khi initializer range-init (tương ứng với b.nums) xuất hiện trong phạm vi gốc, trong đó b nên giải quyết đối tượng thuộc loại bar.

+0

Nhưng 'b' trong * phạm vi-init * sẽ sai' b'. –

+0

@sftrabbit: Bạn nói đúng, tôi đã bỏ qua điều đó ban đầu. Tôi đã chỉnh sửa câu trả lời, cảm ơn bạn –

+3

Nó không phải là dễ dàng như vậy ... từ một giải thích theo nghĩa đen của tiêu chuẩn, trong 'auto && __range = range-init;' phạm vi-init' thực sự là 'b.num', nhưng 'int b' không nhập vào định nghĩa cho đến 5 dòng sau ...Nhưng một lần nữa, nhìn thấy mã ban đầu, nó sẽ được mong đợi rằng 'int b' ẩn' thanh b'. – rodrigo

2

Đối với những gì đáng giá, lỗi này hiện đã được khắc phục trên gcc trunk. :)

+0

Thật tuyệt khi nghe: D – inf

Các vấn đề liên quan