为什么模板模板参数在参数列表后不允许使用“typename”关键字?

34

什么是模板模板参数?

当使用 template <template <typename> class T> 这样的语法时,必须使用关键字 class,如果使用 typename 会出现以下错误:

error: template template parameter requires 'class' after the parameter list

在声明模板参数的基本情况下,typenameclass 关键字可以互换使用。

你可以认为在使用模板模板时要求使用 class 是因为你需要传递一个类类型,但并非总是如此(特别是在C++11引入模板类型别名之后)。

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为什么在模板模板声明中不被允许?是否有特定原因?
  • C++标准是否对此有规定?

7
现在有一个提案允许使用typename - chris
4
我更惊讶的是它不允许使用struct。 - BЈовић
3
GCC 5现在允许在模板模板参数中使用typename关键字。 - zangw
可能是模板模板参数为什么要强制使用类(class)的重复问题。 - Walter
2个回答

36

简短回答: 因为标准规定如此

详细回答: 在标准化之前,C++模板需要使用class关键字来定义所有的模板参数。然而,为了强调模板也可以是非类(即内置)类型,引入了另一个关键字typename。然而,在C++98中,模板模板参数只能是类类型,这就是typename关键字没有在该上下文中添加的原因。

随着C++11及其新特性模板别名的引入,现在还引入了非类模板和非类模板模板参数:

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

以上示例摘自当前的C++1z提案N4051,名为允许在模板模板参数中使用typename,并建议准确实现。

Clang 3.5 SVN现在支持此功能,需使用-std=c++1z标志。


2
Visual Studio 2015现在也支持N4051(刚刚检查过)。 - Dwayne Robinson

7

我想了解这个限制背后的理由[...]

在C++11之前,您只能传递给模板模板参数模板。因此必须使用关键字class。 此外,关键字typename意味着模板参数是任意类型的替换,而不是模板,因此在该上下文中使用typename只会模糊类型名称和(模板之间的界限。 这很容易理解。

现在,这些参数可以是类模板或别名模板的名称,并且由于它们根本没有任何联系,因此强制执行关键字class已经过时。 提案 N4051 计划在C++1Z中更改此设置。


这个答案是在问题被提出之前('14年5月31日)给出的。这怎么可能??? - Walter
@Walter 这是从http://stackoverflow.com/questions/23965105/why-cant-template-template-parameters-be-introduced-with-typename合并而来的。 - T.C.
@T.C. 嗯,为什么合并标记将第一个问题标记为重复(因此禁用了对其的投票),而不是第二个问题?请注意,还有一个更早的相同内容的问题。链接。它也应该被合并吗? - Walter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接