std :: begin和std :: end的const重载的目的是什么?

时间:2015-11-07 18:07:44

标签: c++ c++11

对于std::begin,我们有两个容器重载:

template< class C > 
auto begin( C& c ) -> decltype(c.begin());
template< class C > 
auto begin( const C& c ) -> decltype(c.begin());

但是C的常量可以通过通常的模板推导规则来推断,所以看起来第二次重载是多余的。我错过了什么?

1 个答案:

答案 0 :(得分:10)

在rvalue上调用begin(以及end)是合理的,前提是我们在容器被销毁后不使用生成的迭代器。但是,将rvalue传递给T&形式的参数将不起作用,这是第二次重载发挥作用的地方。

然而,很可能我们正在处理对前range-based for proposal wording的轻率转变:

  

将以下内容添加到[container.concepts.member] 的末尾:

template<Container C> concept_map Range<C> {
    typedef C::iterator iterator;
    iterator begin( C& c ) { return Container<C>::begin(c); }
    iterator end( C& c )   { return Container<C>::end(c); } };

template<Container C> concept_map Range<const C> {
    typedef C::const_iterator iterator;
    iterator begin( const C& c ) { return Container<C>::begin(c); }
    iterator end( const C& c )   { return Container<C>::end(c); } };

当很明显概念没有进入C ++ 11时,论文被修改了,并且所有四个函数temploids都可能被翻译成等效的命名空间范围函数模板。这会导致rvalues被接受(可能是无意的)后果,而原始代码只是为了区分不同的合格容器类型。

请注意,begin / end的现代实现会使用转发引用 - 例如

template <typename T>
constexpr auto begin(T&& t)
  -> decltype(std::forward<T>(t).begin()) {
    return    std::forward<T>(t).begin();
}
相关问题