The fundamental concept to understand is that an instance of a template is just a class. It is fundamentally no different than any other class.
When you have a typical template definition:
template<typename T> class Base;
Then the template instance:
Base<int>
Is just a class of that name. It has nothing to do with int
, and has absolutely no relationship, whatsoever, with an int
. It doesn't inherit from it, in some way, or in any way.
Next step:
class Derived;
template<typename T> class Base {};
Base<Derived> foo;
Again, Base<Derived>
is just a class. It has no intrinsic relationship with Derived
. It doesn't derive from it, does not inherit from it, nothing.
So, now we take the final step:
template<class T>
class Base
{
};
class Derived : public Base<Derived>
{
};
This declares a class called Derived
, which inherits from a class called Base<Derived>
. And Base<Derived>
is just a class. It's a very simple class. Can't get any simpler than that. It doesn't have any methods. It doesn't have any members. Nor private, protected, or public. It's a tiny class, but it has the same rights and privileges as any other class. You can declare a pointer to it. Or a reference to it. It's just a class.
Again, the key concept is that an instance of a template is just a class. It doesn't "inherit" in any way from the class that's the parameter to the template. In this case, the template instance is completely empty, but it can do anything that any other class can do. It can have public, private, and protected members. It can derive from some other class, which could be another template instance (since a template instance is just a class). Or, some other class can derive from the template instance, because a template instance is just a class.
There is no infinite nesting here. You just have one class inheriting from another class. The second class happens to be a template instance, but did I happen to mention that a template instance is just a class?
Base
,T
is not a fully complete type. Because of this, you can't access things liketypedef
s defined inT
fromBase
(see 1 and 2). SinceT
isn't a fully complete type, the compiler doesn't have to infinitely recurse in this situation. At least that's my understanding. – Bonded