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