我在 Boost.Range 中发现了这个有趣的部分:
提供时free-standing functions range_begin/end()
, the docs state that :
...
range_begin()
andrange_end()
must be overloaded for bothconst
andmutable
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/