ひがきの日記

2016-02-07

C++ で Ruby の inject みたいなやつを作ってみる

仕事で C++ を使うことになったので、リハビリを兼て Ruby の inject みたいな (lisp の apply みたいな) 関数を書いてみた。

#include <iostream>
#include <vector>
#include <functional>

using namespace std;

#define ARRSIZ(a) (sizeof(a)/sizeof((a)[0]))
#define ARREND(a) ((a)+ARRSIZ(a))

template <class T, class R, class F>
R inject(T begin, T end, R result, F func) {
    for (; begin != end; ++begin)
	result = func(result, *begin);
    return result;
}

template <class T>
struct PLUS {
    T operator()(const T& a, const T& b) const {
        return a + b;
    }
};

int main() {
    int src[] = {1, 2, 3, 4, 5};
    vector<int> v;
    vector<double> w;

    for (int* i = src; i != ARREND(src); ++i) {
	v.push_back(*i);
	w.push_back(*i * 1.1);
    }

    cout << inject(src, ARREND(src),   0,   plus<int>())    << endl;
    cout << inject(v.begin(), v.end(), 0,   plus<int>())    << endl;
    cout << inject(w.begin(), w.end(), 0.0, plus<double>()) << endl;
    cout << inject(v.begin(), v.end(), 0,   PLUS<int>())    << endl;
    cout << inject(w.begin(), w.end(), 0.0, PLUS<double>()) << endl;

    return 0;
}

inject の受け取る、型 F がなんかよく分からん。

template 使うと、関数オブジェクト関数内でちょいちょいっと書けないのかね。

    struct _plus_ {
	int operator()(const int& a, const int& b) const {
	    return a + b;
	}
    };
    cout << inject(v.begin(), v.end(), 0, _plus_()) << endl;

上のように main() の中で struct を書くと、

warning: template argument uses local type '_plus_'

こんな感じで怒られる。めんどくさい。

今時ならラムダ式を使うといいんだろうか?

そもそも inject に相当する関数はどこかに定義されてるんじゃないのか?

mas-higamas-higa 2016/02/09 16:36 std::accumulate が inject やった X-(

mas-higamas-higa 2016/02/10 22:37 cout << accumulate(w.begin(), w.end(), 0.0, [](double r, double x){return r + x;}) << endl;

λ式、最高か。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/mas-higa/20160207/1454811035
リンク元