// Experimental sliding window class. (3.00)
#include <iostream>
template<typename T>
struct window_wrapper {
T m_first, m_last;
T begin() const
{ return m_first; }
T end() const
{ return m_last; }
};
// class sliding_window
// Group a sequence into sequential n-element chunks.
// sliding_window(string("ABCDEF"), 4) -> ABCD, BCDE, CDEF
template<typename Iter>
struct sliding_window {
typedef window_wrapper<Iter> value_type;
template<typename Iterable>
sliding_window(Iterable&&, size_t n);
sliding_window(Iter, Iter, size_t n);
sliding_window begin() const
{ return *this; }
sliding_window end() const
{ return sliding_window(m_last, m_last, 0); }
value_type operator*() const
{ return {m_first, std::next(m_next)}; }
sliding_window& operator++()
{ ++m_first; ++m_next; return *this; }
sliding_window operator++(int)
{ sliding_window temp(*this); ++*this; return temp; }
bool operator==(const sliding_window& other) const
{ return m_next == other.m_next; }
bool operator!=(const sliding_window& other) const
{ return !(*this == other); }
private:
Iter m_first, m_next, m_last;
};
#if __cplusplus >= 201703L
template<typename Iterable>
sliding_window(Iterable&& t, size_t) ->
sliding_window<decltype(std::begin(t))>;
#endif // C++17
template<typename Iter>
template<typename Iterable>
sliding_window<Iter>::sliding_window(Iterable&& v, size_t n)
: sliding_window(std::begin(v), std::end(v), n)
{}
template<typename Iter>
sliding_window<Iter>::sliding_window(Iter first, Iter last, size_t n)
: m_first(first), m_next(n > 0 ? first : last), m_last(last)
{
for (size_t i = 1; i < n && m_next != m_last; i++)
++m_next;
}
// Ease creation of sliding windows.
// (the C++17 deduction guides make these obsolete)
template<typename Iter>
auto make_sliding_window(Iter first, Iter last, size_t n)
{
return sliding_window<decltype(first)>(first, last, n);
}
template<typename Iterable>
auto make_sliding_window(Iterable&& v, size_t n)
{
return make_sliding_window(std::begin(v), std::end(v), n);
}
// Testing.
int main()
{
auto print = [](auto&& iterable) {
for (auto item : iterable) std::cout << item;
std::cout << ' ';
};
std::string s = "ABCDEFGH";
std::cout << s << std::endl;
// Ensure all constness and value categories compile.
make_sliding_window(s, 1);
make_sliding_window(const_cast<const std::string&>(s), 1);
make_sliding_window(std::string(), 1);
for (size_t i = 0; i <= s.size()+1; i++) {
auto sw = make_sliding_window(s, i);
std::cout << i << "> ";
for (auto window : sw)
print(window);
std::cout << std::endl;
}
for (size_t i = 0; i <= s.size()+1; i++) {
auto sw = make_sliding_window(s.begin(), s.end(), i);
std::cout << i << "> ";
for (auto window : sw)
print(window);
std::cout << std::endl;
}
// Modify non-const sequence through window.
for (auto window : make_sliding_window(s, 1))
for (auto& x : window)
x = '-';
std::cout << s << std::endl;
}