C++ - 如何在自定义模板化数据容器中的迭代器上使用 advance() 启用 ADL?

标签 c++ templates containers argument-dependent-lookup stdadvance

这是一个容器:

namespace container_namespace
{

template <class element_type, class element_allocator_type = std::allocator<element_type> >
class container
{
    // stuff

    class iterator
    {
        // stuff
    };
};

}

我在上面的什么地方定义了 advance(InputIt &, Distance N) 以便允许在我的 main() 中使用 advance() 通过 ADL(参数相关查找):

int main(int argc, char **argv)
{
    using namespace std;
    using namespace container_namespace;

    container<int> c;

    // Add elements to c here

    container<int>::iterator it = c.begin();
    advance(it, 20);
}

是否选择了自定义 advance() 函数而不是 std::advance? 我已经看到在迭代器类中定义自定义 advance() 函数的示例,以及在命名空间中定义的示例,其中仅在迭代器类中声明了友元。哪项对于启用 ADL 是正确的?其他关于 SO 的例子在这一点上并不清楚。

最佳答案

我认为最安全的方法是将它定义为 containeriteratorfriend。这样定义的函数被放到namespace container_namespace中,这样就可以被ADL找到:

namespace container_namespace {
    template <class element_type, class element_allocator_type = std::allocator<element_type> >
    class container {
        //...
        template <typename Diff>
        friend void advance(iterator&, Diff) {
            //...
        }
    };
}

DEMO

另一种选择是直接在 namespace container_namespace 中定义它。通过这种方式,您可以为所有容器提供通用实现和/或实现标记分派(dispatch)以处理不同的迭代器类别,就像在 std::advance 实现中所做的那样:

namespace container_namespace {
    template <typename Iter, typename Diff>
    void advance(Iter&, Diff) {
        std::cout << "ADL-ed advance\n";
    }
}

这种方法的问题在于,当 std::advance 在范围内时,它会导致歧义(感谢@TC): DEMO

另请注意,您不能按如下方式定义 advance:

namespace container_namespace {
    template <typename element_type, typename element_allocator_type, typename Diff>
    void advance(typename container<element_type, element_allocator_type>::iterator&, Diff) {
        std::cout << "ADL-ed advance\n";
    }
}

因为它的第一个参数的类型会失败(参见 Non-deduced contexts )。

关于C++ - 如何在自定义模板化数据容器中的迭代器上使用 advance() 启用 ADL?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35144435/

相关文章:

C++ 模板特化改变了 constexpr 规则?

docker - 是否可以在由 docker 提供支持的容器中隔离模块内核?

docker - 更改 Docker 容器中的 memlock 限制;是否可以?

image - 在Windows 10上的Docker中将目录作为卷挂载

c++ - 最简单的 “error: taking the address of a temporary object”修复程序?

templates - C++ 部分模板特化结合 std::is_base_of 和 std::enable_if

c++ - 将 zlib 与 mingw 一起使用

c++ - 使用有意义的词来获取元组元素

c++ - boost multi_index - 如果元素类型仅支持移动语义,如何遍历它?

c++ - 如何遍历一组集合 C++