zipを使うと簡単にスライシングのコードが書けます。
template<typename T> class cSlice : public cIterable<T> { shared_ptr<cIterable<tuple<int,T>>> gen; int current; int end; int delta; bool last; shared_ptr<cIterable<int>> counter; public: cSlice(shared_ptr<cIterable<T>> g, int n) : current(0), end(n), delta(1), last(false) { gen = zip(count(), g); counter = range(n); } cSlice(shared_ptr<cIterable<T>> g, int b, int e, int d) : current(b), end(e), delta(d), last(false) { gen = zip(count(), g); if(e == -1) counter = count(b, d); else counter = range(b, e, d); } bool exists_next() { if(!counter->exists_next()) return false; int k = counter->value(); while(gen->exists_next()) { if(fst(gen->value()) == k) return true; } return false; } T value() const { return snd(gen->value()); } }; template<typename T> shared_ptr<cIterable<T>> slice(shared_ptr<cIterable<T>> g, int n) { return shared_ptr<cIterable<T>>(new cSlice<T>(g, n)); } template<typename T> shared_ptr<cIterable<T>> slice(shared_ptr<cIterable<T>> g, int b, int e, int d = 1) { return shared_ptr<cIterable<T>>(new cSlice<T>(g, b, e, d)); }
Pythonのisliceとだいたい同じ仕様です。rangeと同じような感じです。ただし、途中で打ち切らないときは第3引数を-1にします(最後の例)。
int main() { cout << slice(range(5), 3) << endl; // 0 1 2 cout << slice(range(5), 1, 3) << endl; // 1 2 cout << slice(range(5), 1, 4, 2) << endl; // 1 3 cout << slice(range(5), 2, -1) << endl; // 2 3 4 }