When using template template syntax as in template <template <typename> class T>
, it is required to use the keyword class
, as using typename
gives an error along the lines of:
error: template template parameter requires 'class' after the parameter list
Everywhere else the keywords typename
and class
are interchangeable in the basic case of declaring a template parameter.
You could argue that the requirement when using template template is a hint that you are expected to pass a class type, but this is not always the case (especially not after C++11 introduced templated type aliases).
template <template <typename> class T> // 'class' keyword required.
struct Foo {
using type = T<int>;
};
template <typename T>
using type = T (*)();
using func_ptr_t = Foo<type>::type;
typename
is not allowed in template template declarations?Short answer: because the Standard says so.
Longer answer: prior to Standardization, C++ templates required the class
keyword for all template parameters. However, to stress the fact that templates could also be of non-class (i.e. builtin) type, an alternative keyword typename
was introduced. However, in C++98, template-template parameters could only be of class-type, and this was the reason that the typename
keyword was not added in that context.
Enter C++11 and its new feature template aliases, that now also introduced non-class templates, and hence non-class template-template parameters:
template<typename T> struct A {};
template<typename T> using B = int;
template<template<typename> class X> struct C;
C<A> ca; // ok
C<B> cb; // ok, not a class template
template<template<typename> typename X> struct D; // error, cannot use typename here
The above example was taken from the current C++1z proposal N4051 titled Allow typename
in a template template parameter, and proposes to allow precisely that.
Clang 3.5 SVN now supports this with the -std=c++1z
flag.
I'm looking for the rational behind this restriction [...]
Before C++11 was introduced, the only templates you could pass to a template template parameter were class templates.
That's why the use of the keyword class
was enforced.
Additionally, the keyword typename
implies that the template parameter is a substitution for an arbitrary type and not a template, so using typename
in that context would just blur the line between the names of types and (class) templates.
That's comprehensible.
Nowadays, such arguments can be the names of class templates or alias templates, and since those aren't even remotely connected, the enforcement of the keyword class
is more or less obsolete. The proposal N4051 opts to change this with C++1Z.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With