簡體   English   中英

對於帶有附加(非推斷)模板參數的函數,ADL是否失敗(或未完成?)

[英]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
}

我假定參數依賴查找會發現二者foundnotfound通過最內層的命名空間(這是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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM