A type is an identifier used for discrimination. In the case of a template class, this identifier is the result of an instantiation.
This is what static typing is all about: identifying types, so as to apply specific rules. Thus static typing follows Aristotle against Plato: a type is a category, not an idea.
Dynamically typed languages such as Smalltalk take the opposite approach!
Two types with different names are distinct, even if their signatures are identical.
Identifiers are needed in order to discriminate. Suppose a function foo, and two types A and B. The justification for the distinction between A and B is the need to discriminate between them while overloading foo. Therefore, two signatures: foo(const A&) and foo(const B&). Making foo a member function of these two classes (and of their common base class) is mainly "syntactic sugar": the class argument becomes implicit and filled with this.
In this way, a type is determined by all the contexts in which it may be used (be them its member functions or not). Furthermore, the definition of A is bound to this of B. Its semantics are not encapsulated within the class declaration!