Почему код "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 компилирует это.
Какое правило делает этот компилятор?
Ответы
Ответ 1
Здесь используется имя введенного класса,
имя класса в пределах его собственного определения действует как псевдоним публичного элемента для себя с целью lookup (за исключением при использовании constructor): это известно как имя введенного класса
затем
foo::
foo::
foo::foob
то есть. foo::foo::foo::foob
совпадает с foo::foob
.
И тогда for (auto x : {foo::foobar, foo::fbar, foo::foob })
является основанный на диапазоне для цикла (начиная с С++ 11), который выполняет итерацию на braced-init-list, сформированный из 3-х перечислений.
Ответ 2
Я изменил этот код на это:
#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;
}
для цикла выполняется три раза. выход: "x = 1 x = 2 x = 3".
foo::foo::foo::foob
является тем же самым foo::foob
.
Итак,
for( auto x : { foo::foobar,
foo::fbar,
foo::
foo::
foo::foob } )
является тем же самым
for( auto x : { foo::foobar, foo::fbar, foo::foob } )
{
}
Это означает, что x
находится в диапазоне { foo::foobar, foo::fbar, foo::foob }