由于 ADL 在实例化时未找到最佳重载匹配,何时会出现 UB?

Oli*_*liv 6 c++ templates undefined-behavior language-lawyer name-lookup

当一个函数体被实例化时,依赖函数调用重载解析应该通过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 ??
}
//TU2.cpp
//....
struct C {
   operator B();
   friend void f(B){}
   };
Run Code Online (Sandbox Code Playgroud)

问题2

函数模板特化也能触发这种未定义的行为吗?(潜在实例化或实例化函数模板特化)

例子:

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 ??
}
//TU2.cpp
//...
template <class T> void f(T){}

// optionaly also with:
// template void f(B);
Run Code Online (Sandbox Code Playgroud)