clang ++ - 将模板类名称视为类范围中的模板

时间:2013-01-12 07:52:30

标签: c++ templates clang++

似乎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;
}

我应该怎么做才能编译?

2 个答案:

答案 0 :(得分:3)

C ++ 03

以这种方式解析B(称为 inject-class-name ,包含模板实例化的每个类的隐式声明的成员)是为了方便起见。我从来没有见过这样的事情!

要解决此问题,请通过在其前面添加::来限定名称(如果需要,还可以添加名称空间的名称)。

template <typename T>
class B {
    A< ::B> member; // whitespace required to prevent digraph; see comments
};

C ++ 11

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实现中失败。

但是现在没有必要打开关于此的错误报告。我已经回去了。