ADL 不在外面工作即使是结构

问题描述

如果我有一个结构重载 beginend 等,如下所示:

#include <array>

template<typename T>
struct Array10
{
private:
    std::array<T,10> m_array;
public:
    constexpr auto begin()
    {
        return std::begin(m_array); // #1
    }

    constexpr auto end()
    {
        return std::end(m_array);
    }

    // cbegin,cend,rbegin,rend,crbegin,crend
};

int main()
{
    Array10<int> arr;
    std::fill(
    std::begin(arr),// #2
    std::end(arr),0);
}

然后我明白为什么我必须在 #1 中使用 std::begin 而不是 begin(因为这是最接近的范围 begin 被定义),但我不明白为什么我必须在#2 中使用它。 我的第一个猜测是因为 Array10main 在同一个命名空间中,但将其放入自己的命名空间并不能解决问题。

那么:为什么 ADL 在 std::begin(#2) 中找不到 main

解决方法

ADL 找不到成员。它会找到免费功能。

您有一个成员 foo.begin(),而不是一个免费函数 begin(foo)

friend constexpr auto begin(Array10&)
{
    return std::begin(m_array); // #1
}
friend constexpr auto begin(Array10 const&)
{
    return std::begin(m_array); // #1
}

那些是将通过 ADL 找到的非成员 begin 函数。