1

C++ 11 では、要素をコピーせずstd::vectorに、指定された関数 (API を変更できない) によって返される多くの s をコンテナーに蓄積することは可能ですか?std

std::vector<int> make_vect();
container acc;                           // what is container?
do {
    acc.append(std::move(make_vect()));  // how to implement this?
} while(acc.size() < n);

例のように移動代入演算子の移動コンストラクターがない場合でも、要素をコピーしてはならないことに注意intしてください。そのため、要素のチャンクを (ポインターをコピーして) 移動することはできますが、個々の要素を移動することはできません。

単一のイテレータを使用して、すべてのcontainer累積された要素を反復できるようにする必要があることに注意してください。そのようなものは許可されていませんstd::vector<std::vector<>>

明らかに、これを許可するコンテナを作成するかstd::list<std::vector<>>、独自のイテレータを使用して提供するのは簡単ですが、stdライブラリは、そのようなユーザー作成の追加なしで目的の機能を提供しますか?

要求された機能は特に突飛なものではないようで、C++11 を使用しても (不可能ではないにしても) 難しいことに驚いています。

4

1 に答える 1

3

TL;DR在庫の標準コンテナがあなたの要求に応えられるとは思えません。理由は次のとおりです。

コンテナーの移動セマンティクスは、動的に割り当てられたメモリへのスコープ バインド ハンドルとして実装されるため、効率的であることに注意してください。コンテナーの移動は、ハンドルをコピーすることで実装されますが、含まれている要素には触れません。

最初の (明示的な) 制約は、コンテナーの要素をコピーしないことです。そのため、ハンドルを推定にコピーする必要がありますacc_container。つまり、 が必要ですacc_container<std::vector<T>>T標準コンテナのいずれかを使用すると、個々の要素がどれほど大きくても、効率的にそれを行うことができます.

2番目の(コメントから推測される暗黙の)制約は、すべての個々のベクトルのすべての要素に対して統一されたインターフェースを持ちたいということです。つまり、これを として使用したいということですacc_container<T>。これには、 your のイテレータで余分なレベルの間接化が必要です。イテレータはacc_container、現在の の 1 つの終わりに到達したことを検出しvector<T>、次の の先頭にジャンプしvector<T>ます。

そのようなコンテナは標準ライブラリには存在しません。

最も簡単な回避策は、std::vector<std::vector<T>>(要素のコピーを避けるためにT) を使用し、独自のイテレータ アダプタを作成することです (たとえば、要素のboost::indirect_iterator反復を提供するために を使用しTます)。

残念ながら、メンバー/からこれらの間接反復子を初期化する非メンバーbegin()/end()関数を提供しても、range-for は古いメンバー関数/を優先するため、ADL を使用してこれらの関数を検索しません。さらに、 non-member も提供しない限り(他の機能についても同様に) 、要素を複合コンテナーに直接入れることはできません。.begin().end().begin().end()insert()Tinsert()

したがって、range-for サポートとメンバー関数のネイティブ インターフェイスを備えた本物の複合コンテナーが必要な場合は、自分で作成する必要があります ( std::vector<std::vector<T>as バックエンドを使用し、そのstd::vector<T>上にインターフェイス全体を記述します)。素敵なプロジェクトとして、Boost メーリングリストで提案できるかもしれません。

更新:このアプローチによるパフォーマンスの利点を示す、セグメント化されたイテレーターと階層アルゴリズムに関するマット・オースターンによる古い論文へのリンクは次のとおりです。欠点は、これらの反復子を標準アルゴリズムに認識させる必要があることです。

于 2013-09-13T07:24:50.947 に答える