Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does this use of using declaration compile? [duplicate]

Tags:

c++

Recently, I saw a strange C++ feature: injected class name.

class X { };
X x1;
class X::X x2; // class X::X is equal to X
class X::X::X x3; // ...and so on...

But I cannot figure out why this feature is necessary. Is there any practice that requires this feature?

And I heard this feature didn't exist in old C++. Then, when was it introduced? C++03? C++11?

like image 950
ikh Avatar asked Aug 28 '14 13:08

ikh


People also ask

What is the use of using declaration?

A using declaration introduces an unqualified name as a synonym for an entity declared elsewhere. It allows a single name from a specific namespace to be used without explicit qualification in the declaration region in which it appears.

What is the use of using declaration in C++?

A using declaration in a definition of a class A allows you to introduce a name of a data member or member function from a base class of A into the scope of A .

What does duplicate declaration in current scope mean?

Duplicate declaration in current scope means that you are declaring two variables of the same name within the same variable scope. In this case, this would be within the same subroutine. If you are using the variable endRow for the same purpose, you only need to remove one of the Dim endRow As Long declarations.

What is declarative region?

A declarative region is a place where names can be declared in. I.e. they can be declared in a block, a class body, or in the bodies of a namespace, etc. A scope is just some snippet of program text.


1 Answers

The injected class name means that X is declared as a member of X, so that name lookup inside X always finds the current class, not another X that might be declared at the same enclosing scope, e.g.

void X() { }
class X {
public:
  static X create() { return X(); }
};

Is the create() function creating a temporary X object or calling the function X? At namespace scope it would call the function, so the purpose of the injected-class-name is to ensure that within the body of X the name always finds the class itself (because name lookup starts in the class' own scope before looking in the enclosing scope).

It's also helpful inside class templates, where the injected class name can be used without a template argument list, e.g. using simply Foo instead of the full template-id Foo<blah, blah, blah>, so it's easy to refer to the current instantiation. See DR 176 for a change between C++98 and C++03 that clarified that.

The idea of the injected class name was present in C++98, but the terminology was new for C++03.

C++98 says:

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.

The second sentence was changed by DR 147 so C++03 says in [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.

Even before C++98, the ARM has roughly equivalent wording that means the class' name can always be used in the class body to refer to the class itself:

The name of a class can be used as a class-name even within the member-list of the class specifier itself.

  • For example,

    class link { link* next; };

like image 188
Jonathan Wakely Avatar answered Sep 17 '22 12:09

Jonathan Wakely