#pragma once
#include <vector>
#include <cmath>
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, std::size_t pageSize) {
slicedPages = ceil((static_cast<double>(std::distance(begin, end)) / pageSize));
Slice(begin, end, pageSize);
}
std::size_t size() const {
return slicedPages;
}
auto begin() { return std::begin(pages_); }
auto end() { return std::end(pages_); }
private:
void Slice(It begin, It end, std::size_t pageSize) {
It pageIter = begin;
for (; pageIter != end;) {
std::size_t count{};
begin = pageIter;
for (; count < pageSize && pageIter != end;) {
count++;
pageIter++;
}
pages_.push_back({begin, pageIter});
}
}
std::vector<IteratorRange<It>> pages_;
std::size_t slicedPages = 0;
};
template<typename C>
auto Slice(C &c, size_t page_size) {
return Slicer<typename C::iterator>(std::begin(c), std::end(c), page_size);
}
template<typename C>
auto Slice(const C &c, size_t page_size) {
return Slicer<typename C::const_iterator>(c.begin(), c.end(), page_size);
}
template<>
auto Slice(const IteratorRange<std::vector<int>::iterator> &c, size_t page_size) {
return Slicer<std::vector<int>::iterator>(c.begin(), c.end(), page_size);
}