C++ Clang(OS X)要求;模板";关键字,而VS禁止它

C++ Clang(OS X)要求;模板";关键字,而VS禁止它,c++,templates,visual-studio-2012,c++11,clang,C++,Templates,Visual Studio 2012,C++11,Clang,我正在用两个编译器(Xcode v5.0.2上的Clang和Visual Studio 2012 Update 4)编写一个跨平台应用程序,我遇到了两个编译器在嵌套声明中使用模板关键字所需的语法方面存在分歧的情况 以下是代码(归结为一个易于复制的测试用例): 模板 结构基 { 模板 结构内基 {}; }; 模板 结构派生:公共基 { //Clang/OSX中需要“template”关键字 struct InnerDerived:public Base::template InnerBase {}

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

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

模板
结构基
{
模板
结构内基
{};
};
模板
结构派生:公共基
{
//Clang/OSX中需要“template”关键字
struct InnerDerived:public Base::template InnerBase
{};
//Visual Studio 2012中禁止使用“模板”关键字
结构InnerDerived:public Base::InnerBase
{};
};
int main()
{
派生::内部派生的foo;
}
如前所述,两个编译器在“template”关键字的使用上存在分歧

对于Clang,当
模板
关键字未包含时,错误为:

使用“模板”关键字将“InnerBase”视为从属模板 名字

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

“Base::InnerBase”:使用类模板需要模板 参数表

我已经研究了关于
模板
关键字使用规则的各种其他StackOverflow问题(例如,)。然而,看看这个问题和其他类似的问题,并不能让我有信心断言一个编译器正确地实现了C++11,而另一个编译器没有

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

在这种情况下,哪个编译器是正确的?上面的示例代码中是否应该包含
模板
关键字(为了符合C++11)


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

Clang是正确的,
Base
取决于模板参数。这是Visual C++不为模板实现二相名称查找的另一个症状。

< P>看来相关的子句是14.2(临时名称)第4段:

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

我想这说明需要
模板
。在评论之后,拒绝关键字似乎是错误的,即使它不是必需的(同一条款的第5段):

以关键字
template
为前缀的名称应为模板id或名称应指类模板。[注:关键字
template
不能应用于类模板的非模板成员。-结束注][注:与
类型名称
前缀的情况一样,
模板
前缀在不严格必要的情况下是允许的;例如,嵌套的名称说明符或
->
左侧的表达式不依赖于模板参数,或者使用不出现在temp的范围内迟交.-尾注]


根据gcc测试它以创建多数!:-)我认为clang要求使用
模板
关键字是正确的。经验法则:如果VS与另一个编译器不一致,那么VS是错误的。准确率约为90-95%。gcc同意clang。特别是在模板和查找方面,VS倾向于不正确,因为它已经被删除了这是一个标准缺陷,因为语法使包含“模板”的代码格式不正确。请参阅我还应该对DR中Richard的话进行评论,尽管14.2[临时名称]中的相关措辞第4段只要求在限定id中使用它,而不是在类或decltype中。通常情况下,标准指的是限定id,而实际上它的意思类似于“限定名称”。请看,有趣的是,这里有一个1710的旧复制品:
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;
}