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
plask
utils
iterators.hpp
Generated by
1.9.8