NuriKit v0.1.0b2
Loading...
Searching...
No Matches
iterator.h
Go to the documentation of this file.
1//
2// Project NuriKit - Copyright 2025 SNU Compbio Lab.
3// SPDX-License-Identifier: Apache-2.0
4//
5#ifndef NURI_ITERATOR_H_
6#define NURI_ITERATOR_H_
7
9#include <cstddef>
10#include <functional>
11#include <iterator>
12#include <tuple>
13#include <type_traits>
14#include <utility>
15
16#include <boost/iterator/iterator_facade.hpp>
18
19#include "nuri/meta.h"
20
21namespace nuri {
22namespace internal {
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> { };
27
28 template <class Derived, class RefLike, class Difference>
29 class ProxyIterator<Derived, RefLike, std::random_access_iterator_tag,
30 Difference>
31 : public boost::iterator_facade<Derived, RefLike,
32 std::random_access_iterator_tag, RefLike,
33 Difference> {
34 using Parent = typename ProxyIterator::iterator_facade_;
35
36 public:
37 // Required to override boost's implementation that returns a proxy
38 constexpr typename Parent::reference
39 operator[](typename Parent::difference_type n) const noexcept {
40 return *(*static_cast<const Derived *>(this) + n);
41 }
42 };
43
44 template <class Derived, class Iter, class UnaryOp, auto op,
45 bool = std::is_class_v<UnaryOp>>
46 class TransformIteratorTrampoline;
47
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>;
53
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>,
57 decltype(std::invoke(
58 op, *std::declval<Iter>()))> {
59 protected:
60 using Parent = TransformIteratorTrampoline;
61 constexpr static auto dereference_impl(Iter it) {
62 return std::invoke(op, *it);
63 }
64 };
65
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>()))> {
71 protected:
72 using Parent = TransformIteratorTrampoline;
73
74 TransformIteratorTrampoline(const UnaryOp &op): op_(op) { }
75
76 TransformIteratorTrampoline(UnaryOp &&op): op_(std::move(op)) { }
77
78 constexpr auto dereference_impl(Iter it) const { return op_(*it); }
79
80 private:
81 UnaryOp op_;
82 };
83
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;
89 using Traits =
90 std::iterator_traits<typename TransformIterator::iterator_facade_>;
91
92 public:
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;
98
99 constexpr TransformIterator() = default;
100
101 template <class... Args>
102 constexpr explicit TransformIterator(Iter it, Args &&...args)
103 : Base(std::forward<Args>(args)...), it_(it) { }
104
105 constexpr Iter base() const { return it_; }
106
107 private:
108 friend class boost::iterator_core_access;
109
110 constexpr reference dereference() const {
111 return Base::dereference_impl(it_);
112 }
113
114 constexpr bool equal(TransformIterator rhs) const { return it_ == rhs.it_; }
115
116 constexpr void increment() { ++it_; }
117 constexpr void decrement() { --it_; }
118 constexpr void advance(difference_type n) { it_ += n; }
119
120 constexpr difference_type distance_to(TransformIterator lhs) const {
121 return lhs.it_ - it_;
122 }
123
124 Iter it_;
125 };
126
127 template <auto unaryop, class Iter>
128 constexpr auto make_transform_iterator(Iter it) {
129 return TransformIterator<Iter, decltype(unaryop), unaryop>(it);
130 }
131
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));
136 }
137
138 template <class ZIT>
139 struct ZippedIteratorTraits;
140
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>;
151 };
152
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...>;
159 using reference =
160 std::tuple<typename std::iterator_traits<Iters>::reference...>;
161 };
162
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>;
171
172 public:
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;
178 };
179} // namespace internal
180
181template <class... Iters>
183 : public internal::ZippedIteratorBase<ZippedIterator<Iters...>> {
184 static_assert(sizeof...(Iters) > 1, "At least two iterators are required");
185
186 using Base = internal::ZippedIteratorBase<ZippedIterator>;
187
188public:
189 constexpr ZippedIterator() = default;
190
191 constexpr ZippedIterator(Iters... its): its_(its...) { }
192
193 template <size_t N = 0>
194 constexpr auto base() const {
195 return std::get<N>(its_);
196 }
197
198 template <size_t N = sizeof...(Iters), std::enable_if_t<N == 2, int> = 0>
199 constexpr auto first() const {
200 return base<0>();
201 }
202
203 template <size_t N = sizeof...(Iters), std::enable_if_t<N == 2, int> = 0>
204 constexpr auto second() const {
205 return base<1>();
206 }
207
208private:
210
211 constexpr typename Base::reference dereference() const {
212 return std::apply(
213 [](auto &...it) { return typename Base::reference(*it...); }, its_);
214 }
215
216 constexpr bool equal(const ZippedIterator &rhs) const {
217 return base() == rhs.base();
218 }
219
220 constexpr void increment() {
221 std::apply([](auto &...it) { (static_cast<void>(++it), ...); }, its_);
222 }
223
224 constexpr void decrement() {
225 std::apply([](auto &...it) { (static_cast<void>(--it), ...); }, its_);
226 }
227
228 constexpr void advance(typename Base::difference_type n) {
229 std::apply([n](auto &...it) { (static_cast<void>(it += n), ...); }, its_);
230 }
231
232 constexpr typename Base::difference_type
233 distance_to(const ZippedIterator &lhs) const {
234 return lhs.base() - base();
235 }
236
237 std::tuple<Iters...> its_;
238};
239
240template <class... Iters>
241constexpr auto make_zipped_iterator(Iters... iters) {
242 return ZippedIterator<Iters...>(iters...);
243}
244} // namespace nuri
245
246#endif /* NURI_ITERATOR_H_ */
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
Definition crdgen.h:16
constexpr auto make_zipped_iterator(Iters... iters)
Definition iterator.h:241