Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't template template parameters be introduced with "typename"? [duplicate]

Template template typename?

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;

What is the reasoning behind this?

  • Is there any specific reason as to why typename is not allowed in template template declarations?
  • Does the C++ standard say anything about this?
like image 284
Felix Glas Avatar asked Nov 22 '22 20:11

Felix Glas


2 Answers

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.

like image 154
TemplateRex Avatar answered Nov 29 '22 05:11

TemplateRex


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.

like image 22
Columbo Avatar answered Nov 29 '22 06:11

Columbo