简体   繁体   English

ADL with std :: function:可以通过std :: function的参数列表中的类型找到带std :: function对象的函数吗?

[英]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 ): 唯一的区别是FuncArg 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::functionnamespace 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM