2

カスタムイテレータを定義する方法についてSOに関する多くの投稿を見てきましたが、私の質問に正確に答えているように見えるものは何もありません...

ネストされた for ループを隠すイテレータを作成するにはどうすればよいですか?

たとえば、クラス Foo があり、Foo の内部は Bar であり、Bar の内部は文字列です。私は書くことができました

for (const Foo& foo : foo_set)
  for (const Bar& bar : foo.bar_set)
    if (bar.my_string != "baz")
      cout << bar.my_string << endl;

しかし、代わりに次のようなことができるようにしたい:

for (const string& good : foo_set)
  cout << good << endl;

どうすればこのようなことをすることができますか?

4

2 に答える 2

2

セグメント化された反復子に関する提案と議論はありましたが、実際に C++ 標準に組み込まれたものはありません (とにかく)。

現状では、それを処理する最もクリーンな方法について (とにかく、IMO) は、アイテムのコレクションであり、それぞれがコレクションです。

std::ostream &operator<<(std::ostream &os, bar const &b) { 
     return os << b.my_string;
}

std::ostream &operator<<(std::ostream &os, foo const &f) { 
     std::remove_copy_if(f.begin(), f.end(), 
                         std::ostream_iterator<bar>(os, "\n"),
                         [](bar const &b) { return b.my_string != "baz"; });

     return os;
}

std::copy(foo_set.begin(), foo_set.end(), 
          std::ostream_iterator<foo>(std::cout, "\n"));

または、あなたが主張する場合:

for (auto s : foo_set)
    std::cout << s << "\n";
于 2012-11-20T21:55:57.750 に答える
1

はい。

なに、もっと詳しく知りたい?

これは大いに役立つはずです: http://www.boost.org/doc/libs/1_52_0/libs/iterator/doc/index.html#iterator-facade-and-adaptor

または: http://www.boost.org/doc/libs/1_52_0/libs/iterator/doc/iterator_facade.html#usage (関数入力反復子もうまく機能する場合があります)。

あなたは範囲に取り組んでいます。イテレータの内部状態は、内側のイテレータ、外側のイテレータ、および最後にいるかどうかを示すフラグのタプルです。インクリメントは内側の反復子を進め、それが内側の範囲の end に等しいかどうかをチェックし、等しい場合は、外側の範囲の終わりまたは空でない内側の範囲に到達するまで外側の反復子を進めます (その後、内側の反復子を外側の反復子、外側の反復子が end でない場合)

逆参照は、内部反復子を逆参照するだけです。やみくもに!(まあ、いくつかのアサートを投入してください)

等しい場合は、外側の反復子が等しいかどうかをチェックし、等しい場合は「終了フラグ」が設定されているかどうかをチェックします。そうでない場合は、内部反復子が等しいかどうかを比較します。(その終了フラグを回避するエレガントな方法はありますか?)

最初の要素を取得するには、最初の空でない内部範囲への反復子を見つける必要があります。

デクリメントは少しトリッキーですが、タスクには必要ありません。

外側の反復子が有効であるのに無効な内側の反復子を持たないように注意する必要があります。上記の落とし穴のほとんどをリストしたと思います。

于 2012-11-20T21:50:42.930 に答える