pragma once
#include <vector>
#include <math.h>
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 b, It e, int page_size) : size_(ceil(std::distance(b, e) / static_cast<double>(page_size))) {
auto beg = b;
for (; b != e; ++b) {
if (std::distance(beg, b)+1 == page_size) {
pages_.push_back(IteratorRange<It>(beg, ++b));
beg = b;
}
if (std::distance(beg, e) < page_size) {
if (std::distance(beg, e) > 0) {
pages_.push_back(IteratorRange<It>(beg, e));
}
break;
}
}
}
auto begin() const {
return pages_.begin();
}
auto end() const {
return pages_.end();
}
size_t size() const {
return size_;
}
private:
std::vector<IteratorRange<It>> pages_;
size_t size_;
};
template<typename C>
auto Slice(C &c, size_t page_size) {
return Slicer<typename C::iterator>(c.begin(), c.end(), 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);
}