似乎clang ++(我尝试过clang 3.2)将模板类的名称视为实例化类,而不是类范围内任何出现的模板。例如,以下代码
template <template <class> class T>
class A {};
template <typename T>
class B {
A<B> member;
// ^---- clang++ treats B as an instantiated class
// but I want it to be a template here
// this code could compile in g++
};
int main()
{
B<int> b;
return 0;
}
我应该怎么做才能编译?
答案 0 :(得分:3)
以这种方式解析B
(称为 inject-class-name ,包含模板实例化的每个类的隐式声明的成员)是为了方便起见。我从来没有见过这样的事情!
要解决此问题,请通过在其前面添加::
来限定名称(如果需要,还可以添加名称空间的名称)。
template <typename T>
class B {
A< ::B> member; // whitespace required to prevent digraph; see comments
};
C ++11§14.6.1/ 1指定(强调我的)
与普通(非模板)类一样,类模板具有注入类名(第9节)。 inject-class-name可以用作模板名称或类型名称。当它与template-argument-list一起使用时,作为模板模板参数的模板参数,或作为友元类模板声明的详细类型说明符中的最终标识符, 它指的是类模板本身。否则,它等同于模板名称,后跟包含在&lt;&gt;中的类模板的模板参数。
因此,如果在C ++ 11下发生此问题则是编译器错误。解决方法如上所述。
注 - 为了进行比较,C ++ 03中的相应段落是
与普通(非模板)类一样,类模板具有注入类名(第9节)。 inject-class-name可以使用或不使用template-argument-list。如果在没有template-argument-list的情况下使用它,它等同于inject-name-name,后跟&lt;&gt;中包含的类模板的template-parameters。当它与template-argument-list一起使用时,它引用指定的类模板特化,可以是当前的特化或其他特化。
正如您所看到的,已经有一个特殊情况允许标识符为类或模板,具体取决于它是否出现在模板名称中。他们刚刚增加了几个案例。
答案 1 :(得分:1)
这是C ++ 11中的不一致行为,因为C ++ 11表示注入的类名(在类体中自动声明的名称)在传递给模板模板参数时是一个模板。所以你的代码应该只在C ++ 03实现中失败。
但是现在没有必要打开关于此的错误报告。我已经回去了。