[英]Argument Dependent Look (ADL) considering template arguments?
我有幾個命名空間,每個命名空間都有一個名為f
的函數模板。
// f() and Widget
namespace A {
struct Widget { };
template <typename T>
void func(const T&) { }
}
// f() and caller()
namespace B {
template <typename T>
void func(const T&) { }
template <typename T>
void caller(const T& t) {
func(t); // error occurs here
}
}
template <typename T>
class Wrap { };
int main() {
Wrap<A::Widget> w{};
B::caller(w); // triggers error
}
上面產生以下錯誤
error: call of overloaded ‘func(const Wrap<A::Widget>&)’ is ambiguous
func(t);
~~~~^~~
note: candidate: void B::func(const T&) [with T = Wrap<A::Widget>]
void func(const T&) { }
^~~~
note: candidate: void A::func(const T&) [with T = Wrap<A::Widget>]
void func(const T&) { }
^~~~
如果Wrap
在全局名稱空間中,為什么要考慮A::func
? B::caller
不應該呼叫B::func
嗎?
在模板的情況下,ADL不僅考慮了函數的參數。 在這里,您將Wrap<A::Widget>
作為B::caller
的參數。 因為caller
在namespace B
,所以顯然考慮了B::func
。 考慮A::func
的原因來自以下(添加了重點)
N659 6.4.2 /(2.2)[basic.lookup.argdep]
如果T是一個類類型(包括並集),則其關聯的類為:類本身; 它所屬的類(如果有); 及其直接和間接基類。 其關聯的名稱空間是其關聯類的最內部封閉的名稱空間。 此外,如果T是類模板專業化,則其關聯的名稱空間和類還包括:與為模板類型參數提供的模板參數類型相關的名稱空間和類 [...]
因為A::Widget
是Wrap
的模板參數,所以A
也是Wrap<A::Widget>
的關聯命名空間
通過使用限定名稱來防止ADL,可以使此示例按預期進行編譯:
template <typename T>
void caller(const T& t) {
B::func(t);
}
或將函數名稱括在parethese中
template <typename T>
void caller(const T& t) {
(func)(t);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.