zip

2つのIterableが並行に(tupleにして)値を出せるようにします。長さが違う場合は短いほうにあわせます。

#include <tuple>
#include "itertools.h"

using namespace std;
using namespace itertools;

template<typename T, typename U>
class cZip : public cIterable<tuple<T,U>> {
    shared_ptr<cIterable<T>>    gen1;
    shared_ptr<cIterable<U>>    gen2;

public:
    cZip(shared_ptr<cIterable<T>> g1,
                shared_ptr<cIterable<U>> g2) : gen1(g1), gen2(g2) { }
    
    bool exists_next() {
        return gen1->exists_next() && gen2->exists_next();
    }
    tuple<T,U> value() const {
        return tuple<T,U>(gen1->value(), gen2->value());
    }
};

template<typename T, typename U>
shared_ptr<cIterable<tuple<T,U>>> zip(shared_ptr<cIterable<T>> g1,
                                      shared_ptr<cIterable<U>> g2) {
    return shared_ptr<cIterable<tuple<T,U>>>(new cZip<T,U>(g1, g2));
}

ついでにfst, sndも定義しておきましょう。これは、タプルの最初の要素と2番目を返します。

template<typename T, typename U>
T fst(tuple<T,U> x) { return get<0>(x); }

template<typename T, typename U>
U snd(tuple<T,U> x) { return get<1>(x); }

次は1 * 1 + 2 * 3 + 3 * 5 + ... + 10 * 19という計算を行います。

int main() {
    auto    g = zip(count(1), range(1, 20, 2));
    auto    f = [] (tuple<int,int> x) { return fst(x) * snd(x); };
    cout << sum(map(f, g)) << endl;
}