1

根据cppreference,在Argument-dependent查找

除了通常的非限定名称查找所考虑的范围和名称空间之外,还在其参数的名称空间中查找函数名称。

但是,为什么在下面的函数 A::member_function() 示例中,选择了类方法begin(),其中 1) 采用 0 个参数,而 2) 甚至不在 std::vector 的命名空间中,函数的参数?ADL 不应该转到参数的命名空间(对于向量来说是 std)并选择自由函数 std::begin() 吗?

#include <unordered_map>
#include <vector>


class A
{
public:
    using value_t = std::unordered_map<int, char>;
public:
    void member_function();
    value_t::iterator begin() { return map_.begin(); }

private:
    value_t map_;
};


void A::member_function() 
{
    std::vector<int> hello;
    auto it = begin(hello);
}

如果这真的是 ADL 的工作方式,我也很高兴有一个解决方法。

4

1 回答 1

1

如果普通的非限定名称查找找到类成员,则不会执行 ADL。

您可以使用 using-declaration 来避免此问题,因此可以保证非限定名称查找始终导致std::begin

using std::begin;
auto it = begin(hello);

这总是会找到std::begin,但也会做 ADL 以找到其他begin重载。

如果可能,您还可以使用一个合格的调用std::begin(hello);,它将正确地转发到.begin参数的成员,但不会执行任何 ADL。

在 C++20 中有std::ranges::begin,可以用来代替上面的方法。它是一个自定义点对象,并且begin将更一般地转发给参数的正确值,如果可能,或者通过 ADL 转发给成员。

于 2022-02-21T17:43:24.613 回答