Clang(OS X)要求在特定嵌套声明中"template"关键字,而VS禁止它

Clang (OS X) requires "template" keyword in a particular nested declaration, while VS forbids it

本文关键字:关键字 template 禁止 VS 声明 嵌套 OS Clang      更新时间:2023-10-16

我正在用两个编译器(Clang on Xcode v5.0.2和Visual Studio 2012 Update 4)编写一个跨平台应用程序,遇到了这样一种情况:两个编译器在嵌套声明中使用template关键字所需的语法上存在分歧。

以下是代码(归结为一个易于复制的测试用例):

template<typename T>
struct Base
{
template<typename U>
struct InnerBase
{};
};
template<typename T, typename U>
struct Derived : public Base<T>
{
// the "template" keyword is REQUIRED in Clang/OSX
struct InnerDerived : public Base<T>::template InnerBase<U>
{};
// the "template" keyword is FORBIDDEN in Visual Studio 2012
struct InnerDerived : public Base<T>::InnerBase<U>
{};
};
int main()
{
Derived<int, int>::InnerDerived foo;
}

如前所述,两位编译器在"template"关键字的使用上存在分歧。

对于Clang,当template关键字不包括时,错误为:

使用"template"关键字将"InnerBase"视为依赖模板名称

对于Visual Studio,当包含template关键字时,错误为:

'Base::InnerBase':使用类模板需要模板参数列表

我已经研究了关于template关键字使用规则的其他各种StackOverflow问题(例如,我必须将"template"answers"typename"关键字放在哪里以及为什么放?)。然而,考虑到这一点和其他类似的问题,我并没有信心声称一个编译器正确地实现了C++11,而另一个则不是。

(请注意,Clang的错误对我来说有意义,而VS错误对我没有多大意义,因为我似乎包括模板参数列表。)

在这种情况下,哪个编译器是正确的?template关键字是否应该包含在上面的示例代码中(对于C++11的遵从性)?

(可能我没有正确设置编译器设置,在一种或另一种情况下使用C++11——在这种情况下,我的问题仍然存在:上面的代码的哪个版本是正确的C++11代码?)

似乎相关条款是14.2(临时名称)第4段:

当成员模板专用化的名称出现在后缀表达式中的.->之后,或出现在限定id中的嵌套名称说明符之后,并且后缀表达式的对象表达式是类型依赖的,或限定id中嵌套名称说明符指代依赖类型,但名称不是当前实例化的成员时(14.6.2.1),成员模板名称必须以关键字CCD_ 8作为前缀。

我认为这说明template是必需的。根据DyP的评论,即使不需要也拒绝关键词似乎是错误的(同一条款的第5段):

以关键字template为前缀的名称应为模板id,或者该名称应引用类模板。[注意:关键字template不能应用于类模板的非模板成员。--结束注释][注意:与typename前缀的情况一样,template前缀在非严格必要的情况下是允许的;即,当嵌套的名称说明符或->.左侧的表达式不依赖于模板参数,或者该用法不出现在模板的范围内时。--结束注释]。

Clang是正确的,Base<T>依赖于模板参数。这是Visual C++没有为模板实现两阶段名称查找的另一个症状。