This question already has an answer here:
Closed 2 years ago.
A co-worker accidentally wrote code like this:
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 compiles this.
What's the rule that makes this compile?
The injected-class-name is used here,
the name of the class within its own definition acts as a public member type alias of itself for the purpose of lookup (except when used to name a constructor): this is known as injected-class-name
then
foo::
foo::
foo::foob
i.e. foo::foo::foo::foob
is same as foo::foob
.
And then for (auto x : {foo::foobar, foo::fbar, foo::foob })
is a range-based for loop (since C++11), which iterates on the braced-init-list formed by the 3 enumerators.
I changed this code to this:
#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;
}
for loop runs 3 times. output is: "x=1 x=2 x=3".
foo::foo::foo::foob
is the same foo::foob
.
So
for( auto x : { foo::foobar,
foo::fbar,
foo::
foo::
foo::foob } )
is the same
for( auto x : { foo::foobar, foo::fbar, foo::foob } )
{
}
It means that x
is in range { foo::foobar, foo::fbar, foo::foob }