aGrUM
0.20.3
a C++ library for (probabilistic) graphical models
set_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 Implementation of the Set.
25
*
26
* @author Christophe GONZALES(@AMU) and Pierre-Henri WUILLEMIN(@LIP6)
27
*/
28
29
#
include
<
agrum
/
tools
/
core
/
set
.
h
>
30
31
namespace
gum
{
32
33
// ===========================================================================
34
// === SAFE SET ITERATORS ===
35
// ===========================================================================
36
37
// default constructor: the iterator points toward nothing
38
template
<
typename
Key >
39
INLINE SetIteratorSafe<
Key
>::
SetIteratorSafe
() {
40
GUM_CONSTRUCTOR
(
SetIteratorSafe
);
41
}
42
43
// creates an iterator for a given set
44
template
<
typename
Key
>
45
template
<
typename
Alloc
>
46
INLINE
SetIteratorSafe
<
Key
>::
SetIteratorSafe
(
const
Set
<
Key
,
Alloc
>&
set
,
Position
pos
) :
47
_ht_iter_
{
pos
==
SetIteratorSafe
<
Key
>::
END
?
set
.
_inside_
.
cendSafe
()
48
:
set
.
_inside_
.
cbeginSafe
()} {
49
GUM_CONSTRUCTOR
(
SetIteratorSafe
);
50
}
51
52
// copy constructor
53
template
<
typename
Key
>
54
INLINE
SetIteratorSafe
<
Key
>::
SetIteratorSafe
(
const
SetIteratorSafe
<
Key
>&
iter
) :
55
_ht_iter_
{
iter
.
_ht_iter_
} {
56
GUM_CONS_CPY
(
SetIteratorSafe
);
57
}
58
59
// copy constructor
60
template
<
typename
Key
>
61
INLINE
SetIteratorSafe
<
Key
>::
SetIteratorSafe
(
const
SetIterator
<
Key
>&
iter
) :
62
_ht_iter_
{
iter
.
_ht_iter_
} {
63
GUM_CONS_CPY
(
SetIteratorSafe
);
64
}
65
66
// move constructor
67
template
<
typename
Key
>
68
INLINE
SetIteratorSafe
<
Key
>::
SetIteratorSafe
(
SetIteratorSafe
<
Key
>&&
from
) :
69
_ht_iter_
{
std
::
move
(
from
.
_ht_iter_
)} {
70
GUM_CONS_MOV
(
SetIteratorSafe
);
71
}
72
73
// destructor
74
template
<
typename
Key
>
75
INLINE
SetIteratorSafe
<
Key
>::~
SetIteratorSafe
()
noexcept
{
76
GUM_DESTRUCTOR
(
SetIteratorSafe
);
77
}
78
79
// assignment operator
80
template
<
typename
Key
>
81
INLINE
SetIteratorSafe
<
Key
>&
82
SetIteratorSafe
<
Key
>::
operator
=(
const
SetIteratorSafe
<
Key
>&
from
) {
83
_ht_iter_
=
from
.
_ht_iter_
;
84
return
*
this
;
85
}
86
87
// assignment operator
88
template
<
typename
Key
>
89
INLINE
SetIteratorSafe
<
Key
>&
SetIteratorSafe
<
Key
>::
operator
=(
const
SetIterator
<
Key
>&
from
) {
90
_ht_iter_
=
from
.
_ht_iter_
;
91
return
*
this
;
92
}
93
94
// move operator
95
template
<
typename
Key
>
96
INLINE
SetIteratorSafe
<
Key
>&
97
SetIteratorSafe
<
Key
>::
operator
=(
SetIteratorSafe
<
Key
>&&
from
)
noexcept
{
98
_ht_iter_
=
std
::
move
(
from
.
_ht_iter_
);
99
return
*
this
;
100
}
101
102
// increments the iterator
103
template
<
typename
Key
>
104
INLINE
SetIteratorSafe
<
Key
>&
SetIteratorSafe
<
Key
>::
operator
++()
noexcept
{
105
// note that, if the hashtable's iterator points toward nothing, the
106
// hashtable's iterator incrementation will do nothing. In particular, it
107
// will not segfault.
108
++
_ht_iter_
;
109
return
*
this
;
110
}
111
112
// makes the iterator point to i elements further in the set
113
template
<
typename
Key
>
114
INLINE
SetIteratorSafe
<
Key
>&
SetIteratorSafe
<
Key
>::
operator
+=(
Size
nb
)
noexcept
{
115
_ht_iter_
+=
nb
;
116
return
*
this
;
117
}
118
119
// returns a new iterator
120
template
<
typename
Key
>
121
INLINE
SetIteratorSafe
<
Key
>
SetIteratorSafe
<
Key
>::
operator
+(
Size
nb
)
const
{
122
return
SetIteratorSafe
<
Key
>{*
this
} +=
nb
;
123
}
124
125
// indicates whether two iterators point to different elements or sets
126
template
<
typename
Key
>
127
INLINE
bool
128
SetIteratorSafe
<
Key
>::
operator
!=(
const
SetIteratorSafe
<
Key
>&
from
)
const
noexcept
{
129
return
_ht_iter_
!=
from
.
_ht_iter_
;
130
}
131
132
// indicates whether two iterators point toward the same element of a same
133
// set
134
template
<
typename
Key
>
135
INLINE
bool
136
SetIteratorSafe
<
Key
>::
operator
==(
const
SetIteratorSafe
<
Key
>&
from
)
const
noexcept
{
137
return
_ht_iter_
==
from
.
_ht_iter_
;
138
}
139
140
// returns the element pointed to by the iterator
141
template
<
typename
Key
>
142
INLINE
const
Key
&
SetIteratorSafe
<
Key
>::
operator
*()
const
{
143
// note that, if the hashtable's iterator points toward nothing, it will
144
// raise an UndefinedIteratorValue exception
145
return
_ht_iter_
.
key
();
146
}
147
148
// returns aointer to the element pointed to by the iterator
149
template
<
typename
Key
>
150
INLINE
const
Key
*
SetIteratorSafe
<
Key
>::
operator
->()
const
{
151
// note that, if the hashtable's iterator points toward nothing, it will
152
// raise an UndefinedIteratorValue exception
153
return
&(
_ht_iter_
.
key
());
154
}
155
156
// @brief makes the iterator point toward nothing (in particular, it is not
157
// related anymore to its current set) */
158
template
<
typename
Key
>
159
INLINE
void
SetIteratorSafe
<
Key
>::
clear
()
noexcept
{
160
_ht_iter_
.
clear
();
161
}
162
163
// ===========================================================================
164
// === UNSAFE SET ITERATORS ===
165
// ===========================================================================
166
167
// default constructor: the iterator points toward nothing
168
template
<
typename
Key
>
169
INLINE
SetIterator
<
Key
>::
SetIterator
()
noexcept
{
170
GUM_CONSTRUCTOR
(
SetIterator
);
171
}
172
173
// creates an iterator for a given set
174
template
<
typename
Key
>
175
template
<
typename
Alloc
>
176
INLINE
SetIterator
<
Key
>::
SetIterator
(
const
Set
<
Key
,
Alloc
>&
set
,
Position
pos
) :
177
_ht_iter_
{
pos
==
SetIterator
<
Key
>::
END
?
set
.
_inside_
.
cend
() :
set
.
_inside_
.
cbegin
()} {
178
GUM_CONSTRUCTOR
(
SetIterator
);
179
}
180
181
// copy constructor
182
template
<
typename
Key
>
183
INLINE
SetIterator
<
Key
>::
SetIterator
(
const
SetIterator
<
Key
>&
iter
)
noexcept
:
184
_ht_iter_
{
iter
.
_ht_iter_
} {
185
GUM_CONS_CPY
(
SetIterator
);
186
}
187
188
// move constructor
189
template
<
typename
Key
>
190
INLINE
SetIterator
<
Key
>::
SetIterator
(
SetIterator
<
Key
>&&
from
)
noexcept
:
191
_ht_iter_
{
std
::
move
(
from
.
_ht_iter_
)} {
192
GUM_CONS_MOV
(
SetIterator
);
193
}
194
195
// destructor
196
template
<
typename
Key
>
197
INLINE
SetIterator
<
Key
>::~
SetIterator
()
noexcept
{
198
GUM_DESTRUCTOR
(
SetIterator
);
199
}
200
201
// assignment operator
202
template
<
typename
Key
>
203
INLINE
SetIterator
<
Key
>&
204
SetIterator
<
Key
>::
operator
=(
const
SetIterator
<
Key
>&
from
)
noexcept
{
205
_ht_iter_
=
from
.
_ht_iter_
;
206
return
*
this
;
207
}
208
209
// move operator
210
template
<
typename
Key
>
211
INLINE
SetIterator
<
Key
>&
SetIterator
<
Key
>::
operator
=(
SetIterator
<
Key
>&&
from
)
noexcept
{
212
_ht_iter_
=
std
::
move
(
from
.
_ht_iter_
);
213
return
*
this
;
214
}
215
216
// increments the iterator
217
template
<
typename
Key
>
218
INLINE
SetIterator
<
Key
>&
SetIterator
<
Key
>::
operator
++()
noexcept
{
219
// note that, if the hashtable's iterator points toward nothing, the
220
// hashtable's iterator incrementation will do nothing. In particular, it
221
// will not segfault.
222
++
_ht_iter_
;
223
return
*
this
;
224
}
225
226
// makes the iterator point to i elements further in the set
227
template
<
typename
Key
>
228
INLINE
SetIterator
<
Key
>&
SetIterator
<
Key
>::
operator
+=(
Size
nb
)
noexcept
{
229
_ht_iter_
+=
nb
;
230
return
*
this
;
231
}
232
233
// returns a new iterator
234
template
<
typename
Key
>
235
INLINE
SetIterator
<
Key
>
SetIterator
<
Key
>::
operator
+(
Size
nb
)
const
noexcept
{
236
return
SetIterator
<
Key
>{*
this
} +=
nb
;
237
}
238
239
// indicates whether two iterators point to different elements or sets
240
template
<
typename
Key
>
241
INLINE
bool
SetIterator
<
Key
>::
operator
!=(
const
SetIterator
<
Key
>&
from
)
const
noexcept
{
242
return
_ht_iter_
!=
from
.
_ht_iter_
;
243
}
244
245
// indicates whether two iterators point toward the same element of a same
246
// set
247
template
<
typename
Key
>
248
INLINE
bool
SetIterator
<
Key
>::
operator
==(
const
SetIterator
<
Key
>&
from
)
const
noexcept
{
249
return
_ht_iter_
==
from
.
_ht_iter_
;
250
}
251
252
// returns the element pointed to by the iterator
253
template
<
typename
Key
>
254
INLINE
const
Key
&
SetIterator
<
Key
>::
operator
*()
const
{
255
// note that, if the hashtable's iterator points toward nothing, it will
256
// raise an UndefinedIteratorValue exception
257
return
_ht_iter_
.
key
();
258
}
259
260
// returns aointer to the element pointed to by the iterator
261
template
<
typename
Key
>
262
INLINE
const
Key
*
SetIterator
<
Key
>::
operator
->()
const
{
263
// note that, if the hashtable's iterator points toward nothing, it will
264
// raise an UndefinedIteratorValue exception
265
return
&(
_ht_iter_
.
key
());
266
}
267
268
// @brief makes the iterator point toward nothing (in particular, it is not
269
// related anymore to its current set) */
270
template
<
typename
Key
>
271
INLINE
void
SetIterator
<
Key
>::
clear
()
noexcept
{
272
_ht_iter_
.
clear
();
273
}
274
275
// ===========================================================================
276
// === SETS ===
277
// ===========================================================================
278
279
// returns the end iterator for other classes' statics
280
template
<
typename
Key
,
typename
Alloc
>
281
INLINE
const
SetIteratorSafe
<
Key
>&
Set
<
Key
,
Alloc
>::
endSafe4Statics
() {
282
return
*(
283
reinterpret_cast
<
const
SetIteratorSafe
<
Key
>* >(
SetIteratorStaticEnd
::
endSafe4Statics
()));
284
}
285
286
// returns the end iterator for other classes' statics
287
template
<
typename
Key
,
typename
Alloc
>
288
INLINE
const
SetIteratorSafe
<
Key
>&
Set
<
Key
,
Alloc
>::
constEndSafe4Statics
() {
289
return
*(
reinterpret_cast
<
const
SetIteratorSafe
<
Key
>* >(
290
SetIteratorStaticEnd
::
constEndSafe4Statics
()));
291
}
292
293
// returns the end iterator for other classes' statics
294
template
<
typename
Key
,
typename
Alloc
>
295
INLINE
const
SetIterator
<
Key
>&
Set
<
Key
,
Alloc
>::
end4Statics
() {
296
return
*(
reinterpret_cast
<
const
SetIterator
<
Key
>* >(
SetIteratorStaticEnd
::
end4Statics
()));
297
}
298
299
// returns the end iterator for other classes' statics
300
template
<
typename
Key
,
typename
Alloc
>
301
INLINE
const
SetIterator
<
Key
>&
Set
<
Key
,
Alloc
>::
constEnd4Statics
() {
302
return
*(
303
reinterpret_cast
<
const
SetIterator
<
Key
>* >(
SetIteratorStaticEnd
::
constEnd4Statics
()));
304
}
305
306
// default constructor
307
template
<
typename
Key
,
typename
Alloc
>
308
INLINE
Set
<
Key
,
Alloc
>::
Set
(
Size
capacity
,
bool
resize_policy
) :
309
// create the hash table without key uniqueness policy (as we will
310
// check
311
// ourselves the uniqueness of Keys before inserting new elements)
312
_inside_
(
capacity
,
resize_policy
,
false
) {
313
GUM_CONSTRUCTOR
(
Set
);
314
315
// make sure the end() iterator is constructed properly
316
endSafe4Statics
();
317
end4Statics
();
318
}
319
320
// initializer list constructor
321
template
<
typename
Key
,
typename
Alloc
>
322
INLINE
Set
<
Key
,
Alloc
>::
Set
(
std
::
initializer_list
<
Key
>
list
) :
323
_inside_
(
Size
(
list
.
size
()) / 2,
true
,
false
) {
324
GUM_CONSTRUCTOR
(
Set
);
325
for
(
const
auto
&
elt
:
list
) {
326
insert
(
elt
);
327
}
328
329
// make sure the end() iterator is constructed properly
330
endSafe4Statics
();
331
end4Statics
();
332
}
333
334
// copy constructor
335
template
<
typename
Key
,
typename
Alloc
>
336
INLINE
Set
<
Key
,
Alloc
>::
Set
(
const
Set
<
Key
,
Alloc
>&
s
) :
_inside_
(
s
.
_inside_
) {
337
GUM_CONS_CPY
(
Set
);
338
}
339
340
// generalized copy constructor
341
template
<
typename
Key
,
typename
Alloc
>
342
template
<
typename
OtherAlloc
>
343
INLINE
Set
<
Key
,
Alloc
>::
Set
(
const
Set
<
Key
,
OtherAlloc
>&
s
) :
_inside_
(
s
.
_inside_
) {
344
GUM_CONS_CPY
(
Set
);
345
}
346
347
// move constructor
348
template
<
typename
Key
,
typename
Alloc
>
349
INLINE
Set
<
Key
,
Alloc
>::
Set
(
Set
<
Key
,
Alloc
>&&
s
) :
_inside_
(
std
::
move
(
s
.
_inside_
)) {
350
GUM_CONS_MOV
(
Set
);
351
}
352
353
// destructor
354
template
<
typename
Key
,
typename
Alloc
>
355
INLINE
Set
<
Key
,
Alloc
>::
Set
::~
Set
() {
356
GUM_DESTRUCTOR
(
Set
);
357
}
358
359
// removes all the elements, if any, from the set
360
template
<
typename
Key
,
typename
Alloc
>
361
INLINE
void
Set
<
Key
,
Alloc
>::
clear
() {
362
// first we remove all the elements from the hashtable actually containing
363
// the elements of the set. Note that, doing so, all the hashtable iterators
364
// will be updated as well. In turn, this will imply that, whenever an
365
// operation will be performed on a SetIteratorSafe, this will raise an
366
// exception.
367
_inside_
.
clear
();
368
369
// Note that actually there is no need to update the end iterator as this
370
// one
371
// is not affected by changes within hashtables (adding/deleting elements).
372
// Hence, for speedup, we do not update the end iterator
373
}
374
375
// copy operator
376
template
<
typename
Key
,
typename
Alloc
>
377
Set
<
Key
,
Alloc
>&
Set
<
Key
,
Alloc
>::
operator
=(
const
Set
<
Key
,
Alloc
>&
s
) {
378
// avoid self assignment
379
if
(&
s
!=
this
) {
380
// remove the old content of the set. Actually, we remove all the elements
381
// from the underlying hashtable. Note that, doing so, all the hashtable
382
// iterators will be updated as well. In turn, this will imply that,
383
// whenever
384
// an operation will be performed on a SetIteratorSafe, this will raise an
385
// exception.
386
clear
();
387
388
// prepare the set for its new data
389
resize
(
s
.
capacity
());
390
setResizePolicy
(
s
.
resizePolicy
());
391
392
// copy the set
393
_inside_
=
s
.
_inside_
;
394
395
// Note that actually there is no need to update the end iterator as this
396
// one
397
// is not affected by changes within hashtables (adding/deleting
398
// elements).
399
// Hence, for speedup, we do not update the end iterator
400
}
401
402
return
*
this
;
403
}
404
405
// generalized copy operator
406
template
<
typename
Key
,
typename
Alloc
>
407
template
<
typename
OtherAlloc
>
408
Set
<
Key
,
Alloc
>&
Set
<
Key
,
Alloc
>::
operator
=(
const
Set
<
Key
,
OtherAlloc
>&
s
) {
409
// avoid self assignment
410
if
(
this
!=
reinterpret_cast
<
const
Set
<
Key
,
Alloc
>* >(&
s
)) {
411
// remove the old content of the set. Actually, we remove all the elements
412
// from the underlying hashtable. Note that, doing so, all the hashtable
413
// iterators will be updated as well. In turn, this will imply that,
414
// whenever
415
// an operation will be performed on a SetIteratorSafe, this will raise an
416
// exception.
417
clear
();
418
419
// prepare the set for its new data
420
resize
(
s
.
capacity
());
421
setResizePolicy
(
s
.
resizePolicy
());
422
423
// copy the set
424
_inside_
=
s
.
_inside_
;
425
426
// Note that actually there is no need to update the end iterator as this
427
// one
428
// is not affected by changes within hashtables (adding/deleting
429
// elements).
430
// Hence, for speedup, we do not update the end iterator
431
}
432
433
return
*
this
;
434
}
435
436
// move operator
437
template
<
typename
Key
,
typename
Alloc
>
438
Set
<
Key
,
Alloc
>&
Set
<
Key
,
Alloc
>::
operator
=(
Set
<
Key
,
Alloc
>&&
from
) {
439
_inside_
=
std
::
move
(
from
.
_inside_
);
440
return
*
this
;
441
}
442
443
// mathematical equality between two sets
444
template
<
typename
Key
,
typename
Alloc
>
445
template
<
typename
OtherAlloc
>
446
bool
Set
<
Key
,
Alloc
>::
operator
==(
const
Set
<
Key
,
OtherAlloc
>&
s2
)
const
{
447
const
HashTable
<
Key
,
bool
,
OtherAlloc
>&
h2
=
s2
.
_inside_
;
448
449
// check whether both sets have the same number of elements
450
if
(
size
() !=
h2
.
size
())
return
false
;
451
452
// check the content of the sets
453
for
(
HashTableConstIterator
<
Key
,
bool
>
iter
=
_inside_
.
cbegin
();
iter
!=
_inside_
.
cend
();
454
++
iter
) {
455
if
(!
h2
.
exists
(
iter
.
key
()))
return
false
;
456
}
457
458
return
true
;
459
}
460
461
// mathematical inequality between two sets
462
template
<
typename
Key
,
typename
Alloc
>
463
template
<
typename
OtherAlloc
>
464
INLINE
bool
Set
<
Key
,
Alloc
>::
operator
!=(
const
Set
<
Key
,
OtherAlloc
>&
s2
)
const
{
465
return
!(
operator
==(
s2
));
466
}
467
468
// the usual begin iterator to parse the set
469
template
<
typename
Key
,
typename
Alloc
>
470
INLINE
typename
Set
<
Key
,
Alloc
>::
iterator_safe
Set
<
Key
,
Alloc
>::
beginSafe
()
const
{
471
return
SetIteratorSafe
<
Key
>{*
this
};
472
}
473
474
// the usual begin iterator to parse the set
475
template
<
typename
Key
,
typename
Alloc
>
476
INLINE
typename
Set
<
Key
,
Alloc
>::
const_iterator_safe
Set
<
Key
,
Alloc
>::
cbeginSafe
()
const
{
477
return
SetIteratorSafe
<
Key
>{*
this
};
478
}
479
480
// the usual end iterator to parse the set
481
template
<
typename
Key
,
typename
Alloc
>
482
INLINE
const
typename
Set
<
Key
,
Alloc
>::
iterator_safe
&
483
Set
<
Key
,
Alloc
>::
endSafe
()
const
noexcept
{
484
return
*(
485
reinterpret_cast
<
const
SetIteratorSafe
<
Key
>* >(
SetIteratorStaticEnd
::
_SetIterEndSafe_
));
486
}
487
488
// the usual end iterator to parse the set
489
template
<
typename
Key
,
typename
Alloc
>
490
INLINE
const
typename
Set
<
Key
,
Alloc
>::
const_iterator_safe
&
491
Set
<
Key
,
Alloc
>::
cendSafe
()
const
noexcept
{
492
return
*(
493
reinterpret_cast
<
const
SetIteratorSafe
<
Key
>* >(
SetIteratorStaticEnd
::
_SetIterEndSafe_
));
494
}
495
496
// the usual begin iterator to parse the set
497
template
<
typename
Key
,
typename
Alloc
>
498
INLINE
typename
Set
<
Key
,
Alloc
>::
iterator
Set
<
Key
,
Alloc
>::
begin
()
const
{
499
return
SetIterator
<
Key
>{*
this
};
500
}
501
502
// the usual begin iterator to parse the set
503
template
<
typename
Key
,
typename
Alloc
>
504
INLINE
typename
Set
<
Key
,
Alloc
>::
const_iterator
Set
<
Key
,
Alloc
>::
cbegin
()
const
{
505
return
SetIterator
<
Key
>{*
this
};
506
}
507
508
// the usual end iterator to parse the set
509
template
<
typename
Key
,
typename
Alloc
>
510
INLINE
const
typename
Set
<
Key
,
Alloc
>::
iterator
&
Set
<
Key
,
Alloc
>::
end
()
const
noexcept
{
511
return
*(
reinterpret_cast
<
const
SetIterator
<
Key
>* >(
SetIteratorStaticEnd
::
_SetIterEnd_
));
512
}
513
514
// the usual end iterator to parse the set
515
template
<
typename
Key
,
typename
Alloc
>
516
INLINE
const
typename
Set
<
Key
,
Alloc
>::
const_iterator
&
517
Set
<
Key
,
Alloc
>::
cend
()
const
noexcept
{
518
return
*(
reinterpret_cast
<
const
SetIterator
<
Key
>* >(
SetIteratorStaticEnd
::
_SetIterEnd_
));
519
}
520
521
// returns the size of the underlying hashtable containing the set
522
template
<
typename
Key
,
typename
Alloc
>
523
INLINE
Size
Set
<
Key
,
Alloc
>::
capacity
()
const
{
524
return
_inside_
.
capacity
();
525
}
526
527
// changes the size of the underlying hashtable
528
template
<
typename
Key
,
typename
Alloc
>
529
INLINE
void
Set
<
Key
,
Alloc
>::
resize
(
Size
new_size
) {
530
_inside_
.
resize
(
new_size
);
531
532
// Note that actually there is no need to update the end iterator as this
533
// one
534
// is not affected by changes within hashtables (adding/deleting elements).
535
// Hence, for speedup, we do not update the end iterator
536
}
537
538
// enables the user to change dynamically the resizing policy of the
539
// underlying hashtable
540
template
<
typename
Key
,
typename
Alloc
>
541
INLINE
void
Set
<
Key
,
Alloc
>::
setResizePolicy
(
const
bool
new_policy
) {
542
_inside_
.
setResizePolicy
(
new_policy
);
543
544
// Note that actually there is no need to update the end iterator as this
545
// one
546
// is not affected by changes within hashtables (adding/deleting elements).
547
// Hence, for speedup, we do not update the end iterator
548
}
549
550
// returns the current resizing policy of the underlying hashtable
551
template
<
typename
Key
,
typename
Alloc
>
552
INLINE
bool
Set
<
Key
,
Alloc
>::
resizePolicy
()
const
{
553
return
_inside_
.
resizePolicy
();
554
}
555
556
// indicates whether a given elements belong to the set
557
template
<
typename
Key
,
typename
Alloc
>
558
INLINE
bool
Set
<
Key
,
Alloc
>::
contains
(
const
Key
&
k
)
const
{
559
return
_inside_
.
exists
(
k
);
560
}
561
562
563
template
<
typename
Key
,
typename
Alloc
>
564
template
<
typename
OtherAlloc
>
565
INLINE
bool
Set
<
Key
,
Alloc
>::
isProperSubsetOf
(
const
Set
<
Key
,
OtherAlloc
>&
s
)
const
{
566
if
(
this
->
size
() >=
s
.
size
()) {
return
false
; }
567
568
for
(
const
auto
&
elt
: *
this
) {
569
if
(!
s
.
contains
(
elt
)) {
return
false
; }
570
}
571
return
true
;
572
}
573
574
template
<
typename
Key
,
typename
Alloc
>
575
template
<
typename
OtherAlloc
>
576
INLINE
bool
Set
<
Key
,
Alloc
>::
isProperSupersetOf
(
const
Set
<
Key
,
OtherAlloc
>&
s
)
const
{
577
return
s
.
isProperSubsetOf
(*
this
);
578
}
579
580
581
template
<
typename
Key
,
typename
Alloc
>
582
template
<
typename
OtherAlloc
>
583
INLINE
bool
Set
<
Key
,
Alloc
>::
isSubsetOrEqual
(
const
Set
<
Key
,
OtherAlloc
>&
s
)
const
{
584
if
(
this
->
size
() >
s
.
size
()) {
return
false
; }
585
586
for
(
const
auto
&
elt
: *
this
) {
587
if
(!
s
.
contains
(
elt
)) {
return
false
; }
588
}
589
return
true
;
590
}
591
592
template
<
typename
Key
,
typename
Alloc
>
593
template
<
typename
OtherAlloc
>
594
INLINE
bool
Set
<
Key
,
Alloc
>::
isSupersetOrEqual
(
const
Set
<
Key
,
OtherAlloc
>&
s
)
const
{
595
return
s
.
isSubsetOrEqual
(*
this
);
596
}
597
598
// indicates whether a given elements belong to the set
599
template
<
typename
Key
,
typename
Alloc
>
600
INLINE
bool
Set
<
Key
,
Alloc
>::
exists
(
const
Key
&
k
)
const
{
601
return
_inside_
.
exists
(
k
);
602
}
603
604
// inserts a new element in the set
605
template
<
typename
Key
,
typename
Alloc
>
606
INLINE
void
Set
<
Key
,
Alloc
>::
insert
(
const
Key
&
k
) {
607
// WARNING: we shall always test whether k already belongs to the set before
608
// trying to insert it because we set _inside_'s key uniqueness policy to
609
// false
610
if
(!
contains
(
k
)) {
611
// insert the element
612
_inside_
.
insert
(
k
,
true
);
613
614
// Note that actually there is no need to update the end iterator as this
615
// one
616
// is not affected by changes within hashtables (adding/deleting
617
// elements).
618
// Hence, for speedup, we do not update the end iterator
619
}
620
}
621
622
// inserts a new element in the set
623
template
<
typename
Key
,
typename
Alloc
>
624
INLINE
void
Set
<
Key
,
Alloc
>::
insert
(
Key
&&
k
) {
625
// WARNING: we shall always test whether k already belongs to the set before
626
// trying to insert it because we set _inside_'s key uniqueness policy to
627
// false
628
if
(!
contains
(
k
)) {
629
// insert the element
630
_inside_
.
insert
(
std
::
move
(
k
),
true
);
631
632
// Note that actually there is no need to update the end iterator as this
633
// one
634
// is not affected by changes within hashtables (adding/deleting
635
// elements).
636
// Hence, for speedup, we do not update the end iterator
637
}
638
}
639
640
// emplace a new element in the set
641
template
<
typename
Key
,
typename
Alloc
>
642
template
<
typename
...
Args
>
643
INLINE
void
Set
<
Key
,
Alloc
>::
emplace
(
Args
&&...
args
) {
644
insert
(
std
::
move
(
Key
(
std
::
forward
<
Args
>(
args
)...)));
645
}
646
647
// erases an element from the set
648
template
<
typename
Key
,
typename
Alloc
>
649
INLINE
void
Set
<
Key
,
Alloc
>::
erase
(
const
Key
&
k
) {
650
// erase the element (if it exists)
651
_inside_
.
erase
(
k
);
652
653
// Note that actually there is no need to update the end iterator as this
654
// one
655
// is not affected by changes within hashtables (adding/deleting elements).
656
// Hence, for speedup, we do not update the end iterator
657
}
658
659
// erases an element from the set
660
template
<
typename
Key
,
typename
Alloc
>
661
INLINE
void
Set
<
Key
,
Alloc
>::
erase
(
const
SetIteratorSafe
<
Key
>&
iter
) {
662
// erase the element
663
_inside_
.
erase
(
iter
.
_ht_iter_
);
664
665
// Note that actually there is no need to update the end iterator as this
666
// one
667
// is not affected by changes within hashtables (adding/deleting elements).
668
// Hence, for speedup, we do not update the end iterator
669
}
670
671
// adds a new element to the set
672
template
<
typename
Key
,
typename
Alloc
>
673
INLINE
Set
<
Key
,
Alloc
>&
Set
<
Key
,
Alloc
>::
operator
<<(
const
Key
&
k
) {
674
insert
(
k
);
675
return
*
this
;
676
}
677
678
// adds a new element to the set
679
template
<
typename
Key
,
typename
Alloc
>
680
INLINE
Set
<
Key
,
Alloc
>&
Set
<
Key
,
Alloc
>::
operator
<<(
Key
&&
k
) {
681
insert
(
std
::
move
(
k
));
682
return
*
this
;
683
}
684
685
// removes an element from the set
686
template
<
typename
Key
,
typename
Alloc
>
687
INLINE
Set
<
Key
,
Alloc
>&
Set
<
Key
,
Alloc
>::
operator
>>(
const
Key
&
k
) {
688
erase
(
k
);
689
return
*
this
;
690
}
691
692
// returns the number of elements in the set
693
template
<
typename
Key
,
typename
Alloc
>
694
INLINE
Size
Set
<
Key
,
Alloc
>::
size
()
const
noexcept
{
695
return
_inside_
.
size
();
696
}
697
698
// indicates whether the set is the empty set
699
template
<
typename
Key
,
typename
Alloc
>
700
INLINE
bool
Set
<
Key
,
Alloc
>::
empty
()
const
noexcept
{
701
return
_inside_
.
empty
();
702
}
703
704
// Intersection operator
705
template
<
typename
Key
,
typename
Alloc
>
706
template
<
typename
OtherAlloc
>
707
Set
<
Key
,
Alloc
>
Set
<
Key
,
Alloc
>::
operator
*(
const
Set
<
Key
,
OtherAlloc
>&
s2
)
const
{
708
Set
<
Key
,
Alloc
>
res
;
709
const
HashTable
<
Key
,
bool
,
OtherAlloc
>&
h2
=
s2
.
_inside_
;
710
HashTable
<
Key
,
bool
,
Alloc
>&
h_r
=
res
.
_inside_
;
711
712
if
(
size
() <
h2
.
size
()) {
713
for
(
HashTableConstIterator
<
Key
,
bool
>
iter
=
_inside_
.
cbegin
();
iter
!=
_inside_
.
cend
();
714
++
iter
) {
715
if
(
h2
.
exists
(
iter
.
key
()))
h_r
.
insert
(
iter
.
key
(),
true
);
716
}
717
}
else
{
718
for
(
HashTableConstIterator
<
Key
,
bool
>
iter
=
h2
.
cbegin
();
iter
!=
h2
.
cend
(); ++
iter
) {
719
if
(
_inside_
.
exists
(
iter
.
key
()))
h_r
.
insert
(
iter
.
key
(),
true
);
720
}
721
}
722
723
return
res
;
724
}
725
726
727
// Intersection update operator
728
template
<
typename
Key
,
typename
Alloc
>
729
template
<
typename
OtherAlloc
>
730
const
Set
<
Key
,
Alloc
>&
Set
<
Key
,
Alloc
>::
operator
*=(
const
Set
<
Key
,
OtherAlloc
>&
s2
) {
731
if
(&
s2
!=
this
) {
732
const
HashTable
<
Key
,
bool
,
OtherAlloc
>&
h2
=
s2
.
_inside_
;
733
for
(
auto
iter
=
_inside_
.
beginSafe
();
iter
!=
_inside_
.
endSafe
(); ++
iter
) {
734
if
(!
h2
.
exists
(
iter
.
key
()))
_inside_
.
erase
(
iter
);
735
}
736
}
737
738
return
*
this
;
739
}
740
741
742
// Union update operator
743
template
<
typename
Key
,
typename
Alloc
>
744
template
<
typename
OtherAlloc
>
745
const
Set
<
Key
,
Alloc
>&
Set
<
Key
,
Alloc
>::
operator
+=(
const
Set
<
Key
,
OtherAlloc
>&
s2
) {
746
if
(&
s2
!=
this
) {
747
for
(
auto
pair
:
s2
.
_inside_
) {
748
if
(!
_inside_
.
exists
(
pair
.
first
))
_inside_
.
insert
(
pair
.
first
,
true
);
749
}
750
}
751
752
return
*
this
;
753
}
754
755
756
// Union operator
757
template
<
typename
Key
,
typename
Alloc
>
758
template
<
typename
OtherAlloc
>
759
Set
<
Key
,
Alloc
>
Set
<
Key
,
Alloc
>::
operator
+(
const
Set
<
Key
,
OtherAlloc
>&
s2
)
const
{
760
Set
<
Key
,
Alloc
>
res
= *
this
;
761
const
HashTable
<
Key
,
bool
,
OtherAlloc
>&
h2
=
s2
.
_inside_
;
762
HashTable
<
Key
,
bool
,
Alloc
>&
h_r
=
res
.
_inside_
;
763
764
for
(
HashTableConstIterator
<
Key
,
bool
>
iter
=
h2
.
cbegin
();
iter
!=
h2
.
cend
(); ++
iter
) {
765
if
(!
h_r
.
exists
(
iter
.
key
()))
h_r
.
insert
(
iter
.
key
(),
true
);
766
}
767
768
return
res
;
769
}
770
771
772
// Disjunction operator
773
template
<
typename
Key
,
typename
Alloc
>
774
template
<
typename
OtherAlloc
>
775
Set
<
Key
,
Alloc
>
Set
<
Key
,
Alloc
>::
operator
-(
const
Set
<
Key
,
OtherAlloc
>&
s2
)
const
{
776
Set
<
Key
,
Alloc
>
res
;
777
const
HashTable
<
Key
,
bool
,
OtherAlloc
>&
h2
=
s2
.
_inside_
;
778
HashTable
<
Key
,
bool
,
Alloc
>&
h_r
=
res
.
_inside_
;
779
780
for
(
HashTableConstIterator
<
Key
,
bool
>
iter
=
_inside_
.
cbegin
();
iter
!=
_inside_
.
cend
();
781
++
iter
)
782
if
(!
h2
.
exists
(
iter
.
key
()))
h_r
.
insert
(
iter
.
key
(),
true
);
783
784
return
res
;
785
}
786
787
// to display the content of the set
788
template
<
typename
Key
,
typename
Alloc
>
789
INLINE
std
::
string
Set
<
Key
,
Alloc
>::
toString
()
const
{
790
std
::
stringstream
out
;
791
bool
first
=
true
;
792
out
<<
"{"
;
793
794
for
(
iterator
iter
=
begin
();
iter
!=
end
(); ++
iter
) {
795
if
(
first
) {
796
out
<< *
iter
;
797
first
=
false
;
798
}
else
{
799
out
<<
","
<< *
iter
;
800
}
801
}
802
803
out
<<
"}"
;
804
805
std
::
string
res
;
806
out
>>
res
;
807
return
res
;
808
}
809
810
// to friendly display the content of the set
811
template
<
typename
Key
,
typename
Alloc
>
812
std
::
ostream
&
operator
<<(
std
::
ostream
&
stream
,
const
Set
<
Key
,
Alloc
>&
set
) {
813
stream
<<
set
.
toString
();
814
return
stream
;
815
}
816
817
// creates a hashtable of NewKey from the set
818
template
<
typename
Key
,
typename
Alloc
>
819
template
<
typename
NewKey
,
typename
NewAlloc
>
820
HashTable
<
Key
,
NewKey
,
NewAlloc
>
Set
<
Key
,
Alloc
>::
hashMap
(
NewKey
(*
f
)(
const
Key
&),
821
Size
size
)
const
{
822
// determine the proper size of the hashtable
823
// by default, the size of the table is set so that the table does not take
824
// too much space while allowing to add a few elements without resizing
825
if
(
size
== 0)
size
=
std
::
max
(
Size
(2),
_inside_
.
size
() / 2);
826
827
// create a new table
828
HashTable
<
Key
,
NewKey
,
NewAlloc
>
table
(
size
);
829
830
// fill the new hash table
831
for
(
HashTableConstIterator
<
Key
,
bool
>
iter
=
_inside_
.
cbegin
();
iter
!=
_inside_
.
cend
();
832
++
iter
) {
833
table
.
insert
(
iter
.
key
(),
f
(
iter
.
key
()));
834
}
835
836
return
table
;
837
}
838
839
// creates a hashtable of NewKey from the set
840
template
<
typename
Key
,
typename
Alloc
>
841
template
<
typename
NewKey
,
typename
NewAlloc
>
842
HashTable
<
Key
,
NewKey
,
NewAlloc
>
Set
<
Key
,
Alloc
>::
hashMap
(
const
NewKey
&
val
,
843
Size
size
)
const
{
844
// determine the proper size of the hashtable
845
// by default, the size of the table is set so that the table does not take
846
// too much space while allowing to add a few elements without resizing
847
if
(
size
== 0)
size
=
std
::
max
(
Size
(2),
_inside_
.
size
() / 2);
848
849
// create a new table
850
HashTable
<
Key
,
NewKey
,
NewAlloc
>
table
(
size
);
851
852
// fill the new hash table
853
for
(
HashTableConstIterator
<
Key
,
bool
>
iter
=
_inside_
.
cbegin
();
iter
!=
_inside_
.
cend
();
854
++
iter
) {
855
table
.
insert
(
iter
.
key
(),
val
);
856
}
857
858
return
table
;
859
}
860
861
// a method to create a list of NewKey from the set
862
template
<
typename
Key
,
typename
Alloc
>
863
template
<
typename
NewKey
,
typename
NewAlloc
>
864
List
<
NewKey
,
NewAlloc
>
Set
<
Key
,
Alloc
>::
listMap
(
NewKey
(*
f
)(
const
Key
&))
const
{
865
// create a new list
866
List
<
NewKey
,
NewAlloc
>
list
;
867
868
// fill the new list
869
for
(
HashTableConstIterator
<
Key
,
bool
>
iter
=
_inside_
.
cbegin
();
iter
!=
_inside_
.
cend
();
870
++
iter
) {
871
list
.
pushBack
(
f
(
iter
.
key
()));
872
}
873
874
return
list
;
875
}
876
877
// Returns the value of a key as a Size
878
template
<
typename
T
,
typename
Alloc
>
879
INLINE
Size
HashFunc
<
Set
<
T
,
Alloc
> >::
castToSize
(
const
Set
<
T
,
Alloc
>&
key
) {
880
Size
h
=
Size
(0);
881
for
(
const
auto
&
k
:
key
) {
882
const
auto
hs
=
HashFunc
<
T
>::
castToSize
(
k
);
883
h
+=
hs
* (
hs
^
HashFuncConst
::
gold
);
884
}
885
886
return
h
;
887
}
888
889
890
// Returns the hashed value of a key.
891
template
<
typename
T
,
typename
Alloc
>
892
INLINE
Size
HashFunc
<
Set
<
T
,
Alloc
> >::
operator
()(
const
Set
<
T
,
Alloc
>&
key
)
const
{
893
return
(
castToSize
(
key
) *
HashFuncConst
::
gold
) &
this
->
hash_mask_
;
894
}
895
896
}
/* namespace gum */
gum::Set::emplace
INLINE void emplace(Args &&... args)
Definition:
set_tpl.h:643