为什么BOOST.RANGE RANGE_BEGIN/END FREE功能对const和非const引用都重载



我在boost.range中发现了这个有趣的位:

提供独立式函数range_begin/end()时,文档指出:

... range_begin()range_end()必须对两个const重载 和mutable参考参数。

确实,查看他们在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;
    }

您将注意(文档中给出的示例也这样做),这两个版本都返回相同的Iterator类型。

为什么我们首先需要超载?是为了使ADL工作吗?

您显然需要const &版本,因为否则您的range_begin对于constemified对象是无适合的。

不太明显的是为什么您还需要&版本,但这很简单:如果您不提供它,那么您的自定义功能就比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 &)避免了此问题。

相关内容

  • 没有找到相关文章

最新更新