boostのiterator adaptorをSTLのアルゴリズムと組み合わせて遊んでいたら,またしてもしょーもないことを思いついてしまった.
boostのiterator adaptorの中には,STLのアルゴリズムとほぼ同等な機能を提供しているように捉えることができるものもあります.たとえば,boost::transform_iteratorはstd::transformとほとんど機能的に同じに見えます.このような関係を他にもpick upしてみたのが以下です.
- boost::counting_iterator + boost::transform_iterator(count無視 + 生成関数) -> std::generate_n
- boost::counting_iterator + boost::transform_iterator(count無視 + 定数を返す関数) -> std::fill_n
- boost::filter_iterator -> std::remove_copy_ifの逆,あるいはcopy_if(標準ライブラリにはありません)
- boost::function_output_iterator -> std::for_each
- boost::reverse_iterator -> std::copy_backward
- boost::transform_iterator -> std::transform
で,ここまでは良いのですが,上のことを逆に捉えて自然に拡張した結果,以下のような結論に達しました.
「他のアルゴリズムについても同等な機能を提供するiterator adaptorがあってもいいじゃん.」
で,例としてstd::inplace_mergeと同じことを行う(ように見せかける)iterator adaptorを作ってみました.
inplace_merge_iterator.hpp
で,使い方サンプル.
#include#include #include #include #include #include #include #include "inplace_merge_iterator.hpp" int main(int argc, char *argv[]) { using namespace std; using namespace boost; using namespace cry; // vの前方に2の倍数を昇順で詰める vector v( make_transform_iterator( make_counting_iterator(0), bind2nd(multiplies (), 2)), make_transform_iterator( make_counting_iterator(10), bind2nd(multiplies (), 2))); // inplace_mergeのためにindexを記録しておく. // 注:iteratorの記録は,挿入で無効化されるのでダメ. vector ::difference_type mid = distance(v.begin(), v.end()); // vの後方に3の倍数を昇順で詰める v.insert( v.end(), make_transform_iterator( make_counting_iterator(0), bind2nd(multiplies (), 3)), make_transform_iterator( make_counting_iterator(7), bind2nd(multiplies (), 3))); // vをinplace_mergeした結果をostream_iteratorにコピー copy( make_inplace_merge_iterator( v.begin(), v.begin() + mid, v.end(), less ()), make_inplace_merge_iterator( v.end(), v.end(), v.end(), less ()), ostream_iterator (cout, "\n")); return 0; }
こんな感じです.標準ライブラリにはアルゴリズムがたくさんありますが,これと同じことができるアルゴリズムって結構あると思います.で,問題は
「だから何?」
って聞かれても何も答えらないことで,考えた本人が言うのもなんですが正直,使い道が良く分かりません.上のinplace_mergeの場合,他にコピーするSTLのアルゴリズムのほうが効率的に動きますし・・・(特に,要素数に大きい差がある場合).