aGrUM
0.20.2
a C++ library for (probabilistic) graphical models
bijection_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 Class providing generic double hash tables
25
*
26
* @author Jean-Philippe DUBUS, Christophe GONZALES(@AMU) and Pierre-Henri
27
* WUILLEMIN(@LIP6)
28
*/
29
30
// To simply IDE parsing
31
#
include
<
agrum
/
tools
/
core
/
bijection
.
h
>
32
33
namespace
gum
{
34
35
// ===========================================================================
36
// === NON SCALAR BIJECTION IMPLEMENTATION ===
37
// ===========================================================================
38
39
// returns the end iterator for other classes' statics
40
template
<
typename
T1,
typename
T2,
typename
Alloc,
bool
Gen >
41
const
BijectionIteratorSafe< T1, T2 >&
42
BijectionImplementation<
T1
,
T2
,
Alloc
,
Gen
>::
endSafe4Statics
() {
43
return
*(
reinterpret_cast
<
const
BijectionIteratorSafe
<
T1
,
T2
>* >(
44
BijectionIteratorStaticEnd
::
endSafe4Statics
()));
45
}
46
47
// returns the end iterator for other classes' statics
48
template
<
typename
T1
,
typename
T2
,
typename
Alloc
,
bool
Gen
>
49
const
BijectionIterator
<
T1
,
T2
>&
50
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
end4Statics
() {
51
return
*(
reinterpret_cast
<
const
BijectionIterator
<
T1
,
T2
>* >(
52
BijectionIteratorStaticEnd
::
end4Statics
()));
53
}
54
55
// a function that performs a complete copy of another bijection
56
template
<
typename
T1
,
typename
T2
,
typename
Alloc
,
bool
Gen
>
57
template
<
typename
OtherAlloc
>
58
INLINE
void
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
copy__
(
59
const
HashTable
<
T1
,
T2
*,
OtherAlloc
>&
f2s
) {
60
// parse f2s and perform copies
61
for
(
auto
iter
=
f2s
.
cbegin
();
iter
!=
f2s
.
cend
(); ++
iter
) {
62
typename
HashTable12
::
value_type
*
val1
63
= &(
firstToSecond__
.
insert
(
iter
.
key
(),
nullptr
));
64
typename
HashTable21
::
value_type
*
val2
;
65
66
try
{
67
val2
= &(
secondToFirst__
.
insert
(*(
iter
.
val
()),
nullptr
));
68
}
catch
(...) {
69
firstToSecond__
.
erase
(
iter
.
key
());
70
throw
;
71
}
72
73
val1
->
second
= &(
const_cast
<
T2
& >(
val2
->
first
));
74
val2
->
second
= &(
const_cast
<
T1
& >(
val1
->
first
));
75
}
76
77
// note that iter_end__ is actually a constant, whatever we add/remove
78
// to/from firstToSecond__. As a consequence, it need not be updated
79
// after copy__
80
}
81
82
// Default constructor: creates a bijection without association
83
template
<
typename
T1
,
typename
T2
,
typename
Alloc
,
bool
Gen
>
84
INLINE
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
BijectionImplementation
(
85
Size
size
,
86
bool
resize_policy
) :
87
// warning: below, we create the internal hashTables with a key
88
// uniqueness
89
// policy set to false because we will do the uniqueness tests ourselves
90
// (this
91
// will speed-up the process)
92
firstToSecond__
(
size
,
resize_policy
,
false
),
93
secondToFirst__
(
size
,
resize_policy
,
false
) {
94
GUM_CONSTRUCTOR
(
BijectionImplementation
);
95
96
// make sure the end() iterator is constructed properly
97
end4Statics
();
98
endSafe4Statics
();
99
}
100
101
// initializer list constructor
102
template
<
typename
T1
,
typename
T2
,
typename
Alloc
,
bool
Gen
>
103
INLINE
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
BijectionImplementation
(
104
std
::
initializer_list
<
std
::
pair
<
T1
,
T2
> >
list
) :
105
firstToSecond__
(
Size
(
list
.
size
()) / 2,
true
,
false
),
106
secondToFirst__
(
Size
(
list
.
size
()) / 2,
true
,
false
) {
107
GUM_CONSTRUCTOR
(
BijectionImplementation
);
108
109
for
(
const
auto
&
elt
:
list
) {
110
insert
(
elt
.
first
,
elt
.
second
);
111
}
112
113
// make sure the end() iterator is constructed properly
114
end4Statics
();
115
endSafe4Statics
();
116
}
117
118
// Copy constructor
119
template
<
typename
T1
,
typename
T2
,
typename
Alloc
,
bool
Gen
>
120
INLINE
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
BijectionImplementation
(
121
const
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>&
toCopy
) :
122
firstToSecond__
(
toCopy
.
firstToSecond__
.
capacity
(),
true
,
false
),
123
secondToFirst__
(
toCopy
.
secondToFirst__
.
capacity
(),
true
,
false
) {
124
GUM_CONS_CPY
(
BijectionImplementation
);
125
copy__
(
toCopy
.
firstToSecond__
);
126
}
127
128
// Generalized copy constructor
129
template
<
typename
T1
,
typename
T2
,
typename
Alloc
,
bool
Gen
>
130
template
<
typename
OtherAlloc
>
131
INLINE
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
BijectionImplementation
(
132
const
BijectionImplementation
<
T1
,
T2
,
OtherAlloc
,
Gen
>&
toCopy
) :
133
firstToSecond__
(
toCopy
.
firstToSecond__
.
capacity
(),
true
,
false
),
134
secondToFirst__
(
toCopy
.
secondToFirst__
.
capacity
(),
true
,
false
) {
135
GUM_CONS_CPY
(
BijectionImplementation
);
136
copy__
(
toCopy
.
firstToSecond__
);
137
}
138
139
// move constructor
140
template
<
typename
T1
,
typename
T2
,
typename
Alloc
,
bool
Gen
>
141
INLINE
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
BijectionImplementation
(
142
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>&&
from
)
noexcept
:
143
firstToSecond__
(
std
::
move
(
from
.
firstToSecond__
)),
144
secondToFirst__
(
std
::
move
(
from
.
secondToFirst__
)) {
145
GUM_CONS_MOV
(
BijectionImplementation
);
146
}
147
148
// destructor
149
template
<
typename
T1
,
typename
T2
,
typename
Alloc
,
bool
Gen
>
150
INLINE
151
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::~
BijectionImplementation
() {
152
GUM_DESTRUCTOR
(
BijectionImplementation
);
153
}
154
155
// removes all the associations from the bijection
156
template
<
typename
T1
,
typename
T2
,
typename
Alloc
,
bool
Gen
>
157
INLINE
void
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
clear
() {
158
firstToSecond__
.
clear
();
159
secondToFirst__
.
clear
();
160
// note that iter_end__ is actually a constant, whatever we add/remove
161
// to/from firstToSecond__. As a consequence, it need not be updated
162
// after the clear's
163
}
164
165
// Copy operator
166
template
<
typename
T1
,
typename
T2
,
typename
Alloc
,
bool
Gen
>
167
INLINE
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>&
168
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
operator
=(
169
const
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>&
toCopy
) {
170
// avoid self assignment
171
if
(
this
!= &
toCopy
) {
172
clear
();
173
copy__
(
toCopy
.
firstToSecond__
);
174
}
175
176
// note that iter_end__ is actually a constant, whatever we add/remove
177
// to/from firstToSecond__. As a consequence, it need not be updated
178
// after copy__
179
return
*
this
;
180
}
181
182
// Generalized copy operator
183
template
<
typename
T1
,
typename
T2
,
typename
Alloc
,
bool
Gen
>
184
template
<
typename
OtherAlloc
>
185
INLINE
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>&
186
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
operator
=(
187
const
BijectionImplementation
<
T1
,
T2
,
OtherAlloc
,
Gen
>&
toCopy
) {
188
clear
();
189
copy__
(
toCopy
.
firstToSecond__
);
190
191
// note that iter_end__ is actually a constant, whatever we add/remove
192
// to/from firstToSecond__. As a consequence, it need not be updated
193
// after copy__
194
return
*
this
;
195
}
196
197
// move operator
198
template
<
typename
T1
,
typename
T2
,
typename
Alloc
,
bool
Gen
>
199
INLINE
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>&
200
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
operator
=(
201
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>&&
from
) {
202
// avoid self assignment
203
if
(
this
!= &
from
) {
204
clear
();
205
firstToSecond__
=
std
::
move
(
from
.
firstToSecond__
);
206
secondToFirst__
=
std
::
move
(
from
.
secondToFirst__
);
207
}
208
209
// note that iter_end__ is actually a constant, whatever we add/remove
210
// to/from firstToSecond__. As a consequence, it need not be updated
211
// after copy__
212
return
*
this
;
213
}
214
215
// returns the iterator at the beginning of the bijection
216
template
<
typename
T1
,
typename
T2
,
typename
Alloc
,
bool
Gen
>
217
INLINE
typename
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
iterator
218
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
begin
()
const
{
219
return
BijectionIterator
<
T1
,
T2
>{*
this
};
220
}
221
222
// returns the iterator at the beginning of the bijection
223
template
<
typename
T1
,
typename
T2
,
typename
Alloc
,
bool
Gen
>
224
INLINE
typename
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
const_iterator
225
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
cbegin
()
const
{
226
return
BijectionIterator
<
T1
,
T2
>{*
this
};
227
}
228
229
// returns the iterator to the end of the bijection
230
template
<
typename
T1
,
typename
T2
,
typename
Alloc
,
bool
Gen
>
231
INLINE
const
typename
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
iterator
&
232
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
end
()
const
noexcept
{
233
return
*(
reinterpret_cast
<
const
BijectionIterator
<
T1
,
T2
>* >(
234
BijectionIteratorStaticEnd
::
BijectionIterEnd__
));
235
}
236
237
// returns the iterator to the end of the bijection
238
template
<
typename
T1
,
typename
T2
,
typename
Alloc
,
bool
Gen
>
239
INLINE
const
typename
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
240
const_iterator
&
241
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
cend
()
const
noexcept
{
242
return
*(
reinterpret_cast
<
const
BijectionIterator
<
T1
,
T2
>* >(
243
BijectionIteratorStaticEnd
::
BijectionIterEnd__
));
244
}
245
246
// returns the iterator at the beginning of the bijection
247
template
<
typename
T1
,
typename
T2
,
typename
Alloc
,
bool
Gen
>
248
INLINE
typename
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
iterator_safe
249
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
beginSafe
()
const
{
250
return
BijectionIteratorSafe
<
T1
,
T2
>{*
this
};
251
}
252
253
// returns the iterator at the beginning of the bijection
254
template
<
typename
T1
,
typename
T2
,
typename
Alloc
,
bool
Gen
>
255
INLINE
256
typename
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
const_iterator_safe
257
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
cbeginSafe
()
const
{
258
return
BijectionIteratorSafe
<
T1
,
T2
>{*
this
};
259
}
260
261
// returns the iterator to the end of the bijection
262
template
<
typename
T1
,
typename
T2
,
typename
Alloc
,
bool
Gen
>
263
INLINE
const
typename
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
264
iterator_safe
&
265
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
endSafe
()
const
noexcept
{
266
return
*(
reinterpret_cast
<
const
BijectionIteratorSafe
<
T1
,
T2
>* >(
267
BijectionIteratorStaticEnd
::
BijectionIterEndSafe__
));
268
}
269
270
// returns the iterator to the end of the bijection
271
template
<
typename
T1
,
typename
T2
,
typename
Alloc
,
bool
Gen
>
272
INLINE
const
typename
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
273
const_iterator_safe
&
274
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
cendSafe
()
const
noexcept
{
275
return
*(
reinterpret_cast
<
const
BijectionIteratorSafe
<
T1
,
T2
>* >(
276
BijectionIteratorStaticEnd
::
BijectionIterEndSafe__
));
277
}
278
279
// returns the value associated to the element passed in argument
280
template
<
typename
T1
,
typename
T2
,
typename
Alloc
,
bool
Gen
>
281
INLINE
const
T1
&
282
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
first
(
const
T2
&
second
)
const
{
283
return
*(
secondToFirst__
[
second
]);
284
}
285
286
// returns the value associated to the element passed in argument
287
template
<
typename
T1
,
typename
T2
,
typename
Alloc
,
bool
Gen
>
288
INLINE
const
T2
&
289
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
second
(
const
T1
&
first
)
const
{
290
return
*(
firstToSecond__
[
first
]);
291
}
292
293
// Test whether the bijection contains the "first" value
294
template
<
typename
T1
,
typename
T2
,
typename
Alloc
,
bool
Gen
>
295
INLINE
bool
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
existsFirst
(
296
const
T1
&
first
)
const
{
297
return
firstToSecond__
.
exists
(
first
);
298
}
299
300
// Test whether the bijection contains the "second" value
301
template
<
typename
T1
,
typename
T2
,
typename
Alloc
,
bool
Gen
>
302
INLINE
bool
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
existsSecond
(
303
const
T2
&
second
)
const
{
304
return
secondToFirst__
.
exists
(
second
);
305
}
306
307
// inserts a new association in the bijection
308
template
<
typename
T1
,
typename
T2
,
typename
Alloc
,
bool
Gen
>
309
INLINE
typename
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
HashTable12
::
310
value_type
*
311
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
insert__
(
const
T1
&
first
,
312
const
T2
&
second
) {
313
// check the uniqueness property
314
if
(
existsFirst
(
first
) ||
existsSecond
(
second
)) {
315
GUM_ERROR
(
DuplicateElement
,
316
"the bijection contains an element with the same couple ("
317
<<
first
<<
","
<<
second
<<
")"
);
318
}
319
320
// insert copies of first and second
321
typename
HashTable12
::
value_type
*
val1
322
= &(
firstToSecond__
.
insert
(
first
,
nullptr
));
323
typename
HashTable21
::
value_type
*
val2
;
324
325
try
{
326
val2
= &(
secondToFirst__
.
insert
(
second
,
nullptr
));
327
}
catch
(...) {
328
firstToSecond__
.
erase
(
first
);
329
throw
;
330
}
331
332
val1
->
second
= &(
const_cast
<
T2
& >(
val2
->
first
));
333
val2
->
second
= &(
const_cast
<
T1
& >(
val1
->
first
));
334
335
return
val1
;
336
}
337
338
// inserts a new association in the bijection
339
template
<
typename
T1
,
typename
T2
,
typename
Alloc
,
bool
Gen
>
340
INLINE
typename
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
HashTable12
::
341
value_type
*
342
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
insert__
(
T1
&&
first
,
343
T2
&&
second
) {
344
// check the uniqueness property
345
if
(
existsFirst
(
first
) ||
existsSecond
(
second
)) {
346
GUM_ERROR
(
DuplicateElement
,
347
"the bijection contains an element with the same couple ("
348
<<
first
<<
","
<<
second
<<
")"
);
349
}
350
351
// insert copies of first and second
352
typename
HashTable12
::
value_type
*
val1
353
= &(
firstToSecond__
.
insert
(
std
::
move
(
first
),
nullptr
));
354
typename
HashTable21
::
value_type
*
val2
;
355
356
try
{
357
val2
= &(
secondToFirst__
.
insert
(
std
::
move
(
second
),
nullptr
));
358
}
catch
(...) {
359
firstToSecond__
.
erase
(
val1
->
first
);
360
throw
;
361
}
362
363
val1
->
second
= &(
const_cast
<
T2
& >(
val2
->
first
));
364
val2
->
second
= &(
const_cast
<
T1
& >(
val1
->
first
));
365
366
return
val1
;
367
}
368
369
/* @brief Same method as first, but if the value is not found, a default
370
* value is inserted into the bijection */
371
template
<
typename
T1
,
typename
T2
,
typename
Alloc
,
bool
Gen
>
372
INLINE
const
T1
&
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
firstWithDefault
(
373
const
T2
&
second
,
374
const
T1
&
val
)
const
{
375
try
{
376
return
first
(
second
);
377
}
catch
(
NotFound
&) {
return
insert__
(
val
,
second
)->
first
; }
378
}
379
380
/* @brief Same method as second, but if the value is not found, a default
381
* value is inserted into the bijection */
382
template
<
typename
T1
,
typename
T2
,
typename
Alloc
,
bool
Gen
>
383
INLINE
const
T2
&
384
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
secondWithDefault
(
385
const
T1
&
first
,
386
const
T2
&
val
)
const
{
387
try
{
388
return
second
(
first
);
389
}
catch
(
NotFound
&) {
return
*(
insert__
(
first
,
val
)->
second
); }
390
}
391
392
// inserts a new association in the bijection
393
template
<
typename
T1
,
typename
T2
,
typename
Alloc
,
bool
Gen
>
394
INLINE
void
395
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
insert
(
const
T1
&
first
,
396
const
T2
&
second
) {
397
insert__
(
first
,
second
);
398
}
399
400
// inserts a new association in the bijection
401
template
<
typename
T1
,
typename
T2
,
typename
Alloc
,
bool
Gen
>
402
INLINE
void
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
insert
(
T1
&&
first
,
403
T2
&&
second
) {
404
insert__
(
std
::
move
(
first
),
std
::
move
(
second
));
405
}
406
407
// emplace a new element in the bijection
408
template
<
typename
T1
,
typename
T2
,
typename
Alloc
,
bool
Gen
>
409
template
<
typename
...
Args
>
410
INLINE
void
411
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
emplace
(
Args
&&...
args
) {
412
std
::
pair
<
T1
,
T2
>
new_elt
(
std
::
forward
<
Args
>(
args
)...);
413
insert__
(
std
::
move
(
new_elt
.
first
),
std
::
move
(
new_elt
.
second
));
414
}
415
416
// returns true if the bijection doesn't contain any relation
417
template
<
typename
T1
,
typename
T2
,
typename
Alloc
,
bool
Gen
>
418
INLINE
bool
419
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
empty
()
const
noexcept
{
420
GUM_ASSERT
(
firstToSecond__
.
empty
() ==
secondToFirst__
.
empty
());
421
return
firstToSecond__
.
empty
();
422
}
423
424
// returns the number of associations stored within the bijection
425
template
<
typename
T1
,
typename
T2
,
typename
Alloc
,
bool
Gen
>
426
INLINE
Size
427
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
size
()
const
noexcept
{
428
GUM_ASSERT
(
firstToSecond__
.
size
() ==
secondToFirst__
.
size
());
429
return
firstToSecond__
.
size
();
430
}
431
432
// erases an association containing the given first element
433
template
<
typename
T1
,
typename
T2
,
typename
Alloc
,
bool
Gen
>
434
INLINE
void
435
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
eraseFirst
(
const
T1
&
first
) {
436
try
{
437
secondToFirst__
.
erase
(*
firstToSecond__
[
first
]);
438
firstToSecond__
.
erase
(
first
);
439
}
catch
(
NotFound
&) {}
440
}
441
442
// erase an association containing the given second element
443
template
<
typename
T1
,
typename
T2
,
typename
Alloc
,
bool
Gen
>
444
INLINE
void
445
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
eraseSecond
(
const
T2
&
second
) {
446
try
{
447
firstToSecond__
.
erase
(*
secondToFirst__
[
second
]);
448
secondToFirst__
.
erase
(
second
);
449
}
catch
(
NotFound
&) {}
450
}
451
452
// returns the number of hashtables' slots used (@sa hashTable's capacity)
453
template
<
typename
T1
,
typename
T2
,
typename
Alloc
,
bool
Gen
>
454
INLINE
Size
455
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
capacity
()
const
noexcept
{
456
return
firstToSecond__
.
capacity
();
457
}
458
459
// similar to the hashtable's resize
460
template
<
typename
T1
,
typename
T2
,
typename
Alloc
,
bool
Gen
>
461
INLINE
void
462
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
resize
(
Size
new_size
) {
463
firstToSecond__
.
resize
(
new_size
);
464
secondToFirst__
.
resize
(
new_size
);
465
}
466
467
// enables the user to change dynamically the resizing policy
468
template
<
typename
T1
,
typename
T2
,
typename
Alloc
,
bool
Gen
>
469
INLINE
void
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
setResizePolicy
(
470
const
bool
new_policy
)
noexcept
{
471
firstToSecond__
.
setResizePolicy
(
new_policy
);
472
secondToFirst__
.
setResizePolicy
(
new_policy
);
473
}
474
475
// returns the current resizing policy
476
template
<
typename
T1
,
typename
T2
,
typename
Alloc
,
bool
Gen
>
477
INLINE
bool
478
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
resizePolicy
()
const
noexcept
{
479
return
firstToSecond__
.
resizePolicy
();
480
}
481
482
// friendly displays the content of the CliqueGraph
483
template
<
typename
T1
,
typename
T2
,
typename
Alloc
,
bool
Gen
>
484
std
::
string
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>::
toString
()
const
{
485
std
::
stringstream
stream
;
486
stream
<<
"{ "
;
487
bool
first
=
true
;
488
489
for
(
iterator
iter
=
begin
();
iter
!=
end
(); ++
iter
) {
490
if
(!
first
)
491
stream
<<
", "
;
492
else
493
first
=
false
;
494
495
stream
<<
'('
<<
iter
.
first
() <<
" <-> "
<<
iter
.
second
() <<
')'
;
496
}
497
498
stream
<<
" }"
;
499
return
stream
.
str
();
500
}
501
502
// ===========================================================================
503
// === SCALAR BIJECTION IMPLEMENTATION ===
504
// ===========================================================================
505
506
// returns the end iterator for other classes' statics
507
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
508
const
BijectionIteratorSafe
<
T1
,
T2
>&
509
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
endSafe4Statics
() {
510
return
*(
reinterpret_cast
<
const
BijectionIteratorSafe
<
T1
,
T2
>* >(
511
BijectionIteratorStaticEnd
::
endSafe4Statics
()));
512
}
513
514
// returns the end iterator for other classes' statics
515
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
516
const
BijectionIterator
<
T1
,
T2
>&
517
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
end4Statics
() {
518
return
*(
reinterpret_cast
<
const
BijectionIterator
<
T1
,
T2
>* >(
519
BijectionIteratorStaticEnd
::
end4Statics
()));
520
}
521
522
// Default constructor: creates a bijection without association
523
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
524
INLINE
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
BijectionImplementation
(
525
Size
size
,
526
bool
resize_policy
) :
527
// warning: below, we create the internal hashTables with a key
528
// uniqueness
529
// policy set to false because we will do the uniqueness tests ourselves
530
// (this
531
// will speed-up the process)
532
firstToSecond__
(
size
,
resize_policy
,
false
),
533
secondToFirst__
(
size
,
resize_policy
,
false
) {
534
GUM_CONSTRUCTOR
(
BijectionImplementation
);
535
536
// make sure the end() iterator is constructed properly
537
end4Statics
();
538
endSafe4Statics
();
539
}
540
541
// initializer list constructor
542
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
543
INLINE
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
BijectionImplementation
(
544
std
::
initializer_list
<
std
::
pair
<
T1
,
T2
> >
list
) :
545
firstToSecond__
(
Size
(
list
.
size
()) / 2,
true
,
false
),
546
secondToFirst__
(
Size
(
list
.
size
()) / 2,
true
,
false
) {
547
GUM_CONSTRUCTOR
(
BijectionImplementation
);
548
549
for
(
const
auto
&
elt
:
list
) {
550
insert
(
elt
.
first
,
elt
.
second
);
551
}
552
553
// make sure the end() iterator is constructed properly
554
end4Statics
();
555
endSafe4Statics
();
556
}
557
558
// a function that performs a complete copy of another bijection
559
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
560
template
<
typename
OtherAlloc
>
561
INLINE
void
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
copy__
(
562
const
HashTable
<
T1
,
T2
,
OtherAlloc
>&
f2s
) {
563
// parse f2s and perform copies
564
for
(
auto
iter
=
f2s
.
cbegin
();
iter
!=
f2s
.
cend
(); ++
iter
) {
565
firstToSecond__
.
insert
(
iter
.
key
(),
iter
.
val
());
566
567
try
{
568
secondToFirst__
.
insert
(
iter
.
val
(),
iter
.
key
());
569
}
catch
(...) {
570
firstToSecond__
.
erase
(
iter
.
key
());
571
throw
;
572
}
573
}
574
575
// note that iter_end__ is actually a constant, whatever we add/remove
576
// to/from firstToSecond__. As a consequence, it need not be updated
577
// after copy__
578
}
579
580
// Copy constructor
581
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
582
INLINE
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
BijectionImplementation
(
583
const
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>&
toCopy
) :
584
firstToSecond__
(
toCopy
.
firstToSecond__
.
capacity
(),
true
,
false
),
585
secondToFirst__
(
toCopy
.
secondToFirst__
.
capacity
(),
true
,
false
) {
586
GUM_CONS_CPY
(
BijectionImplementation
);
587
copy__
(
toCopy
.
firstToSecond__
);
588
}
589
590
// Generalized copy constructor
591
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
592
template
<
typename
OtherAlloc
>
593
INLINE
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
BijectionImplementation
(
594
const
BijectionImplementation
<
T1
,
T2
,
OtherAlloc
,
true
>&
toCopy
) :
595
firstToSecond__
(
toCopy
.
firstToSecond__
.
capacity
(),
true
,
false
),
596
secondToFirst__
(
toCopy
.
secondToFirst__
.
capacity
(),
true
,
false
) {
597
GUM_CONS_CPY
(
BijectionImplementation
);
598
copy__
(
toCopy
.
firstToSecond__
);
599
}
600
601
// move constructor
602
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
603
INLINE
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
BijectionImplementation
(
604
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>&&
toCopy
)
noexcept
:
605
firstToSecond__
(
std
::
move
(
toCopy
.
firstToSecond__
)),
606
secondToFirst__
(
std
::
move
(
toCopy
.
secondToFirst__
)) {
607
GUM_CONS_MOV
(
BijectionImplementation
);
608
}
609
610
// destructor
611
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
612
INLINE
613
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::~
BijectionImplementation
() {
614
GUM_DESTRUCTOR
(
BijectionImplementation
);
615
}
616
617
// returns the iterator at the beginning of the bijection
618
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
619
INLINE
typename
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
iterator
620
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
begin
()
const
{
621
return
BijectionIterator
<
T1
,
T2
>{*
this
};
622
}
623
624
// returns the iterator at the beginning of the bijection
625
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
626
INLINE
typename
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
const_iterator
627
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
cbegin
()
const
{
628
return
BijectionIterator
<
T1
,
T2
>{*
this
};
629
}
630
631
// returns the iterator to the end of the bijection
632
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
633
INLINE
const
typename
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
iterator
&
634
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
end
()
const
noexcept
{
635
return
*(
reinterpret_cast
<
const
BijectionIterator
<
T1
,
T2
>* >(
636
BijectionIteratorStaticEnd
::
BijectionIterEnd__
));
637
}
638
639
// returns the iterator to the end of the bijection
640
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
641
INLINE
const
typename
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
642
const_iterator
&
643
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
cend
()
const
noexcept
{
644
return
*(
reinterpret_cast
<
const
BijectionIterator
<
T1
,
T2
>* >(
645
BijectionIteratorStaticEnd
::
BijectionIterEnd__
));
646
}
647
648
// returns the iterator at the beginning of the bijection
649
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
650
INLINE
typename
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
iterator_safe
651
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
beginSafe
()
const
{
652
return
BijectionIteratorSafe
<
T1
,
T2
>{*
this
};
653
}
654
655
// returns the iterator at the beginning of the bijection
656
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
657
INLINE
658
typename
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
const_iterator_safe
659
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
cbeginSafe
()
const
{
660
return
BijectionIteratorSafe
<
T1
,
T2
>{*
this
};
661
}
662
663
// returns the iterator to the end of the bijection
664
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
665
INLINE
const
typename
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
666
iterator_safe
&
667
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
endSafe
()
const
noexcept
{
668
return
*(
reinterpret_cast
<
const
BijectionIteratorSafe
<
T1
,
T2
>* >(
669
BijectionIteratorStaticEnd
::
BijectionIterEndSafe__
));
670
}
671
672
// returns the iterator to the end of the bijection
673
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
674
INLINE
const
typename
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
675
const_iterator_safe
&
676
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
cendSafe
()
const
noexcept
{
677
return
*(
reinterpret_cast
<
const
BijectionIteratorSafe
<
T1
,
T2
>* >(
678
BijectionIteratorStaticEnd
::
BijectionIterEndSafe__
));
679
}
680
681
// removes all the associations from the bijection
682
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
683
INLINE
void
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
clear
() {
684
firstToSecond__
.
clear
();
685
secondToFirst__
.
clear
();
686
// note that iter_end__ is actually a constant, whatever we add/remove
687
// to/from firstToSecond__. As a consequence, it need not be updated
688
// after the clear's
689
}
690
691
// Copy operator
692
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
693
INLINE
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>&
694
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
operator
=(
695
const
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>&
toCopy
) {
696
// avoid self assignment
697
if
(
this
!= &
toCopy
) {
698
clear
();
699
copy__
(
toCopy
.
firstToSecond__
);
700
}
701
702
// note that iter_end__ is actually a constant, whatever we add/remove
703
// to/from firstToSecond__. As a consequence, it need not be updated
704
// after copy__
705
return
*
this
;
706
}
707
708
// Generalized copy operator
709
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
710
template
<
typename
OtherAlloc
>
711
INLINE
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>&
712
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
operator
=(
713
const
BijectionImplementation
<
T1
,
T2
,
OtherAlloc
,
true
>&
toCopy
) {
714
clear
();
715
copy__
(
toCopy
.
firstToSecond__
);
716
717
// note that iter_end__ is actually a constant, whatever we add/remove
718
// to/from firstToSecond__. As a consequence, it need not be updated
719
// after copy__
720
return
*
this
;
721
}
722
723
// move operator
724
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
725
INLINE
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>&
726
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
operator
=(
727
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>&&
toCopy
) {
728
// avoid self assignment
729
if
(
this
!= &
toCopy
) {
730
clear
();
731
firstToSecond__
=
std
::
move
(
toCopy
.
firstToSecond__
);
732
secondToFirst__
=
std
::
move
(
toCopy
.
secondToFirst__
);
733
}
734
735
// note that iter_end__ is actually a constant, whatever we add/remove
736
// to/from firstToSecond__. As a consequence, it need not be updated
737
// after copy__
738
return
*
this
;
739
}
740
741
// returns the value associated to the element passed in argument
742
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
743
INLINE
const
T1
&
744
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
first
(
T2
second
)
const
{
745
return
secondToFirst__
[
second
];
746
}
747
748
// returns the value associated to the element passed in argument
749
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
750
INLINE
const
T2
&
751
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
second
(
T1
first
)
const
{
752
return
firstToSecond__
[
first
];
753
}
754
755
// Test whether the bijection contains the "first" value
756
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
757
INLINE
bool
758
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
existsFirst
(
T1
first
)
const
{
759
return
firstToSecond__
.
exists
(
first
);
760
}
761
762
// Test whether the bijection contains the "second" value
763
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
764
INLINE
bool
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
existsSecond
(
765
T2
second
)
const
{
766
return
secondToFirst__
.
exists
(
second
);
767
}
768
769
// inserts a new association in the bijection
770
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
771
INLINE
void
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
insert__
(
T1
first
,
772
T2
second
) {
773
// check the uniqueness property
774
if
(
existsFirst
(
first
) ||
existsSecond
(
second
)) {
775
GUM_ERROR
(
DuplicateElement
,
776
"the bijection contains an element with the same couple ("
777
<<
first
<<
","
<<
second
<<
")"
);
778
}
779
780
// insert copies of first and second
781
firstToSecond__
.
insert
(
first
,
second
);
782
783
try
{
784
secondToFirst__
.
insert
(
second
,
first
);
785
}
catch
(...) {
786
firstToSecond__
.
erase
(
first
);
787
throw
;
788
}
789
}
790
791
// inserts a new association in the bijection
792
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
793
INLINE
void
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
insert
(
T1
first
,
794
T2
second
) {
795
insert__
(
first
,
second
);
796
}
797
798
// emplace a new element in the bijection
799
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
800
template
<
typename
...
Args
>
801
INLINE
void
802
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
emplace
(
Args
&&...
args
) {
803
std
::
pair
<
T1
,
T2
>
new_elt
(
std
::
forward
<
Args
>(
args
)...);
804
insert__
(
new_elt
.
first
,
new_elt
.
second
);
805
}
806
807
/* @brief Same method as first, but if the value is not found, a default
808
* value is inserted into the bijection */
809
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
810
INLINE
const
T1
&
811
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
firstWithDefault
(
812
T2
second
,
813
T1
val
)
const
{
814
try
{
815
return
first
(
second
);
816
}
catch
(
NotFound
&) {
817
insert__
(
val
,
second
);
818
return
val
;
819
}
820
}
821
822
/* @brief Same method as second, but if the value is not found, a default
823
* value is inserted into the bijection */
824
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
825
INLINE
const
T2
&
826
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
secondWithDefault
(
827
T1
first
,
828
T2
val
)
const
{
829
try
{
830
return
second
(
first
);
831
}
catch
(
NotFound
&) {
832
insert__
(
first
,
val
);
833
return
val
;
834
}
835
}
836
837
// returns true if the bijection doesn't contain any relation
838
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
839
INLINE
bool
840
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
empty
()
const
noexcept
{
841
GUM_ASSERT
(
firstToSecond__
.
empty
() ==
secondToFirst__
.
empty
());
842
return
firstToSecond__
.
empty
();
843
}
844
845
// returns the number of associations stored within the bijection
846
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
847
INLINE
Size
848
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
size
()
const
noexcept
{
849
GUM_ASSERT
(
firstToSecond__
.
size
() ==
secondToFirst__
.
size
());
850
return
firstToSecond__
.
size
();
851
}
852
853
// erases an association containing the given first element
854
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
855
INLINE
void
856
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
eraseFirst
(
T1
first
) {
857
try
{
858
secondToFirst__
.
erase
(
firstToSecond__
[
first
]);
859
firstToSecond__
.
erase
(
first
);
860
}
catch
(
NotFound
&) {}
861
}
862
863
// erase an association containing the given second element
864
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
865
INLINE
void
866
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
eraseSecond
(
T2
second
) {
867
try
{
868
firstToSecond__
.
erase
(
secondToFirst__
[
second
]);
869
secondToFirst__
.
erase
(
second
);
870
}
catch
(
NotFound
&) {}
871
}
872
873
// returns the number of hashtables' slots used (@sa hashTable's capacity)
874
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
875
INLINE
Size
876
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
capacity
()
const
noexcept
{
877
return
firstToSecond__
.
capacity
();
878
}
879
880
// similar to the hashtable's resize
881
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
882
INLINE
void
883
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
resize
(
Size
new_size
) {
884
firstToSecond__
.
resize
(
new_size
);
885
secondToFirst__
.
resize
(
new_size
);
886
}
887
888
// enables the user to change dynamically the resizing policy
889
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
890
INLINE
void
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
setResizePolicy
(
891
const
bool
new_policy
)
noexcept
{
892
firstToSecond__
.
setResizePolicy
(
new_policy
);
893
secondToFirst__
.
setResizePolicy
(
new_policy
);
894
}
895
896
// returns the current resizing policy
897
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
898
INLINE
bool
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
resizePolicy
()
899
const
noexcept
{
900
return
firstToSecond__
.
resizePolicy
();
901
}
902
903
// friendly displays the content of the CliqueGraph
904
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
905
std
::
string
BijectionImplementation
<
T1
,
T2
,
Alloc
,
true
>::
toString
()
const
{
906
std
::
stringstream
stream
;
907
stream
<<
"{ "
;
908
bool
first
=
true
;
909
910
for
(
iterator
iter
=
begin
();
iter
!=
end
(); ++
iter
) {
911
if
(!
first
)
912
stream
<<
", "
;
913
else
914
first
=
false
;
915
916
stream
<<
'('
<<
iter
.
first
() <<
" <-> "
<<
iter
.
second
() <<
')'
;
917
}
918
919
stream
<<
" }"
;
920
return
stream
.
str
();
921
}
922
923
// ===========================================================================
924
// === BIJECTION SAFE ITERATORS ===
925
// ===========================================================================
926
927
/// Default constructor
928
template
<
typename
T1
,
typename
T2
>
929
INLINE
BijectionIteratorSafe
<
T1
,
T2
>::
BijectionIteratorSafe
()
noexcept
{
930
GUM_CONSTRUCTOR
(
BijectionIteratorSafe
);
931
}
932
933
/// Constructor
934
template
<
typename
T1
,
typename
T2
>
935
template
<
typename
Alloc
,
bool
Gen
>
936
INLINE
BijectionIteratorSafe
<
T1
,
T2
>::
BijectionIteratorSafe
(
937
const
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>&
bijection
) :
938
iter__
{
bijection
.
firstToSecond__
.
cbeginSafe
()} {
939
GUM_CONSTRUCTOR
(
BijectionIteratorSafe
);
940
}
941
942
/// Constructor
943
template
<
typename
T1
,
typename
T2
>
944
template
<
typename
Alloc
>
945
INLINE
BijectionIteratorSafe
<
T1
,
T2
>::
BijectionIteratorSafe
(
946
const
Bijection
<
T1
,
T2
,
Alloc
>&
bijection
) :
947
iter__
{
bijection
.
firstToSecond__
.
cbeginSafe
()} {
948
GUM_CONSTRUCTOR
(
BijectionIteratorSafe
);
949
}
950
951
/// Copy constructor
952
template
<
typename
T1
,
typename
T2
>
953
INLINE
BijectionIteratorSafe
<
T1
,
T2
>::
BijectionIteratorSafe
(
954
const
BijectionIteratorSafe
<
T1
,
T2
>&
toCopy
) :
955
iter__
{
toCopy
.
iter__
} {
956
GUM_CONS_CPY
(
BijectionIteratorSafe
);
957
}
958
959
/// move constructor
960
template
<
typename
T1
,
typename
T2
>
961
INLINE
BijectionIteratorSafe
<
T1
,
T2
>::
BijectionIteratorSafe
(
962
BijectionIteratorSafe
<
T1
,
T2
>&&
from
)
noexcept
:
963
iter__
{
std
::
move
(
from
.
iter__
)} {
964
GUM_CONS_MOV
(
BijectionIteratorSafe
);
965
}
966
967
/// Destructor
968
template
<
typename
T1
,
typename
T2
>
969
INLINE
BijectionIteratorSafe
<
T1
,
T2
>::~
BijectionIteratorSafe
()
noexcept
{
970
GUM_DESTRUCTOR
(
BijectionIteratorSafe
);
971
}
972
973
/// Copy operator
974
template
<
typename
T1
,
typename
T2
>
975
INLINE
BijectionIteratorSafe
<
T1
,
T2
>&
976
BijectionIteratorSafe
<
T1
,
T2
>::
operator
=(
977
const
BijectionIteratorSafe
<
T1
,
T2
>&
toCopy
) {
978
iter__
=
toCopy
.
iter__
;
979
return
*
this
;
980
}
981
982
/// move operator
983
template
<
typename
T1
,
typename
T2
>
984
INLINE
BijectionIteratorSafe
<
T1
,
T2
>&
985
BijectionIteratorSafe
<
T1
,
T2
>::
operator
=(
986
BijectionIteratorSafe
<
T1
,
T2
>&&
toCopy
)
noexcept
{
987
iter__
=
std
::
move
(
toCopy
.
iter__
);
988
return
*
this
;
989
}
990
991
/// Go to the next association (if exists)
992
template
<
typename
T1
,
typename
T2
>
993
INLINE
BijectionIteratorSafe
<
T1
,
T2
>&
994
BijectionIteratorSafe
<
T1
,
T2
>::
operator
++()
noexcept
{
995
++
iter__
;
996
return
*
this
;
997
}
998
999
/// moves the iterator by nb elements
1000
template
<
typename
T1
,
typename
T2
>
1001
INLINE
BijectionIteratorSafe
<
T1
,
T2
>&
1002
BijectionIteratorSafe
<
T1
,
T2
>::
operator
+=(
Size
nb
)
noexcept
{
1003
iter__
+=
nb
;
1004
return
*
this
;
1005
}
1006
1007
/// returns a new iterator
1008
template
<
typename
T1
,
typename
T2
>
1009
INLINE
BijectionIteratorSafe
<
T1
,
T2
>
1010
BijectionIteratorSafe
<
T1
,
T2
>::
operator
+(
Size
nb
)
noexcept
{
1011
return
BijectionIteratorSafe
<
T1
,
T2
>{*
this
} +=
nb
;
1012
}
1013
1014
/// Comparison of iterators
1015
template
<
typename
T1
,
typename
T2
>
1016
INLINE
bool
BijectionIteratorSafe
<
T1
,
T2
>::
operator
!=(
1017
const
BijectionIteratorSafe
<
T1
,
T2
>&
toCompare
)
const
noexcept
{
1018
return
iter__
!=
toCompare
.
iter__
;
1019
}
1020
1021
/// Comparison of iterators
1022
template
<
typename
T1
,
typename
T2
>
1023
INLINE
bool
BijectionIteratorSafe
<
T1
,
T2
>::
operator
==(
1024
const
BijectionIteratorSafe
<
T1
,
T2
>&
toCompare
)
const
noexcept
{
1025
return
iter__
==
toCompare
.
iter__
;
1026
}
1027
1028
/// return the first element of the current association
1029
template
<
typename
T1
,
typename
T2
>
1030
INLINE
const
T1
&
BijectionIteratorSafe
<
T1
,
T2
>::
first
()
const
{
1031
return
iter__
.
key
();
1032
}
1033
1034
/// return the second element of the current association
1035
template
<
typename
T1
,
typename
T2
>
1036
INLINE
const
T2
&
BijectionIteratorSafe
<
T1
,
T2
>::
second
()
const
{
1037
return
Getter
::
op_second
(
iter__
.
val
());
1038
}
1039
1040
/* ===========================================================================
1041
*/
1042
/* === BIJECTION UNSAFE ITERATORS ===
1043
*/
1044
/* ===========================================================================
1045
*/
1046
1047
/// Default constructor
1048
template
<
typename
T1
,
typename
T2
>
1049
INLINE
BijectionIterator
<
T1
,
T2
>::
BijectionIterator
()
noexcept
{
1050
GUM_CONSTRUCTOR
(
BijectionIterator
);
1051
}
1052
1053
/// Constructor
1054
template
<
typename
T1
,
typename
T2
>
1055
template
<
typename
Alloc
,
bool
Gen
>
1056
INLINE
BijectionIterator
<
T1
,
T2
>::
BijectionIterator
(
1057
const
BijectionImplementation
<
T1
,
T2
,
Alloc
,
Gen
>&
bijection
) :
1058
iter__
{
bijection
.
firstToSecond__
.
cbegin
()} {
1059
GUM_CONSTRUCTOR
(
BijectionIterator
);
1060
}
1061
1062
/// Constructor
1063
template
<
typename
T1
,
typename
T2
>
1064
template
<
typename
Alloc
>
1065
INLINE
BijectionIterator
<
T1
,
T2
>::
BijectionIterator
(
1066
const
Bijection
<
T1
,
T2
,
Alloc
>&
bijection
) :
1067
iter__
{
bijection
.
firstToSecond__
.
cbegin
()} {
1068
GUM_CONSTRUCTOR
(
BijectionIterator
);
1069
}
1070
1071
/// Copy constructor
1072
template
<
typename
T1
,
typename
T2
>
1073
INLINE
BijectionIterator
<
T1
,
T2
>::
BijectionIterator
(
1074
const
BijectionIterator
<
T1
,
T2
>&
toCopy
) :
1075
iter__
{
toCopy
.
iter__
} {
1076
GUM_CONS_CPY
(
BijectionIterator
);
1077
}
1078
1079
/// move constructor
1080
template
<
typename
T1
,
typename
T2
>
1081
INLINE
BijectionIterator
<
T1
,
T2
>::
BijectionIterator
(
1082
BijectionIterator
<
T1
,
T2
>&&
from
)
noexcept
:
1083
iter__
{
std
::
move
(
from
.
iter__
)} {
1084
GUM_CONS_MOV
(
BijectionIterator
);
1085
}
1086
1087
/// Destructor
1088
template
<
typename
T1
,
typename
T2
>
1089
INLINE
BijectionIterator
<
T1
,
T2
>::~
BijectionIterator
()
noexcept
{
1090
GUM_DESTRUCTOR
(
BijectionIterator
);
1091
}
1092
1093
/// Copy operator
1094
template
<
typename
T1
,
typename
T2
>
1095
INLINE
BijectionIterator
<
T1
,
T2
>&
BijectionIterator
<
T1
,
T2
>::
operator
=(
1096
const
BijectionIterator
<
T1
,
T2
>&
toCopy
) {
1097
iter__
=
toCopy
.
iter__
;
1098
return
*
this
;
1099
}
1100
1101
/// move operator
1102
template
<
typename
T1
,
typename
T2
>
1103
INLINE
BijectionIterator
<
T1
,
T2
>&
BijectionIterator
<
T1
,
T2
>::
operator
=(
1104
BijectionIterator
<
T1
,
T2
>&&
toCopy
)
noexcept
{
1105
iter__
=
std
::
move
(
toCopy
.
iter__
);
1106
return
*
this
;
1107
}
1108
1109
/// Go to the next association (if exists)
1110
template
<
typename
T1
,
typename
T2
>
1111
INLINE
BijectionIterator
<
T1
,
T2
>&
1112
BijectionIterator
<
T1
,
T2
>::
operator
++()
noexcept
{
1113
++
iter__
;
1114
return
*
this
;
1115
}
1116
1117
/// moves the iterator by nb elements
1118
template
<
typename
T1
,
typename
T2
>
1119
INLINE
BijectionIterator
<
T1
,
T2
>&
1120
BijectionIterator
<
T1
,
T2
>::
operator
+=(
Size
nb
)
noexcept
{
1121
iter__
+=
nb
;
1122
return
*
this
;
1123
}
1124
1125
/// returns a new iterator
1126
template
<
typename
T1
,
typename
T2
>
1127
INLINE
BijectionIterator
<
T1
,
T2
>
1128
BijectionIterator
<
T1
,
T2
>::
operator
+(
Size
nb
)
noexcept
{
1129
return
BijectionIterator
<
T1
,
T2
>{*
this
} +=
nb
;
1130
}
1131
1132
/// Comparison of iterators
1133
template
<
typename
T1
,
typename
T2
>
1134
INLINE
bool
BijectionIterator
<
T1
,
T2
>::
operator
!=(
1135
const
BijectionIterator
<
T1
,
T2
>&
toCompare
)
const
noexcept
{
1136
return
iter__
!=
toCompare
.
iter__
;
1137
}
1138
1139
/// Comparison of iterators
1140
template
<
typename
T1
,
typename
T2
>
1141
INLINE
bool
BijectionIterator
<
T1
,
T2
>::
operator
==(
1142
const
BijectionIterator
<
T1
,
T2
>&
toCompare
)
const
noexcept
{
1143
return
iter__
==
toCompare
.
iter__
;
1144
}
1145
1146
/// return the first element of the current association
1147
template
<
typename
T1
,
typename
T2
>
1148
INLINE
const
T1
&
BijectionIterator
<
T1
,
T2
>::
first
()
const
{
1149
return
iter__
.
key
();
1150
}
1151
1152
/// return the second element of the current association
1153
template
<
typename
T1
,
typename
T2
>
1154
INLINE
const
T2
&
BijectionIterator
<
T1
,
T2
>::
second
()
const
{
1155
return
Getter
::
op_second
(
iter__
.
val
());
1156
}
1157
1158
// ============================================================================
1159
// BIJECTION
1160
// ============================================================================
1161
1162
// Default constructor: creates a bijection without any association
1163
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
1164
INLINE
Bijection
<
T1
,
T2
,
Alloc
>::
Bijection
(
Size
size
,
bool
resize_policy
) :
1165
BijectionImplementation
<
T1
,
1166
T2
,
1167
Alloc
,
1168
std
::
is_scalar
<
T1
>::
value
1169
&&
std
::
is_scalar
<
T2
>::
value
>(
size
,
1170
resize_policy
) {
1171
GUM_CONSTRUCTOR
(
Bijection
);
1172
}
1173
1174
// initializer list constructor
1175
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
1176
INLINE
Bijection
<
T1
,
T2
,
Alloc
>::
Bijection
(
1177
std
::
initializer_list
<
std
::
pair
<
T1
,
T2
> >
list
) :
1178
BijectionImplementation
<
T1
,
1179
T2
,
1180
Alloc
,
1181
std
::
is_scalar
<
T1
>::
value
1182
&&
std
::
is_scalar
<
T2
>::
value
>(
list
) {
1183
GUM_CONSTRUCTOR
(
Bijection
);
1184
}
1185
1186
// Copy constructor
1187
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
1188
INLINE
Bijection
<
T1
,
T2
,
Alloc
>::
Bijection
(
1189
const
Bijection
<
T1
,
T2
,
Alloc
>&
toCopy
) :
1190
BijectionImplementation
<
T1
,
1191
T2
,
1192
Alloc
,
1193
std
::
is_scalar
<
T1
>::
value
1194
&&
std
::
is_scalar
<
T2
>::
value
>(
toCopy
) {
1195
GUM_CONS_CPY
(
Bijection
);
1196
}
1197
1198
// Generalized copy constructor
1199
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
1200
template
<
typename
OtherAlloc
>
1201
INLINE
Bijection
<
T1
,
T2
,
Alloc
>::
Bijection
(
1202
const
Bijection
<
T1
,
T2
,
OtherAlloc
>&
toCopy
) :
1203
BijectionImplementation
<
T1
,
1204
T2
,
1205
Alloc
,
1206
std
::
is_scalar
<
T1
>::
value
1207
&&
std
::
is_scalar
<
T2
>::
value
>(
toCopy
) {
1208
GUM_CONS_CPY
(
Bijection
);
1209
}
1210
1211
// move constructor
1212
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
1213
INLINE
Bijection
<
T1
,
T2
,
Alloc
>::
Bijection
(
1214
Bijection
<
T1
,
T2
,
Alloc
>&&
from
)
noexcept
:
1215
BijectionImplementation
<
T1
,
1216
T2
,
1217
Alloc
,
1218
std
::
is_scalar
<
T1
>::
value
1219
&&
std
::
is_scalar
<
T2
>::
value
>(
1220
std
::
move
(
from
)) {
1221
GUM_CONS_MOV
(
Bijection
);
1222
}
1223
1224
// destructor
1225
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
1226
INLINE
Bijection
<
T1
,
T2
,
Alloc
>::~
Bijection
() {
1227
GUM_DESTRUCTOR
(
Bijection
);
1228
}
1229
1230
// copy operator
1231
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
1232
INLINE
Bijection
<
T1
,
T2
,
Alloc
>&
Bijection
<
T1
,
T2
,
Alloc
>::
operator
=(
1233
const
Bijection
<
T1
,
T2
,
Alloc
>&
toCopy
) {
1234
Implementation
::
operator
=(
toCopy
);
1235
return
*
this
;
1236
}
1237
1238
// generalized copy operator
1239
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
1240
template
<
typename
OtherAlloc
>
1241
INLINE
Bijection
<
T1
,
T2
,
Alloc
>&
Bijection
<
T1
,
T2
,
Alloc
>::
operator
=(
1242
const
Bijection
<
T1
,
T2
,
OtherAlloc
>&
toCopy
) {
1243
Implementation
::
operator
=(
toCopy
);
1244
return
*
this
;
1245
}
1246
1247
// move operator
1248
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
1249
INLINE
Bijection
<
T1
,
T2
,
Alloc
>&
1250
Bijection
<
T1
,
T2
,
Alloc
>::
operator
=(
Bijection
<
T1
,
T2
,
Alloc
>&&
bij
) {
1251
Implementation
::
operator
=(
std
::
move
(
bij
));
1252
return
*
this
;
1253
}
1254
1255
// for friendly displaying the content of bijections
1256
template
<
typename
T1
,
typename
T2
,
typename
Alloc
>
1257
std
::
ostream
&
operator
<<(
std
::
ostream
&
stream
,
1258
const
Bijection
<
T1
,
T2
,
Alloc
>&
b
) {
1259
stream
<<
b
.
toString
();
1260
return
stream
;
1261
}
1262
1263
}
/* namespace gum */
gum::Set::emplace
INLINE void emplace(Args &&... args)
Definition:
set_tpl.h:669