#pragma once 
 
#include <vector> 
#include <cstddef> 
template<class It> 
class IteratorRange { 
 private: 
  It begin_, end_; 
  std::size_t size_; 
   
 public: 
  IteratorRange(It b, It e) : begin_(b), end_(e), size_(std::distance(b, e)) {} 
  typedef It iterator; 
  It begin() const { 
    return begin_; 
  } 
  It end() const { 
    return end_; 
  } 
  std::size_t size() const { 
    return size_; 
  } 
}; 
 
template<typename It> 
class Slicer { 
 private: 
  It begin_, end_; 
  int size_; 
  std::vector<IteratorRange<It>> pages_; 
   
 public: 
  Slicer(It begin, It end, int size) : begin_(begin), end_(end), size_(size) { 
    while (std::distance(begin, end) >= size) { 
      auto temp = begin; 
      advance(begin, size); 
      pages_.push_back(IteratorRange<It>(temp, begin)); 
    } 
    if (begin != end) { 
      pages_.push_back(IteratorRange<It>(begin, end)); 
    } 
  } 
  typename std::vector<IteratorRange<It>>::iterator begin() { 
    return pages_.begin(); 
  } 
  typename std::vector<IteratorRange<It>>::iterator end() { 
    return pages_.end(); 
  } 
  std::size_t size() const { 
    return pages_.size(); 
  } 
 
}; 
 
template<typename C> 
Slicer<typename C::iterator> Slice(C &c, std::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, std::size_t page_size) { 
  return Slicer<typename C::const_iterator>(c.begin(), c.end(), page_size); 
}