From 6f6a263553bb81e05802e19a9a2ab0ec7400077a Mon Sep 17 00:00:00 2001 From: lisyarus Date: Sat, 6 May 2023 12:53:33 +0300 Subject: [PATCH] Add util::cyclic_iterator --- .../include/psemek/util/cyclic_iterator.hpp | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 libs/util/include/psemek/util/cyclic_iterator.hpp diff --git a/libs/util/include/psemek/util/cyclic_iterator.hpp b/libs/util/include/psemek/util/cyclic_iterator.hpp new file mode 100644 index 00000000..d64a6a0a --- /dev/null +++ b/libs/util/include/psemek/util/cyclic_iterator.hpp @@ -0,0 +1,97 @@ +#pragma once + +#include + +#include + +namespace psemek::util +{ + + template + struct cyclic_iterator + { + using traits = std::iterator_traits; + 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 + cyclic_iterator(Iterator, Iterator, Iterator) -> cyclic_iterator; + + template + cyclic_iterator(Iterator, Iterator) -> cyclic_iterator; + + template + auto make_cyclic_iterator(Container & container) + { + return cyclic_iterator{util::begin(container), util::end(container)}; + } + +}