8

単項、バイナリ、およびおそらく (n-ary!) バリアントの両方をサポートするシングル パス アルゴリズムにstd::transform結合する C++ STL 準拠のアルゴリズムを作成した人はいますか? このパターンは、(l1-)ノルム計算などの線形代数で非常に再利用できることがわかったため、これが必要です。l1-ノルムは、要素の絶対値の合計を計算します。std::accumulatestd::transformed_accumulate

4

5 に答える 5

11

ええと...私の賭けは、変換をバイナリ述語に埋め込み、要素を変換し、変換後に蓄積することでそれを行うことができるということです。

struct times2accumulator {
   int operator()( int oldvalue, int newvalue ) const {
      return oldvalue + 2*newvalue;
   }
};
int r = std::accumulate( v.begin(), v.end(), 2, times2accumulator() );

そのファンクタは次と同等です。

struct times2 {
   int operator()( int x ) {
      return 2*x;
   }
};
std::vector<int> tmp; tmp.reserve( v.size() );
std::transform( v.begin(), v.end(), std::back_inserter(tmp), times2 );
int r = std::accumulate( tmp.begin(), tmp.end(), 0 );

もちろん、これをジェネリックにすることもできます。変換ファンクターをジェネリック基本ファンクターに渡すだけです。

template <typename Transform>
struct transform_accumulator_t {
    Transform t;
    transform_accumulator_t( Transform t ) : t(t) {}
    int operator()( int oldvalue, int newvalue ) const {
        return oldvalue + t(newvalue);
    }
};
// syntactic sugar:
template <typename T>
transform_accumulator_t<T> transform_accumulator( T t ) {
    return transform_accumulator_t<T>(t);
}
int r = std::accumulate(v.begin(), v.end(), 0, transform_accumulator(times2));

また、コンテナ内の型を一般化することもできます...または、アキュムレータと変換ファンクタの両方を取り、それらを順番に適用する、より一般的な transform_accumulator を作成することもできます。実際の実装は、読者の課題として残しておきます。

于 2012-05-14T23:24:19.697 に答える