4

次のコードを検討してください。

typedef istream_iterator<char> char_itr ;
char_itr eos;

string ll("some text here");

istringstream line_in(ll);
char_itr start(line_in);

move_iterator<char_itr> mstart(start); // !!!
move_iterator<char_itr> meos(eos);
vector<char> vc(mstart, meos);

上記のコードは、次の行のためにコンパイルされません (!!!):

error C2440: 'return' : cannot convert from 'const char' to 'char &&'

しかし、 andをそれぞれ (通常の反復子) および に置き換えるmstartと、コードはコンパイルされます。なぜ私は作ることができないのですか?meosstarteosmove_iterators

編集: なぜストリーム/文字列から文字を移動したいのか疑問に思っている人のために。char実際の問題には、文字列からのコピーを避けるべきよりも複雑なデータ型が含まれます。char簡単にするために、エラーの原因となるメカニズムを提示するために使用されました。

4

2 に答える 2

1

これについては、今年初めに std-discussion ニュースグループで議論がありました: https://groups.google.com/a/isocpp.org/forum/#!topic/std-discussion/h7jGY95j1oc

コンセンサスは、契約を強制することでistream_iterator::referenceあると思われます。つまり、ユーザーの書き込みを防ぐためです。残念ながら、これはキャッシュされた値からの移動も妨げます。T const&InputIterator*it = value;

TC が前述したように、解決策をLWG2106に投稿すると、コードがコンパイルされます。残念ながら、それは暗黙のうちに間違ったことmove_iterator::referenceT const&&行い、おそらくあなたの型のコピー コンストラクターを呼び出すからです。

インクリメントされたときにキャッシュされた値を変更するためistream_iterator、(言語の POV から) へconst_castの返された参照に対して正当T&です。const_cast残念ながら (ここでも) と の間にistream_iteratoraを挿入する簡単な方法がないため、ここでは役に立ちませんmove_iterator

考えられる回避策:

  • istream_iteratorconst 以外のreferencetypedefを使用して、独自の を記述します。
  • 自分のmove_iterator演奏を書きますconst_cast
  • 挿入const_castイテレータを記述します。
  • 値の型の周りに変更可能なラッパーを使用します。

後者のオプションは驚くほど簡単です。

template<class T>
  struct mutable_wrapper {
    T mutable value;
    operator T&() const { return value; }
  };
// ...
using itr = std::istream_iterator<mutable_wrapper<MyType>>;

于 2015-08-13T10:40:03.790 に答える
0

を見るとistream_iterator::reference、それが であることがわかりますT const &。イテレータを逆参照すると、そのような参照が得られます。しかし、何かから移動できるようにするには、その何かが変更可能である必要があります。それがエラーメッセージが伝えようとしていることです。

内部(非定数)ストレージを保持するカスタムイテレータを配置することにより、move_iteratorからを作成できます。istream_iterator

しかし、なぜあなたはから移動したいのistream_iteratorですか? これらは単一パス iteratorであるため、内部ストレージがほとんどない可能性があります。

于 2015-08-13T10:27:08.437 に答える