如果类头名称包含嵌套名称说明符,则该类说明符不应位于类范围内。 如果其类名是标识符,则类说明符应对应于嵌套名称说明符所引用的类、类模板或命名空间中可命名的一个或多个声明;它们都应具有相同的目标范围,并且类说明符的目标范围的目标范围就是该范围。
[例子:
Run Code Online (Sandbox Code Playgroud)namespace N { template<class> struct A { struct B; }; } using N::A; template<class T> struct A<T>::B {}; // OK template<> struct A<void> {}; // OK--结束示例]
第一句话和例子似乎有所不同。
不包含嵌套名称说明符(但仅“依赖”使用A<void>)的模板的专业化是否仍然符合?
clang 和 msvc 接受它,gcc 显示错误
错误:在其命名空间之外显式特化“模板结构 N::A”必须使用嵌套名称说明符 [-fpermissive]
介绍原始措辞和示例注释的论文是P1787R6:声明以及在哪里找到它们,包含以下行:
Run Code Online (Sandbox Code Playgroud)template<> struct A<void> {}; // error: A not nominable in …
当一个函数体被实例化时,依赖函数调用重载解析应该通过ADL在关联的命名空间中找到最佳匹配,否则行为未定义,[temp.dep.candidate]§1
如果调用格式错误或找到更好的匹配,则在关联命名空间中的查找会考虑在所有翻译单元的这些命名空间中引入的具有外部链接的所有函数声明,而不仅仅是考虑在模板定义和模板中找到的那些声明实例化上下文,则程序具有未定义的行为。
举个例子:
struct A {
friend void f(A a){};
};
struct B : A {};
template <class T>
void g (T a) {
f(a);
}
void h(B b){
g(b);//undefined behavior (UB)
}
//TU2.cpp
//...
void f(B){}
Run Code Online (Sandbox Code Playgroud)
我对哪些函数可能是在这些命名空间中引入的具有外部链接的所有函数声明之一有两个疑问
问题 1
是否考虑在封闭命名空间中引入内联友元函数?
例子:
struct A {
friend void f(A a){};
};
struct B : A {};
template <class T>
void g (T a) {
f(a);
}
void h(B b){
g(b);//undefined behavior ?? …Run Code Online (Sandbox Code Playgroud) c++ templates undefined-behavior language-lawyer name-lookup