2017-10-18 70 views
12

Współpracownik przypadkowo napisał kod jak poniżej:Dlaczego kompilowany jest kod "foo :: foo :: foo :: foob"?

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 kompiluje to.

Jaka jest reguła, która powoduje, że ta kompilacja?

+14

można być nieco bardziej szczegółowe dotyczące tego, co część nie oczekiwać, aby skompilować czysto? – neuhaus

+1

Nie ma: https://godbolt.org/g/j2AbVn – Timbo

+1

Istnieje brakujący plik include, a dla pętli for brakuje instrukcji, ale poza tym kompiluje – Johan

Odpowiedz

30

injected-class-name służy tu

nazwa klasy w swoich aktach definicji jako rodzaj członek publiczny alias sobie za cel lookup (o ile nie użyto by wymienić constructor): ten jest znany jako wstrzykiwany-nazwa-klasy

następnie

foo:: 
foo:: 
foo::foob 

czyli foo::foo::foo::foob jest to samo, co foo::foob.

A następnie for (auto x : {foo::foobar, foo::fbar, foo::foob }) jest range-based for loop (since C++11), który wykonuje iterację na braced-init-list utworzoną przez 3 moduły.

4

Zmieniłem ten kod do tego:

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

pętli odbywa się 3 razy. wyjście to: "x = 1 x = 2 x = 3".


foo::foo::foo::foob jest taka sama foo::foob. Więc

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

jest taka sama

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

Oznacza to, że x jest w zasięgu { foo::foobar, foo::fbar, foo::foob }