std :: begin和std :: end的const重载的目的是什么? [英] What is the purpose of the const overloads of std::begin and std::end?

查看:136
本文介绍了std :: begin和std :: end的const重载的目的是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

For std::begin, we have two overloads for containers:

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

但是可以推导出 C 的常数按照通常的模板推导规则,因此似乎第二次重载是多余的。我缺少什么?

But the constness of C can be deduced by the usual template deduction rules, so it seems like the second overload is redundant. What am I missing?

推荐答案

调用开始是合理的(并且(对于此问题, end ),前提是在销毁容器后不使用生成的迭代器。但是,将右值传递给 T& 形式的参数将不起作用,这是第二个重载起作用的地方。

It's reasonable to call begin (and end, for that matter) on an rvalue, provided we don't use the resulting iterator after the container has been destroyed. However, passing an rvalue to a parameter of the form T& will not work, which is where the second overload comes into play.

但是,很可能是我们正在对以前的基于范围的提案措辞

However, it may well be that we're dealing with a thoughtless transformation of a former range-based for proposal wording:


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

Add the following to the end of [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中,对论文进行了修改,并且将所有四个函数类倍体都翻译为等效的命名空间范围函数模板。这具有接受rvalue的(可能是意料之外的)结果,而原始代码仅是为了区分不同合格的容器类型。

When it became clear that concepts weren't going to make it into C++11, papers were amended, and all four function temploids were presumably translated into equivalent namespace-scope function templates. This had the (potentially unintended) consequence of rvalues being accepted, while the original code was simply intended to distinguish between differently qualified container types.

请注意,开始 / end 会改用转发引用-例如

Note that a modern implementation of begin/end would use forwarding references instead - e.g.

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

这篇关于std :: begin和std :: end的const重载的目的是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆