There are three ontological tiers in C++: values, types and templates.
A template instantiation is a type. An object is of a certain type, and it has a value.
All three sorts of entities can appear as template parameters:
template <int N, typename T, template <typename> C>
{
C<T> array[N];
};
The parameter are classified, in this order, as "non-type template parameter", "template parameter", and "template template parameter" (I think).
Having template parameters can be very useful, for example if you want to allow something to be parametrized on arbitrary containers (especially with variadic templates!):
template <typename T, template <typename...> Container>
void print(const Container<T> & c)
{ /* ... */ }
Incidentally, when a class template contains members, you have to use the words typename
and template
, respectively to address them according to their nature (saying nothing means you want to refer to a value):
template <typename T> struct Foo
{
T value;
typedef T * pointer;
template <typename S> struct Nested;
};
// now refer to them as:
Foo<T>::value;
typename Foo<T>::pointer;
template<typename S> Foo<T>::template Nested<S>;