さて,ここまでは話の半分で次からが本題です.
日々boostと戯れる変態(褒め言葉ですからね!)なら,当然,transform_iteratorに渡すファンクタをlambdaでinlineに書きたいと思いますね?思いませんか?思わない人はここでさようなら.
で,実際にやってみます.
// headerのincludeは適切に行われているとします copy( make_transform_iterator( make_counting_iterator(0), _1 * 2, make_transform_iterator( make_counting_iterator (20), _1 * 2, ostream_iterator (cout, "\n"));
残念ながら上のコードはコンパイルされません.上のコードをコンパイルしてもらえば分かりますが(分からないかも知れませんがw),エラーの中にlambda_functor
ドキュメントにあるように,transform_iteratorが必要とするファンクタはAdaptive Unary Function(今更ですけど,SGIのSTLサイトって滅茶苦茶有用ですね)のモデルである必要があり(注:古い(boost.cppll.jpにある方)の記述です.新しい方(boost.org)ではresult_of
なので,lambdaが返すファンクタをラップし,Adaptive Unary Functionの要件を満たすようtypedefを行う関数アダプタを自作してしまいました.
// functor adaptor class templateclass unary_adaptor { typedef FunctorType functor_type; typedef unary_adaptor this_type; public: typedef ArgumentType argument_type; typedef ResultType result_type; unary_adaptor(FunctorType functor) : f(functor) { } unary_adaptor(this_type const &r) : f(r.f) { } ~unary_adaptor() { } this_type &operator=(this_type const &rhs) { f = rhs.f; return *this; } result_type operator()( argument_type const &arg) const { return f(arg); } private: functor_type f; }; // object generator template inline unary_adaptor adapt1(FunctorType const &functor) { return unary_adaptor (functor); }
これで準備は整いました.以下のコードは,若干格好は悪くなりますがOKなはずです.
// headerのincludeは適切に行われているとします copy( make_transform_iterator( make_counting_iterator(0), adapt1 (_1 * 2), make_transform_iterator( make_counting_iterator (20), adapt1 (_1 * 2), ostream_iterator (cout, "\n"));
lambdaを使えば即席のファンクタを生成できるように,transform_iteratorを使えば即席のiteratorを生成できるのです!
最後に,以上をまとめる例示コードとして即席iteratorによるvectorの初期化のコードをここにおいておきます.
補足1:範囲のiteratorのうち,終端の方のiteratorに複雑なファンクタを渡す必要はないと思われます.
補足2:lambdaの返り値の型(今,これを規定しているtraitsを探しています)でresult_of