Template parameters may be of any of the three kinds of C++ entities: values, types, or templates:
template <int N> struct Foo; // N is a value
template <typename T> struct Bar; // T is a type
template <template <typename> class X> struct Zip; // X is a template
Example usage:
Foo<10> a;
Bar<int> b;
Zip<Bar> c;
Note that this corresponds to the three ways of disamiguating dependent names:
X::a = 10; // X::a is a value
typename X::B n = 10; // X::B is a type
X::template C<int> m; // X::C is a template
An interesting combination arises when you want to "typify" a value. This can be done like so:
template <typename T, T Val> struct Typificate;
Now you can say e.g. Typificate<int, 10>
to get a unique type that represents the integer 10. This can occasionally be very useful, e.g. when T
is a member function pointer (e.g. in this delegate implementation); or it can be used to create value-unique overloads for tag dispatch, etc.