c++ - 为什么 Boost.Range range_begin/end 自由函数对于 const 和非 const 引用都重载了?

标签 c++ boost overload-resolution argument-dependent-lookup boost-range

我在 Boost.Range 中发现了这个有趣的部分:

提供时free-standing functions range_begin/end(), the docs state that :

... range_begin() and range_end() must be overloaded for both const and mutable reference arguments.

事实上,看看他们在 end.hpp 中的默认值,我们看到:

    //////////////////////////////////////////////////////////////////////
    // pair
    //////////////////////////////////////////////////////////////////////

    template< typename Iterator >
    inline Iterator range_end( const std::pair<Iterator,Iterator>& p )
    {
        return p.second;
    }

    template< typename Iterator >
    inline Iterator range_end( std::pair<Iterator,Iterator>& p )
    {
        return p.second;
    }

您会注意到(example given in the docs 也这样做)两个版本返回相同的 Iterator 类型。

为什么我们首先需要两个重载?是为了制作 ADL工作?

最佳答案

您显然需要 const &版本因为否则你的range_begin对于 const 限定的对象将不可调用。

不太明显的是为什么你还需要 &版本,但这很简单:如果你不提供它,那么你的自定义函数比 Boost 自己的版本匹配更差。

这是一个简短的非 Boost 示例:

namespace M {
  struct S { };
  void f(const S &);
}

namespace N {
  template <typename T>
  void f(T &);

  template <typename T>
  void g(T &t) { f(t); }
}

void h() {
  M::S s {};
  N::g(s);
}

此处,在 N::g<M::S> 的实例化过程中, 一个不合格的调用 f(t)已成立,论点t类型为 M::S .有两个候选人:N::f<M::S>在同一个命名空间中,但 ADL 也找到了 M::f .前者的参数是M::S & .后者是 const M::S & .这意味着前者是更好的匹配,即使你真的想要命名空间 M 中的版本被使用。

额外的重载 M::f(S &)避免了这个问题。

关于c++ - 为什么 Boost.Range range_begin/end 自由函数对于 const 和非 const 引用都重载了?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22237138/

相关文章:

c# - 过载分辨率异常

c++ - 使用 ref-qualifiers 成员函数重载的调用不明确

c++ - CRTP - 我可以创建一个私有(private)方法吗?

c++ - 优化复合 std::functions

c++ - 如何使用 <system_error> 将 errno 转换为异常

c++ - 带有 boost::zip_iterator 的 std::for_each 编译失败

c++ - 如何使内部 boost 已弃用的消息静音

c++ - 将基类 2 参数构造函数调用到子类 1 参数构造函数中

c++ - C++ 中的类型删除: boost::shared_ptr 和 boost::function 如何工作?

c++ - 在非常量对象上,为什么 C++ 不调用具有 public-const 和 private-nonconst 重载的方法的 const 版本?