编译器的不同行为 - 模板模板参数

时间:2013-02-14 19:41:10

标签: c++

假设我有以下代码:

template <template <typename> class T>
class A {};

template <typename T>
class B
{
    A<B> instance;
};

int main()
{
   B<int> instance;
}

gcc 4.7.2和gcc 4.8.0编译这段代码ok,而icc 13.0.1和clang 3.2给了我一个错误(clang require :: B而不是B,而icc在&lt; in template instantiaion之后也需要空格)。

谁是对的?

我找到了关于它的线程(Template class that refers to itself as a template template parameter?),但是我无法理解标准的14.6.1 / 2并且还看到了LLVM错误14350(http://www.mail-archive.com/llvmbugs@cs.uiuc.edu/msg21095.html)。那么,clang和intel在这里错了吗?

1 个答案:

答案 0 :(得分:1)

14.6.1说:

  

inject-class-name可以用作模板名称类型名称。当它与 template-argument-list 一起使用时,作为模板 template-parameter template-argument ,或作为最终标识符在友元类模板声明的 elaborated-type-specifier 中,它引用了类模板本身。

“inject-class-name”是类模板的名称(B)“注入”类的范围。换句话说,它指的是在类B的定义中使用非限定名B。如果在需要模板名称的上下文中使用该名称:即,使用显式模板参数(B<int>)或作为采用模板模板参数(A<B>)的模板的模板参数,它应该引用模板本身。

所以,gcc是对的。

此外,在C ++ 11中,<中的<::B>之后不需要空格。根据第2.5节第3段,将输入流分为令牌时:

  

如果接下来的三个字符为<::且后续字符既不是:也不是>,则<本身会被视为预处理程序令牌,而不是备用标记<:的第一个字符。 (<:是撰写[的另一种方式。)