2つのiterableの直積です。タプルを返します。
template<typename T, typename U> class cProduct : public cIterable<tuple<T,U>> { shared_ptr<cIterable<T>> gen1; shared_ptr<cIterable<U>> gen2; vector<U> v; typename vector<U>::const_iterator p; int mode; public: cProduct(shared_ptr<cIterable<T>> g1, shared_ptr<cIterable<U>> g2) : gen1(g1), gen2(g2), mode(0) { } bool exists_next() { if(mode == 0) { if(!gen1->exists_next()) return false; else if(!gen2->exists_next()) return false; mode = 1; v.push_back(gen2->value()); return true; } else if(mode == 1) { if(gen2->exists_next()) { v.push_back(gen2->value()); return true; } else if(gen1->exists_next()) { p = v.begin(); mode = 2; return true; } else { return false; } } else { ++p; if(p != v.end()) { return true; } else if(gen1->exists_next()) { p = v.begin(); return true; } else { return false; } } } tuple<T,U> value() const { T y = mode == 1 ? gen2->value() : *p; return tuple<T,U>(gen1->value(), y); } }; template<typename T, typename U> shared_ptr<cIterable<tuple<T,U>>> product(shared_ptr<cIterable<T>> g1, shared_ptr<cIterable<U>> g2) { return shared_ptr<cIterable<tuple<T,U>>>(new cProduct<T,U>(g1, g2)); }
これも第2引数はvectorに値を保持しています。
int main() { cout << product(range(2), range(3)) << endl; }
(0, 0) (0, 1) (0, 2) (1, 0) (1, 1) (1, 2)