Injected-class-name - cppreference.com (original) (raw)
The injected-class-name is the unqualified name of a class within the scope of said class.
In a class template, the injected-class-name can be used either as a template name that refers to the current template, or as a class name that refers to the current instantiation.
Contents
[edit] Explanation
In a class scope, the class name of the current class or the template name of the current class template is treated as if it were a public member name; this is called injected-class-name. The point of declaration of the name is immediately following the opening brace of the class (template) definition.
int X; struct X { void f() { X* p; // OK, X is an injected-class-name ::X* q; // Error: name lookup finds a variable name, which hides the struct name } }; template struct Y { void g() { Y* p; // OK, Y is an injected-class-name Y* q; // OK, Y is an injected-class-name, but Y is not } };
Like other members, injected-class-names are inherited. In the presence of private or protected inheritance, the injected-class-name of an indirect base class might end up being inaccessible in a derived class.
struct A {}; struct B : private A {}; struct C : public B { A* p; // Error: injected-class-name A is inaccessible ::A* q; // OK, does not use the injected-class-name };
[edit] In class template
The injected-class-name of a class template can be used as a template-name or a type-name.
In the following cases, the injected-class-name is treated as a template-name of the class template itself:
- It is followed by
**<**
. - It is used as a template template argument.
- It is the final identifier in the elaborated class specifier of a friend class template declaration.
Otherwise, it is treated as a type-name, and is equivalent to the template-name followed by the template-parameters of the class template enclosed in **<>**
.
template<template<class, class> class> struct A; template<class T1, class T2> struct X { X<T1, T2>* p; // OK, X is treated as a template-name using a = A; // OK, X is treated as a template-name template<class U1, class U2> friend class X; // OK, X is treated as a template-name X* q; // OK, X is treated as a type-name, equivalent to X<T1, T2> };
Within the scope of a class template specialization or partial specialization, when the injected-class-name is used as a type-name, it is equivalent to the template-name followed by the template-arguments of the class template specialization or partial specialization enclosed in **<>**
.
template<> struct X<void, void> { X* p; // OK, X is treated as a type-name, equivalent to X<void, void> template<class, class> friend class X; // OK, X is treated as a template-name (same as in primary template) X<void, void>* q; // OK, X is treated as a template-name }; template struct X<char, T> { X* p, q; // OK, X is treated as a type-name, equivalent to X<char, T> using r = X<int, int>; // OK, can be used to name another specialization };
The injected-class-name of a class template or class template specialization can be used either as a template-name or a type-name wherever it is in scope.
template<> class X<int, char> { class B { X a; // meaning X<int, char> template<class, class> friend class X; // meaning ::X }; }; template struct Base { Base* p; // OK: Base means Base }; template struct Derived : public Base<T*> { typename Derived::Base* p; // OK: Derived::Base means Derived::Base, // which is Base<T*> }; template<class T, template class U = T::template Base> struct Third {}; Third<Derived> t; // OK: default argument uses injected-class-name as a template
A lookup that finds an injected-class-name can result in an ambiguity in certain cases (for example, if it is found in more than one base class). If all of the injected-class-names that are found refer to specializations of the same class template, and if the name is used as a template-name, the reference refers to the class template itself and not a specialization thereof, and is not ambiguous.
template struct Base {}; template struct Derived: Base, Base { typename Derived::Base b; // error: ambiguous typename Derived::Base d; // OK };
[edit] injected-class-name and constructors
Constructors do not have names, but the injected-class-name of the enclosing class is considered to name a constructor in constructor declarations and definitions.
In a qualified name C::D
, if
- name lookup does not ignore function names, and
- lookup of
D
in the scope of the classC
finds its injected-class-name
the qualified name is always considered to name C
's constructor. Such a name can only be used in the declaration of a constructor (e.g. in a friend constructor declaration, a constructor template specialization, constructor template instantiation, or constructor definition) or be used to inherit constructors(since C++11).
struct A { A(); A(int); template A(T) {} }; using A_alias = A; A::A() {} A_alias::A(int) {} template A::A(double); struct B : A { using A_alias::A; }; A::A a; // Error: A::A is considered to name a constructor, not a type struct A::A a2; // OK, same as 'A a2;' B::A b; // OK, same as 'A b;'
[edit] Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
CWG 1004 | C++98 | an injected-class-name could notbe a template template argument | allowed, it refers to the classtemplate itself in this case |
CWG 2637 | C++98 | the entire template-id could be an injected-class-name | only the template name can |