clang++ -在类作用域中将模板类名视为模板

clang++ - treat template class name as template in the class scope

本文关键字:作用域 clang++      更新时间:2023-10-16

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

我应该做什么来编译它?

c++ 03

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

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

template <typename T>
class B {
    A< ::B> member; // whitespace required to prevent digraph; see comments
};
<标题> c++ 11 h1> c++ 11§14.6.1/1指定(强调我的)

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

因此,如果这个问题在c++ 11下出现,它是一个编译器错误。如上所述。

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

与普通(非模板)类一样,类模板也有一个注入的类名(第9条)。注入的类名可以与模板参数列表一起使用,也可以不带模板参数列表。当不使用模板实参列表时,它相当于注入的class-name后跟<>中所包含的类模板的模板形参。当它与template-argument-list一起使用时,它引用指定的类模板特化,可以是当前的特化,也可以是另一个特化。

可以看到,已经有一种特殊情况允许标识符是类还是模板,这取决于它是否出现在模板名中。

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

但是现在没有必要打开关于这个的bug报告。我早就做过了