2017-10-18 42 views
12

Một đồng nghiệp vô tình đã viết code như thế này:Tại sao mã "foo :: foo :: foo :: foob" biên dịch?

struct foo { 
    foo() : baz(foobar) {} 
    enum bar {foobar, fbar, foob}; 
    bar baz; 
}; 

void f() { 
    for(auto x : { foo::foobar, 
        foo::fbar, 
        foo:: 
        foo:: 
        foo::foob }); 
    // ... 
} 

GCC 5.1.0 biên dịch này.

Quy tắc thực hiện việc biên dịch này là gì?

+14

bạn có thể là một chút cụ thể hơn về những gì phần bạn không mong đợi để biên dịch sạch? – neuhaus

+1

Nó không: https://godbolt.org/g/j2AbVn – Timbo

+1

Có một tệp bao gồm bị thiếu và vòng lặp for thiếu một câu lệnh nhưng ngoài việc nó biên dịch – Johan

Trả lời

30

Các injected-class-name được sử dụng ở đây,

tên của lớp trong hành vi định nghĩa riêng của nó như là một loại thành viên nào bí danh của bản thân với mục đích lookup (trừ khi được sử dụng để đặt tên một constructor): đây được gọi là tiêm-class-name

sau đó

foo:: 
foo:: 
foo::foob 

tức là foo::foo::foo::foob giống với foo::foob.

Và sau đó for (auto x : {foo::foobar, foo::fbar, foo::foob })range-based for loop (since C++11), lặp lại trên braced-init-list được tạo thành bởi 3 điều tra viên.

4

tôi đã thay đổi mã này như sau:

#include <initializer_list> 
#include <iostream> 
struct foo { 
    foo() : baz(foobar) {} 
    enum bar {foobar, fbar, foob}; 
    bar baz; 
}; 

int main() { 
    for(auto x : { foo::foobar, 
        foo::fbar, 
        foo:: 
        foo:: 
        foo::foob }) 
        { 
         std::cout << "x=" << x << std::endl; 
        } 
    return 0; 
} 

cho vòng lặp chạy 3 lần. đầu ra là: "x = 1 x = 2 x = 3".


foo::foo::foo::foob giống nhau foo::foob. Vì vậy

for(auto x : { foo::foobar, 
        foo::fbar, 
        foo:: 
        foo:: 
        foo::foob }) 

là như nhau

for(auto x : { foo::foobar, foo::fbar, foo::foob }) 
{ 
} 

Nó có nghĩa là x nằm trong phạm vi { foo::foobar, foo::fbar, foo::foob }

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