命名空间和类模板之间的名称冲突:不同的编译器行为

Con*_*tor 9 c++ templates namespaces language-lawyer c++14

不同的编译器显示编译以下代码的不同行为:

namespace N
{
    namespace Foo
    {
        template <typename>
        struct Foo
        {
        };
    }
}

template <typename Type>
using Foo = N::Foo::Foo<Type>;

namespace N
{
    template <typename Type>
    struct Bar : Foo<Type>
    {
    };
}


int main()
{
}
Run Code Online (Sandbox Code Playgroud)

测试编译器及其编译标志:

  • clang ++ 5.0.0:-std=c++14 -Wall -Wextra -Werror -pedantic-errors
  • g ++ 7.2:-std=c++14 -Wall -Wextra -Werror -pedantic-errors
  • vc ++ 19.10.25017(VS 2017):/EHsc /Za /std:c++14 /permissive-
  • icc 18.0.0:-std=c++14 -Wall -Werror

汇编结果:

  • clang ++:

    18 : <source>:18:15: error: expected class name
            struct Bar : Foo
                         ^
    
    Run Code Online (Sandbox Code Playgroud)
  • g ++:成功编译

  • vc ++:

    18 : <source>(18): error C2516: 'Foo': is not a legal base class
    13 : <source>(13): note: see declaration of 'Foo'
    20 : <source>(20): note: see reference to class template instantiation 'N::Bar<Type>' being compiled
    18 : <source>(18): error C2143: syntax error: missing ',' before '<'
    
    Run Code Online (Sandbox Code Playgroud)
  • icc:成功编译

哪种编译器行为符合标准?

附加信息:

Joh*_*itb 5

规范说

在查找基类名称期间,将忽略非类型名称([basic.scope.hiding])

名字是Foo<Type>,它是一个类型名称.并且名称N::Foo不是类型名称,因此必须将其忽略.在忽略某些名称的类似情况下,措辞更明确

如果嵌套名称说明符中的:: scope resolution运算符前面没有decltype-specifier,那么查找::之前的名称只会考虑其特化是类型的名称空间,类型和模板

在这里,当它想要允许时,它不仅会说"类型名称""非类型名称"type-template<arguments>.但它具体说明了"专业化类型的模板".我认为这种混乱是导致实现分歧的原因.这个名称Foo<Type>就是我所说的"复合名称",因为它由嵌入的名称组成.因此,可能不清楚其中的哪些确切名称被忽略,哪些不被忽略.