它是 clang 中的一个错误,它在不使用嵌套名称说明符的情况下定义名称空间的成员
Is it a bug in clang that defines a member of a namespace without using nested-name-specifier
namespace A{
namespace B{
template<typename T>
struct Test{
};
}
using namespace B;
template<>
struct Test<int>{}; //#1
}
int main(){
}
考虑上面的代码,GCC
抱怨这样的代码格式错误,Clang
认为这样的代码格式正确。结果是here。在 #1
,它是 class 模板 Test
的显式特化声明。根据这个规则:
temp.expl.spec#2
An explicit specialization may be declared in any scope in which the corresponding primary template may be defined.
主模板 Test
可以在命名空间 B
之外定义,只要它遵守以下规则:
namespace.memdef#2
Members of a named namespace can also be defined outside that namespace by explicit qualification ([namespace.qual]) of the name being defined, provided that the entity being defined was already declared in the namespace and the definition appears after the point of declaration in a namespace that encloses the declaration's namespace.
也就是说我们可以这样定义主模板Test
:
namespace A{
namespace B{
template<typename T>
struct Test;
}
template<typename T>
struct B::Test{ // Test is explicit qualified by B
};
}
因此,我们可以在此时定义显式专业化。但是不清楚是否有必要使用 qualified-id 来声明这种显式专业化?但是这里有一条附加规则:
temp.expl.spec#8
A template explicit specialization is in the scope of the namespace in which the template was defined.
所以Clang
是错的?如何解读这种情况。
你是对的,现有的措辞有点不清楚。我不会试图去理解它所写的意思,如果它有一个,比你已经有的更远;我认为这一切都糟糕到需要 complete rewrite.
然而,意图是这段代码的格式正确(如 Clang 所说);因为(class 模板的显式特化)必须包含 Test<
,它可能是 nested-name-specifier (template<> struct Test<int>::Nested<float> {};
) 的一部分, Test
受遵循 using-directive(以及许多其他事项)的正常名称查找的约束。请注意,这不同于 [class.pre]/3,后者禁止使用 nested-name-specifier 重新声明通过 引入的 class使用声明。 (函数模板的显式特化和实例化规则有点复杂,因为模板参数列表是可选的。)
几周内,我的链接文件将进行 public 更新,根据这些内容调整重新声明的规则(在本例中为 [class.pre])。
namespace A{
namespace B{
template<typename T>
struct Test{
};
}
using namespace B;
template<>
struct Test<int>{}; //#1
}
int main(){
}
考虑上面的代码,GCC
抱怨这样的代码格式错误,Clang
认为这样的代码格式正确。结果是here。在 #1
,它是 class 模板 Test
的显式特化声明。根据这个规则:
temp.expl.spec#2
An explicit specialization may be declared in any scope in which the corresponding primary template may be defined.
主模板 Test
可以在命名空间 B
之外定义,只要它遵守以下规则:
namespace.memdef#2
Members of a named namespace can also be defined outside that namespace by explicit qualification ([namespace.qual]) of the name being defined, provided that the entity being defined was already declared in the namespace and the definition appears after the point of declaration in a namespace that encloses the declaration's namespace.
也就是说我们可以这样定义主模板Test
:
namespace A{
namespace B{
template<typename T>
struct Test;
}
template<typename T>
struct B::Test{ // Test is explicit qualified by B
};
}
因此,我们可以在此时定义显式专业化。但是不清楚是否有必要使用 qualified-id 来声明这种显式专业化?但是这里有一条附加规则:
temp.expl.spec#8
A template explicit specialization is in the scope of the namespace in which the template was defined.
所以Clang
是错的?如何解读这种情况。
你是对的,现有的措辞有点不清楚。我不会试图去理解它所写的意思,如果它有一个,比你已经有的更远;我认为这一切都糟糕到需要 complete rewrite.
然而,意图是这段代码的格式正确(如 Clang 所说);因为(class 模板的显式特化)必须包含 Test<
,它可能是 nested-name-specifier (template<> struct Test<int>::Nested<float> {};
) 的一部分, Test
受遵循 using-directive(以及许多其他事项)的正常名称查找的约束。请注意,这不同于 [class.pre]/3,后者禁止使用 nested-name-specifier 重新声明通过 引入的 class使用声明。 (函数模板的显式特化和实例化规则有点复杂,因为模板参数列表是可选的。)
几周内,我的链接文件将进行 public 更新,根据这些内容调整重新声明的规则(在本例中为 [class.pre])。