use*_*653 6 c++ language-lawyer argument-dependent-lookup std-function
考虑以下代码片段:
#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());
}
Run Code Online (Sandbox Code Playgroud)
上面的代码使用各种编译器进行编译。相反,以下代码段不会编译。唯一的区别是Func(Argvs 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);
}
Run Code Online (Sandbox Code Playgroud)
我理解后一个版本的错误:被调用operator+是在名称空间中定义的,因此,如果未明确指定名称空间,则不会找到该被调用对象。依赖于参数的查找在这里无济于事,因为operator+定义ns的参数名称空间()与参数的类型(std::function定义于namespace std,using声明与此无关)。
但是,为什么operator+在Func有争议的情况下找到正确的答案ns::Arg呢?的名称空间Func未更改。Arg根据C ++标准使用的代码是否有效?
使用Arg的代码根据C ++标准是否有效?
它是。根据[basic.lookup.argdep / 2.2],ADL的关联名称空间包括任何专门化模板参数的关联名称空间。
...此外,如果T是类模板专业化,则其关联的名称空间和类还包括:与为模板类型参数(不包括模板模板参数)提供的模板参数的类型相关联的名称空间和类;任何模板模板参数为其成员的名称空间;以及用作模板模板参数的任何成员模板都是成员的类。[?注意:非类型模板参数不会影响关联的名称空间。?-?注意事项?]
std::function<int(Arg)>是类模板专门化,并且ns与其参数之一相关联。因此ns,包含在operator+ADL 搜索的名称空间集中。
存在此规则是为了使可重用组件更有用。这个想法是允许一个库公开一个以a std::unique_ptr<ns::Foo>作为句柄类型的API ,并让ADL ns在出现一个句柄时从中选取正确的函数。
| 归档时间: |
|
| 查看次数: |
62 次 |
| 最近记录: |