5#ifndef NURI_ITERATOR_H_
6#define NURI_ITERATOR_H_
16#include <boost/iterator/iterator_facade.hpp>
23 template <
class Derived,
class RefLike,
class Category,
24 class Difference = std::ptrdiff_t>
25 class ProxyIterator:
public boost::iterator_facade<Derived, RefLike, Category,
26 RefLike, Difference> { };
28 template <
class Derived,
class RefLike,
class Difference>
29 class ProxyIterator<Derived, RefLike, std::random_access_iterator_tag,
31 :
public boost::iterator_facade<Derived, RefLike,
32 std::random_access_iterator_tag, RefLike,
34 using Parent =
typename ProxyIterator::iterator_facade_;
38 constexpr typename Parent::reference
39 operator[](
typename Parent::difference_type n)
const noexcept {
40 return *(*
static_cast<const Derived *
>(
this) + n);
44 template <
class Derived,
class Iter,
class UnaryOp,
auto op,
45 bool = std::is_class_v<UnaryOp>>
46 class TransformIteratorTrampoline;
48 template <
class Derived,
class Traits,
class Ref>
49 using TransformIteratorBase =
50 boost::iterator_facade<Derived, std::remove_reference_t<Ref>,
51 typename Traits::iterator_category, Ref,
52 typename Traits::difference_type>;
54 template <
class Derived,
class Iter,
class UnaryOp, UnaryOp op>
55 class TransformIteratorTrampoline<Derived, Iter, UnaryOp, op, false>
56 :
public TransformIteratorBase<Derived, std::iterator_traits<Iter>,
58 op, *std::declval<Iter>()))> {
60 using Parent = TransformIteratorTrampoline;
61 constexpr static auto dereference_impl(Iter it) {
62 return std::invoke(op, *it);
66 template <
class Derived,
class Iter,
class UnaryOp>
67 class TransformIteratorTrampoline<Derived, Iter, UnaryOp, nullptr, true>
68 :
public TransformIteratorBase<Derived, std::iterator_traits<Iter>,
69 decltype(std::declval<UnaryOp>()(
70 *std::declval<Iter>()))> {
72 using Parent = TransformIteratorTrampoline;
74 TransformIteratorTrampoline(
const UnaryOp &op): op_(op) { }
76 TransformIteratorTrampoline(UnaryOp &&op): op_(std::move(op)) { }
78 constexpr auto dereference_impl(Iter it)
const {
return op_(*it); }
84 template <
class Iter,
class UnaryOp, auto unaryop =
nullptr>
85 class TransformIterator
86 :
public TransformIteratorTrampoline<
87 TransformIterator<Iter, UnaryOp, unaryop>, Iter, UnaryOp, unaryop> {
88 using Base =
typename TransformIterator::Parent;
90 std::iterator_traits<typename TransformIterator::iterator_facade_>;
93 using iterator_category =
typename Traits::iterator_category;
94 using value_type =
typename Traits::value_type;
95 using difference_type =
typename Traits::difference_type;
96 using pointer =
typename Traits::pointer;
97 using reference =
typename Traits::reference;
99 constexpr TransformIterator() =
default;
101 template <
class... Args>
102 constexpr explicit TransformIterator(Iter it, Args &&...args)
103 : Base(std::forward<Args>(args)...), it_(it) { }
105 constexpr Iter base()
const {
return it_; }
108 friend class boost::iterator_core_access;
110 constexpr reference dereference()
const {
111 return Base::dereference_impl(it_);
114 constexpr bool equal(TransformIterator rhs)
const {
return it_ == rhs.it_; }
116 constexpr void increment() { ++it_; }
117 constexpr void decrement() { --it_; }
118 constexpr void advance(difference_type n) { it_ += n; }
120 constexpr difference_type distance_to(TransformIterator lhs)
const {
121 return lhs.it_ - it_;
127 template <auto unaryop,
class Iter>
128 constexpr auto make_transform_iterator(Iter it) {
129 return TransformIterator<Iter, decltype(unaryop), unaryop>(it);
132 template <
class UnaryOp,
class Iter>
133 constexpr auto make_transform_iterator(Iter it, UnaryOp &&op) {
134 return TransformIterator<Iter, remove_cvref_t<UnaryOp>>(
135 it, std::forward<UnaryOp>(op));
139 struct ZippedIteratorTraits;
141 template <
template <
class...>
class ZIT,
class Iter,
class Jter>
142 struct ZippedIteratorTraits<ZIT<Iter, Jter>> {
143 using iterator_category = std::common_type_t<
144 typename std::iterator_traits<Iter>::iterator_category,
145 typename std::iterator_traits<Jter>::iterator_category>;
146 using difference_type =
147 std::common_type_t<typename std::iterator_traits<Iter>::difference_type,
148 typename std::iterator_traits<Jter>::difference_type>;
149 using reference = std::pair<typename std::iterator_traits<Iter>::reference,
150 typename std::iterator_traits<Jter>::reference>;
153 template <
template <
class...>
class ZIT,
class... Iters>
154 struct ZippedIteratorTraits<ZIT<Iters...>> {
155 using iterator_category = std::common_type_t<
156 typename std::iterator_traits<Iters>::iterator_category...>;
157 using difference_type = std::common_type_t<
158 typename std::iterator_traits<Iters>::difference_type...>;
160 std::tuple<typename std::iterator_traits<Iters>::reference...>;
163 template <
class Derived>
164 class ZippedIteratorBase
165 :
public ProxyIterator<
166 Derived, typename ZippedIteratorTraits<Derived>::reference,
167 typename ZippedIteratorTraits<Derived>::iterator_category,
168 typename ZippedIteratorTraits<Derived>::difference_type> {
169 using Root =
typename ZippedIteratorBase::iterator_facade_;
170 using Traits = std::iterator_traits<Root>;
173 using iterator_category =
typename Traits::iterator_category;
174 using value_type =
typename Traits::value_type;
175 using difference_type =
typename Traits::difference_type;
176 using pointer =
typename Traits::pointer;
177 using reference =
typename Traits::reference;
181template <
class... Iters>
183 :
public internal::ZippedIteratorBase<ZippedIterator<Iters...>> {
184 static_assert(
sizeof...(Iters) > 1,
"At least two iterators are required");
186 using Base = internal::ZippedIteratorBase<ZippedIterator>;
193 template <
size_t N = 0>
195 return std::get<N>(its_);
198 template <
size_t N =
sizeof...(Iters), std::enable_if_t<N == 2, int> = 0>
203 template <
size_t N =
sizeof...(Iters), std::enable_if_t<N == 2, int> = 0>
211 constexpr typename Base::reference dereference()
const {
213 [](
auto &...it) {
return typename Base::reference(*it...); }, its_);
220 constexpr void increment() {
221 std::apply([](
auto &...it) { (
static_cast<void>(++it), ...); }, its_);
224 constexpr void decrement() {
225 std::apply([](
auto &...it) { (
static_cast<void>(--it), ...); }, its_);
228 constexpr void advance(
typename Base::difference_type n) {
229 std::apply([n](
auto &...it) { (
static_cast<void>(it += n), ...); }, its_);
232 constexpr typename Base::difference_type
234 return lhs.base() -
base();
237 std::tuple<Iters...> its_;
240template <
class... Iters>
Definition iterator.h:183
constexpr auto second() const
Definition iterator.h:204
constexpr auto base() const
Definition iterator.h:194
friend class boost::iterator_core_access
Definition iterator.h:209
constexpr ZippedIterator(Iters... its)
Definition iterator.h:191
constexpr ZippedIterator()=default
constexpr auto first() const
Definition iterator.h:199
constexpr auto make_zipped_iterator(Iters... iters)
Definition iterator.h:241