#pragma once

#include <vector>
#include <iterator>

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

    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:
     Slicer(It begin, It end, size_t page_size) {
         It i = begin;
         while (i != end) {
             It j = i;
             for (int k = page_size; k != 0 && j != end; k--) j++;
             pages_.push_back(IteratorRange<It>(i, j));
             i = j;
         }
     }

     typename std::vector<IteratorRange<It>>::iterator begin() {
         return pages_.begin();
     }

     typename std::vector<IteratorRange<It>>::iterator end() {
         return pages_.end();
     }

     size_t size() const {
         return pages_.size();
     }
 private:
    std::vector<IteratorRange<It>> pages_;
};

template <typename C>
Slicer<typename C::iterator> Slice(C& c, size_t page_size) {
    return Slicer<typename C::iterator>(c.begin(), c.end(), page_size);
}

template <typename C>
Slicer<typename C::const_iterator> Slice(const C& c, size_t page_size) {
    return Slicer<typename C::const_iterator>(c.begin(), c.end(), page_size);
}