There are, broadly, two categories of template parameters.
template<typename T> (This is more general than marking parameter T as a class or struct or union, as it can also include primitive types like int, bool, etc.)
Integral constants, i.e. template<int i>. For instance the following construction is useful in some TMP techniques.
:
template<int k> struct Rank : Rank<k-1> {};
template<> struct Rank<0> {};
This template generates a hierarchy of Rank types which each inherit from one another, i.e. Rank<0> is a superclass of Rank<1> is a superclass of Rank<2> ...
Integral constants can be broadly construed to include char, and also pointers like int * or even a pointer to some struct. You can for instance template a class against a pointer to some fixed (static storage duration) instance of a struct of some type in memory somewhere, this can be useful.
You cannot template against anything with a ctor or dtor (when would they run?). You cannot template against a const char * string literal -- if you attempted to instantiate a type my_type<"foo"> you would never be able to refer to that type again, because when you typed my_type<"foo"> later you would get a different string literal "foo" and therefore a different pointer and a different type. (You can however template against a particular string with static storage duration.) You also cannot template against float either, because you might expect things like my_type<2.0/3> and my_type<6.0/9> to always give you the same type, and then get a rude surprise caused by floating point rounding.
You can also template against function pointers, that's sometimes really useful also.
Pointer-to-member-function templating is also possible, I've used that in the past when making some code that binds C++ classes to lua.
Here's the actual text of C++11 standard (14.1.4)
A non-type template-parameter shall have one of the following (optionally cv-qualified) types:
(4.1) — integral or enumeration type,
(4.2) — pointer to object or pointer to function,
(4.3) — lvalue reference to object or lvalue reference to function,
(4.4) — pointer to member,
(4.5) — std::nullptr_t.
[ Note: Other types are disallowed either explicitly below or implicitly by the rules governing the form of
template-arguments (14.3). — end note ] The top-level cv-qualifiers on the template-parameter are ignored
when determining its type.
Actually I didn't know about lvalue reference, I've never actually used that, nor have I used pointer to member besides pointer to member function. I have templated against nullptr, that is also useful at times.