为什么以下模板声明格式不正确?

Mat*_*sen 5 c++ standards templates c++11

为什么以下声明无效?

template<template<typename> typename T>
struct S {};
Run Code Online (Sandbox Code Playgroud)

我认为这是有效的,因为以下是有效的:

template<template<typename> class T>
struct S {};
Run Code Online (Sandbox Code Playgroud)

我可以从[gram.temp]中的标准中读到它似乎是有效的,但是gcc给了我以下输出:

prog.cpp:4:38: error: expected 'class' before 'T'
 template<template<typename> typename T>
                                  ^
Run Code Online (Sandbox Code Playgroud)

Rei*_*ica 4

基本上,“因为标准是这么说的”。C++11 14.1/1 列出了类型参数的语法:

类型参数:
  class ...opt 标识符opt
  class 标识符opt = type-id
  typename ...opt 标识符opt
  typename 标识符opt = type-id
  template < 模板参数列表 > class ...opt 标识符opt
  template < 模板参数列表 > class 标识符opt = id-表达式

如您所见,仅class允许使用模板模板参数。

我的猜测是,任何类型都可以用作类型参数,包括非类类型。但在 C++11 之前,不存在“非类类型模板”这样的东西——唯一的类型模板是类模板。

C++11 的别名模板改变了这一点,但模板模板参数语法显然没有跟上。然而,在 C++11 后(实际上是 C++14 后)草案 N4296中,此限制实际上被解除,并且template <class> typename是有效的模板模板参数语法。