std :: begin和std :: end的const重载的目的是什么? [英] What is the purpose of the const overloads of std::begin and std::end?
问题描述
对于 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屋!