I have a singleton:
struct foo { static foo& instance() { static foo f; return f; } };
When re-arranging some code I ended up with this statement "by error":
foo::foo::instance()
But this is deemed correct by my compiler (gcc 4.7). In fact, even foo::foo::foo::instance()
compiles. Why?
It is due to "injected-name" — which means if foo
is a class-name, and the same name "foo" is also injected into the class-scope which is why your code works. It is 100% Standard-conformant.
Here is one interesting example which shows the benefits of this feature:
namespace N { //define a class here struct A { void f() { std::cout << "N::A" << std::endl; } }; } namespace M { //define another class with same name! struct A { void f() { std::cout << "M::A" << std::endl; } }; struct B : N::A //NOTE : deriving from N::A { B() { A a; a.f(); //what should it print? } }; }
What should a.f()
call? What is the type of a
? Is it M::A
or N::A
? The answer is, N::A
, not M::A
.
It is because of name-injection, N::A
is available inside the constructor of B
without qualification. It also hides M::A
, which remains outside the scope of B
. If you want to use M::A
, then you've to write M::A
(or better ::M::A
).
Because of [class]/2
:
A class-name is inserted into the scope in which it is declared immediately after the class-name is seen. The class-name is also inserted into the scope of the class itself; this is known as the injected-class-name.
So foo::foo
is an injected class name, denoting foo
itself.
Actually it's a bit more complicated: according to [class.qual]/2
, foo::foo
alone denotes a constructor of foo
. In order to denote a class, it should either be preceded by struct
(making it elaborated-type-specifier), or followed by ::
(making it a nested-name-specifier - this is your case), or be a base-specifier (for example struct bar : foo::foo {};
).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With