PLaSK library
Loading...
Searching...
No Matches
iterators.hpp
Go to the documentation of this file.
1/*
2 * This file is part of PLaSK (https://plask.app) by Photonics Group at TUL
3 * Copyright (c) 2022 Lodz University of Technology
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 3.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14#ifndef PLASK__UTILS_ITERATORS_H
15#define PLASK__UTILS_ITERATORS_H
16
21//general iterators utils
22
23#include <boost/iterator/iterator_facade.hpp>
24#include <type_traits>
25#include <memory>
26
27namespace plask {
28
36template <typename ValueT, typename ReferenceT = ValueT&>
38
39 // some typedefs compatible with stl:
40
43
46
48 virtual ReferenceT dereference() const = 0;
49
51 virtual void increment() = 0;
52
55
60 virtual bool equal(const PolymorphicForwardIteratorImpl& other) const = 0;
61
62 /*
63 * Move iterator @a distanse steps forward. By default call increment @a distanse times.
64 * @param distanse how many steps
65 */
66 /*virtual void advance(std::size_t distanse) {
67 while (distanse) { increment(); --distanse; }
68 }*/
69
74 virtual std::unique_ptr<PolymorphicForwardIteratorImpl<ValueT, ReferenceT>> clone() const = 0;
75};
76
86template <typename ValueT, typename ReferenceT = ValueT&>
88
93 virtual std::size_t getIndex() const = 0;
94};
95
99template <typename wrapped_iterator_type, typename ValueT, typename ReferenceT = ValueT&>
101
103
105
106 ReferenceT dereference() const override { return *wrapped_iterator; }
107
108 void increment() override { ++wrapped_iterator; }
109
113
114 std::unique_ptr<PolymorphicForwardIteratorImpl<ValueT, ReferenceT>> clone() const override {
115 return std::unique_ptr<PolymorphicForwardIteratorImpl<ValueT, ReferenceT>>(
117 }
118
119};
120
128template <typename ImplT>
130 public boost::iterator_facade<
131 PolymorphicForwardIterator<ImplT>,
132 typename ImplT::value_type,
133 boost::forward_traversal_tag,
134 typename ImplT::reference
135 > {
136
137 protected:
138 std::unique_ptr<ImplT> impl;
139
140 public:
141
148
153 PolymorphicForwardIterator(const PolymorphicForwardIterator& src) { impl = src.impl ? src.impl->clone() : nullptr; }
154
160
165 void swap(PolymorphicForwardIterator & to_swap) noexcept { std::swap(this->impl, to_swap.impl); }
166
168 this->impl = src.impl->clone();
169 return *this;
170 }
171
173
174
175 private: //--- methods used by boost::iterator_facade: ---
177 template <class> friend struct PolymorphicForwardIterator;
178
179 bool equal(const PolymorphicForwardIterator<ImplT>& other) const {
180 return impl->equal(*other.impl);
181 }
182
183 void increment() {
184 impl->increment();
185 }
186
187 typename ImplT::reference dereference() const { return impl->dereference(); }
188
189 //TODO use advance?
190};
191
199template <typename ImplT>
201
208
213 std::size_t getIndex() const {
214 return this->impl->getIndex();
215 }
216};
217
218
219template <typename ContainerType, typename Reference>
220inline Reference dereferenceByIndexOperator(ContainerType& container, std::size_t index) { return container[index]; }
221
256template <
257 typename ContainerType,
258 typename Reference = decltype(std::declval<ContainerType>()[0]),
261
264
266 std::size_t index;
267
270
276 IndexedIterator(ContainerType* container, std::size_t index): container(container), index(index) {}
277
282 std::size_t getIndex() const { return index; }
283
284 private: //--- methods used by boost::iterator_facade: ---
285 friend class boost::iterator_core_access;
286
287 template <typename OtherT>
288 bool equal(const OtherT& other) const {
289 return index == other.index;
290 }
291
292 void increment() { ++index; }
293
294 void decrement() { --index; }
295
296 void advance(std::ptrdiff_t to_add) { index = size_t(index + to_add); }
297
298 template <typename OtherT>
299 std::ptrdiff_t distance_to(OtherT z) const { return std::ptrdiff_t(z.index) - std::ptrdiff_t(index); }
300
301 Reference dereference() const { return dereference_f(*container, index); }
302
303};
304
312template <typename ContainerType>
316
323template <typename FunctorType,
324 typename Reference = decltype(std::declval<FunctorType>()(0)),
325 typename Value = typename std::remove_reference<Reference>::type>
326struct FunctorIndexedIterator: public boost::iterator_facade< FunctorIndexedIterator<FunctorType, Reference, Value>, Value, boost::random_access_traversal_tag, Reference > {
327
330
332 std::size_t index;
333
340
345 std::size_t getIndex() const { return index; }
346
347 private: //--- methods used by boost::iterator_facade: ---
349 template <class, class, class> friend struct FunctorIndexedIterator;
350
351 template <typename OtherT>
352 bool equal(const OtherT& other) const {
353 return index == other.index;
354 }
355
356 void increment() { ++index; }
357
358 void decrement() { --index; }
359
360 void advance(std::ptrdiff_t to_add) { index += to_add; }
361
362 template <typename OtherT>
363 std::ptrdiff_t distance_to(OtherT z) const { return z.index - index; }
364
365 Reference dereference() const { return functor(index); }
366
367};
368
377template <
378 typename ContainerType,
379 typename ReturnedType,
380 ReturnedType (ContainerType::*Method)(std::size_t),
384
387
389 std::size_t index;
390
393
399 MethodIterator(ContainerType* container, std::size_t index): container(container), index(index) {}
400
405 std::size_t getIndex() const { return index; }
406
407 private: //--- methods used by boost::iterator_facade: ---
408 friend class boost::iterator_core_access;
409 template <
410 typename _ContainerType,
411 typename _ReturnedType,
416
417 template <typename OtherT>
418 bool equal(const OtherT& other) const {
419 return index == other.index;
420 }
421
422 void increment() { ++index; }
423
424 void decrement() { --index; }
425
426 void advance(std::ptrdiff_t to_add) { index += to_add; }
427
428 template <typename OtherT>
429 std::ptrdiff_t distance_to(OtherT z) const { return z.index - index; }
430
431 Reference dereference() const { return (container->*Method)(index); }
432
433};
434
442template <typename Functor>
446
456template <typename ContainerType>
458
460
461 int firstIndex, delta;
462
463 ReindexedContainer(ContainerType& originalContainer, int firstIndex = 0, int delta = 1)
464 : originalContainer(originalContainer), firstIndex(firstIndex), delta(delta) {}
465
466 auto operator[](const std::size_t& this_index) -> decltype(originalContainer[0]) {
467 return originalContainer[firstIndex + this_index * delta];
468 }
469
470 auto operator[](const std::size_t& this_index) const -> decltype(const_cast<const ContainerType&>(originalContainer)[0]) {
471 return originalContainer[firstIndex + this_index * delta];
472 }
473
474};
475
482template <typename ContainerType>
483ReindexedContainer<ContainerType> reindexContainer(ContainerType& originalContainer, int firstIndex = 0, int delta = 1) {
484 return ReindexedContainer<ContainerType>(originalContainer, firstIndex, delta);
485}
486
487} // namespace plask
488
489#endif