592

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;
};
Rakete1111
  • 42,521
  • 11
  • 108
  • 141
Mat
  • 9,423
  • 10
  • 40
  • 48

6 Answers6

489

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.

Hedede
  • 882
  • 9
  • 25
Aaron Klotz
  • 9,919
  • 1
  • 25
  • 22
  • 50
    That last one is pretty much a special case of the fact that you must use class or struct, not typename, to define a class. Obviously neither of your first two bits of code could be replaced with `template typename Foo {};`, because Foo is most definitely a class. – Steve Jessop Jan 07 '10 at 23:31
  • 3
    `std::vector::value_type` is not a dependent type, you don't need `typename` there - you only need it if a type depends on a template parameter, say `template struct C { typedef typename std::vector::value_type type; };` – Georg Fritzsche Jan 07 '10 at 23:46
  • 2
    And again, `param_t` is not a dependent type. Dependent types are *names that are dependent on a template parameter*, e.g. `foo::some_type`, not template parameters themselves. – Georg Fritzsche Jan 26 '10 at 20:22
  • 2
    A C++1z proposal [N4051](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4051.html) will allow you to use `typename`, i.e. `template typename C`. – user4112979 Oct 06 '14 at 13:57
  • 4
    As of [`GCC 5`](https://gcc.gnu.org/gcc-5/changes.html), _G++ now allows typename in a template template parameter_. – Chnossos Nov 08 '14 at 11:16
  • @SteveJessop, template typename Foo {};, because Foo is most definitely a class.----ultimately a class is gonna be a type wasn't it, then why we can't typename? – RaGa__M Jun 07 '16 at 18:47
107

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.

Victor2748
  • 3,967
  • 10
  • 46
  • 80
Georg Fritzsche
  • 93,086
  • 26
  • 183
  • 232
  • 4
    I understand the rule, but what exactly prevents the compiler from treating some_template as a type internally? Sorry if I am missing something obvious. – batbrat Mar 28 '19 at 08:45
  • 2
    @batbrat [Here](https://stackoverflow.com/a/613132/23715) is the elaborate answer on that topic. E.g., `some_template::something * p;` may be a pointer declaration or multiplication. – Alex Che Sep 28 '20 at 07:46
  • Thanks @AlexChe I'll go through the link! – batbrat Sep 28 '20 at 14:10
25

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

Michael Anderson
  • 61,385
  • 7
  • 119
  • 164
  • 18
    I don't blame you for mentioning it, but I think this policy is pretty misguided, since programmers end up taking time thinking about something that doesn't matter ("have I used the right one?") to indicate something that doesn't matter ("does there exist a built-in type which implements the interface required of this template parameter?"). If any members of the template parameter are used (`T t; int i = t.toInt();`) then you need a "real class", and your code won't compile if you supply `int` for `T`... – Steve Jessop Jan 07 '10 at 23:26
  • 1
    If you want to limit the use to actual classes, you're better off adding a specialization to throw/cause an error for non-class types. If you want to limit use to particular classes, only specialize for them. In any case, such a stylistic distinction is too subtle to get the message across. – Potatoswatter Jan 08 '10 at 01:34
  • 3
    Since they meant the same thing, please use just one. Otherwise, it's like using inline {, unless it's a Tuesday, and then you using next-line {. – Paul Draper Oct 08 '14 at 06:58
  • +1 I do this myself sometimes... `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. – Tony Delroy Jul 07 '15 at 05:48
  • 1
    I'd like to understand what kinds of real-world situations exist where a template would work for ANY class, but would not work with built-in types. Do you have an example? – lfalin Nov 23 '15 at 16:32
9
  1. No difference
  2. Template type parameter Container is itself a template with two type parameters.
Nikolai Fetissov
  • 77,392
  • 11
  • 105
  • 164
  • 3
    there is a difference in general. – Hassan Syed Jan 07 '10 at 22:06
  • could those two parameters the container is templated with also be named? in the example they don't have any names. And also - in this example it's written 'class Container' - could there also be written 'typename Container' instead? – Mat Jan 07 '10 at 22:40
  • 2
    @Mat: yes, the term to search for is *template template parameters/arguments*. E.g.: `template – Georg Fritzsche Jan 07 '10 at 22:47
6

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

K.K
  • 283
  • 7
  • 15
0

There is no difference between using OR ; i.e. it is a convention used by C++ programmers. I myself prefer as it more clearly describes it 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 class T> class C { }; // valid!

template <template 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...