Difference of keywords 'typename' and 'class' in templates?

typename and class are interchangeable in the basic case of specifying a template:

template<class T>
class Foo
{
};

and

template<typename T>
class Foo
{
};

are equivalent.

Having said that, there are specific cases where there is a difference between typename and class.

The first one is in the case of dependent types. typename is used to declare when you are referencing a nested type that depends on another template parameter, such as the typedef in this example:

template<typename param_t>
class Foo
{
    typedef typename param_t::baz sub_t;
};

The second one you actually show in your question, though you might not realize it:

template < template < typename, typename > class Container, typename Type >

When specifying a template template, the class keyword MUST be used as above -- it is not interchangeable with typename in this case (note: since C++17 both keywords are allowed in this case).

You also must use class when explicitly instantiating a template:

template class Foo<int>;

I'm sure that there are other cases that I've missed, but the bottom line is: these two keywords are not equivalent, and these are some common cases where you need to use one or the other.


For naming template parameters, typename and class are equivalent. §14.1.2:

There is no semantic difference between class and typename in a template-parameter.

typename however is possible in another context when using templates - to hint at the compiler that you are referring to a dependent type. §14.6.2:

A name used in a template declaration or definition and that is dependent on a template-parameter is assumed not to name a type unless the applicable name lookup finds a type name or the name is qualified by the keyword typename.

Example:

typename some_template<T>::some_type

Without typename the compiler can't tell in general whether you are referring to a type or not.


While there is no technical difference, I have seen the two used to denote slightly different things.

For a template that should accept any type as T, including built-ins (such as an array )

template<typename T>
class Foo { ... }

For a template that will only work where T is a real class.

template<class T>
class Foo { ... }

But keep in mind that this is purely a style thing some people use. Not mandated by the standard or enforced by compilers