在不使用嵌套名称说明符的情况下定义名称空间的成员的 clang 中是否存在错误

jac*_*k X 5 c++ templates language-lawyer

namespace A{
    namespace B{
        template<typename T>
        struct Test{
        };
    }
    using namespace B;
    template<>
    struct Test<int>{};  //#1
}

int main(){

}
Run Code Online (Sandbox Code Playgroud)

考虑上面的代码,GCC抱怨这样的代码Clang格式错误并认为这样的代码格式良好。结果就在这里。在#1,它是类模板的显式特化声明Test。根据这个规则:
temp.expl.spec#2

可以在可以定义相应主模板的任何范围内声明显式特化。

主模板Test可以在 namespace 之外定义B,只要它遵守以下规则:
namespace.memdef#2

命名空间的成员也可以通过定义的名称的显式限定 ([namespace.qual])在该命名空间之外定义,前提是正在定义的实体已经在命名空间中声明并且定义出现在包含声明的 namespace 的命名空间

也就是说,我们可以Test像这样定义主模板:

namespace A{
    namespace B{
        template<typename T>
        struct Test;
    }
    template<typename T>
    struct B::Test{  // Test is explicit qualified by B
    }; 
}
Run Code Online (Sandbox Code Playgroud)

因此,我们可以在此时定义显式专业化。但是不清楚是否有必要通过使用qualified-id来声明这种显式专业化?但是这里有一个额外的规则:
temp.expl.spec#8

模板显式特化在定义模板的命名空间范围内

所以Clang有错吗?如何解释这种情况。

Dav*_*ing 4

你说得对,现有的措辞有点不清楚。我不会\xe2\x80\x99t尝试理解它所写的含义,如果它有的话,比你已经有的更进一步;我认为这一切已经糟糕到需要完全重写

\n

然而,其目的是使这段代码格式良好(正如 Clang 所说);因为(类模板的)显式特化必须包含Test<,它可能是嵌套名称说明符( template<> struct Test<int>::Nested<float> {};) 的一部分,并且受到遵循using 指令(以及许多其他内容)的Test正常名称查找的约束。请注意,这与 [class.pre]/3 不同,后者禁止使用嵌套名称说明符重新声明通过using-declaration引入的类。(函数模板的显式特化和实例化的规则有点复杂,因为模板参数列表是可选的。)

\n

几周内,我的链接论文将进行公开更新,调整重新声明的规则(在本例中为 [class.pre])。

\n