#pragma once

#include <vector>

template<class It>
class IteratorRange {
public:
    IteratorRange(It x, It y) : begin_(x), end_(y), size_(std::distance(x, y)) {}

    It begin() const {
        return begin_;
    }

    It end() const {
        return end_;
    }

    size_t size() const {
        return size_;
    }
private:
    It begin_, end_;
    size_t size_;
};

template <typename It>
class Slicer {
 public:
    explicit Slicer(It begin, It end, size_t page_size) :
            begin_(begin), end_(end), page_size_(page_size) {
            auto allElements = std::distance(begin_, end_);
            unsigned int count = allElements / page_size_;
            for (unsigned int n = 0; n < count; n++) {
                IteratorRange<It> tmp(begin_, begin_ + page_size_);
                begin_ += page_size_;
                pages_.push_back(tmp);
            }
            count = allElements % page_size_;
            if (count > 0) {
                IteratorRange<It> tmp(begin_, end_);
                pages_.push_back(tmp);
            }
    }

    size_t size() const {
        return pages_.size();
    }

    auto begin() {
        return pages_.begin();
    }

    auto end() {
        return pages_.end();
    }
};

template <typename S>
auto Slice(S& s, size_t page_size) {
    return Slicer(s.begin(), s.end(), page_size);
}