2017-10-18 31 views
12

Un collègue a écrit accidentellement le code comme ceci:Pourquoi le code "foo :: foo :: foo :: foob" est-il compilé?

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 compile cela.

Quelle est la règle qui rend cette compilation?

+14

pouvez-vous être un peu plus précis sur ce que vous ne vous attendez partie de ne pas compiler proprement? – neuhaus

+1

Il n'est pas: https://godbolt.org/g/j2AbVn – Timbo

+1

Il y a un fichier include manquant et la boucle for manque une instruction mais à part ça compile – Johan

Répondre

30

Le injected-class-name est utilisé ici,

le nom de la classe dans ses propres actes de définition comme un alias de type de membre public de lui-même dans le but de lookup (sauf lorsqu'il est utilisé pour nommer un constructor): cette il est connu que le nom de classe injectée-

puis

foo:: 
foo:: 
foo::foob 

-à-dire foo::foo::foo::foob est identique à foo::foob.

Et puis for (auto x : {foo::foobar, foo::fbar, foo::foob }) est un range-based for loop (since C++11), qui itère sur le braced-init-list formé par les 3 énumérateurs.

4

j'ai changé ce code à ceci:

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

boucle for court 3 fois. la sortie est: "x = 1 x = 2 x = 3".


foo::foo::foo::foob est le même foo::foob. Alors

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

est le même

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

Cela signifie que x est à portée { foo::foobar, foo::fbar, foo::foob }