4

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

我应该怎么做才能编译它?

4

2 回答 2

3

C++03

解决B这种方式(称为注入类名称,每个类的隐式声明的成员,包括模板实例化)是为了方便。我从来没有见过它像这样挡道!

要解决此问题,请通过在名称::之前添加来限定名称(如有必要,添加名称空间的名称)。

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

C++11

C++11 §14.6.1/1 指定(强调我的)

像普通(非模板)类一样,类模板有一个注入类名(第 9 条)。注入的类名可以用作模板名或类型名。当它与模板参数列表一起使用时,作为模板模板参数的模板参数,或作为朋友类模板声明的详细类型说明符中的最终标识符,它指的是类模板本身. 否则,它相当于模板名称后跟 <> 中包含的类模板的模板参数。

因此,如果在 C++11 下出现此问题,则它是编译器错误。解决方法如上。

注意——为了比较,C++03 中对应的段落是

与普通(非模板)类一样,类模板有一个注入类名(第 9 条)。注入的类名可以与模板参数列表一起使用,也可以不与模板参数列表一起使用。当它在没有模板参数列表的情况下使用时,它等效于注入的类名后跟 <> 中包含的类模板的模板参数。当它与模板参数列表一起使用时,它指的是指定的类模板特化,可以是当前特化或另一个特化。

如您所见,已经有一种特殊情况允许标识符是类或模板,这取决于它是否出现在模板名称中。他们只是增加了几个案例。

于 2013-01-12T08:05:24.837 回答
1

这是 C++11 的不一致行为,因为 C++11 表示注入的类名(这是在类主体中自动声明的名称)在传递给模板模板参数时是一个模板。所以你的代码应该只在 C++03 实现中失败。

但是,现在无需打开有关此问题的错误报告。我已经这样做了。

于 2013-01-12T12:00:24.043 回答