2012年12月21日金曜日

std::move と std::set_difference

 ウィンドウズ系のプログラムは、win2k をサポートしないといけないとかいう理由で、vc8 を変える訳にはいかないのであった。そんな理由から、C++03 以外に選択肢が無い現状なのであった。  ただ、今回 android ndk でコードを書いてまして、所有権のあるクラスを管理する事になりました。そうなんです。コピー禁止で、std::move が、使いたくて使いたくてしょうがない症候群。これ、今までだと、リソースをマネージャクラスに保持させて管理するとかいう設計にしなくてはならず、スレッドが絡んでくると煩雑になってしょうがない部分でした。  android ndk r8b なんか Foo::Foo( Foo&& foo ) とかしてもコンパイル通るし、いろいろ調べてると、どうも c++11も使えるっぽい。まじめに gcc の状況を見たら、gcc-4.4.3 と gcc-4.6 が入っていて、gcc-4.6 の gnu-stl だと、まさに表にある通りで -std=gnu++0x のオプションでも一部機能には対応していました。ヘッダーの中身を確認しましたが、std::swap も std::move で実装されてます。  と、ここで std::set_difference の move を使うバージョンみたいなんが欲しくなって、実装してみました。コンパイルが通ってしまったんで、ついつい嬉しくなって、晒してみる事に…。あくまで、コンパイルが通っただけなんで、動作の保証はありません。はい。
#pragma once
#ifndef MOVE_DIFFERENCE_HPP
#define MOVE_DIFFERENCE_HPP

  template<typename ITER1, typename ITER2>
  ITER2 move(
    ITER1 first1, ITER1 last1,
    ITER2 first2
  ) {
    while( first1 != last1 ) {
      *first2 = std::move( *first1 );
      ++first1; ++first2;
    }
    return first2;
  }

  template<typename ITER1, typename ITER2, typename ITER3>
  void move_difference(
    ITER1& first1, ITER1 last1,
    ITER2  first2, ITER2 last2,
    ITER3& first3
  ) {
    ITER1 pos1 = first1;
    while( pos1 != last1 ) {
      if( first2 == last2) {
        first3 = std::move(pos1, last1, first3);
        return;
      }
      if( *pos1 < *first2 ) { // 取り除く候補
        *first3 = std::move( *pos1 );
        ++pos1;
        ++first3;
      } else if( *first2 < *pos1 ) { // 関係無い候補はスキップ
        ++first2;
      } else { // 等しいので双方インクリメント
        std::swap( *first1, *pos1 );
        ++first1; ++pos1;
        ++first2;
      }
    }
    return;
  }

  template<typename ITER1, typename ITER2, typename ITER3, typename COMP>
  void move_difference(
    ITER1& first1, ITER1 last1,
    ITER2  first2, ITER2 last2,
    ITER3& first3, COMP ope
  ) {
    ITER1 pos1 = first1;
    while( pos1 != last1 ) {
      if( first2 == last2) {
        first3 = std::move(pos1, last1, first3);
        return;
      }
      if( ope( *pos1, *first2) ) { // 取り除く候補
        *first3 = std::move( *pos1 );
        ++pos1;
        ++first3;
      } else if( ope( *first2, *pos1 ) ) { // 関係無い候補はスキップ
        ++first2;
      } else { // 等しいので双方インクリメント
        std::swap( *first1, *pos1 );
        ++first1; ++pos1;
        ++first2;
      }
    }
    return;
  }
  
#endif // MOVE_DIFFERENCE_HPP

0 件のコメント: