Add util::cyclic_iterator

This commit is contained in:
Nikita Lisitsa 2023-05-06 12:53:33 +03:00
parent aae4fa238f
commit 6f6a263553

View file

@ -0,0 +1,97 @@
#pragma once
#include <psemek/util/range.hpp>
#include <iterator>
namespace psemek::util
{
template <typename Iterator>
struct cyclic_iterator
{
using traits = std::iterator_traits<Iterator>;
using value_type = typename traits::value_type;
using reference = typename traits::reference;
using pointer = typename traits::pointer;
using difference_type = typename traits::difference_type;
using iterator_category = std::bidirectional_iterator_tag;
Iterator begin, end;
Iterator iter;
cyclic_iterator() = default;
cyclic_iterator(cyclic_iterator const &) = default;
cyclic_iterator(Iterator begin, Iterator end, Iterator iter)
: begin(begin)
, end(end)
, iter(iter)
{}
cyclic_iterator(Iterator begin, Iterator end)
: begin(begin)
, end(end)
, iter(begin)
{}
cyclic_iterator & operator = (cyclic_iterator const &) = default;
decltype(auto) operator *()
{
return *iter;
}
cyclic_iterator & operator++()
{
if (++iter == end)
iter = begin;
return *this;
}
cyclic_iterator operator++(int)
{
auto copy = *this;
this->operator++();
return copy;
}
cyclic_iterator & operator--()
{
if (iter == begin)
iter = end;
--iter;
return *this;
}
cyclic_iterator operator--(int)
{
auto copy = *this;
this->operator--();
return copy;
}
friend bool operator == (cyclic_iterator const & it1, cyclic_iterator const & it2)
{
return it1.iter == it2.iter;
}
friend bool operator != (cyclic_iterator const & it1, cyclic_iterator const & it2)
{
return it1.iter != it2.iter;
}
};
template <typename Iterator>
cyclic_iterator(Iterator, Iterator, Iterator) -> cyclic_iterator<Iterator>;
template <typename Iterator>
cyclic_iterator(Iterator, Iterator) -> cyclic_iterator<Iterator>;
template <typename Container>
auto make_cyclic_iterator(Container & container)
{
return cyclic_iterator{util::begin(container), util::end(container)};
}
}