[英]ADL with std::function: Can functions taking std::function objects be found via the types in the std::function's argument list?
Consider the following code snippet: 请考虑以下代码段:
#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());
}
The above code compiles with various compilers. 上面的代码汇编了各种编译器。 In contrast, the following code snippet does not compile.
相反,以下代码片段无法编译。 The only difference is the type of the argument used inside
Func
( Arg
vs int
): 唯一的区别是
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);
}
I understand the error of the latter version: The called operator+
is defined in a namespace and thus not found without explicit specification of the namespace. 我理解后一个版本的错误:被调用的
operator+
在命名空间中定义,因此在没有明确指定命名空间的情况下找不到。 Argument dependent lookup will not help here, because the operator+
is defined in a different namespace ( ns
) than the type of the argument ( std::function
is defined in namespace std
, the using
declaration is irrelevant for this). 依赖于参数的查找在这里没有用,因为
operator+
是在与参数类型不同的命名空间( ns
)中定义的( std::function
在namespace std
定义, using
声明与此无关)。
But why is the correct operator+
found in the case where Func
takes an argument ns::Arg
? 但是为什么在
Func
采用参数ns::Arg
的情况下找到正确的operator+
? The namespace of Func
has not changed. Func
的命名空间没有改变。 Is the code using Arg
valid according to the C++ standard? 使用
Arg
的代码是否符合C ++标准?
Is the code using Arg valid according to the C++ standard?
使用Arg的代码是否符合C ++标准?
It is. 它是。 The associated namespaces for ADL include the associated namespaces of any template argument for a specialization, according to [basic.lookup.argdep/2.2]
根据[basic.lookup.argdep / 2.2] ,ADL的关联命名空间包括专门化的任何模板参数的关联命名空间。
... Furthermore, if T is a class template specialization, its associated namespaces and classes also include: the namespaces and classes associated with the types of the template arguments provided for template type parameters (excluding template template parameters);
...此外,如果T是类模板特化,其关联的名称空间和类还包括:与模板类型参数(模板模板参数除外)提供的模板参数类型相关联的名称空间和类; the namespaces of which any template template arguments are members;
任何模板模板参数都是成员的名称空间; and the classes of which any member templates used as template template arguments are members.
以及用作模板模板参数的任何成员模板的类都是成员。 [ Note: Non-type template arguments do not contribute to the set of associated namespaces.
[注意:非类型模板参数不会对关联的命名空间集合产生影响。 — end note ]
- 结束说明]
std::function<int(Arg)>
is a class template specialization, and ns
is associated with one of its arguments. std::function<int(Arg)>
是一个类模板特化, ns
与其中一个参数相关联。 Therefore ns
is included in the set of namespaces that is searched for operator+
by ADL. 因此,
ns
包含在由ADL搜索operator+
的命名空间集中。
This rule exists to make reusable components more useful. 存在此规则是为了使可重用组件更有用。 The idea is to allow a library to expose say an API that takes a
std::unique_ptr<ns::Foo>
as a handle type, and for ADL to pick up the correct functions from ns
when presented with a handle. 我们的想法是允许库公开一个API,它将
std::unique_ptr<ns::Foo>
作为句柄类型,并且当呈现句柄时,ADL从ns
获取正确的函数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.