The other day, I discovered that this was possible:
template <class T> struct base {};
struct derived: base<int> {};
int main()
{
// The base class template is accessible here
typename derived::base<double> x;
// from the comments, even this works
typename derived::derived::base<double>::base<int>::base<void> y;
}
I have no recollection of ever reading this on cppreference or in C++ tutorials, or this being exploited in clever template metaprogramming tricks (because I'm sure it can be). I have several questions:
Inheriting from a template classIt is possible to inherit from a template class. All the usual rules for inheritance and polymorphism apply. If we want the new, derived class to be generic it should also be a template class; and pass its template parameter along to the base class.
Class Template Inheritance in C++ If we need the new derived class to be general, we must make it a template class with a template argument sent to the base class. This is because inheritance is only possible with a class, and a template is not a class unless it is instantiated by passing some data type to it.
The class whose members are inherited is called the base class, and the class that inherits those members is called the derived class. A derived class can have only one direct base class. However, inheritance is transitive.
Accessing template base class members in C++ In order to access a member (method or field) of a templated base class, you need to either use the “this” pointer or use the explicit name of the base class with template arguments. without “this->” in front of “this->x”, it would not be able to find the member.
As pointed out by @Nir Friedman in comment, typename derived::derived::base<double>::base<int>::base<void> y;
might actually be ill-formed because derived::derived::base<double>::base<int>::base
is treated as a constructor of base
, per [class.qual]/2.
- Does this thing have a specific name?
It is called injected-class-name.
- Where is it documented in the C++ standard and on cppreference?
In the standard: [class]/2 specifies that the name of a class is treated as if it were a public member of that class. [temp.local] specifies that the injected-class-name of a class template can be used as either a template-name or a type-name.
On cppreference: it is (incompletely) documented in http://en.cppreference.com/w/cpp/language/unqualified_lookup#Injected_class_name.
- Is there any template metaprogramming trick exploiting this?
I'm not aware of any such tricks, though in everyday use, injected-class-name is employed whenever the current class is named in the class definition:
template<class T>
struct A {
A<T>& operator=(const A<T>&); // injected-class-name as template-name
A& operator=(A&&); // injected-class-name as type-name
};
The latter may be deliberately used to shorten member declaration.
The injected-class-name of a base class is mostly used (unconsciously) in a member initializer list:
struct B : A<int> {
B() : A() {}
};
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