为什么模板模板参数不允许在参数列表后面加上'typename'

Snp*_*nps 28 c++ templates typename language-lawyer c++11

模板模板typename?

当使用模板模板语法时template <template <typename> class T>,需要使用关键字class,因为using typename会给出以下行的错误:

错误:模板模板参数在参数列表后面需要'class'

在其他地方的关键字typename,并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;
Run Code Online (Sandbox Code Playgroud)

这背后的原因是什么?

  • 有没有什么特别的原因,为什么typename没有模板模板声明允许吗?
  • C++标准是否说明了这一点?

Tem*_*Rex 31

简短的回答:因为标准这么说.

更长的答案:在标准化之前,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
Run Code Online (Sandbox Code Playgroud)

上面的示例取自当前的C++ 1z提案N4051,名为Allow typenamein a template template parameter,并建议准确允许.

锵3.5 SVN现在支持这种-std=c++1z标志.

  • Visual Studio 2015现在也支持N4051(刚检查过). (2认同)

Col*_*mbo 7

我正在寻找这种限制背后的理性[...]

在引入C++ 11之前,您可以传递给模板模板参数的唯一模板是模板.这就是class强制使用关键字的原因.此外,关键字typename意味着模板参数是任意类型而不是模板的替代,因此typename在该上下文中使用只会模糊类型名称和()模板之间界限.这是可以理解的.

如今,这些参数可以是类模板或别名模板的名称,由于这些参数甚至没有远程连接,因此关键字的强制执行class或多或少已经过时.提案N4051选择用C++ 1Z改变它.