slice

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
}