[英]first friend function template declaration is visible through `using namespace` but not through qualified name lookup
我有以下代碼,我用 C++11 編譯。這段代碼是對現實世界用法的簡化。
namespace bar {
template<int M = 10>
struct S {
template<int N = M*2>
friend int foo(S) {
return N-M;
}
};
template<int M, int N>
int foo(S<M>);
} /* end of bar */
int main() {
bar::S<> s;
/* OK { using namespace bar; return foo<42>(s) + foo<>(s); } // */
/* NOK { return foo<42>(s) + foo<>(s); } // */
/* NOK { using namespace bar; return bar::foo<42>(s) + bar::foo<>(s); } // */
/* NOK */{ return bar::foo<42>(s) + bar::foo<>(s); } // */
}
我的問題是:為什么它使用using namespace bar;
使用不合格的名稱查找(請參閱帶有/* OK
的行)? 雖然它不會在使用限定名稱查找 ( bar::foo<>()
) 或不using namespace
的非限定名稱查找的變體中編譯(請參閱帶有/* NOK
的行)?
命名空間bar
包含對稱為foo
的不同模板函數的聲明。
一個是template<int M, int N> int foo(S<M>);
最后聲明,每個S<M>
都有一個聲明為友元函數。
好友 function 只能通過 ADL 找到。 因此,當您擁有bar::foo<42>(s)
時,您只能調用免費的 function(其中42
是M
的值,無法推導出N
,因此無法編譯)。
在 C++20 之前, foo<42>(s)
將被解釋為foo < 42 > (s)
( (foo < 42) > s
具有等效的括號),因為<
不被解釋為模板頭,因為查找for foo
找不到模板。
添加時using namespace bar;
,查找foo
會找到模板 function,因此foo<42>(s)
被解析為模板化的 function 調用。 這最終會選擇在重載解析期間通過 ADL 找到的朋友 function。
這是通過在全局命名空間中添加 function 模板foo
來解決的:
// Only for ADL purposes so `foo` is parsed as a template
template<typename> void foo() = delete;
int main() {
bar::S<> s;
return foo<42>(s) + foo<>(s);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.