2015-11-07 10 views
14

は、我々は、コンテナの2つのオーバーロードがあります。std :: beginとendのconstのオーバーロードの目的は何ですか? <code>std::begin</code>については

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

しかしCのconst性は、通常のテンプレート控除ルールによって推論することができるが、その2番目のオーバーロードが冗長であるように思えます。私は何が欠けていますか?

答えて

9

コンテナが破棄された後に結果のイテレータを使用しない場合は、begin(およびその点についてはend)を右辺値と呼ぶのが妥当です。しかし、右辺値をT&という形式のパラメータに渡すと、2番目の過負荷が発生します。

しかし、それも私たちがかつて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になっていないことが明らかになったときに、論文が修正され、4つの関数のすべてのテンプレートオブジェクトが、おそらく同等の名前空間に変換されましたcope関数テンプレート。これにより、価値が受け入れられる(意図しない)結果が得られました。元のコードは、異なる資格を持つコンテナの種類を区別するためのものです。

begin/endの最新の実装では、代わりに転送参照が使用されることに注意してください。

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

私は本当にこれが意図的なデザインであるとは確信していません。 'end()'を同じコンテナから得ることができずにコンテナから 'begin()'を取得することは有用ではないようです。 –

+0

@ T.C。 ...あなたがその長さの上限を知らない限り。とにかく、私はその論文を追跡しようとしています。 – Columbo

+2

確かに、長さが実際に型にある配列rvaluesのオーバーロードがないことを除いて、コールサイトで確実にわかっています。個人的には、古いコンテナコンセプトマップ(http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2778.htm#container-concept- 'const_iterator'と' iterator'を使って別々の 'const'バージョンと非'const'バージョンを持っていました。 –

関連する問題