For templates I have seen both declarations:
template < typename T >
template < class T >
What's the difference?
And what exactly do those keywords mean in the following example (taken from the German Wikipedia article about templates)?
template < template < typename, typename > class Container, typename Type >
class Example
{
Container< Type, std::allocator < Type > > baz;
};
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.
some_template<T>::something * p;
may be a pointer declaration or multiplication.
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
T t; int i = t.toInt();
) then you need a "real class", and your code won't compile if you supply int
for T
...
class
implies that you're not just expecting a "value" perhaps supporting some operators, copy or move construction and/or assignment, but specifically need a type supporting some member-access semantics. The quickest glance at the declaration then sets expectations and discourages e.g. supplying built-in types for class
parameters when that would certainly be an error.
No difference Template type parameter Container is itself a template with two type parameters.
template<template<class U> class V> struct C {};
This piece of snippet is from c++ primer book. Although I am sure this is wrong.
Each type parameter must be preceded by the keyword class or typename:
// error: must precede U with either typename or class
template <typename T, U> T calc(const T&, const U&);
These keywords have the same meaning and can be used interchangeably inside a template parameter list. A template parameter list can use both keywords:
// ok: no distinction between typename and class in a template parameter list
template <typename T, class U> calc (const T&, const U&);
It may seem more intuitive to use the keyword typename rather than class to designate a template type parameter. After all, we can use built-in (nonclass) types as a template type argument. Moreover, typename more clearly indicates that the name that follows is a type name. However, typename was added to C++ after templates were already in widespread use; some programmers continue to use class exclusively
There is no difference between using <typename T>
OR <class T>
; i.e. it is a convention used by C++ programmers. I myself prefer <typename T>
as it more clearly describes its use; i.e. defining a template with a specific type.
Note: There is one exception where you do have to use class
(and not typename
) when declaring a template template parameter:
template <template <typename> class T> class C { }; // valid!
template <template <typename> typename T> class C { }; // invalid!
In most cases, you will not be defining a nested template definition, so either definition will work -- just be consistent in your use.
Success story sharing
template <typename T> typename Foo {};
, because Foo<T> is most definitely a class.std::vector<int>::value_type
is not a dependent type, you don't needtypename
there - you only need it if a type depends on a template parameter, saytemplate<class T> struct C { typedef typename std::vector<T>::value_type type; };
param_t
is not a dependent type. Dependent types are names that are dependent on a template parameter, e.g.foo<param_t>::some_type
, not template parameters themselves.typename
, i.e.template <typename> typename C
.GCC 5
, G++ now allows typename in a template template parameter.