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
27 namespace plask {
28
36 template <typename ValueT, typename ReferenceT = ValueT&>
37 struct PolymorphicForwardIteratorImpl {
38
39 // some typedefs compatible with stl:
40
42 typedef ValueT value_type;
43
45 typedef ReferenceT reference;
46
48 virtual ReferenceT dereference() const = 0;
49
51 virtual void increment() = 0;
52
54 virtual ~PolymorphicForwardIteratorImpl() {}
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
86 template <typename ValueT, typename ReferenceT = ValueT&>
87 struct PolymorphicForwardIteratorWithIndexImpl: public PolymorphicForwardIteratorImpl<ValueT, ReferenceT> {
88
93 virtual std::size_t getIndex() const = 0;
94};
95
99 template <typename wrapped_iterator_type, typename ValueT, typename ReferenceT = ValueT&>
100 struct PolymorphicForwardIteratorWrapperImpl: public PolymorphicForwardIteratorImpl<ValueT, ReferenceT> {
101
102 wrapped_iterator_type wrapped_iterator;
103
104 PolymorphicForwardIteratorWrapperImpl(wrapped_iterator_type wrapped_iterator): wrapped_iterator(std::move(wrapped_iterator)) {}
105
106 ReferenceT dereference() const override { return *wrapped_iterator; }
107
108 void increment() override { ++wrapped_iterator; }
109
110 bool equal(const PolymorphicForwardIteratorImpl<ValueT, ReferenceT>& other) const override {
111 return wrapped_iterator == static_cast<const PolymorphicForwardIteratorWrapperImpl<wrapped_iterator_type, ValueT, ReferenceT>&>(other).wrapped_iterator;
112 }
113
114 std::unique_ptr<PolymorphicForwardIteratorImpl<ValueT, ReferenceT>> clone() const override {
115 return std::unique_ptr<PolymorphicForwardIteratorImpl<ValueT, ReferenceT>>(
116 new PolymorphicForwardIteratorWrapperImpl<wrapped_iterator_type, ValueT, ReferenceT>(wrapped_iterator));
117 }
118
119};
120
128 template <typename ImplT>
129 struct PolymorphicForwardIterator:
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
147 PolymorphicForwardIterator(ImplT* impl = nullptr): impl(impl) {}
148
153 PolymorphicForwardIterator(const PolymorphicForwardIterator& src) { impl = src.impl ? src.impl->clone() : nullptr; }
154
159 PolymorphicForwardIterator(PolymorphicForwardIterator&& src) = default;
160
165 void swap(PolymorphicForwardIterator & to_swap) noexcept { std::swap(this->impl, to_swap.impl); }
166
167 PolymorphicForwardIterator& operator=(const PolymorphicForwardIterator &src) {
168 this->impl = src.impl->clone();
169 return *this;
170 }
171
172 PolymorphicForwardIterator& operator=(PolymorphicForwardIterator &&src) = default;
173
174
175 private: //--- methods used by boost::iterator_facade: ---
176 friend class boost::iterator_core_access;
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
199 template <typename ImplT>
200 struct PolymorphicForwardIteratorWithIndex: public PolymorphicForwardIterator<ImplT> {
201
207 PolymorphicForwardIteratorWithIndex(ImplT* impl = nullptr): PolymorphicForwardIterator<ImplT>(impl) {}
208
213 std::size_t getIndex() const {
214 return this->impl->getIndex();
215 }
216};
217
218
219 template <typename ContainerType, typename Reference>
220 inline Reference dereferenceByIndexOperator(ContainerType& container, std::size_t index) { return container[index]; }
221
256 template <
257 typename ContainerType,
258 typename Reference = decltype(std::declval<ContainerType>()[0]),
259 Reference (*dereference_f)(ContainerType& container, std::size_t index) = dereferenceByIndexOperator<ContainerType, Reference>>
260 struct IndexedIterator: public boost::iterator_facade< IndexedIterator<ContainerType, Reference, dereference_f>, typename std::remove_reference<Reference>::type, boost::random_access_traversal_tag, Reference > {
261
263 ContainerType* container;
264
266 std::size_t index;
267
269 IndexedIterator() {}
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
312 template <typename ContainerType>
313 inline IndexedIterator<ContainerType> makeIndexedIterator(ContainerType* c, std::size_t index) {
314 return IndexedIterator<ContainerType>(c, index);
315}
316
323 template <typename FunctorType,
324 typename Reference = decltype(std::declval<FunctorType>()(0)),
325 typename Value = typename std::remove_reference<Reference>::type>
326 struct FunctorIndexedIterator: public boost::iterator_facade< FunctorIndexedIterator<FunctorType, Reference, Value>, Value, boost::random_access_traversal_tag, Reference > {
327
329 FunctorType functor;
330
332 std::size_t index;
333
339 FunctorIndexedIterator(FunctorType functor, std::size_t index): functor(functor), index(index) {}
340
345 std::size_t getIndex() const { return index; }
346
347 private: //--- methods used by boost::iterator_facade: ---
348 friend class boost::iterator_core_access;
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
377 template <
378 typename ContainerType,
379 typename ReturnedType,
380 ReturnedType (ContainerType::*Method)(std::size_t),
381 typename Reference = ReturnedType,
382 typename Value = typename std::remove_reference<Reference>::type>
383 struct MethodIterator: public boost::iterator_facade< MethodIterator<ContainerType, ReturnedType, Method, Value, Reference>, Value, boost::random_access_traversal_tag, Reference > {
384
386 ContainerType* container;
387
389 std::size_t index;
390
392 MethodIterator() {}
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,
412 _ReturnedType(_ContainerType::*_Method)(std::size_t),
413 typename _Reference,
414 typename _Value>
415 friend struct MethodIterator;
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
442 template <typename Functor>
443 inline FunctorIndexedIterator<Functor> makeFunctorIndexedIterator(Functor f, std::size_t index) {
444 return FunctorIndexedIterator<Functor>(f, index);
445}
446
456 template <typename ContainerType>
457 struct ReindexedContainer {
458
459 ContainerType& originalContainer;
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
482 template <typename ContainerType>
483 ReindexedContainer<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