aGrUM
0.20.3
a C++ library for (probabilistic) graphical models
list_tpl.h
Go to the documentation of this file.
1
/**
2
*
3
* Copyright (c) 2005-2021 by Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
4
* info_at_agrum_dot_org
5
*
6
* This library is free software: you can redistribute it and/or modify
7
* it under the terms of the GNU Lesser General Public License as published by
8
* the Free Software Foundation, either version 3 of the License, or
9
* (at your option) any later version.
10
*
11
* This library is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU Lesser General Public License for more details.
15
*
16
* You should have received a copy of the GNU Lesser General Public License
17
* along with this library. If not, see <http://www.gnu.org/licenses/>.
18
*
19
*/
20
21
22
/**
23
* @file
24
* @brief template implementation of chained lists
25
*
26
* @author Christophe GONZALES(@AMU) and Pierre-Henri WUILLEMIN(@LIP6)
27
*/
28
29
// to ease parser
30
#
include
<
agrum
/
tools
/
core
/
list
.
h
>
31
32
namespace
gum
{
33
34
// ===========================================================================
35
// ===========================================================================
36
// === BUCKET IMPLEMENTATION ===
37
// ===========================================================================
38
// ===========================================================================
39
40
// default constructor
41
template
<
typename
Val >
42
INLINE ListBucket<
Val
>::
ListBucket
(
const
Val
&
v
) :
_val_
{
v
} {
43
// for debugging purposes
44
GUM_CONSTRUCTOR
(
ListBucket
);
45
}
46
47
// constructor for Val rvalues
48
template
<
typename
Val
>
49
INLINE
ListBucket
<
Val
>::
ListBucket
(
Val
&&
v
)
noexcept
:
_val_
{
std
::
move
(
v
)} {
50
// for debugging purposes
51
GUM_CONSTRUCTOR
(
ListBucket
);
52
}
53
54
// emplace constructor
55
template
<
typename
Val
>
56
template
<
typename
...
Args
>
57
INLINE
ListBucket
<
Val
>::
ListBucket
(
typename
ListBucket
<
Val
>::
Emplace
,
Args
&&...
args
) :
58
_val_
(
std
::
forward
<
Args
>(
args
)...) {
59
// for debugging purposes
60
GUM_CONSTRUCTOR
(
ListBucket
);
61
}
62
63
// copy constructor
64
template
<
typename
Val
>
65
INLINE
ListBucket
<
Val
>::
ListBucket
(
const
ListBucket
<
Val
>&
src
) :
_val_
{
src
.
_val_
} {
66
// for debugging purposes
67
GUM_CONS_CPY
(
ListBucket
);
68
}
69
70
// copy operator
71
template
<
typename
Val
>
72
INLINE
ListBucket
<
Val
>&
ListBucket
<
Val
>::
operator
=(
const
ListBucket
<
Val
>&
src
) {
73
// for debugging purposes
74
GUM_OP_CPY
(
ListBucket
);
75
76
// no need to avoid self assignment
77
_val_
=
src
.
_val_
;
78
return
*
this
;
79
}
80
81
// WARNING: during its deletion, the bucket does not take care of properly
82
// re-chaining the chained list. This should be done by the Lists themselves
83
template
<
typename
Val
>
84
INLINE
ListBucket
<
Val
>::~
ListBucket
() {
85
// for debugging purposes
86
GUM_DESTRUCTOR
(
ListBucket
);
87
}
88
89
// equality check
90
template
<
typename
Val
>
91
INLINE
bool
ListBucket
<
Val
>::
operator
==(
const
ListBucket
<
Val
>&
src
)
const
{
92
return
(
src
.
_val_
==
_val_
);
93
}
94
95
// inequality check
96
template
<
typename
Val
>
97
INLINE
bool
ListBucket
<
Val
>::
operator
!=(
const
ListBucket
<
Val
>&
src
)
const
{
98
return
(
src
.
_val_
!=
_val_
);
99
}
100
101
// dereferencing operator
102
template
<
typename
Val
>
103
INLINE
const
Val
&
ListBucket
<
Val
>::
operator
*()
const
noexcept
{
104
return
_val_
;
105
}
106
107
// dereferencing operator
108
template
<
typename
Val
>
109
INLINE
Val
&
ListBucket
<
Val
>::
operator
*()
noexcept
{
110
return
_val_
;
111
}
112
113
// returns the bucket toward the next element
114
template
<
typename
Val
>
115
INLINE
const
ListBucket
<
Val
>*
ListBucket
<
Val
>::
next
()
const
noexcept
{
116
return
_next_
;
117
}
118
119
// returns the bucket toward the preceding element
120
template
<
typename
Val
>
121
INLINE
const
ListBucket
<
Val
>*
ListBucket
<
Val
>::
previous
()
const
noexcept
{
122
return
_prev_
;
123
}
124
125
// ===========================================================================
126
// ===========================================================================
127
// === UNSAFE_CONST_LIST_ITERATOR IMPLEMENTATION ===
128
// ===========================================================================
129
// ===========================================================================
130
131
// default constructor
132
template
<
typename
Val
>
133
INLINE
ListConstIterator
<
Val
>::
ListConstIterator
()
noexcept
{
134
// for debugging purposes
135
GUM_CONSTRUCTOR
(
ListConstIterator
);
136
}
137
138
// default constructor
139
template
<
typename
Val
>
140
template
<
typename
Alloc
>
141
INLINE
ListConstIterator
<
Val
>::
ListConstIterator
(
const
List
<
Val
,
Alloc
>&
theList
)
noexcept
:
142
_bucket_
{
theList
.
_deb_list_
} {
143
// for debugging purposes
144
GUM_CONSTRUCTOR
(
ListConstIterator
);
145
}
146
147
// copy constructor
148
template
<
typename
Val
>
149
INLINE
ListConstIterator
<
Val
>::
ListConstIterator
(
const
ListConstIterator
<
Val
>&
src
)
noexcept
:
150
_bucket_
{
src
.
_bucket_
} {
151
// for debugging purposes
152
GUM_CONS_CPY
(
ListConstIterator
);
153
}
154
155
// move constructor
156
template
<
typename
Val
>
157
INLINE
ListConstIterator
<
Val
>::
ListConstIterator
(
ListConstIterator
<
Val
>&&
src
)
noexcept
:
158
_bucket_
{
std
::
move
(
src
.
_bucket_
)} {
159
// for debugging purposes
160
GUM_CONS_MOV
(
ListConstIterator
);
161
}
162
163
// Constructor for an iterator pointing to the \e ind_eltth element of a
164
// List.
165
template
<
typename
Val
>
166
INLINE
ListConstIterator
<
Val
>::
ListConstIterator
(
const
List
<
Val
>&
theList
,
Size
ind_elt
) {
167
// for debugging purposes
168
GUM_CONSTRUCTOR
(
ListConstIterator
);
169
170
// check if the index ind_elt passed as parameter is valid
171
if
(
ind_elt
>=
theList
.
_nb_elements_
) {
172
GUM_ERROR
(
UndefinedIteratorValue
,
"Not enough elements in the list"
)
173
}
174
175
// check if it is faster to find the indexth element from the start or
176
// from the end of the list
177
if
(
ind_elt
< (
theList
.
_nb_elements_
>> 1)) {
178
// find the element we shall point to src the start of the list
179
for
(
_bucket_
=
theList
.
_deb_list_
;
ind_elt
; --
ind_elt
,
_bucket_
=
_bucket_
->
_next_
) {}
180
}
else
{
181
// find the element we shall point to src the end of the list
182
for
(
_bucket_
=
theList
.
_end_list_
,
ind_elt
=
theList
.
_nb_elements_
-
ind_elt
- 1;
ind_elt
;
183
--
ind_elt
,
_bucket_
=
_bucket_
->
_prev_
) {}
184
}
185
}
186
187
// Destructor
188
template
<
typename
Val
>
189
INLINE
ListConstIterator
<
Val
>::~
ListConstIterator
()
noexcept
{
190
// for debugging purposes
191
GUM_DESTRUCTOR
(
ListConstIterator
);
192
}
193
194
// Copy operator
195
template
<
typename
Val
>
196
INLINE
ListConstIterator
<
Val
>&
197
ListConstIterator
<
Val
>::
operator
=(
const
ListConstIterator
<
Val
>&
src
)
noexcept
{
198
// for debugging purposes
199
GUM_OP_CPY
(
ListConstIterator
);
200
201
_bucket_
=
src
.
_bucket_
;
202
return
*
this
;
203
}
204
205
// move operator
206
template
<
typename
Val
>
207
INLINE
ListConstIterator
<
Val
>&
208
ListConstIterator
<
Val
>::
operator
=(
ListConstIterator
<
Val
>&&
src
)
noexcept
{
209
// for debugging purposes
210
GUM_OP_MOV
(
ListConstIterator
);
211
_bucket_
=
src
.
_bucket_
;
212
return
*
this
;
213
}
214
215
// returns the bucket the iterator is pointing to
216
template
<
typename
Val
>
217
INLINE
ListBucket
<
Val
>*
ListConstIterator
<
Val
>::
_getBucket_
()
const
noexcept
{
218
return
_bucket_
;
219
}
220
221
// Makes the iterator point toward nothing
222
template
<
typename
Val
>
223
INLINE
void
ListConstIterator
<
Val
>::
clear
()
noexcept
{
224
_bucket_
=
nullptr
;
225
}
226
227
// positions the iterator to the end of the list
228
template
<
typename
Val
>
229
INLINE
void
ListConstIterator
<
Val
>::
setToEnd
()
noexcept
{
230
_bucket_
=
nullptr
;
231
}
232
233
// returns a bool indicating whether the iterator points to the end of the
234
// list
235
template
<
typename
Val
>
236
INLINE
bool
ListConstIterator
<
Val
>::
isEnd
()
const
noexcept
{
237
return
(
_bucket_
==
nullptr
);
238
}
239
240
// makes the iterator point to the next element in the List
241
template
<
typename
Val
>
242
INLINE
ListConstIterator
<
Val
>&
ListConstIterator
<
Val
>::
operator
++()
noexcept
{
243
// if we are pointing to an element of the chained list, just
244
// point on the next bucket in this list
245
if
(
_bucket_
!=
nullptr
) {
_bucket_
=
_bucket_
->
_next_
; }
246
247
return
*
this
;
248
}
249
250
// makes the iterator point to the next element in the List
251
template
<
typename
Val
>
252
INLINE
ListConstIterator
<
Val
>&
ListConstIterator
<
Val
>::
operator
+=(
253
typename
ListConstIterator
<
Val
>::
difference_type
i
)
noexcept
{
254
if
(
i
>= 0) {
255
for
(;
i
&& (
_bucket_
!=
nullptr
); --
i
,
_bucket_
=
_bucket_
->
_next_
) {}
256
}
else
{
257
for
(;
i
&& (
_bucket_
!=
nullptr
); ++
i
,
_bucket_
=
_bucket_
->
_prev_
) {}
258
}
259
return
*
this
;
260
}
261
262
// makes the iterator point to the preceding element in the List
263
template
<
typename
Val
>
264
INLINE
ListConstIterator
<
Val
>&
ListConstIterator
<
Val
>::
operator
--()
noexcept
{
265
// if we are pointing to an element of the chained list, just
266
// point on the preceding bucket in this list
267
if
(
_bucket_
!=
nullptr
) {
_bucket_
=
_bucket_
->
_prev_
; }
268
269
return
*
this
;
270
}
271
272
// makes the iterator point to i elements before in the list
273
template
<
typename
Val
>
274
INLINE
ListConstIterator
<
Val
>&
ListConstIterator
<
Val
>::
operator
-=(
275
typename
ListConstIterator
<
Val
>::
difference_type
i
)
noexcept
{
276
if
(
i
>= 0) {
277
for
(;
i
&& (
_bucket_
!=
nullptr
); --
i
,
_bucket_
=
_bucket_
->
_prev_
) {}
278
}
else
{
279
for
(;
i
&& (
_bucket_
!=
nullptr
); ++
i
,
_bucket_
=
_bucket_
->
_next_
) {}
280
}
281
return
*
this
;
282
}
283
284
// returns a new iterator
285
template
<
typename
Val
>
286
INLINE
ListConstIterator
<
Val
>
ListConstIterator
<
Val
>::
operator
+(
287
typename
ListConstIterator
<
Val
>::
difference_type
i
)
noexcept
{
288
return
ListConstIterator
<
Val
>(*
this
) +=
i
;
289
}
290
291
// returns a new iterator
292
template
<
typename
Val
>
293
INLINE
ListConstIterator
<
Val
>
ListConstIterator
<
Val
>::
operator
-(
294
typename
ListConstIterator
<
Val
>::
difference_type
i
)
noexcept
{
295
return
ListConstIterator
<
Val
>(*
this
) -=
i
;
296
}
297
298
// checks whether two iterators point toward different elements
299
template
<
typename
Val
>
300
INLINE
bool
301
ListConstIterator
<
Val
>::
operator
!=(
const
ListConstIterator
<
Val
>&
src
)
const
noexcept
{
302
return
(
_bucket_
!=
src
.
_bucket_
);
303
}
304
305
// checks whether two iterators point toward the same elements.
306
template
<
typename
Val
>
307
INLINE
bool
308
ListConstIterator
<
Val
>::
operator
==(
const
ListConstIterator
<
Val
>&
src
)
const
noexcept
{
309
return
(
_bucket_
==
src
.
_bucket_
);
310
}
311
312
// dereferences the value pointed to by the iterator
313
template
<
typename
Val
>
314
INLINE
const
Val
*
ListConstIterator
<
Val
>::
operator
->()
const
{
315
if
(
_bucket_
!=
nullptr
)
316
return
&(
_bucket_
->
_val_
);
317
else
{
318
GUM_ERROR
(
UndefinedIteratorValue
,
"Accessing a NULL object"
)
319
}
320
}
321
322
// gives access to the content of the iterator
323
template
<
typename
Val
>
324
INLINE
const
Val
&
ListConstIterator
<
Val
>::
operator
*()
const
{
325
if
(
_bucket_
!=
nullptr
)
326
return
_bucket_
->
_val_
;
327
else
{
328
GUM_ERROR
(
UndefinedIteratorValue
,
"Accessing a NULL object"
)
329
}
330
}
331
332
// for STL compliance, a distance operator
333
template
<
typename
Val
>
334
INLINE
typename
ListConstIterator
<
Val
>::
difference_type
335
operator
-(
const
ListConstIterator
<
Val
>&
iter1
,
const
ListConstIterator
<
Val
>&
iter2
) {
336
typename
ListConstIterator
<
Val
>::
difference_type
res
= 0;
337
338
for
(
ListConstIterator
<
Val
>
iter3
=
iter2
;
iter1
!=
iter3
; ++
iter3
, ++
res
) {}
339
340
return
res
;
341
}
342
343
// ===========================================================================
344
// ===========================================================================
345
// === UNSAFE_LIST_ITERATOR IMPLEMENTATION ===
346
// ===========================================================================
347
// ===========================================================================
348
349
// basic constructor
350
template
<
typename
Val
>
351
INLINE
ListIterator
<
Val
>::
ListIterator
()
noexcept
:
ListConstIterator
<
Val
>() {
352
GUM_CONSTRUCTOR
(
ListIterator
);
353
}
354
355
// constructor for a begin
356
template
<
typename
Val
>
357
template
<
typename
Alloc
>
358
INLINE
ListIterator
<
Val
>::
ListIterator
(
const
List
<
Val
,
Alloc
>&
theList
)
noexcept
:
359
ListConstIterator
<
Val
>(
theList
) {
360
GUM_CONSTRUCTOR
(
ListIterator
);
361
}
362
363
// copy constructor
364
template
<
typename
Val
>
365
INLINE
ListIterator
<
Val
>::
ListIterator
(
const
ListIterator
<
Val
>&
src
)
noexcept
:
366
ListConstIterator
<
Val
>(
src
) {
367
GUM_CONS_CPY
(
ListIterator
);
368
}
369
370
// move constructor
371
template
<
typename
Val
>
372
INLINE
ListIterator
<
Val
>::
ListIterator
(
ListIterator
<
Val
>&&
src
)
noexcept
:
373
ListConstIterator
<
Val
>(
std
::
move
(
src
)) {
374
GUM_CONS_MOV
(
ListIterator
);
375
}
376
377
// Constructor for an iterator pointing to the \e ind_eltth element of a
378
// List.
379
template
<
typename
Val
>
380
INLINE
ListIterator
<
Val
>::
ListIterator
(
const
List
<
Val
>&
theList
,
Size
ind_elt
) :
381
ListConstIterator
<
Val
>(
theList
,
ind_elt
) {
382
GUM_CONSTRUCTOR
(
ListIterator
);
383
}
384
385
// Copy operator
386
template
<
typename
Val
>
387
INLINE
ListIterator
<
Val
>&
388
ListIterator
<
Val
>::
operator
=(
const
ListIterator
<
Val
>&
src
)
noexcept
{
389
GUM_OP_CPY
(
ListIterator
);
390
ListConstIterator
<
Val
>::
operator
=(
src
);
391
return
*
this
;
392
}
393
394
// move operator
395
template
<
typename
Val
>
396
INLINE
ListIterator
<
Val
>&
ListIterator
<
Val
>::
operator
=(
ListIterator
<
Val
>&&
src
)
noexcept
{
397
GUM_OP_MOV
(
ListIterator
);
398
ListConstIterator
<
Val
>::
operator
=(
std
::
move
(
src
));
399
return
*
this
;
400
}
401
402
// Destructor
403
template
<
typename
Val
>
404
INLINE
ListIterator
<
Val
>::~
ListIterator
()
noexcept
{
405
GUM_DESTRUCTOR
(
ListIterator
);
406
}
407
408
// makes the iterator point to the next element in the List
409
template
<
typename
Val
>
410
INLINE
ListIterator
<
Val
>&
ListIterator
<
Val
>::
operator
++()
noexcept
{
411
ListConstIterator
<
Val
>::
operator
++();
412
return
*
this
;
413
}
414
415
// makes the iterator point to i elements further in the List
416
template
<
typename
Val
>
417
INLINE
ListIterator
<
Val
>&
418
ListIterator
<
Val
>::
operator
+=(
typename
ListIterator
<
Val
>::
difference_type
i
)
noexcept
{
419
ListConstIterator
<
Val
>::
operator
+=(
i
);
420
return
*
this
;
421
}
422
423
// makes the iterator point to the preceding element in the List
424
template
<
typename
Val
>
425
INLINE
ListIterator
<
Val
>&
ListIterator
<
Val
>::
operator
--()
noexcept
{
426
ListConstIterator
<
Val
>::
operator
--();
427
return
*
this
;
428
}
429
430
// makes the iterator point to i elements before in the List
431
template
<
typename
Val
>
432
INLINE
ListIterator
<
Val
>&
433
ListIterator
<
Val
>::
operator
-=(
typename
ListIterator
<
Val
>::
difference_type
i
)
noexcept
{
434
ListConstIterator
<
Val
>::
operator
-=(
i
);
435
return
*
this
;
436
}
437
438
// returns a new iterator
439
template
<
typename
Val
>
440
INLINE
ListIterator
<
Val
>
441
ListIterator
<
Val
>::
operator
+(
typename
ListIterator
<
Val
>::
difference_type
i
)
noexcept
{
442
return
ListIterator
<
Val
>(*
this
) +=
i
;
443
}
444
445
// returns a new iterator
446
template
<
typename
Val
>
447
INLINE
ListIterator
<
Val
>
448
ListIterator
<
Val
>::
operator
-(
typename
ListIterator
<
Val
>::
difference_type
i
)
noexcept
{
449
return
ListIterator
<
Val
>(*
this
) -=
i
;
450
}
451
452
// dereferences the value pointed to by the iterator
453
template
<
typename
Val
>
454
INLINE
Val
*
ListIterator
<
Val
>::
operator
->() {
455
return
const_cast
<
Val
* >(
ListConstIterator
<
Val
>::
operator
->());
456
}
457
458
// gives access to the content of the iterator
459
template
<
typename
Val
>
460
INLINE
Val
&
ListIterator
<
Val
>::
operator
*() {
461
return
const_cast
<
Val
& >(
ListConstIterator
<
Val
>::
operator
*());
462
}
463
464
// ===========================================================================
465
// ===========================================================================
466
// === SAFE LIST CONST ITERATOR IMPLEMENTATION ===
467
// ===========================================================================
468
// ===========================================================================
469
470
// basic constructor
471
template
<
typename
Val
>
472
INLINE
ListConstIteratorSafe
<
Val
>::
ListConstIteratorSafe
()
noexcept
{
473
// for debugging purposes
474
GUM_CONSTRUCTOR
(
ListConstIteratorSafe
);
475
}
476
477
// Constructor for a begin
478
template
<
typename
Val
>
479
template
<
typename
Alloc
>
480
INLINE
ListConstIteratorSafe
<
Val
>::
ListConstIteratorSafe
(
const
List
<
Val
,
Alloc
>&
theList
) :
481
_list_
{
reinterpret_cast
<
const
List
<
Val
,
std
::
allocator
<
Val
> >* >(&
theList
)},
482
_bucket_
{
theList
.
_deb_list_
} {
483
// for debugging purposes
484
GUM_CONSTRUCTOR
(
ListConstIteratorSafe
);
485
486
// add the iterator to the list of safe iterators
487
theList
.
_safe_iterators_
.
push_back
(
this
);
488
}
489
490
// copy constructor
491
template
<
typename
Val
>
492
INLINE
493
ListConstIteratorSafe
<
Val
>::
ListConstIteratorSafe
(
const
ListConstIteratorSafe
<
Val
>&
src
) :
494
_list_
{
src
.
_list_
},
495
_bucket_
{
src
.
_bucket_
},
_next_current_bucket_
{
src
.
_next_current_bucket_
},
496
_prev_current_bucket_
{
src
.
_prev_current_bucket_
},
_null_pointing_
{
src
.
_null_pointing_
} {
497
// for debugging purposes
498
GUM_CONS_CPY
(
ListConstIteratorSafe
);
499
500
// add the iterator to the list of safe iterators
501
if
(
_list_
!=
nullptr
)
_list_
->
_safe_iterators_
.
push_back
(
this
);
502
}
503
504
// Constructor for an iterator pointing to the \e ind_eltth element of a
505
// List.
506
template
<
typename
Val
>
507
template
<
typename
Alloc
>
508
ListConstIteratorSafe
<
Val
>::
ListConstIteratorSafe
(
const
List
<
Val
,
Alloc
>&
theList
,
509
Size
ind_elt
) :
510
_list_
{
reinterpret_cast
<
const
List
<
Val
,
std
::
allocator
<
Val
> >* >(&
theList
)} {
511
// for debugging purposes
512
GUM_CONSTRUCTOR
(
ListConstIteratorSafe
);
513
514
// check if the index ind_elt passed as parameter is valid
515
if
(
ind_elt
>=
_list_
->
_nb_elements_
) {
516
GUM_ERROR
(
UndefinedIteratorValue
,
"Not enough elements in the list"
)
517
}
518
519
// check if it is faster to find the indexth element src the start or
520
// src the end of the list
521
if
(
ind_elt
< (
_list_
->
_nb_elements_
>> 1)) {
522
// find the element we shall point to src the start of the list
523
for
(
_bucket_
=
_list_
->
_deb_list_
;
ind_elt
; --
ind_elt
,
_bucket_
=
_bucket_
->
_next_
) {}
524
}
else
{
525
// find the element we shall point to src the end of the list
526
for
(
_bucket_
=
_list_
->
_end_list_
,
ind_elt
=
_list_
->
_nb_elements_
-
ind_elt
- 1;
ind_elt
;
527
--
ind_elt
,
_bucket_
=
_bucket_
->
_prev_
) {}
528
}
529
530
// add the iterator to the list of safe iterators
531
theList
.
_safe_iterators_
.
push_back
(
this
);
532
}
533
534
// move constructor
535
template
<
typename
Val
>
536
INLINE
ListConstIteratorSafe
<
Val
>::
ListConstIteratorSafe
(
ListConstIteratorSafe
<
Val
>&&
src
) :
537
_list_
{
src
.
_list_
},
_bucket_
{
src
.
_bucket_
},
_next_current_bucket_
{
src
.
_next_current_bucket_
},
538
_prev_current_bucket_
{
src
.
_prev_current_bucket_
},
_null_pointing_
{
src
.
_null_pointing_
} {
539
// for debugging purposes
540
GUM_CONS_MOV
(
ListConstIteratorSafe
);
541
542
if
(
_list_
!=
nullptr
) {
543
// substitute src by this in the list of safe iterators
544
std
::
vector
<
ListConstIteratorSafe
<
Val
>* >&
vect
=
_list_
->
_safe_iterators_
;
545
546
for
(
auto
ptr
=
vect
.
rbegin
();
ptr
!=
vect
.
rend
(); --
ptr
) {
547
if
(*
ptr
== &
src
) {
548
*
ptr
=
this
;
549
break
;
550
}
551
}
552
553
src
.
_list_
=
nullptr
;
554
src
.
_bucket_
=
nullptr
;
555
src
.
_null_pointing_
=
false
;
556
}
557
}
558
559
// remove the iterator for its list' safe iterators list
560
template
<
typename
Val
>
561
INLINE
void
ListConstIteratorSafe
<
Val
>::
_removeFromSafeList_
()
const
{
562
// find where the iterator is
563
std
::
vector
<
ListConstIteratorSafe
<
Val
>* >&
vect
=
_list_
->
_safe_iterators_
;
564
565
for
(
auto
i
=
vect
.
size
() - 1;
i
>= 0; --
i
) {
566
if
(
vect
[
i
] ==
this
) {
567
vect
.
erase
(
vect
.
begin
() +
i
);
568
break
;
569
}
570
}
571
}
572
573
// Copy operator
574
template
<
typename
Val
>
575
ListConstIteratorSafe
<
Val
>&
576
ListConstIteratorSafe
<
Val
>::
operator
=(
const
ListConstIteratorSafe
<
Val
>&
src
) {
577
// avoid self assignment
578
if
(
this
!= &
src
) {
579
// for debugging purposes
580
GUM_OP_CPY
(
ListConstIteratorSafe
);
581
582
// check if src and this belong to the same list. If this is not
583
// the case, we shall remove this from its iterator's list and
584
// put it into src's list one.
585
if
(
_list_
&& (
src
.
_list_
!=
_list_
)) {
586
_removeFromSafeList_
();
587
_list_
=
nullptr
;
588
}
589
590
// if necessary, put this into the same list of safe iterators as src
591
if
(
src
.
_list_
&& (
src
.
_list_
!=
_list_
)) {
592
try
{
593
src
.
_list_
->
_safe_iterators_
.
push_back
(
this
);
594
}
catch
(...) {
595
_list_
=
nullptr
;
596
_bucket_
=
nullptr
;
597
_null_pointing_
=
false
;
598
throw
;
599
}
600
}
601
602
_list_
=
src
.
_list_
;
603
_bucket_
=
src
.
_bucket_
;
604
_prev_current_bucket_
=
src
.
_prev_current_bucket_
;
605
_next_current_bucket_
=
src
.
_next_current_bucket_
;
606
_null_pointing_
=
src
.
_null_pointing_
;
607
}
608
609
return
*
this
;
610
}
611
612
// move operator
613
template
<
typename
Val
>
614
ListConstIteratorSafe
<
Val
>&
615
ListConstIteratorSafe
<
Val
>::
operator
=(
ListConstIteratorSafe
<
Val
>&&
src
) {
616
// avoid self assignment
617
if
(
this
!= &
src
) {
618
// for debugging purposes
619
GUM_OP_MOV
(
ListConstIteratorSafe
);
620
621
// if the two iterators do not point to the same list, remove
622
// the current iterator from its safe iterators list
623
if
((
_list_
!=
nullptr
) && (
src
.
_list_
!=
_list_
)) {
624
_removeFromSafeList_
();
625
_list_
=
nullptr
;
626
}
627
628
// now if src points to a list, put this at its location
629
if
((
src
.
_list_
!=
nullptr
)) {
630
std
::
vector
<
ListConstIteratorSafe
<
Val
>* >&
vect
=
src
.
_list_
->
_safe_iterators_
;
631
Idx
index_src
=
Size
(
vect
.
size
()) - 1;
632
633
for
(;; --
index_src
) {
634
if
(
vect
[
index_src
] == &
src
) {
break
; }
635
}
636
637
if
(
_list_
==
nullptr
) {
638
vect
[
index_src
] =
this
;
639
}
else
{
640
vect
.
erase
(
vect
.
begin
() +
index_src
);
641
}
642
}
643
644
_list_
=
src
.
_list_
;
645
_bucket_
=
src
.
_bucket_
;
646
_prev_current_bucket_
=
src
.
_prev_current_bucket_
;
647
_next_current_bucket_
=
src
.
_next_current_bucket_
;
648
_null_pointing_
=
src
.
_null_pointing_
;
649
650
src
.
_list_
=
nullptr
;
651
src
.
_bucket_
=
nullptr
;
652
src
.
_null_pointing_
=
false
;
653
}
654
655
return
*
this
;
656
}
657
658
// Destructor
659
template
<
typename
Val
>
660
INLINE
ListConstIteratorSafe
<
Val
>::~
ListConstIteratorSafe
() {
661
// for debugging purposes
662
GUM_DESTRUCTOR
(
ListConstIteratorSafe
);
663
664
// remove the iterator src the table's iterator list
665
if
(
_list_
)
_removeFromSafeList_
();
666
}
667
668
// returns the bucket the iterator is pointing to
669
template
<
typename
Val
>
670
INLINE
ListBucket
<
Val
>*
ListConstIteratorSafe
<
Val
>::
_getBucket_
()
const
noexcept
{
671
return
_bucket_
;
672
}
673
674
// Makes the iterator point toward nothing
675
template
<
typename
Val
>
676
INLINE
void
ListConstIteratorSafe
<
Val
>::
clear
() {
677
// remove the iterator src the list's iterator list
678
if
(
_list_
)
_removeFromSafeList_
();
679
680
// set its list as well as the element it points to to nullptr
681
_list_
=
nullptr
;
682
_bucket_
=
nullptr
;
683
_null_pointing_
=
false
;
684
}
685
686
// positions the iterator to the end of the list
687
template
<
typename
Val
>
688
INLINE
void
ListConstIteratorSafe
<
Val
>::
setToEnd
() {
689
clear
();
690
}
691
692
// returns a bool indicating whether the iterator points to the end of the
693
// list
694
template
<
typename
Val
>
695
INLINE
bool
ListConstIteratorSafe
<
Val
>::
isEnd
()
const
{
696
return
_null_pointing_
697
? (
_next_current_bucket_
==
nullptr
) && (
_prev_current_bucket_
==
nullptr
)
698
: (
_bucket_
==
nullptr
);
699
}
700
701
// makes the iterator point to the next element in the List
702
template
<
typename
Val
>
703
INLINE
ListConstIteratorSafe
<
Val
>&
ListConstIteratorSafe
<
Val
>::
operator
++()
noexcept
{
704
// check if we are pointing to something that has been deleted
705
if
(
_null_pointing_
) {
706
_null_pointing_
=
false
;
707
708
// if we are pointing to an element of the chained list that has been
709
// deleted
710
// but that has a next element, just point on the latter
711
if
(
_next_current_bucket_
!=
nullptr
) {
712
_bucket_
=
_next_current_bucket_
->
_next_
;
713
return
*
this
;
714
}
715
716
// here we were pointing on an extremity of the list (either end or rend)
717
// if prev_current_bucket is not null, then we are at rend and doing
718
// a ++ shall now point to the beginning of the list
719
if
(
_prev_current_bucket_
!=
nullptr
) {
720
_bucket_
=
_prev_current_bucket_
;
721
return
*
this
;
722
}
723
724
// here, we are at the end of the chained list, hence we shall remain at
725
// end
726
_bucket_
=
nullptr
;
727
return
*
this
;
728
}
else
{
729
// if we are pointing to an element of the chained list, just
730
// point on the next bucket in this list
731
if
(
_bucket_
!=
nullptr
) {
_bucket_
=
_bucket_
->
_next_
; }
732
733
return
*
this
;
734
}
735
}
736
737
// makes the iterator point to i elements before in the List
738
template
<
typename
Val
>
739
INLINE
ListConstIteratorSafe
<
Val
>&
ListConstIteratorSafe
<
Val
>::
_opMinus_
(
Size
i
)
noexcept
{
740
// check if we are pointing to something that has been deleted
741
if
(
_null_pointing_
) {
742
_null_pointing_
=
false
;
743
744
// if we are pointing to an element of the chained list that has been
745
// deleted
746
// but that has a preceding element, just point on the latter
747
if
(
_prev_current_bucket_
!=
nullptr
) {
748
_bucket_
=
_prev_current_bucket_
->
_prev_
;
749
}
else
{
750
// here we were pointing on an extremity of the list (either end or
751
// rend)
752
// if next_current_bucket is not null, then we are at end and doing
753
// a -- shall now point to the beginning of the list
754
if
(
_next_current_bucket_
!=
nullptr
) {
755
_bucket_
=
_next_current_bucket_
;
756
}
else
{
757
// here, we are at the rend of the chained list, hence we shall remain
758
// at rend
759
_bucket_
=
nullptr
;
760
return
*
this
;
761
}
762
}
763
}
else
{
764
// if we are pointing to an element of the chained list, just
765
// point on the preceding bucket in this list
766
if
(
_bucket_
!=
nullptr
) {
_bucket_
=
_bucket_
->
_prev_
; }
767
}
768
769
for
(--
i
;
i
&& (
_bucket_
!=
nullptr
); --
i
,
_bucket_
=
_bucket_
->
_prev_
) {}
770
771
return
*
this
;
772
}
773
774
// makes the iterator point to the next element in the List
775
template
<
typename
Val
>
776
INLINE
ListConstIteratorSafe
<
Val
>&
ListConstIteratorSafe
<
Val
>::
_opPlus_
(
Size
i
)
noexcept
{
777
// check if we are pointing to something that has been deleted
778
if
(
_null_pointing_
) {
779
_null_pointing_
=
false
;
780
781
// if we are pointing to an element of the chained list that has been
782
// deleted
783
// but that has a next element, just point on the latter
784
if
(
_next_current_bucket_
!=
nullptr
) {
785
_bucket_
=
_next_current_bucket_
->
_next_
;
786
}
else
{
787
// here we were pointing on an extremity of the list (either end or
788
// rend)
789
// if prev_current_bucket is not null, then we are at rend and doing
790
// a ++ shall now point to the beginning of the list
791
if
(
_prev_current_bucket_
!=
nullptr
) {
792
_bucket_
=
_prev_current_bucket_
;
793
}
else
{
794
// here, we are at the end of the chained list, hence we shall
795
// remain at end
796
_bucket_
=
nullptr
;
797
return
*
this
;
798
}
799
}
800
}
else
{
801
// if we are pointing to an element of the chained list, just
802
// point on the next bucket in this list
803
if
(
_bucket_
!=
nullptr
) {
_bucket_
=
_bucket_
->
_next_
; }
804
}
805
806
for
(--
i
;
i
&& (
_bucket_
!=
nullptr
); --
i
,
_bucket_
=
_bucket_
->
_next_
) {}
807
808
return
*
this
;
809
}
810
811
// makes the iterator point to the next element in the List
812
template
<
typename
Val
>
813
INLINE
ListConstIteratorSafe
<
Val
>&
ListConstIteratorSafe
<
Val
>::
operator
+=(
814
typename
ListConstIteratorSafe
<
Val
>::
difference_type
i
)
noexcept
{
815
if
(!
i
)
return
*
this
;
816
817
if
(
i
< 0)
818
return
_opMinus_
(-
i
);
819
else
820
return
_opPlus_
(
i
);
821
}
822
823
// makes the iterator point to the preceding element in the List
824
template
<
typename
Val
>
825
INLINE
ListConstIteratorSafe
<
Val
>&
ListConstIteratorSafe
<
Val
>::
operator
--()
noexcept
{
826
// check if we are pointing to something that has been deleted
827
if
(
_null_pointing_
) {
828
_null_pointing_
=
false
;
829
830
// if we are pointing to an element of the chained list that has been
831
// deleted
832
// but that has a preceding element, just point on the latter
833
if
(
_prev_current_bucket_
!=
nullptr
) {
834
_bucket_
=
_prev_current_bucket_
->
_prev_
;
835
return
*
this
;
836
}
837
838
// here we were pointing on an extremity of the list (either end or rend)
839
// if next_current_bucket is not null, then we are at end and doing
840
// a -- shall now point to the beginning of the list
841
if
(
_next_current_bucket_
!=
nullptr
) {
842
_bucket_
=
_next_current_bucket_
;
843
return
*
this
;
844
}
845
846
// here, we are at the rend of the chained list, hence we shall remain
847
// at rend
848
_bucket_
=
nullptr
;
849
return
*
this
;
850
}
else
{
851
// if we are pointing to an element of the chained list, just
852
// point on the preceding bucket in this list
853
if
(
_bucket_
!=
nullptr
) {
_bucket_
=
_bucket_
->
_prev_
; }
854
855
return
*
this
;
856
}
857
}
858
859
// makes the iterator point to i elements before in the List
860
template
<
typename
Val
>
861
INLINE
ListConstIteratorSafe
<
Val
>&
ListConstIteratorSafe
<
Val
>::
operator
-=(
862
typename
ListConstIteratorSafe
<
Val
>::
difference_type
i
)
noexcept
{
863
if
(!
i
)
return
*
this
;
864
865
if
(
i
< 0)
866
return
_opPlus_
(-
i
);
867
else
868
return
_opMinus_
(
i
);
869
}
870
871
// returns a new iterator
872
template
<
typename
Val
>
873
INLINE
ListConstIteratorSafe
<
Val
>
ListConstIteratorSafe
<
Val
>::
operator
+(
874
typename
ListConstIteratorSafe
<
Val
>::
difference_type
i
)
noexcept
{
875
return
ListConstIteratorSafe
<
Val
>(*
this
) +=
i
;
876
}
877
878
// returns a new iterator
879
template
<
typename
Val
>
880
INLINE
ListConstIteratorSafe
<
Val
>
ListConstIteratorSafe
<
Val
>::
operator
-(
881
typename
ListConstIteratorSafe
<
Val
>::
difference_type
i
)
noexcept
{
882
return
ListConstIteratorSafe
<
Val
>(*
this
) -=
i
;
883
}
884
885
// checks whether two iterators point toward different elements
886
template
<
typename
Val
>
887
INLINE
bool
888
ListConstIteratorSafe
<
Val
>::
operator
!=(
const
ListConstIteratorSafe
<
Val
>&
src
)
const
{
889
return
_null_pointing_
? (
_next_current_bucket_
!=
src
.
_next_current_bucket_
)
890
|| (
_prev_current_bucket_
!=
src
.
_prev_current_bucket_
)
891
: (
_bucket_
!=
src
.
_bucket_
);
892
}
893
894
// checks whether two iterators point toward the same elements.
895
template
<
typename
Val
>
896
INLINE
bool
897
ListConstIteratorSafe
<
Val
>::
operator
==(
const
ListConstIteratorSafe
<
Val
>&
src
)
const
{
898
return
_null_pointing_
? (
_next_current_bucket_
==
src
.
_next_current_bucket_
)
899
&& (
_prev_current_bucket_
==
src
.
_prev_current_bucket_
)
900
: (
_bucket_
==
src
.
_bucket_
);
901
}
902
903
// dereferences the value pointed to by the iterator
904
template
<
typename
Val
>
905
INLINE
const
Val
*
ListConstIteratorSafe
<
Val
>::
operator
->()
const
{
906
if
(
_bucket_
!=
nullptr
)
907
return
&(
_bucket_
->
_val_
);
908
else
{
909
GUM_ERROR
(
UndefinedIteratorValue
,
"Accessing a NULL object"
)
910
}
911
}
912
913
// gives access to the content of the iterator
914
template
<
typename
Val
>
915
INLINE
const
Val
&
ListConstIteratorSafe
<
Val
>::
operator
*()
const
{
916
if
(
_bucket_
!=
nullptr
)
917
return
_bucket_
->
_val_
;
918
else
{
919
GUM_ERROR
(
UndefinedIteratorValue
,
"Accessing a NULL object"
)
920
}
921
}
922
923
// for STL compliance, a distance operator
924
template
<
typename
Val
>
925
INLINE
typename
ListConstIteratorSafe
<
Val
>::
difference_type
926
operator
-(
const
ListConstIteratorSafe
<
Val
>&
iter1
,
927
const
ListConstIteratorSafe
<
Val
>&
iter2
) {
928
typename
ListConstIteratorSafe
<
Val
>::
difference_type
res
= 0;
929
ListConstIteratorSafe
<
Val
>
iter3
{
iter2
};
930
931
for
(;
iter1
!=
iter3
; ++
iter3
, ++
res
) {}
932
933
return
res
;
934
}
935
936
// ===========================================================================
937
// ===========================================================================
938
// === LIST ITERATOR IMPLEMENTATION ===
939
// ===========================================================================
940
// ===========================================================================
941
942
// basic constructor
943
template
<
typename
Val
>
944
INLINE
ListIteratorSafe
<
Val
>::
ListIteratorSafe
()
noexcept
:
ListConstIteratorSafe
<
Val
>() {
945
GUM_CONSTRUCTOR
(
ListIteratorSafe
);
946
}
947
948
// constructor for a begin
949
template
<
typename
Val
>
950
template
<
typename
Alloc
>
951
INLINE
ListIteratorSafe
<
Val
>::
ListIteratorSafe
(
const
List
<
Val
,
Alloc
>&
theList
) :
952
ListConstIteratorSafe
<
Val
>(
theList
) {
953
GUM_CONSTRUCTOR
(
ListIteratorSafe
);
954
}
955
956
// copy constructor
957
template
<
typename
Val
>
958
INLINE
ListIteratorSafe
<
Val
>::
ListIteratorSafe
(
const
ListIteratorSafe
<
Val
>&
src
) :
959
ListConstIteratorSafe
<
Val
>(
src
) {
960
GUM_CONS_CPY
(
ListIteratorSafe
);
961
}
962
963
// Constructor for an iterator pointing to the \e ind_eltth element of a
964
// List.
965
template
<
typename
Val
>
966
template
<
typename
Alloc
>
967
INLINE
ListIteratorSafe
<
Val
>::
ListIteratorSafe
(
const
List
<
Val
,
Alloc
>&
theList
,
968
Size
ind_elt
) :
969
ListConstIteratorSafe
<
Val
>(
theList
,
ind_elt
) {
970
GUM_CONSTRUCTOR
(
ListIteratorSafe
);
971
}
972
973
// move constructor
974
template
<
typename
Val
>
975
INLINE
ListIteratorSafe
<
Val
>::
ListIteratorSafe
(
ListIteratorSafe
<
Val
>&&
src
) :
976
ListConstIteratorSafe
<
Val
>(
std
::
move
(
src
)) {
977
GUM_CONS_MOV
(
ListIteratorSafe
);
978
}
979
980
// Copy operator
981
template
<
typename
Val
>
982
INLINE
ListIteratorSafe
<
Val
>&
983
ListIteratorSafe
<
Val
>::
operator
=(
const
ListIteratorSafe
<
Val
>&
src
) {
984
// for debugging purposes
985
GUM_OP_CPY
(
ListIteratorSafe
);
986
ListConstIteratorSafe
<
Val
>::
operator
=(
src
);
987
return
*
this
;
988
}
989
990
// move operator
991
template
<
typename
Val
>
992
INLINE
ListIteratorSafe
<
Val
>&
993
ListIteratorSafe
<
Val
>::
operator
=(
ListIteratorSafe
<
Val
>&&
src
) {
994
// for debugging purposes
995
GUM_OP_MOV
(
ListIteratorSafe
);
996
ListConstIteratorSafe
<
Val
>::
operator
=(
std
::
move
(
src
));
997
return
*
this
;
998
}
999
1000
// Destructor
1001
template
<
typename
Val
>
1002
INLINE
ListIteratorSafe
<
Val
>::~
ListIteratorSafe
() {
1003
GUM_DESTRUCTOR
(
ListIteratorSafe
);
1004
}
1005
1006
// makes the iterator point to the next element in the List
1007
template
<
typename
Val
>
1008
INLINE
ListIteratorSafe
<
Val
>&
ListIteratorSafe
<
Val
>::
operator
++()
noexcept
{
1009
ListConstIteratorSafe
<
Val
>::
operator
++();
1010
return
*
this
;
1011
}
1012
1013
// makes the iterator point to the next element in the List
1014
template
<
typename
Val
>
1015
INLINE
ListIteratorSafe
<
Val
>&
ListIteratorSafe
<
Val
>::
operator
+=(
1016
typename
ListIteratorSafe
<
Val
>::
difference_type
i
)
noexcept
{
1017
ListConstIteratorSafe
<
Val
>::
operator
+=(
i
);
1018
return
*
this
;
1019
}
1020
1021
// makes the iterator point to the preceding element in the List
1022
template
<
typename
Val
>
1023
INLINE
ListIteratorSafe
<
Val
>&
ListIteratorSafe
<
Val
>::
operator
--()
noexcept
{
1024
ListConstIteratorSafe
<
Val
>::
operator
--();
1025
return
*
this
;
1026
}
1027
1028
// makes the iterator point to the preceding element in the List
1029
template
<
typename
Val
>
1030
INLINE
ListIteratorSafe
<
Val
>&
ListIteratorSafe
<
Val
>::
operator
-=(
1031
typename
ListIteratorSafe
<
Val
>::
difference_type
i
)
noexcept
{
1032
ListConstIteratorSafe
<
Val
>::
operator
-=(
i
);
1033
return
*
this
;
1034
}
1035
1036
// returns a new iterator
1037
template
<
typename
Val
>
1038
INLINE
ListIteratorSafe
<
Val
>
ListIteratorSafe
<
Val
>::
operator
+(
1039
typename
ListIteratorSafe
<
Val
>::
difference_type
i
)
noexcept
{
1040
return
ListIteratorSafe
<
Val
>(*
this
) +=
i
;
1041
}
1042
1043
// returns a new iterator
1044
template
<
typename
Val
>
1045
INLINE
ListIteratorSafe
<
Val
>
ListIteratorSafe
<
Val
>::
operator
-(
1046
typename
ListIteratorSafe
<
Val
>::
difference_type
i
)
noexcept
{
1047
return
ListIteratorSafe
<
Val
>(*
this
) -=
i
;
1048
}
1049
1050
// dereferences the value pointed to by the iterator
1051
template
<
typename
Val
>
1052
INLINE
Val
*
ListIteratorSafe
<
Val
>::
operator
->() {
1053
return
const_cast
<
Val
* >(
ListConstIteratorSafe
<
Val
>::
operator
->());
1054
}
1055
1056
// gives access to the content of the iterator
1057
template
<
typename
Val
>
1058
INLINE
Val
&
ListIteratorSafe
<
Val
>::
operator
*() {
1059
return
const_cast
<
Val
& >(
ListConstIteratorSafe
<
Val
>::
operator
*());
1060
}
1061
1062
// ===========================================================================
1063
// ===========================================================================
1064
// === LIST IMPLEMENTATION ===
1065
// ===========================================================================
1066
// ===========================================================================
1067
1068
// a function used to perform copies of elements of Lists
1069
template
<
typename
Val
,
typename
Alloc
>
1070
template
<
typename
OtherAlloc
>
1071
void
List
<
Val
,
Alloc
>::
_copy_elements_
(
const
List
<
Val
,
OtherAlloc
>&
src
) {
1072
ListBucket
<
Val
>*
ptr
;
1073
ListBucket
<
Val
>*
old_ptr
=
nullptr
;
1074
ListBucket
<
Val
>*
new_elt
=
nullptr
;
1075
1076
// copy src's list
1077
try
{
1078
for
(
ptr
=
src
.
_deb_list_
;
ptr
!=
nullptr
;
ptr
=
ptr
->
_next_
) {
1079
// create a copy bucket
1080
new_elt
=
_alloc_bucket_
.
allocate
(1);
1081
1082
try
{
1083
_alloc_bucket_
.
construct
(
new_elt
, *
ptr
);
1084
}
catch
(...) {
1085
_alloc_bucket_
.
deallocate
(
new_elt
, 1);
1086
throw
;
1087
}
1088
1089
// rechain properly the new list (the next field is already initialized
1090
// with nullptr)
1091
new_elt
->
_prev_
=
old_ptr
;
1092
1093
if
(
old_ptr
)
1094
old_ptr
->
_next_
=
new_elt
;
1095
else
1096
_deb_list_
=
new_elt
;
1097
1098
old_ptr
=
new_elt
;
1099
}
1100
}
catch
(...) {
1101
// problem: we could not allocate an element in the list => we delete
1102
// the elements created so far and we throw an exception
1103
for
(;
_deb_list_
!=
nullptr
;
_deb_list_
=
const_cast
<
ListBucket
<
Val
>* >(
ptr
)) {
1104
ptr
=
_deb_list_
->
_next_
;
1105
_alloc_bucket_
.
destroy
(
_deb_list_
);
1106
_alloc_bucket_
.
deallocate
(
_deb_list_
, 1);
1107
}
1108
1109
_deb_list_
=
nullptr
;
1110
throw
;
1111
}
1112
1113
// update properly the end of the chained list and the number of elements
1114
_end_list_
=
old_ptr
;
1115
_nb_elements_
=
src
.
_nb_elements_
;
1116
}
1117
1118
// deletes all the elements of a chained list.
1119
template
<
typename
Val
,
typename
Alloc
>
1120
void
List
<
Val
,
Alloc
>::
clear
() {
1121
// first we update all the safe iterators of the list : they should now
1122
// point to end/rend
1123
for
(
const
auto
ptr_iter
:
_safe_iterators_
) {
1124
ptr_iter
->
clear
();
1125
}
1126
1127
// clear all the values
1128
for
(
ListBucket
<
Val
>*
ptr
=
_deb_list_
, *
next_ptr
=
nullptr
;
ptr
!=
nullptr
;
ptr
=
next_ptr
) {
1129
next_ptr
=
ptr
->
_next_
;
1130
_alloc_bucket_
.
destroy
(
ptr
);
1131
_alloc_bucket_
.
deallocate
(
ptr
, 1);
1132
}
1133
1134
_nb_elements_
= 0;
1135
_deb_list_
=
nullptr
;
1136
_end_list_
=
nullptr
;
1137
}
1138
1139
// A basic constructor that creates an empty list
1140
template
<
typename
Val
,
typename
Alloc
>
1141
INLINE
List
<
Val
,
Alloc
>::
List
() {
1142
// for debugging purposes
1143
GUM_CONSTRUCTOR
(
List
);
1144
1145
// reserve space for only the default number of iterators
1146
_safe_iterators_
.
reserve
(
GUM_DEFAULT_ITERATOR_NUMBER
);
1147
}
1148
1149
// Copy constructor
1150
template
<
typename
Val
,
typename
Alloc
>
1151
INLINE
List
<
Val
,
Alloc
>::
List
(
const
List
<
Val
,
Alloc
>&
src
) {
1152
// for debugging purposes
1153
GUM_CONS_CPY
(
List
);
1154
1155
// copy the elements
1156
_copy_elements_
(
src
);
1157
1158
// reserve space for only the default number of iterators
1159
_safe_iterators_
.
reserve
(
GUM_DEFAULT_ITERATOR_NUMBER
);
1160
}
1161
1162
// generalized copy constructor
1163
template
<
typename
Val
,
typename
Alloc
>
1164
template
<
typename
OtherAlloc
>
1165
INLINE
List
<
Val
,
Alloc
>::
List
(
const
List
<
Val
,
OtherAlloc
>&
src
) {
1166
// for debugging purposes
1167
GUM_CONS_CPY
(
List
);
1168
1169
// copy the elements
1170
_copy_elements_
(
src
);
1171
1172
// reserve space for only the default number of iterators
1173
_safe_iterators_
.
reserve
(
GUM_DEFAULT_ITERATOR_NUMBER
);
1174
}
1175
1176
// move constructor
1177
template
<
typename
Val
,
typename
Alloc
>
1178
INLINE
List
<
Val
,
Alloc
>::
List
(
List
<
Val
,
Alloc
>&&
src
) :
1179
_deb_list_
{
std
::
move
(
src
.
_deb_list_
)},
_end_list_
{
std
::
move
(
src
.
_end_list_
)},
1180
_nb_elements_
{
std
::
move
(
src
.
_nb_elements_
)},
1181
_safe_iterators_
{
std
::
move
(
src
.
_safe_iterators_
)},
_alloc_bucket_
{
1182
std
::
move
(
src
.
_alloc_bucket_
)} {
1183
// for debugging purposes
1184
GUM_CONS_MOV
(
List
);
1185
1186
src
.
_deb_list_
=
nullptr
;
1187
src
.
_end_list_
=
nullptr
;
1188
src
.
_nb_elements_
= 0;
1189
src
.
_safe_iterators_
.
clear
();
1190
}
1191
1192
// initializer_list constructor
1193
template
<
typename
Val
,
typename
Alloc
>
1194
INLINE
List
<
Val
,
Alloc
>::
List
(
std
::
initializer_list
<
Val
>
list
) {
1195
// for debugging purposes
1196
GUM_CONSTRUCTOR
(
List
);
1197
1198
// adding all the elements
1199
for
(
const
auto
&
val
:
list
) {
1200
pushBack
(
val
);
1201
}
1202
1203
// reserve space for only the default number of iterators
1204
_safe_iterators_
.
reserve
(
GUM_DEFAULT_ITERATOR_NUMBER
);
1205
}
1206
1207
// Destructor
1208
template
<
typename
Val
,
typename
Alloc
>
1209
INLINE
List
<
Val
,
Alloc
>::~
List
() {
1210
// for debugging (although this program is bug-free)
1211
GUM_DESTRUCTOR
(
List
);
1212
1213
// we detach all the safe iterators attached to the current List and we
1214
// remove all the elements from the list
1215
clear
();
1216
}
1217
1218
// Copy operator. The List iterator's list is not shared with that of \e src.
1219
template
<
typename
Val
,
typename
Alloc
>
1220
INLINE
List
<
Val
,
Alloc
>&
List
<
Val
,
Alloc
>::
operator
=(
const
List
<
Val
,
Alloc
>&
src
) {
1221
// avoid self assignment
1222
if
(
this
!= &
src
) {
1223
// for debugging purposes
1224
GUM_OP_CPY
(
List
);
1225
1226
// remove the old content of 'this' and update accordingly the iterators
1227
clear
();
1228
1229
// perform the copy
1230
_copy_elements_
(
src
);
1231
}
1232
1233
return
*
this
;
1234
}
1235
1236
// Generalized copy operator.
1237
template
<
typename
Val
,
typename
Alloc
>
1238
template
<
typename
OtherAlloc
>
1239
INLINE
List
<
Val
,
Alloc
>&
List
<
Val
,
Alloc
>::
operator
=(
const
List
<
Val
,
OtherAlloc
>&
src
) {
1240
// avoid self assignment
1241
if
(
this
!=
reinterpret_cast
<
List
<
Val
,
Alloc
>* >(&
src
)) {
1242
// for debugging purposes
1243
GUM_OP_CPY
(
List
);
1244
1245
// remove the old content of 'this' and update accordingly the iterators
1246
clear
();
1247
1248
// perform the copy
1249
_copy_elements_
(
src
);
1250
}
1251
1252
return
*
this
;
1253
}
1254
1255
// move operator
1256
template
<
typename
Val
,
typename
Alloc
>
1257
INLINE
List
<
Val
,
Alloc
>&
List
<
Val
,
Alloc
>::
operator
=(
List
<
Val
,
Alloc
>&&
src
) {
1258
// avoid self assignment
1259
if
(
this
!= &
src
) {
1260
// for debugging purposes
1261
GUM_OP_MOV
(
List
);
1262
1263
// remove the old content of 'this' and update accordingly the iterators
1264
clear
();
1265
1266
// perform the move
1267
_deb_list_
=
std
::
move
(
src
.
_deb_list_
);
1268
_end_list_
=
std
::
move
(
src
.
_end_list_
);
1269
_nb_elements_
=
std
::
move
(
src
.
_nb_elements_
);
1270
_safe_iterators_
=
std
::
move
(
src
.
_safe_iterators_
);
1271
_alloc_bucket_
=
std
::
move
(
src
.
_alloc_bucket_
);
1272
1273
src
.
_deb_list_
=
nullptr
;
1274
src
.
_end_list_
=
nullptr
;
1275
src
.
_nb_elements_
= 0;
1276
src
.
_safe_iterators_
.
clear
();
1277
}
1278
1279
return
*
this
;
1280
}
1281
1282
// the iterator pointing to the end of the List
1283
template
<
typename
Val
,
typename
Alloc
>
1284
INLINE
const
ListConstIteratorSafe
<
Val
>&
List
<
Val
,
Alloc
>::
cendSafe
()
const
noexcept
{
1285
return
*(
reinterpret_cast
<
const
ListConstIteratorSafe
<
Val
>* >(
_list_end_safe_
));
1286
}
1287
1288
// the iterator pointing to the end of the List
1289
template
<
typename
Val
,
typename
Alloc
>
1290
INLINE
const
ListIteratorSafe
<
Val
>&
List
<
Val
,
Alloc
>::
endSafe
()
noexcept
{
1291
return
*(
reinterpret_cast
<
const
ListIteratorSafe
<
Val
>* >(
_list_end_safe_
));
1292
}
1293
1294
// the iterator pointing to the end of the List
1295
template
<
typename
Val
,
typename
Alloc
>
1296
INLINE
const
ListConstIterator
<
Val
>&
List
<
Val
,
Alloc
>::
cend
()
const
noexcept
{
1297
return
*(
reinterpret_cast
<
const
ListConstIterator
<
Val
>* >(
_list_end_
));
1298
}
1299
1300
// the iterator pointing to the end of the List
1301
template
<
typename
Val
,
typename
Alloc
>
1302
INLINE
const
ListIterator
<
Val
>&
List
<
Val
,
Alloc
>::
end
()
noexcept
{
1303
return
*(
reinterpret_cast
<
const
ListIterator
<
Val
>* >(
_list_end_
));
1304
}
1305
1306
// the iterator pointing to the end of the List
1307
template
<
typename
Val
,
typename
Alloc
>
1308
INLINE
const
ListConstIterator
<
Val
>&
List
<
Val
,
Alloc
>::
end
()
const
noexcept
{
1309
return
*(
reinterpret_cast
<
const
ListConstIterator
<
Val
>* >(
_list_end_
));
1310
}
1311
1312
// the iterator pointing to the rend (just before the beginning) of the List
1313
template
<
typename
Val
,
typename
Alloc
>
1314
INLINE
const
ListConstIteratorSafe
<
Val
>&
List
<
Val
,
Alloc
>::
crendSafe
()
const
noexcept
{
1315
return
*(
reinterpret_cast
<
const
ListConstIteratorSafe
<
Val
>* >(
_list_end_safe_
));
1316
}
1317
1318
// the iterator pointing to the rend (just before the beginning) of the List
1319
template
<
typename
Val
,
typename
Alloc
>
1320
INLINE
const
ListIteratorSafe
<
Val
>&
List
<
Val
,
Alloc
>::
rendSafe
()
noexcept
{
1321
return
*(
reinterpret_cast
<
const
ListIteratorSafe
<
Val
>* >(
_list_end_safe_
));
1322
}
1323
1324
// the iterator pointing to the rend (just before the beginning) of the List
1325
template
<
typename
Val
,
typename
Alloc
>
1326
INLINE
const
ListConstIterator
<
Val
>&
List
<
Val
,
Alloc
>::
crend
()
const
noexcept
{
1327
return
*(
reinterpret_cast
<
const
ListConstIterator
<
Val
>* >(
_list_end_
));
1328
}
1329
1330
// the iterator pointing to the rend (just before the beginning) of the List
1331
template
<
typename
Val
,
typename
Alloc
>
1332
INLINE
const
ListIterator
<
Val
>&
List
<
Val
,
Alloc
>::
rend
()
noexcept
{
1333
return
*(
reinterpret_cast
<
const
ListIterator
<
Val
>* >(
_list_end_
));
1334
}
1335
1336
// the iterator pointing to the rend (just before the beginning) of the List
1337
template
<
typename
Val
,
typename
Alloc
>
1338
INLINE
const
ListConstIterator
<
Val
>&
List
<
Val
,
Alloc
>::
rend
()
const
noexcept
{
1339
return
*(
reinterpret_cast
<
const
ListConstIterator
<
Val
>* >(
_list_end_
));
1340
}
1341
1342
// the iterator pointing to the beginning of the List
1343
template
<
typename
Val
,
typename
Alloc
>
1344
INLINE
ListConstIteratorSafe
<
Val
>
List
<
Val
,
Alloc
>::
cbeginSafe
()
const
{
1345
return
ListConstIteratorSafe
<
Val
>{*
this
};
1346
}
1347
1348
// the iterator pointing to the beginning of the List
1349
template
<
typename
Val
,
typename
Alloc
>
1350
INLINE
ListIteratorSafe
<
Val
>
List
<
Val
,
Alloc
>::
beginSafe
() {
1351
return
ListIteratorSafe
<
Val
>{*
this
};
1352
}
1353
1354
// the iterator pointing to the beginning of the List
1355
template
<
typename
Val
,
typename
Alloc
>
1356
INLINE
ListConstIterator
<
Val
>
List
<
Val
,
Alloc
>::
cbegin
()
const
{
1357
return
ListConstIterator
<
Val
>{*
this
};
1358
}
1359
1360
// the iterator pointing to the beginning of the List
1361
template
<
typename
Val
,
typename
Alloc
>
1362
INLINE
ListIterator
<
Val
>
List
<
Val
,
Alloc
>::
begin
() {
1363
return
ListIterator
<
Val
>{*
this
};
1364
}
1365
1366
// the iterator pointing to the beginning of the List
1367
template
<
typename
Val
,
typename
Alloc
>
1368
INLINE
ListConstIterator
<
Val
>
List
<
Val
,
Alloc
>::
begin
()
const
{
1369
return
ListConstIterator
<
Val
>{*
this
};
1370
}
1371
1372
// the iterator pointing to the rbegin (the last element) of the List
1373
template
<
typename
Val
,
typename
Alloc
>
1374
INLINE
ListConstIteratorSafe
<
Val
>
List
<
Val
,
Alloc
>::
crbeginSafe
()
const
{
1375
if
(
_nb_elements_
)
1376
return
ListConstIteratorSafe
<
Val
>{*
this
,
_nb_elements_
- 1};
1377
else
1378
return
ListConstIteratorSafe
<
Val
>{};
1379
}
1380
1381
// the iterator pointing to the rbegin (the last element) of the List
1382
template
<
typename
Val
,
typename
Alloc
>
1383
INLINE
ListIteratorSafe
<
Val
>
List
<
Val
,
Alloc
>::
rbeginSafe
() {
1384
if
(
_nb_elements_
)
1385
return
ListIteratorSafe
<
Val
>{*
this
,
_nb_elements_
- 1};
1386
else
1387
return
ListIteratorSafe
<
Val
>{};
1388
}
1389
1390
// the iterator pointing to the rbegin (the last element) of the List
1391
template
<
typename
Val
,
typename
Alloc
>
1392
INLINE
ListConstIterator
<
Val
>
List
<
Val
,
Alloc
>::
crbegin
()
const
{
1393
if
(
_nb_elements_
)
1394
return
ListConstIterator
<
Val
>{*
this
,
_nb_elements_
- 1};
1395
else
1396
return
ListConstIterator
<
Val
>{};
1397
}
1398
1399
// the iterator pointing to the rbegin (the last element) of the List
1400
template
<
typename
Val
,
typename
Alloc
>
1401
INLINE
ListIterator
<
Val
>
List
<
Val
,
Alloc
>::
rbegin
() {
1402
if
(
_nb_elements_
)
1403
return
ListIterator
<
Val
>{*
this
,
_nb_elements_
- 1};
1404
else
1405
return
ListIterator
<
Val
>{};
1406
}
1407
1408
// the iterator pointing to the rbegin (the last element) of the List
1409
template
<
typename
Val
,
typename
Alloc
>
1410
INLINE
ListConstIterator
<
Val
>
List
<
Val
,
Alloc
>::
rbegin
()
const
{
1411
if
(
_nb_elements_
)
1412
return
ListConstIterator
<
Val
>{*
this
,
_nb_elements_
- 1};
1413
else
1414
return
ListConstIterator
<
Val
>{};
1415
}
1416
1417
// create a new bucket with a given value
1418
template
<
typename
Val
,
typename
Alloc
>
1419
INLINE
ListBucket
<
Val
>*
List
<
Val
,
Alloc
>::
_createBucket_
(
const
Val
&
val
)
const
{
1420
// create a new bucket (catch allocation and construction exceptions)
1421
ListBucket
<
Val
>*
new_elt
=
_alloc_bucket_
.
allocate
(1);
1422
1423
try
{
1424
_alloc_bucket_
.
construct
(
new_elt
,
val
);
1425
}
catch
(...) {
1426
_alloc_bucket_
.
deallocate
(
new_elt
, 1);
1427
throw
;
1428
}
1429
1430
return
new_elt
;
1431
}
1432
1433
// create a new bucket with a given value
1434
template
<
typename
Val
,
typename
Alloc
>
1435
INLINE
ListBucket
<
Val
>*
List
<
Val
,
Alloc
>::
_createBucket_
(
Val
&&
val
)
const
{
1436
// create a new bucket (catch allocation and construction exceptions)
1437
ListBucket
<
Val
>*
new_elt
=
_alloc_bucket_
.
allocate
(1);
1438
1439
try
{
1440
_alloc_bucket_
.
construct
(
new_elt
,
std
::
move
(
val
));
1441
}
catch
(...) {
1442
_alloc_bucket_
.
deallocate
(
new_elt
, 1);
1443
throw
;
1444
}
1445
1446
return
new_elt
;
1447
}
1448
1449
// create an emplace bucket
1450
template
<
typename
Val
,
typename
Alloc
>
1451
template
<
typename
...
Args
>
1452
INLINE
ListBucket
<
Val
>*
List
<
Val
,
Alloc
>::
_createEmplaceBucket_
(
Args
&&...
args
)
const
{
1453
// create a new bucket (catch allocation and construction exceptions)
1454
ListBucket
<
Val
>*
new_elt
=
_alloc_bucket_
.
allocate
(1);
1455
1456
try
{
1457
_alloc_bucket_
.
construct
(
new_elt
,
1458
ListBucket
<
Val
>::
Emplace
::
EMPLACE
,
1459
std
::
forward
<
Args
>(
args
)...);
1460
}
catch
(...) {
1461
_alloc_bucket_
.
deallocate
(
new_elt
, 1);
1462
throw
;
1463
}
1464
1465
return
new_elt
;
1466
}
1467
1468
// insert a bucket at the front of the list
1469
template
<
typename
Val
,
typename
Alloc
>
1470
INLINE
Val
&
List
<
Val
,
Alloc
>::
_pushFront_
(
ListBucket
<
Val
>*
new_elt
) {
1471
new_elt
->
_next_
=
_deb_list_
;
1472
1473
if
(
_deb_list_
!=
nullptr
)
1474
_deb_list_
->
_prev_
=
new_elt
;
1475
else
1476
_end_list_
=
new_elt
;
1477
1478
_deb_list_
=
new_elt
;
1479
1480
// update the number of elements
1481
++
_nb_elements_
;
1482
1483
// return the inserted element
1484
return
new_elt
->
_val_
;
1485
}
1486
1487
// insert a bucket at the end of the list
1488
template
<
typename
Val
,
typename
Alloc
>
1489
INLINE
Val
&
List
<
Val
,
Alloc
>::
_pushBack_
(
ListBucket
<
Val
>*
new_elt
) {
1490
// place the bucket at the end of the list
1491
new_elt
->
_prev_
=
_end_list_
;
1492
1493
if
(
_end_list_
!=
nullptr
)
1494
_end_list_
->
_next_
=
new_elt
;
1495
else
1496
_deb_list_
=
new_elt
;
1497
1498
_end_list_
=
new_elt
;
1499
1500
// update the number of elements
1501
++
_nb_elements_
;
1502
1503
// returns the current value
1504
return
new_elt
->
_val_
;
1505
}
1506
1507
// Insertion of a new element (a copy) at the beginning of the chained list.
1508
template
<
typename
Val
,
typename
Alloc
>
1509
INLINE
Val
&
List
<
Val
,
Alloc
>::
pushFront
(
const
Val
&
val
) {
1510
return
_pushFront_
(
_createBucket_
(
val
));
1511
}
1512
1513
// Insertion of a new element (a copy) at the beginning of the chained list.
1514
template
<
typename
Val
,
typename
Alloc
>
1515
INLINE
Val
&
List
<
Val
,
Alloc
>::
pushFront
(
Val
&&
val
) {
1516
return
_pushFront_
(
_createBucket_
(
std
::
move
(
val
)));
1517
}
1518
1519
// an alias for pushFront used for STL compliance
1520
template
<
typename
Val
,
typename
Alloc
>
1521
template
<
typename
...
Args
>
1522
INLINE
Val
&
List
<
Val
,
Alloc
>::
push_front
(
Args
&&...
args
) {
1523
return
pushFront
(
std
::
forward
<
Args
>(
args
)...);
1524
}
1525
1526
// emplace elements at the beginning of the chained list
1527
template
<
typename
Val
,
typename
Alloc
>
1528
template
<
typename
...
Args
>
1529
INLINE
Val
&
List
<
Val
,
Alloc
>::
emplaceFront
(
Args
&&...
args
) {
1530
return
_pushFront_
(
_createEmplaceBucket_
(
std
::
forward
<
Args
>(
args
)...));
1531
}
1532
1533
// Insertion of a new element (a copy) at the end of the chained list.
1534
template
<
typename
Val
,
typename
Alloc
>
1535
INLINE
Val
&
List
<
Val
,
Alloc
>::
pushBack
(
const
Val
&
val
) {
1536
return
_pushBack_
(
_createBucket_
(
val
));
1537
}
1538
1539
// pushBack for rvalues
1540
template
<
typename
Val
,
typename
Alloc
>
1541
INLINE
Val
&
List
<
Val
,
Alloc
>::
pushBack
(
Val
&&
val
) {
1542
return
_pushBack_
(
_createBucket_
(
std
::
move
(
val
)));
1543
}
1544
1545
// an alias for pushBack used for STL compliance
1546
template
<
typename
Val
,
typename
Alloc
>
1547
template
<
typename
...
Args
>
1548
INLINE
Val
&
List
<
Val
,
Alloc
>::
push_back
(
Args
&&...
args
) {
1549
return
pushBack
(
std
::
forward
<
Args
>(
args
)...);
1550
}
1551
1552
// emplace elements at the end of the chained list
1553
template
<
typename
Val
,
typename
Alloc
>
1554
template
<
typename
...
Args
>
1555
INLINE
Val
&
List
<
Val
,
Alloc
>::
emplaceBack
(
Args
&&...
args
) {
1556
return
_pushBack_
(
_createEmplaceBucket_
(
std
::
forward
<
Args
>(
args
)...));
1557
}
1558
1559
// Insertion of a new element at the end of the chained list (alias of
1560
// pushBack)
1561
template
<
typename
Val
,
typename
Alloc
>
1562
INLINE
Val
&
List
<
Val
,
Alloc
>::
insert
(
const
Val
&
val
) {
1563
return
pushBack
(
val
);
1564
}
1565
1566
// insert for rvalues
1567
template
<
typename
Val
,
typename
Alloc
>
1568
INLINE
Val
&
List
<
Val
,
Alloc
>::
insert
(
Val
&&
val
) {
1569
return
pushBack
(
std
::
move
(
val
));
1570
}
1571
1572
// returns the bucket corresponding to the ith position
1573
template
<
typename
Val
,
typename
Alloc
>
1574
INLINE
ListBucket
<
Val
>*
List
<
Val
,
Alloc
>::
_getIthBucket_
(
Size
i
)
const
noexcept
{
1575
ListBucket
<
Val
>*
ptr
;
1576
1577
if
(
i
<
_nb_elements_
/ 2) {
1578
for
(
ptr
=
_deb_list_
;
i
; --
i
,
ptr
=
ptr
->
_next_
) {}
1579
}
else
{
1580
for
(
ptr
=
_end_list_
,
i
=
_nb_elements_
-
i
- 1;
i
; --
i
,
ptr
=
ptr
->
_prev_
) {}
1581
}
1582
1583
return
ptr
;
1584
}
1585
1586
// insert a new bucket before another one
1587
template
<
typename
Val
,
typename
Alloc
>
1588
INLINE
Val
&
List
<
Val
,
Alloc
>::
_insertBefore_
(
ListBucket
<
Val
>*
new_elt
,
1589
ListBucket
<
Val
>*
current_elt
) {
1590
new_elt
->
_next_
=
current_elt
;
1591
new_elt
->
_prev_
=
current_elt
->
_prev_
;
1592
current_elt
->
_prev_
=
new_elt
;
1593
1594
if
(
new_elt
->
_prev_
==
nullptr
)
1595
_deb_list_
=
new_elt
;
1596
else
1597
new_elt
->
_prev_
->
_next_
=
new_elt
;
1598
1599
// update the number of elements
1600
++
_nb_elements_
;
1601
1602
// returns the current value
1603
return
new_elt
->
_val_
;
1604
}
1605
1606
// insert a new bucket after another one
1607
template
<
typename
Val
,
typename
Alloc
>
1608
INLINE
Val
&
List
<
Val
,
Alloc
>::
_insertAfter_
(
ListBucket
<
Val
>*
new_elt
,
1609
ListBucket
<
Val
>*
current_elt
) {
1610
new_elt
->
_prev_
=
current_elt
;
1611
new_elt
->
_next_
=
current_elt
->
_next_
;
1612
current_elt
->
_next_
=
new_elt
;
1613
1614
if
(
new_elt
->
_next_
==
nullptr
)
1615
_end_list_
=
new_elt
;
1616
else
1617
new_elt
->
_next_
->
_prev_
=
new_elt
;
1618
1619
// update the number of elements
1620
++
_nb_elements_
;
1621
1622
// returns the current value
1623
return
new_elt
->
_val_
;
1624
}
1625
1626
// inserts a new element at the ith pos of the chained list
1627
template
<
typename
Val
,
typename
Alloc
>
1628
INLINE
Val
&
List
<
Val
,
Alloc
>::
insert
(
Size
pos
,
const
Val
&
val
) {
1629
// if ther are fewer elements than pos, put the value at the end of the list
1630
if
(
_nb_elements_
<=
pos
) {
return
pushBack
(
val
); }
1631
1632
return
_insertBefore_
(
_createBucket_
(
val
),
_getIthBucket_
(
pos
));
1633
}
1634
1635
// insert an rvalue at the ith pos of the chained list
1636
template
<
typename
Val
,
typename
Alloc
>
1637
INLINE
Val
&
List
<
Val
,
Alloc
>::
insert
(
Size
pos
,
Val
&&
val
) {
1638
// if ther are fewer elements than pos, put the value at the end of the list
1639
if
(
_nb_elements_
<=
pos
) {
return
pushBack
(
std
::
move
(
val
)); }
1640
1641
return
_insertBefore_
(
_createBucket_
(
std
::
move
(
val
)),
_getIthBucket_
(
pos
));
1642
}
1643
1644
// inserts a new bucket before or after the location pointed to by an
1645
// iterator
1646
template
<
typename
Val
,
typename
Alloc
>
1647
INLINE
Val
&
List
<
Val
,
Alloc
>::
_insert_
(
const
const_iterator_safe
&
iter
,
1648
ListBucket
<
Val
>*
new_elt
,
1649
location
place
) {
1650
// find the location around which the new element should be inserted
1651
ListBucket
<
Val
>*
ptr
;
1652
1653
if
(
iter
.
_null_pointing_
) {
1654
if
(
place
==
location
::
BEFORE
) {
1655
ptr
=
iter
.
_next_current_bucket_
;
1656
}
else
{
1657
ptr
=
iter
.
_prev_current_bucket_
;
1658
}
1659
}
else
{
1660
ptr
=
iter
.
_getBucket_
();
1661
}
1662
1663
if
(
ptr
==
nullptr
) {
1664
// here, we are at the end of the list
1665
return
_pushBack_
(
new_elt
);
1666
}
else
{
1667
switch
(
place
) {
1668
case
location
::
BEFORE
:
1669
return
_insertBefore_
(
new_elt
,
ptr
);
1670
1671
case
location
::
AFTER
:
1672
return
_insertAfter_
(
new_elt
,
ptr
);
1673
1674
default
:
1675
GUM_ERROR
(
FatalError
,
"List insertion for this location unimplemented"
)
1676
}
1677
}
1678
}
1679
1680
// inserts a new bucket before or after the location pointed to by an
1681
// iterator
1682
template
<
typename
Val
,
typename
Alloc
>
1683
INLINE
Val
&
List
<
Val
,
Alloc
>::
_insert_
(
const
const_iterator
&
iter
,
1684
ListBucket
<
Val
>*
new_elt
,
1685
location
place
) {
1686
// find the location around which the new element should be inserted
1687
ListBucket
<
Val
>*
ptr
=
iter
.
_getBucket_
();
1688
1689
if
(
ptr
==
nullptr
) {
1690
// here, we are at the end of the list
1691
return
_pushBack_
(
new_elt
);
1692
}
else
{
1693
switch
(
place
) {
1694
case
location
::
BEFORE
:
1695
return
_insertBefore_
(
new_elt
,
ptr
);
1696
1697
case
location
::
AFTER
:
1698
return
_insertAfter_
(
new_elt
,
ptr
);
1699
1700
default
:
1701
GUM_ERROR
(
FatalError
,
"List insertion for this location unimplemented"
)
1702
}
1703
}
1704
}
1705
1706
// inserts a new element before or after the location pointed to by an
1707
// iterator
1708
template
<
typename
Val
,
typename
Alloc
>
1709
INLINE
Val
&
1710
List
<
Val
,
Alloc
>::
insert
(
const
const_iterator_safe
&
iter
,
const
Val
&
val
,
location
place
) {
1711
// if the iterator does not point to the list, raise an exception
1712
if
(
iter
.
_list_
!=
this
) {
1713
GUM_ERROR
(
InvalidArgument
,
"the iterator does not point to the correct list"
)
1714
}
1715
1716
return
_insert_
(
iter
,
_createBucket_
(
val
),
place
);
1717
}
1718
1719
// inserts a new element before or after the location pointed to by an
1720
// iterator
1721
template
<
typename
Val
,
typename
Alloc
>
1722
INLINE
Val
&
1723
List
<
Val
,
Alloc
>::
insert
(
const
const_iterator_safe
&
iter
,
Val
&&
val
,
location
place
) {
1724
// if the iterator does not point to the list, raise an exception
1725
if
(
iter
.
_list_
!=
this
) {
1726
GUM_ERROR
(
InvalidArgument
,
"the iterator does not point to the correct list"
)
1727
}
1728
1729
return
_insert_
(
iter
,
_createBucket_
(
std
::
move
(
val
)),
place
);
1730
}
1731
1732
// inserts a new element before or after the location pointed to by an
1733
// iterator
1734
template
<
typename
Val
,
typename
Alloc
>
1735
INLINE
Val
&
1736
List
<
Val
,
Alloc
>::
insert
(
const
const_iterator
&
iter
,
const
Val
&
val
,
location
place
) {
1737
return
_insert_
(
iter
,
_createBucket_
(
val
),
place
);
1738
}
1739
1740
// inserts a new element before or after the location pointed to by an
1741
// iterator
1742
template
<
typename
Val
,
typename
Alloc
>
1743
INLINE
Val
&
List
<
Val
,
Alloc
>::
insert
(
const
const_iterator
&
iter
,
Val
&&
val
,
location
place
) {
1744
return
_insert_
(
iter
,
_createBucket_
(
std
::
move
(
val
)),
place
);
1745
}
1746
1747
// emplace a new element before a given iterator
1748
template
<
typename
Val
,
typename
Alloc
>
1749
template
<
typename
...
Args
>
1750
INLINE
Val
&
List
<
Val
,
Alloc
>::
emplace
(
const
const_iterator
&
iter
,
Args
&&...
args
) {
1751
return
_insert_
(
iter
,
_createEmplaceBucket_
(
std
::
forward
<
Args
>(
args
)...),
location
::
BEFORE
);
1752
}
1753
1754
// emplace a new element before a given iterator
1755
template
<
typename
Val
,
typename
Alloc
>
1756
template
<
typename
...
Args
>
1757
INLINE
Val
&
List
<
Val
,
Alloc
>::
emplace
(
const
const_iterator_safe
&
iter
,
Args
&&...
args
) {
1758
return
_insert_
(
iter
,
_createEmplaceBucket_
(
std
::
forward
<
Args
>(
args
)...),
location
::
BEFORE
);
1759
}
1760
1761
// returns a reference to first element of a list
1762
template
<
typename
Val
,
typename
Alloc
>
1763
INLINE
Val
&
List
<
Val
,
Alloc
>::
front
()
const
{
1764
if
(
_nb_elements_
==
Size
(0)) {
GUM_ERROR
(
NotFound
,
"not enough elements in the chained list"
) }
1765
1766
return
_deb_list_
->
_val_
;
1767
}
1768
1769
// returns a reference to last element of a list
1770
template
<
typename
Val
,
typename
Alloc
>
1771
INLINE
Val
&
List
<
Val
,
Alloc
>::
back
()
const
{
1772
if
(
_nb_elements_
==
Size
(0)) {
GUM_ERROR
(
NotFound
,
"not enough elements in the chained list"
) }
1773
1774
return
_end_list_
->
_val_
;
1775
}
1776
1777
// returns the number of elements in the list.
1778
template
<
typename
Val
,
typename
Alloc
>
1779
INLINE
Size
List
<
Val
,
Alloc
>::
size
()
const
noexcept
{
1780
return
_nb_elements_
;
1781
}
1782
1783
// checks whether there exists a given element in the list.
1784
template
<
typename
Val
,
typename
Alloc
>
1785
INLINE
bool
List
<
Val
,
Alloc
>::
exists
(
const
Val
&
val
)
const
{
1786
for
(
ListBucket
<
Val
>*
ptr
=
_deb_list_
;
ptr
!=
nullptr
;
ptr
=
ptr
->
_next_
)
1787
if
(
ptr
->
_val_
==
val
)
return
true
;
1788
1789
return
false
;
1790
}
1791
1792
// suppresses a given bucket from a chained list.
1793
template
<
typename
Val
,
typename
Alloc
>
1794
INLINE
void
List
<
Val
,
Alloc
>::
_erase_
(
ListBucket
<
Val
>*
bucket
) {
1795
// perform deletion only if there is a bucket to remove
1796
if
(
bucket
!=
nullptr
) {
1797
// update the iterators pointing on this element
1798
for
(
const
auto
ptr_iter
:
_safe_iterators_
) {
1799
if
(
ptr_iter
->
_bucket_
==
bucket
) {
1800
ptr_iter
->
_next_current_bucket_
=
bucket
->
_prev_
;
1801
ptr_iter
->
_prev_current_bucket_
=
bucket
->
_next_
;
1802
ptr_iter
->
_bucket_
=
nullptr
;
1803
ptr_iter
->
_null_pointing_
=
true
;
1804
}
else
{
1805
if
(
ptr_iter
->
_null_pointing_
) {
1806
if
(
ptr_iter
->
_next_current_bucket_
==
bucket
)
1807
ptr_iter
->
_next_current_bucket_
=
bucket
->
_prev_
;
1808
1809
if
(
ptr_iter
->
_prev_current_bucket_
==
bucket
)
1810
ptr_iter
->
_prev_current_bucket_
=
bucket
->
_next_
;
1811
}
1812
}
1813
}
1814
1815
// set properly the begin and end of the chained list (the other chainings
1816
// will be performed by operator delete)
1817
if
(
bucket
->
_prev_
==
nullptr
)
1818
_deb_list_
=
bucket
->
_next_
;
1819
else
1820
bucket
->
_prev_
->
_next_
=
bucket
->
_next_
;
1821
1822
if
(
bucket
->
_next_
==
nullptr
)
1823
_end_list_
=
bucket
->
_prev_
;
1824
else
1825
bucket
->
_next_
->
_prev_
=
bucket
->
_prev_
;
1826
1827
// remove the current element src the list
1828
_alloc_bucket_
.
destroy
(
bucket
);
1829
_alloc_bucket_
.
deallocate
(
bucket
, 1);
1830
1831
--
_nb_elements_
;
1832
}
1833
}
1834
1835
// erases the ith element of the List (the first one is in position 0)
1836
template
<
typename
Val
,
typename
Alloc
>
1837
INLINE
void
List
<
Val
,
Alloc
>::
erase
(
Size
i
) {
1838
if
(
i
>=
_nb_elements_
)
return
;
1839
1840
// erase the ith bucket
1841
_erase_
(
_getIthBucket_
(
i
));
1842
}
1843
1844
// erases the element of the List pointed to by the iterator
1845
template
<
typename
Val
,
typename
Alloc
>
1846
INLINE
void
List
<
Val
,
Alloc
>::
erase
(
const
iterator_safe
&
iter
) {
1847
_erase_
(
iter
.
_getBucket_
());
1848
}
1849
1850
// erases the element of the List pointed to by the iterator
1851
template
<
typename
Val
,
typename
Alloc
>
1852
INLINE
void
List
<
Val
,
Alloc
>::
erase
(
const
const_iterator_safe
&
iter
) {
1853
_erase_
(
iter
.
_getBucket_
());
1854
}
1855
1856
// returns the bucket corresponding to a given value.
1857
template
<
typename
Val
,
typename
Alloc
>
1858
INLINE
ListBucket
<
Val
>*
List
<
Val
,
Alloc
>::
_getBucket_
(
const
Val
&
val
)
const
noexcept
{
1859
for
(
ListBucket
<
Val
>*
ptr
=
_deb_list_
;
ptr
!=
nullptr
;
ptr
=
ptr
->
_next_
)
1860
if
(
ptr
->
_val_
==
val
)
return
ptr
;
1861
1862
return
nullptr
;
1863
}
1864
1865
// erases the first element encountered with a given value
1866
template
<
typename
Val
,
typename
Alloc
>
1867
INLINE
void
List
<
Val
,
Alloc
>::
eraseByVal
(
const
Val
&
val
) {
1868
_erase_
(
_getBucket_
(
val
));
1869
}
1870
1871
// erases all the elements encountered with a given value
1872
template
<
typename
Val
,
typename
Alloc
>
1873
INLINE
void
List
<
Val
,
Alloc
>::
eraseAllVal
(
const
Val
&
val
) {
1874
for
(
ListBucket
<
Val
>*
iter
=
_deb_list_
, *
next_bucket
=
nullptr
;
iter
!=
nullptr
;
1875
iter
=
next_bucket
) {
1876
next_bucket
=
iter
->
_next_
;
1877
1878
if
(
val
==
iter
->
_val_
)
_erase_
(
iter
);
1879
}
1880
}
1881
1882
// removes the last element of a List
1883
template
<
typename
Val
,
typename
Alloc
>
1884
INLINE
void
List
<
Val
,
Alloc
>::
popBack
() {
1885
_erase_
(
_end_list_
);
1886
}
1887
1888
// removes the first element of a List
1889
template
<
typename
Val
,
typename
Alloc
>
1890
INLINE
void
List
<
Val
,
Alloc
>::
popFront
() {
1891
_erase_
(
_deb_list_
);
1892
}
1893
1894
// returns a boolean indicating whether the chained list is empty
1895
template
<
typename
Val
,
typename
Alloc
>
1896
INLINE
bool
List
<
Val
,
Alloc
>::
empty
()
const
noexcept
{
1897
return
(
_nb_elements_
==
Size
(0));
1898
}
1899
1900
// displays the content of a chained list
1901
template
<
typename
Val
,
typename
Alloc
>
1902
std
::
string
List
<
Val
,
Alloc
>::
toString
()
const
{
1903
bool
deja
=
false
;
1904
std
::
stringstream
stream
;
1905
stream
<<
"["
;
1906
1907
for
(
ListBucket
<
Val
>*
ptr
=
_deb_list_
;
ptr
!=
nullptr
;
ptr
=
ptr
->
_next_
,
deja
=
true
) {
1908
if
(
deja
)
stream
<<
" --> "
;
1909
1910
stream
<<
ptr
->
_val_
;
1911
}
1912
1913
stream
<<
"]"
;
1914
1915
return
stream
.
str
();
1916
}
1917
1918
// creates a list of mountains src a list of val
1919
template
<
typename
Val
,
typename
Alloc
>
1920
template
<
typename
Mount
,
typename
OtherAlloc
>
1921
List
<
Mount
,
OtherAlloc
>
List
<
Val
,
Alloc
>::
map
(
Mount
(*
f
)(
Val
))
const
{
1922
// create a new empty list
1923
List
<
Mount
,
OtherAlloc
>
list
;
1924
1925
// fill the new list
1926
for
(
const_iterator
iter
=
begin
();
iter
!=
end
(); ++
iter
) {
1927
list
.
pushBack
(
f
(*
iter
));
1928
}
1929
1930
return
list
;
1931
}
1932
1933
// creates a list of mountains src a list of val
1934
template
<
typename
Val
,
typename
Alloc
>
1935
template
<
typename
Mount
,
typename
OtherAlloc
>
1936
List
<
Mount
,
OtherAlloc
>
List
<
Val
,
Alloc
>::
map
(
Mount
(*
f
)(
Val
&))
const
{
1937
// create a new empty list
1938
List
<
Mount
,
OtherAlloc
>
list
;
1939
1940
// fill the new list
1941
for
(
const_iterator
iter
=
begin
();
iter
!=
end
(); ++
iter
) {
1942
list
.
pushBack
(
f
(*
iter
));
1943
}
1944
1945
return
list
;
1946
}
1947
1948
// creates a list of mountains src a list of val
1949
template
<
typename
Val
,
typename
Alloc
>
1950
template
<
typename
Mount
,
typename
OtherAlloc
>
1951
List
<
Mount
,
OtherAlloc
>
List
<
Val
,
Alloc
>::
map
(
Mount
(*
f
)(
const
Val
&))
const
{
1952
// create a new empty list
1953
List
<
Mount
,
OtherAlloc
>
list
;
1954
1955
// fill the new list
1956
for
(
const_iterator
iter
=
begin
();
iter
!=
end
(); ++
iter
) {
1957
list
.
pushBack
(
f
(*
iter
));
1958
}
1959
1960
return
list
;
1961
}
1962
1963
// creates a list of mountains with a given value src a list of val
1964
template
<
typename
Val
,
typename
Alloc
>
1965
template
<
typename
Mount
,
typename
OtherAlloc
>
1966
List
<
Mount
,
OtherAlloc
>
List
<
Val
,
Alloc
>::
map
(
const
Mount
&
mount
)
const
{
1967
// create a new empty list
1968
List
<
Mount
,
OtherAlloc
>
list
;
1969
1970
// fill the new list
1971
for
(
Size
i
=
Size
(0);
i
<
_nb_elements_
; ++
i
)
1972
list
.
pushBack
(
mount
);
1973
1974
return
list
;
1975
}
1976
1977
// creates and insert a new element at the end of the list (alias of
1978
// pushBack).
1979
template
<
typename
Val
,
typename
Alloc
>
1980
INLINE
Val
&
List
<
Val
,
Alloc
>::
operator
+=(
const
Val
&
val
) {
1981
return
pushBack
(
val
);
1982
}
1983
1984
// creates and insert a new element at the end of the list (alias of
1985
// pushBack).
1986
template
<
typename
Val
,
typename
Alloc
>
1987
INLINE
Val
&
List
<
Val
,
Alloc
>::
operator
+=(
Val
&&
val
) {
1988
return
pushBack
(
std
::
move
(
val
));
1989
}
1990
1991
// checks whether two lists are identical (same elements in the same order)
1992
template
<
typename
Val
,
typename
Alloc
>
1993
template
<
typename
OtherAlloc
>
1994
INLINE
bool
List
<
Val
,
Alloc
>::
operator
==(
const
List
<
Val
,
OtherAlloc
>&
src
)
const
{
1995
// check if the two lists have at least the same number of elements
1996
if
(
_nb_elements_
!=
src
.
_nb_elements_
)
return
false
;
1997
1998
// parse the two lists
1999
for
(
ListBucket
<
Val
>*
iter1
=
_deb_list_
, *
iter2
=
src
.
_deb_list_
;
iter1
!=
nullptr
;
2000
iter1
=
iter1
->
_next_
,
iter2
=
iter2
->
_next_
)
2001
if
(*
iter1
!= *
iter2
)
return
false
;
2002
2003
return
true
;
2004
}
2005
2006
// checks whether two lists are different (different elements or orders)
2007
template
<
typename
Val
,
typename
Alloc
>
2008
template
<
typename
OtherAlloc
>
2009
INLINE
bool
List
<
Val
,
Alloc
>::
operator
!=(
const
List
<
Val
,
OtherAlloc
>&
src
)
const
{
2010
return
!
operator
==(
src
);
2011
}
2012
2013
// returns the ith element in the current chained list.
2014
template
<
typename
Val
,
typename
Alloc
>
2015
INLINE
Val
&
List
<
Val
,
Alloc
>::
operator
[](
const
Size
i
) {
2016
// check if we can return the element we ask for
2017
if
(
i
>=
_nb_elements_
) {
GUM_ERROR
(
NotFound
,
"not enough elements in the chained list"
) }
2018
2019
return
**
_getIthBucket_
(
i
);
2020
}
2021
2022
// returns the ith element in the current chained list.
2023
template
<
typename
Val
,
typename
Alloc
>
2024
INLINE
const
Val
&
List
<
Val
,
Alloc
>::
operator
[](
const
Size
i
)
const
{
2025
// check if we can return the element we ask for
2026
if
(
i
>=
_nb_elements_
) {
GUM_ERROR
(
NotFound
,
"not enough elements in the chained list"
) }
2027
2028
return
**
_getIthBucket_
(
i
);
2029
}
2030
2031
// replace the current list with another one
2032
template
<
typename
Val
,
typename
Alloc
>
2033
INLINE
void
List
<
Val
,
Alloc
>::
swap
(
List
&
other_list
) {
2034
std
::
swap
(
_deb_list_
,
other_list
.
_deb_list_
);
2035
std
::
swap
(
_end_list_
,
other_list
.
_end_list_
);
2036
std
::
swap
(
_nb_elements_
,
other_list
.
_nb_elements_
);
2037
std
::
swap
(
_safe_iterators_
,
other_list
.
_safe_iterators_
);
2038
std
::
swap
(
_alloc_bucket_
,
other_list
.
_alloc_bucket_
);
2039
}
2040
2041
// A \c << operator for List
2042
template
<
typename
Val
>
2043
std
::
ostream
&
operator
<<(
std
::
ostream
&
stream
,
const
List
<
Val
>&
list
) {
2044
stream
<<
list
.
toString
();
2045
return
stream
;
2046
}
2047
2048
}
/* namespace gum */
gum::Set::emplace
INLINE void emplace(Args &&... args)
Definition:
set_tpl.h:643