[英]ADL with std::function: Can functions taking std::function objects be found via the types in the std::function's argument list?
請考慮以下代碼段:
#include <functional>
namespace ns {
struct Arg{};
using Func = std::function<int(Arg)>;
Func operator+(Func lhs, Func rhs) {
return [lhs, rhs](Arg arg) {
return lhs(arg) + rhs(arg);
};
}
}
int main() {
ns::Func foo = [](ns::Arg i) {return 5;};
ns::Func bar = [](ns::Arg i) {return 2;};
auto foobar = foo + bar;
return foobar(ns::Arg());
}
上面的代碼匯編了各種編譯器。 相反,以下代碼片段無法編譯。 唯一的區別是Func
( Arg
vs int
)中使用的參數類型:
#include <functional>
namespace ns {
using Func = std::function<int(int)>;
Func operator+(Func lhs, Func rhs) {
return [lhs, rhs](int i) {
return lhs(i) + rhs(i);
};
}
}
int main() {
ns::Func foo = [](int i) {return i + 5;};
ns::Func bar = [](int i) {return i * 2;};
auto foobar = foo + bar; // BANG! Error here!
return foobar(2);
}
我理解后一個版本的錯誤:被調用的operator+
在命名空間中定義,因此在沒有明確指定命名空間的情況下找不到。 依賴於參數的查找在這里沒有用,因為operator+
是在與參數類型不同的命名空間( ns
)中定義的( std::function
在namespace std
定義, using
聲明與此無關)。
但是為什么在Func
采用參數ns::Arg
的情況下找到正確的operator+
? Func
的命名空間沒有改變。 使用Arg
的代碼是否符合C ++標准?
使用Arg的代碼是否符合C ++標准?
它是。 根據[basic.lookup.argdep / 2.2] ,ADL的關聯命名空間包括專門化的任何模板參數的關聯命名空間。
...此外,如果T是類模板特化,其關聯的名稱空間和類還包括:與模板類型參數(模板模板參數除外)提供的模板參數類型相關聯的名稱空間和類; 任何模板模板參數都是成員的名稱空間; 以及用作模板模板參數的任何成員模板的類都是成員。 [注意:非類型模板參數不會對關聯的命名空間集合產生影響。 - 結束說明]
std::function<int(Arg)>
是一個類模板特化, ns
與其中一個參數相關聯。 因此, ns
包含在由ADL搜索operator+
的命名空間集中。
存在此規則是為了使可重用組件更有用。 我們的想法是允許庫公開一個API,它將std::unique_ptr<ns::Foo>
作為句柄類型,並且當呈現句柄時,ADL從ns
獲取正確的函數。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.