[英]ADL fails (or not done?) for function with additional (non deduced) template parameter
namespace N {
class C {};
template<typename X>
char const * found(X && x) {
return "found";
}
template<typename, typename X>
char const * notfound(X && x) {
return "not found";
}
}
這定義了具有類C
和兩個函數模板的名稱空間N
found
有一個模板參數,可以從函數參數中推導出來。 notfound
有一個額外的模板參數,無法推斷出來。
給出以下測試代碼( 在ideone上 ):
#include <iostream>
int main() {
N::C object;
std::cout
<< found(object) << std::endl
<< notfound<bool>(object) << std::endl // ERROR
<< notfound<bool, N::C>(object) << std::endl; // ERROR
}
我假定參數依賴查找會發現二者found
和notfound
通過最內層的命名空間(這是N
參數類型的) N::C
。
然而:
prog.cpp: In function ‘int main()’:
prog.cpp:21:6: error: ‘notfound’ was not declared in this scope
<< notfound<bool>(object) << std::endl
^~~~~~~~
prog.cpp:21:6: note: suggested alternative:
prog.cpp:12:15: note: ‘N::notfound’
char const * notfound(X && x) {
^~~~~~~~
(注釋掉未notfound<bool>(object)
調用后,未notfound<bool, N::C>(object)
錯誤相同)
為什么notfound
通過ADL發現?
背景:我正在為一些包裝類實現一個get
函數,所有這些都與std::get(std::tuple)
相似。 包裝類是一個實現細節,它位於一些名稱空間lib::aspect::part::impl
。 我不希望庫的用戶指定using lib::aspect::part::impl::get
,原因很明顯。
因為函數調用具有顯式指定的模板參數的函數模板,所以必須通過普通查找找到模板的名稱; 直到那個ADL無法啟動。
來自標准: $ 17.8.1 / 8顯式模板參數規范[temp.arg.explicit]
(強調我的)
[注意:對於簡單的函數名稱,即使函數名稱在調用范圍內不可見,依賴於參數的查找也適用。 這是因為調用仍然具有函數調用的句法形式([basic.lookup.unqual])。 但是當使用帶有顯式模板參數的函數模板時,除非在調用點處有一個具有該名稱的函數模板,否則調用沒有正確的語法形式 。 如果看不到這樣的名稱,則調用語法不完善,並且參數依賴查找不適用。 如果某些此類名稱可見,則應用依賴於參數的查找,並且可以在其他名稱空間中找到其他函數模板。 [例如:
namespace A { struct B { }; template<int X> void f(B); } namespace C { template<class T> void f(T t); } void g(A::B b) { f<3>(b); // ill-formed: not a function call A::f<3>(b); // well-formed C::f<3>(b); // ill-formed; argument dependent lookup applies only to unqualified names using C::f; f<3>(b); // well-formed because C::f is visible; then A::f is found by argument dependent lookup }
- 結束例子] - 結束說明]
最后一句給出了可能的解決方法; 您可以在任何位置添加函數模板的聲明,以使名稱對於被調用是可見的。 例如
template<typename>
void notfound();
int main() {
N::C object;
std::cout
<< found(object) << std::endl
<< notfound<bool>(object) << std::endl
<< notfound<bool, N::C&>(object) << std::endl; // btw the 2nd template argument should be N::C&
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.