aGrUM  0.14.1
bijection_tpl.h
Go to the documentation of this file.
1 /**************************************************************************
2  * Copyright (C) 2005 by Christophe GONZALES and Pierre-Henri WUILLEMIN *
3  * {prenom.nom}_at_lip6.fr *
4  * *
5  * This program is free software; you can redistribute it and/or modify *
6  * it under the terms of the GNU General Public License as published by *
7  * the Free Software Foundation; either version 2 of the License, or *
8  * (at your option) any later version. *
9  * *
10  * This program is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU General Public License *
16  * along with this program; if not, write to the *
17  * Free Software Foundation, Inc., *
18  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19  ***************************************************************************/
27 // To simply IDE parsing
28 #include <agrum/core/bijection.h>
29 
30 namespace gum {
31 
32  // ===========================================================================
33  // === NON SCALAR BIJECTION IMPLEMENTATION ===
34  // ===========================================================================
35 
36  // returns the end iterator for other classes' statics
37  template < typename T1, typename T2, typename Alloc, bool Gen >
38  const BijectionIteratorSafe< T1, T2 >&
40  return *(reinterpret_cast< const BijectionIteratorSafe< T1, T2 >* >(
42  }
43 
44  // returns the end iterator for other classes' statics
45  template < typename T1, typename T2, typename Alloc, bool Gen >
48  return *(reinterpret_cast< const BijectionIterator< T1, T2 >* >(
50  }
51 
52  // a function that performs a complete copy of another bijection
53  template < typename T1, typename T2, typename Alloc, bool Gen >
54  template < typename OtherAlloc >
57  // parse f2s and perform copies
58  for (auto iter = f2s.cbegin(); iter != f2s.cend(); ++iter) {
59  typename HashTable12::value_type* val1 =
60  &(__firstToSecond.insert(iter.key(), nullptr));
61  typename HashTable21::value_type* val2;
62 
63  try {
64  val2 = &(__secondToFirst.insert(*(iter.val()), nullptr));
65  } catch (...) {
66  __firstToSecond.erase(iter.key());
67  throw;
68  }
69 
70  val1->second = &(const_cast< T2& >(val2->first));
71  val2->second = &(const_cast< T1& >(val1->first));
72  }
73 
74  // note that __iter_end is actually a constant, whatever we add/remove
75  // to/from __firstToSecond. As a consequence, it need not be updated
76  // after __copy
77  }
78 
79  // Default constructor: creates a bijection without association
80  template < typename T1, typename T2, typename Alloc, bool Gen >
82  Size size, bool resize_policy) :
83  // warning: below, we create the internal hashTables with a key
84  // uniqueness
85  // policy set to false because we will do the uniqueness tests ourselves
86  // (this
87  // will speed-up the process)
88  __firstToSecond(size, resize_policy, false),
89  __secondToFirst(size, resize_policy, false) {
90  GUM_CONSTRUCTOR(BijectionImplementation);
91 
92  // make sure the end() iterator is constructed properly
93  end4Statics();
94  endSafe4Statics();
95  }
96 
97  // initializer list constructor
98  template < typename T1, typename T2, typename Alloc, bool Gen >
100  std::initializer_list< std::pair< T1, T2 > > list) :
101  __firstToSecond(Size(list.size()) / 2, true, false),
102  __secondToFirst(Size(list.size()) / 2, true, false) {
103  GUM_CONSTRUCTOR(BijectionImplementation);
104 
105  for (const auto& elt : list) {
106  insert(elt.first, elt.second);
107  }
108 
109  // make sure the end() iterator is constructed properly
110  end4Statics();
111  endSafe4Statics();
112  }
113 
114  // Copy constructor
115  template < typename T1, typename T2, typename Alloc, bool Gen >
118  __firstToSecond(toCopy.__firstToSecond.capacity(), true, false),
119  __secondToFirst(toCopy.__secondToFirst.capacity(), true, false) {
120  GUM_CONS_CPY(BijectionImplementation);
121  __copy(toCopy.__firstToSecond);
122  }
123 
124  // Generalized copy constructor
125  template < typename T1, typename T2, typename Alloc, bool Gen >
126  template < typename OtherAlloc >
129  __firstToSecond(toCopy.__firstToSecond.capacity(), true, false),
130  __secondToFirst(toCopy.__secondToFirst.capacity(), true, false) {
131  GUM_CONS_CPY(BijectionImplementation);
132  __copy(toCopy.__firstToSecond);
133  }
134 
135  // move constructor
136  template < typename T1, typename T2, typename Alloc, bool Gen >
139  __firstToSecond(std::move(from.__firstToSecond)),
140  __secondToFirst(std::move(from.__secondToFirst)) {
141  GUM_CONS_MOV(BijectionImplementation);
142  }
143 
144  // destructor
145  template < typename T1, typename T2, typename Alloc, bool Gen >
146  INLINE
148  GUM_DESTRUCTOR(BijectionImplementation);
149  }
150 
151  // removes all the associations from the bijection
152  template < typename T1, typename T2, typename Alloc, bool Gen >
154  __firstToSecond.clear();
155  __secondToFirst.clear();
156  // note that __iter_end is actually a constant, whatever we add/remove
157  // to/from __firstToSecond. As a consequence, it need not be updated
158  // after the clear's
159  }
160 
161  // Copy operator
162  template < typename T1, typename T2, typename Alloc, bool Gen >
166  // avoid self assignment
167  if (this != &toCopy) {
168  clear();
169  __copy(toCopy.__firstToSecond);
170  }
171 
172  // note that __iter_end is actually a constant, whatever we add/remove
173  // to/from __firstToSecond. As a consequence, it need not be updated
174  // after __copy
175  return *this;
176  }
177 
178  // Generalized copy operator
179  template < typename T1, typename T2, typename Alloc, bool Gen >
180  template < typename OtherAlloc >
184  clear();
185  __copy(toCopy.__firstToSecond);
186 
187  // note that __iter_end is actually a constant, whatever we add/remove
188  // to/from __firstToSecond. As a consequence, it need not be updated
189  // after __copy
190  return *this;
191  }
192 
193  // move operator
194  template < typename T1, typename T2, typename Alloc, bool Gen >
198  // avoid self assignment
199  if (this != &from) {
200  clear();
201  __firstToSecond = std::move(from.__firstToSecond);
202  __secondToFirst = std::move(from.__secondToFirst);
203  }
204 
205  // note that __iter_end is actually a constant, whatever we add/remove
206  // to/from __firstToSecond. As a consequence, it need not be updated
207  // after __copy
208  return *this;
209  }
210 
211  // returns the iterator at the beginning of the bijection
212  template < typename T1, typename T2, typename Alloc, bool Gen >
215  return BijectionIterator< T1, T2 >{*this};
216  }
217 
218  // returns the iterator at the beginning of the bijection
219  template < typename T1, typename T2, typename Alloc, bool Gen >
222  return BijectionIterator< T1, T2 >{*this};
223  }
224 
225  // returns the iterator to the end of the bijection
226  template < typename T1, typename T2, typename Alloc, bool Gen >
229  return *(reinterpret_cast< const BijectionIterator< T1, T2 >* >(
230  BijectionIteratorStaticEnd::__BijectionIterEnd));
231  }
232 
233  // returns the iterator to the end of the bijection
234  template < typename T1, typename T2, typename Alloc, bool Gen >
235  INLINE const typename BijectionImplementation< T1, T2, Alloc, Gen >::
236  const_iterator&
238  return *(reinterpret_cast< const BijectionIterator< T1, T2 >* >(
239  BijectionIteratorStaticEnd::__BijectionIterEnd));
240  }
241 
242  // returns the iterator at the beginning of the bijection
243  template < typename T1, typename T2, typename Alloc, bool Gen >
246  return BijectionIteratorSafe< T1, T2 >{*this};
247  }
248 
249  // returns the iterator at the beginning of the bijection
250  template < typename T1, typename T2, typename Alloc, bool Gen >
251  INLINE
254  return BijectionIteratorSafe< T1, T2 >{*this};
255  }
256 
257  // returns the iterator to the end of the bijection
258  template < typename T1, typename T2, typename Alloc, bool Gen >
259  INLINE const typename BijectionImplementation< T1, T2, Alloc, Gen >::
260  iterator_safe&
262  return *(reinterpret_cast< const BijectionIteratorSafe< T1, T2 >* >(
263  BijectionIteratorStaticEnd::__BijectionIterEndSafe));
264  }
265 
266  // returns the iterator to the end of the bijection
267  template < typename T1, typename T2, typename Alloc, bool Gen >
268  INLINE const typename BijectionImplementation< T1, T2, Alloc, Gen >::
269  const_iterator_safe&
271  return *(reinterpret_cast< const BijectionIteratorSafe< T1, T2 >* >(
272  BijectionIteratorStaticEnd::__BijectionIterEndSafe));
273  }
274 
275  // returns the value associated to the element passed in argument
276  template < typename T1, typename T2, typename Alloc, bool Gen >
277  INLINE const T1&
279  return *(__secondToFirst[second]);
280  }
281 
282  // returns the value associated to the element passed in argument
283  template < typename T1, typename T2, typename Alloc, bool Gen >
284  INLINE const T2&
286  return *(__firstToSecond[first]);
287  }
288 
289  // Test whether the bijection contains the "first" value
290  template < typename T1, typename T2, typename Alloc, bool Gen >
292  const T1& first) const {
293  return __firstToSecond.exists(first);
294  }
295 
296  // Test whether the bijection contains the "second" value
297  template < typename T1, typename T2, typename Alloc, bool Gen >
299  const T2& second) const {
300  return __secondToFirst.exists(second);
301  }
302 
303  // inserts a new association in the bijection
304  template < typename T1, typename T2, typename Alloc, bool Gen >
306  value_type*
308  const T2& second) {
309  // check the uniqueness property
310  if (existsFirst(first) || existsSecond(second)) {
312  "the bijection contains an element with the same couple ("
313  << first << "," << second << ")");
314  }
315 
316  // insert copies of first and second
317  typename HashTable12::value_type* val1 =
318  &(__firstToSecond.insert(first, nullptr));
319  typename HashTable21::value_type* val2;
320 
321  try {
322  val2 = &(__secondToFirst.insert(second, nullptr));
323  } catch (...) {
324  __firstToSecond.erase(first);
325  throw;
326  }
327 
328  val1->second = &(const_cast< T2& >(val2->first));
329  val2->second = &(const_cast< T1& >(val1->first));
330 
331  return val1;
332  }
333 
334  // inserts a new association in the bijection
335  template < typename T1, typename T2, typename Alloc, bool Gen >
337  value_type*
339  T2&& second) {
340  // check the uniqueness property
341  if (existsFirst(first) || existsSecond(second)) {
343  "the bijection contains an element with the same couple ("
344  << first << "," << second << ")");
345  }
346 
347  // insert copies of first and second
348  typename HashTable12::value_type* val1 =
349  &(__firstToSecond.insert(std::move(first), nullptr));
350  typename HashTable21::value_type* val2;
351 
352  try {
353  val2 = &(__secondToFirst.insert(std::move(second), nullptr));
354  } catch (...) {
355  __firstToSecond.erase(val1->first);
356  throw;
357  }
358 
359  val1->second = &(const_cast< T2& >(val2->first));
360  val2->second = &(const_cast< T1& >(val1->first));
361 
362  return val1;
363  }
364 
365  /* @brief Same method as first, but if the value is not found, a default
366  * value is inserted into the bijection */
367  template < typename T1, typename T2, typename Alloc, bool Gen >
369  const T2& second, const T1& val) const {
370  try {
371  return first(second);
372  } catch (NotFound&) { return __insert(val, second)->first; }
373  }
374 
375  /* @brief Same method as second, but if the value is not found, a default
376  * value is inserted into the bijection */
377  template < typename T1, typename T2, typename Alloc, bool Gen >
378  INLINE const T2&
380  const T1& first, const T2& val) const {
381  try {
382  return second(first);
383  } catch (NotFound&) { return *(__insert(first, val)->second); }
384  }
385 
386  // inserts a new association in the bijection
387  template < typename T1, typename T2, typename Alloc, bool Gen >
388  INLINE void
390  const T2& second) {
391  __insert(first, second);
392  }
393 
394  // inserts a new association in the bijection
395  template < typename T1, typename T2, typename Alloc, bool Gen >
397  T2&& second) {
398  __insert(std::move(first), std::move(second));
399  }
400 
401  // emplace a new element in the bijection
402  template < typename T1, typename T2, typename Alloc, bool Gen >
403  template < typename... Args >
404  INLINE void
406  std::pair< T1, T2 > new_elt(std::forward< Args >(args)...);
407  __insert(std::move(new_elt.first), std::move(new_elt.second));
408  }
409 
410  // returns true if the bijection doesn't contain any relation
411  template < typename T1, typename T2, typename Alloc, bool Gen >
413  noexcept {
414  GUM_ASSERT(__firstToSecond.empty() == __secondToFirst.empty());
415  return __firstToSecond.empty();
416  }
417 
418  // returns the number of associations stored within the bijection
419  template < typename T1, typename T2, typename Alloc, bool Gen >
421  noexcept {
422  GUM_ASSERT(__firstToSecond.size() == __secondToFirst.size());
423  return __firstToSecond.size();
424  }
425 
426  // erases an association containing the given first element
427  template < typename T1, typename T2, typename Alloc, bool Gen >
428  INLINE void
430  try {
431  __secondToFirst.erase(*__firstToSecond[first]);
432  __firstToSecond.erase(first);
433  } catch (NotFound&) {}
434  }
435 
436  // erase an association containing the given second element
437  template < typename T1, typename T2, typename Alloc, bool Gen >
438  INLINE void
440  try {
441  __firstToSecond.erase(*__secondToFirst[second]);
442  __secondToFirst.erase(second);
443  } catch (NotFound&) {}
444  }
445 
446  // returns the number of hashtables' slots used (@sa hashTable's capacity)
447  template < typename T1, typename T2, typename Alloc, bool Gen >
449  noexcept {
450  return __firstToSecond.capacity();
451  }
452 
453  // similar to the hashtable's resize
454  template < typename T1, typename T2, typename Alloc, bool Gen >
455  INLINE void
457  __firstToSecond.resize(new_size);
458  __secondToFirst.resize(new_size);
459  }
460 
461  // enables the user to change dynamically the resizing policy
462  template < typename T1, typename T2, typename Alloc, bool Gen >
464  const bool new_policy) noexcept {
465  __firstToSecond.setResizePolicy(new_policy);
466  __secondToFirst.setResizePolicy(new_policy);
467  }
468 
469  // returns the current resizing policy
470  template < typename T1, typename T2, typename Alloc, bool Gen >
472  noexcept {
473  return __firstToSecond.resizePolicy();
474  }
475 
476  // friendly displays the content of the CliqueGraph
477  template < typename T1, typename T2, typename Alloc, bool Gen >
479  std::stringstream stream;
480  stream << "{ ";
481  bool first = true;
482 
483  for (iterator iter = begin(); iter != end(); ++iter) {
484  if (!first)
485  stream << ", ";
486  else
487  first = false;
488 
489  stream << '(' << iter.first() << " <-> " << iter.second() << ')';
490  }
491 
492  stream << " }";
493  return stream.str();
494  }
495 
496  // ===========================================================================
497  // === SCALAR BIJECTION IMPLEMENTATION ===
498  // ===========================================================================
499 
500  // returns the end iterator for other classes' statics
501  template < typename T1, typename T2, typename Alloc >
504  return *(reinterpret_cast< const BijectionIteratorSafe< T1, T2 >* >(
505  BijectionIteratorStaticEnd::endSafe4Statics()));
506  }
507 
508  // returns the end iterator for other classes' statics
509  template < typename T1, typename T2, typename Alloc >
512  return *(reinterpret_cast< const BijectionIterator< T1, T2 >* >(
513  BijectionIteratorStaticEnd::end4Statics()));
514  }
515 
516  // Default constructor: creates a bijection without association
517  template < typename T1, typename T2, typename Alloc >
519  Size size, bool resize_policy) :
520  // warning: below, we create the internal hashTables with a key
521  // uniqueness
522  // policy set to false because we will do the uniqueness tests ourselves
523  // (this
524  // will speed-up the process)
525  __firstToSecond(size, resize_policy, false),
526  __secondToFirst(size, resize_policy, false) {
527  GUM_CONSTRUCTOR(BijectionImplementation);
528 
529  // make sure the end() iterator is constructed properly
530  end4Statics();
531  endSafe4Statics();
532  }
533 
534  // initializer list constructor
535  template < typename T1, typename T2, typename Alloc >
536  INLINE BijectionImplementation< T1, T2, Alloc, true >::BijectionImplementation(
537  std::initializer_list< std::pair< T1, T2 > > list) :
538  __firstToSecond(Size(list.size()) / 2, true, false),
539  __secondToFirst(Size(list.size()) / 2, true, false) {
540  GUM_CONSTRUCTOR(BijectionImplementation);
541 
542  for (const auto& elt : list) {
543  insert(elt.first, elt.second);
544  }
545 
546  // make sure the end() iterator is constructed properly
547  end4Statics();
548  endSafe4Statics();
549  }
550 
551  // a function that performs a complete copy of another bijection
552  template < typename T1, typename T2, typename Alloc >
553  template < typename OtherAlloc >
555  const HashTable< T1, T2, OtherAlloc >& f2s) {
556  // parse f2s and perform copies
557  for (auto iter = f2s.cbegin(); iter != f2s.cend(); ++iter) {
558  __firstToSecond.insert(iter.key(), iter.val());
559 
560  try {
561  __secondToFirst.insert(iter.val(), iter.key());
562  } catch (...) {
563  __firstToSecond.erase(iter.key());
564  throw;
565  }
566  }
567 
568  // note that __iter_end is actually a constant, whatever we add/remove
569  // to/from __firstToSecond. As a consequence, it need not be updated
570  // after __copy
571  }
572 
573  // Copy constructor
574  template < typename T1, typename T2, typename Alloc >
575  INLINE BijectionImplementation< T1, T2, Alloc, true >::BijectionImplementation(
577  __firstToSecond(toCopy.__firstToSecond.capacity(), true, false),
578  __secondToFirst(toCopy.__secondToFirst.capacity(), true, false) {
579  GUM_CONS_CPY(BijectionImplementation);
580  __copy(toCopy.__firstToSecond);
581  }
582 
583  // Generalized copy constructor
584  template < typename T1, typename T2, typename Alloc >
585  template < typename OtherAlloc >
586  INLINE BijectionImplementation< T1, T2, Alloc, true >::BijectionImplementation(
588  __firstToSecond(toCopy.__firstToSecond.capacity(), true, false),
589  __secondToFirst(toCopy.__secondToFirst.capacity(), true, false) {
590  GUM_CONS_CPY(BijectionImplementation);
591  __copy(toCopy.__firstToSecond);
592  }
593 
594  // move constructor
595  template < typename T1, typename T2, typename Alloc >
596  INLINE BijectionImplementation< T1, T2, Alloc, true >::BijectionImplementation(
598  __firstToSecond(std::move(toCopy.__firstToSecond)),
599  __secondToFirst(std::move(toCopy.__secondToFirst)) {
600  GUM_CONS_MOV(BijectionImplementation);
601  }
602 
603  // destructor
604  template < typename T1, typename T2, typename Alloc >
605  INLINE
607  GUM_DESTRUCTOR(BijectionImplementation);
608  }
609 
610  // returns the iterator at the beginning of the bijection
611  template < typename T1, typename T2, typename Alloc >
614  return BijectionIterator< T1, T2 >{*this};
615  }
616 
617  // returns the iterator at the beginning of the bijection
618  template < typename T1, typename T2, typename Alloc >
621  return BijectionIterator< T1, T2 >{*this};
622  }
623 
624  // returns the iterator to the end of the bijection
625  template < typename T1, typename T2, typename Alloc >
628  return *(reinterpret_cast< const BijectionIterator< T1, T2 >* >(
629  BijectionIteratorStaticEnd::__BijectionIterEnd));
630  }
631 
632  // returns the iterator to the end of the bijection
633  template < typename T1, typename T2, typename Alloc >
634  INLINE const typename BijectionImplementation< T1, T2, Alloc, true >::
635  const_iterator&
637  return *(reinterpret_cast< const BijectionIterator< T1, T2 >* >(
638  BijectionIteratorStaticEnd::__BijectionIterEnd));
639  }
640 
641  // returns the iterator at the beginning of the bijection
642  template < typename T1, typename T2, typename Alloc >
645  return BijectionIteratorSafe< T1, T2 >{*this};
646  }
647 
648  // returns the iterator at the beginning of the bijection
649  template < typename T1, typename T2, typename Alloc >
650  INLINE
653  return BijectionIteratorSafe< T1, T2 >{*this};
654  }
655 
656  // returns the iterator to the end of the bijection
657  template < typename T1, typename T2, typename Alloc >
658  INLINE const typename BijectionImplementation< T1, T2, Alloc, true >::
659  iterator_safe&
661  return *(reinterpret_cast< const BijectionIteratorSafe< T1, T2 >* >(
662  BijectionIteratorStaticEnd::__BijectionIterEndSafe));
663  }
664 
665  // returns the iterator to the end of the bijection
666  template < typename T1, typename T2, typename Alloc >
667  INLINE const typename BijectionImplementation< T1, T2, Alloc, true >::
668  const_iterator_safe&
670  return *(reinterpret_cast< const BijectionIteratorSafe< T1, T2 >* >(
671  BijectionIteratorStaticEnd::__BijectionIterEndSafe));
672  }
673 
674  // removes all the associations from the bijection
675  template < typename T1, typename T2, typename Alloc >
677  __firstToSecond.clear();
678  __secondToFirst.clear();
679  // note that __iter_end is actually a constant, whatever we add/remove
680  // to/from __firstToSecond. As a consequence, it need not be updated
681  // after the clear's
682  }
683 
684  // Copy operator
685  template < typename T1, typename T2, typename Alloc >
689  // avoid self assignment
690  if (this != &toCopy) {
691  clear();
692  __copy(toCopy.__firstToSecond);
693  }
694 
695  // note that __iter_end is actually a constant, whatever we add/remove
696  // to/from __firstToSecond. As a consequence, it need not be updated
697  // after __copy
698  return *this;
699  }
700 
701  // Generalized copy operator
702  template < typename T1, typename T2, typename Alloc >
703  template < typename OtherAlloc >
707  clear();
708  __copy(toCopy.__firstToSecond);
709 
710  // note that __iter_end is actually a constant, whatever we add/remove
711  // to/from __firstToSecond. As a consequence, it need not be updated
712  // after __copy
713  return *this;
714  }
715 
716  // move operator
717  template < typename T1, typename T2, typename Alloc >
721  // avoid self assignment
722  if (this != &toCopy) {
723  clear();
724  __firstToSecond = std::move(toCopy.__firstToSecond);
725  __secondToFirst = std::move(toCopy.__secondToFirst);
726  }
727 
728  // note that __iter_end is actually a constant, whatever we add/remove
729  // to/from __firstToSecond. As a consequence, it need not be updated
730  // after __copy
731  return *this;
732  }
733 
734  // returns the value associated to the element passed in argument
735  template < typename T1, typename T2, typename Alloc >
736  INLINE const T1&
738  return __secondToFirst[second];
739  }
740 
741  // returns the value associated to the element passed in argument
742  template < typename T1, typename T2, typename Alloc >
743  INLINE const T2&
745  return __firstToSecond[first];
746  }
747 
748  // Test whether the bijection contains the "first" value
749  template < typename T1, typename T2, typename Alloc >
750  INLINE bool
752  return __firstToSecond.exists(first);
753  }
754 
755  // Test whether the bijection contains the "second" value
756  template < typename T1, typename T2, typename Alloc >
758  T2 second) const {
759  return __secondToFirst.exists(second);
760  }
761 
762  // inserts a new association in the bijection
763  template < typename T1, typename T2, typename Alloc >
765  T2 second) {
766  // check the uniqueness property
767  if (existsFirst(first) || existsSecond(second)) {
769  "the bijection contains an element with the same couple ("
770  << first << "," << second << ")");
771  }
772 
773  // insert copies of first and second
774  __firstToSecond.insert(first, second);
775 
776  try {
777  __secondToFirst.insert(second, first);
778  } catch (...) {
779  __firstToSecond.erase(first);
780  throw;
781  }
782  }
783 
784  // inserts a new association in the bijection
785  template < typename T1, typename T2, typename Alloc >
787  T2 second) {
788  __insert(first, second);
789  }
790 
791  // emplace a new element in the bijection
792  template < typename T1, typename T2, typename Alloc >
793  template < typename... Args >
794  INLINE void
796  std::pair< T1, T2 > new_elt(std::forward< Args >(args)...);
797  __insert(new_elt.first, new_elt.second);
798  }
799 
800  /* @brief Same method as first, but if the value is not found, a default
801  * value is inserted into the bijection */
802  template < typename T1, typename T2, typename Alloc >
803  INLINE const T1&
805  T2 second, T1 val) const {
806  try {
807  return first(second);
808  } catch (NotFound&) {
809  __insert(val, second);
810  return val;
811  }
812  }
813 
814  /* @brief Same method as second, but if the value is not found, a default
815  * value is inserted into the bijection */
816  template < typename T1, typename T2, typename Alloc >
817  INLINE const T2&
819  T1 first, T2 val) const {
820  try {
821  return second(first);
822  } catch (NotFound&) {
823  __insert(first, val);
824  return val;
825  }
826  }
827 
828  // returns true if the bijection doesn't contain any relation
829  template < typename T1, typename T2, typename Alloc >
831  noexcept {
832  GUM_ASSERT(__firstToSecond.empty() == __secondToFirst.empty());
833  return __firstToSecond.empty();
834  }
835 
836  // returns the number of associations stored within the bijection
837  template < typename T1, typename T2, typename Alloc >
839  noexcept {
840  GUM_ASSERT(__firstToSecond.size() == __secondToFirst.size());
841  return __firstToSecond.size();
842  }
843 
844  // erases an association containing the given first element
845  template < typename T1, typename T2, typename Alloc >
846  INLINE void
848  try {
849  __secondToFirst.erase(__firstToSecond[first]);
850  __firstToSecond.erase(first);
851  } catch (NotFound&) {}
852  }
853 
854  // erase an association containing the given second element
855  template < typename T1, typename T2, typename Alloc >
856  INLINE void
858  try {
859  __firstToSecond.erase(__secondToFirst[second]);
860  __secondToFirst.erase(second);
861  } catch (NotFound&) {}
862  }
863 
864  // returns the number of hashtables' slots used (@sa hashTable's capacity)
865  template < typename T1, typename T2, typename Alloc >
867  noexcept {
868  return __firstToSecond.capacity();
869  }
870 
871  // similar to the hashtable's resize
872  template < typename T1, typename T2, typename Alloc >
873  INLINE void
875  __firstToSecond.resize(new_size);
876  __secondToFirst.resize(new_size);
877  }
878 
879  // enables the user to change dynamically the resizing policy
880  template < typename T1, typename T2, typename Alloc >
882  const bool new_policy) noexcept {
883  __firstToSecond.setResizePolicy(new_policy);
884  __secondToFirst.setResizePolicy(new_policy);
885  }
886 
887  // returns the current resizing policy
888  template < typename T1, typename T2, typename Alloc >
890  noexcept {
891  return __firstToSecond.resizePolicy();
892  }
893 
894  // friendly displays the content of the CliqueGraph
895  template < typename T1, typename T2, typename Alloc >
897  std::stringstream stream;
898  stream << "{ ";
899  bool first = true;
900 
901  for (iterator iter = begin(); iter != end(); ++iter) {
902  if (!first)
903  stream << ", ";
904  else
905  first = false;
906 
907  stream << '(' << iter.first() << " <-> " << iter.second() << ')';
908  }
909 
910  stream << " }";
911  return stream.str();
912  }
913 
914  // ===========================================================================
915  // === BIJECTION SAFE ITERATORS ===
916  // ===========================================================================
917 
919  template < typename T1, typename T2 >
921  GUM_CONSTRUCTOR(BijectionIteratorSafe);
922  }
923 
925  template < typename T1, typename T2 >
926  template < typename Alloc, bool Gen >
929  __iter{bijection.__firstToSecond.cbeginSafe()} {
930  GUM_CONSTRUCTOR(BijectionIteratorSafe);
931  }
932 
934  template < typename T1, typename T2 >
935  template < typename Alloc >
937  const Bijection< T1, T2, Alloc >& bijection) :
938  __iter{bijection.__firstToSecond.cbeginSafe()} {
939  GUM_CONSTRUCTOR(BijectionIteratorSafe);
940  }
941 
943  template < typename T1, typename T2 >
945  const BijectionIteratorSafe< T1, T2 >& toCopy) :
946  __iter{toCopy.__iter} {
947  GUM_CONS_CPY(BijectionIteratorSafe);
948  }
949 
951  template < typename T1, typename T2 >
953  BijectionIteratorSafe< T1, T2 >&& from) noexcept :
954  __iter{std::move(from.__iter)} {
955  GUM_CONS_MOV(BijectionIteratorSafe);
956  }
957 
959  template < typename T1, typename T2 >
961  GUM_DESTRUCTOR(BijectionIteratorSafe);
962  }
963 
965  template < typename T1, typename T2 >
968  __iter = toCopy.__iter;
969  return *this;
970  }
971 
973  template < typename T1, typename T2 >
976  __iter = std::move(toCopy.__iter);
977  return *this;
978  }
979 
981  template < typename T1, typename T2 >
983  operator++() noexcept {
984  ++__iter;
985  return *this;
986  }
987 
989  template < typename T1, typename T2 >
991  operator+=(Size nb) noexcept {
992  __iter += nb;
993  return *this;
994  }
995 
997  template < typename T1, typename T2 >
999  operator+(Size nb) noexcept {
1000  return BijectionIteratorSafe< T1, T2 >{*this} += nb;
1001  }
1002 
1004  template < typename T1, typename T2 >
1006  operator!=(const BijectionIteratorSafe< T1, T2 >& toCompare) const noexcept {
1007  return __iter != toCompare.__iter;
1008  }
1009 
1011  template < typename T1, typename T2 >
1013  operator==(const BijectionIteratorSafe< T1, T2 >& toCompare) const noexcept {
1014  return __iter == toCompare.__iter;
1015  }
1016 
1018  template < typename T1, typename T2 >
1019  INLINE const T1& BijectionIteratorSafe< T1, T2 >::first() const {
1020  return __iter.key();
1021  }
1022 
1024  template < typename T1, typename T2 >
1025  INLINE const T2& BijectionIteratorSafe< T1, T2 >::second() const {
1026  return Getter::op_second(__iter.val());
1027  }
1028 
1029  /* ===========================================================================
1030  */
1031  /* === BIJECTION UNSAFE ITERATORS ===
1032  */
1033  /* ===========================================================================
1034  */
1035 
1037  template < typename T1, typename T2 >
1039  GUM_CONSTRUCTOR(BijectionIterator);
1040  }
1041 
1043  template < typename T1, typename T2 >
1044  template < typename Alloc, bool Gen >
1047  __iter{bijection.__firstToSecond.cbegin()} {
1048  GUM_CONSTRUCTOR(BijectionIterator);
1049  }
1050 
1052  template < typename T1, typename T2 >
1053  template < typename Alloc >
1055  const Bijection< T1, T2, Alloc >& bijection) :
1056  __iter{bijection.__firstToSecond.cbegin()} {
1057  GUM_CONSTRUCTOR(BijectionIterator);
1058  }
1059 
1061  template < typename T1, typename T2 >
1063  const BijectionIterator< T1, T2 >& toCopy) :
1064  __iter{toCopy.__iter} {
1065  GUM_CONS_CPY(BijectionIterator);
1066  }
1067 
1069  template < typename T1, typename T2 >
1071  BijectionIterator< T1, T2 >&& from) noexcept :
1072  __iter{std::move(from.__iter)} {
1073  GUM_CONS_MOV(BijectionIterator);
1074  }
1075 
1077  template < typename T1, typename T2 >
1079  GUM_DESTRUCTOR(BijectionIterator);
1080  }
1081 
1083  template < typename T1, typename T2 >
1086  __iter = toCopy.__iter;
1087  return *this;
1088  }
1089 
1091  template < typename T1, typename T2 >
1094  __iter = std::move(toCopy.__iter);
1095  return *this;
1096  }
1097 
1099  template < typename T1, typename T2 >
1101  operator++() noexcept {
1102  ++__iter;
1103  return *this;
1104  }
1105 
1107  template < typename T1, typename T2 >
1109  operator+=(Size nb) noexcept {
1110  __iter += nb;
1111  return *this;
1112  }
1113 
1115  template < typename T1, typename T2 >
1117  operator+(Size nb) noexcept {
1118  return BijectionIterator< T1, T2 >{*this} += nb;
1119  }
1120 
1122  template < typename T1, typename T2 >
1123  INLINE bool BijectionIterator< T1, T2 >::
1124  operator!=(const BijectionIterator< T1, T2 >& toCompare) const noexcept {
1125  return __iter != toCompare.__iter;
1126  }
1127 
1129  template < typename T1, typename T2 >
1130  INLINE bool BijectionIterator< T1, T2 >::
1131  operator==(const BijectionIterator< T1, T2 >& toCompare) const noexcept {
1132  return __iter == toCompare.__iter;
1133  }
1134 
1136  template < typename T1, typename T2 >
1137  INLINE const T1& BijectionIterator< T1, T2 >::first() const {
1138  return __iter.key();
1139  }
1140 
1142  template < typename T1, typename T2 >
1143  INLINE const T2& BijectionIterator< T1, T2 >::second() const {
1144  return Getter::op_second(__iter.val());
1145  }
1146 
1147  // ============================================================================
1148  // BIJECTION
1149  // ============================================================================
1150 
1151  // Default constructor: creates a bijection without any association
1152  template < typename T1, typename T2, typename Alloc >
1153  INLINE Bijection< T1, T2, Alloc >::Bijection(Size size, bool resize_policy) :
1155  T2,
1156  Alloc,
1157  std::is_scalar< T1 >::value
1158  && std::is_scalar< T2 >::value >(size,
1159  resize_policy) {
1160  GUM_CONSTRUCTOR(Bijection);
1161  }
1162 
1163  // initializer list constructor
1164  template < typename T1, typename T2, typename Alloc >
1166  std::initializer_list< std::pair< T1, T2 > > list) :
1168  T2,
1169  Alloc,
1170  std::is_scalar< T1 >::value
1171  && std::is_scalar< T2 >::value >(list) {
1172  GUM_CONSTRUCTOR(Bijection);
1173  }
1174 
1175  // Copy constructor
1176  template < typename T1, typename T2, typename Alloc >
1178  const Bijection< T1, T2, Alloc >& toCopy) :
1180  T2,
1181  Alloc,
1182  std::is_scalar< T1 >::value
1183  && std::is_scalar< T2 >::value >(toCopy) {
1184  GUM_CONS_CPY(Bijection);
1185  }
1186 
1187  // Generalized copy constructor
1188  template < typename T1, typename T2, typename Alloc >
1189  template < typename OtherAlloc >
1191  const Bijection< T1, T2, OtherAlloc >& toCopy) :
1193  T2,
1194  Alloc,
1195  std::is_scalar< T1 >::value
1196  && std::is_scalar< T2 >::value >(toCopy) {
1197  GUM_CONS_CPY(Bijection);
1198  }
1199 
1200  // move constructor
1201  template < typename T1, typename T2, typename Alloc >
1203  Bijection< T1, T2, Alloc >&& from) noexcept :
1205  T2,
1206  Alloc,
1207  std::is_scalar< T1 >::value
1208  && std::is_scalar< T2 >::value >(
1209  std::move(from)) {
1210  GUM_CONS_MOV(Bijection);
1211  }
1212 
1213  // destructor
1214  template < typename T1, typename T2, typename Alloc >
1216  GUM_DESTRUCTOR(Bijection);
1217  }
1218 
1219  // copy operator
1220  template < typename T1, typename T2, typename Alloc >
1223  Implementation::operator=(toCopy);
1224  return *this;
1225  }
1226 
1227  // generalized copy operator
1228  template < typename T1, typename T2, typename Alloc >
1229  template < typename OtherAlloc >
1232  Implementation::operator=(toCopy);
1233  return *this;
1234  }
1235 
1236  // move operator
1237  template < typename T1, typename T2, typename Alloc >
1240  Implementation::operator=(std::move(bij));
1241  return *this;
1242  }
1243 
1244  // for friendly displaying the content of bijections
1245  template < typename T1, typename T2, typename Alloc >
1246  std::ostream& operator<<(std::ostream& stream,
1247  const Bijection< T1, T2, Alloc >& b) {
1248  stream << b.toString();
1249  return stream;
1250  }
1251 
1252 } /* namespace gum */
void insert(const T1 &first, const T2 &second)
Inserts a new association in the gum::Bijection.
friend class BijectionImplementation
a friend to speed-up accesses
Definition: bijection.h:649
void __copy(const HashTable< T1, T2 *, OtherAlloc > &source)
A function that performs a complete copy of another gum::Bijection.
void clear()
Removes all the associations from the gum::Bijection.
static const BijectionIterator< int, int > * end4Statics()
Creates (if needed) and returns the iterator __BijectionIterEnd.
Safe iterators for bijectionIterator.
Definition: bijection.h:1409
STL namespace.
HashIter __iter
The hashTable iterator that actually does all the job.
Definition: bijection.h:1591
const_iterator cbegin() const
Returns the constant unsafe iterator at the beginning of the gum::Bjection.
gum is the global namespace for all aGrUM entities
Definition: agrum.h:25
static const iterator_safe & endSafe4Statics()
Returns the safe end iterator for other classes&#39; statics.
Definition: bijection_tpl.h:39
void resize(Size new_size)
Manually resize the gum::Bijection.
The class for generic Hash Tables.
Definition: hashTable.h:676
static const BijectionIteratorSafe< int, int > * endSafe4Statics()
Creates (if needed) and returns the iterator __BijectionIterEndSafe.
Size capacity() const noexcept
Returns the number of hashtables slots used.
std::ostream & operator<<(std::ostream &output, const BayesNet< GUM_SCALAR > &bn)
Prints map&#39;s DAG in output using the Graphviz-dot format.
Definition: BayesNet_tpl.h:574
bool empty() const noexcept
Returns true if the gum::Bijection doesn&#39;t contain any association.
const const_iterator & cend() const noexcept
Returns the unsafe const_iterator pointing to the end of the hashtable.
HashTable12 __firstToSecond
The gum::HashTable associating T2 objects to T1 objects.
Definition: bijection.h:658
LpExpr operator+(LpExpr &&lhs, const T2 &rhs)
Overload of operator + between anything ( a scalar, a variable or an expression ) and anything except...
Unsafe iterators for bijection.
Definition: bijection.h:1607
bool operator==(const TiXmlString &a, const TiXmlString &b)
Definition: tinystr.h:243
Set of pairs of elements with fast search for both elements.
Definition: bijection.h:1803
Size size() const noexcept
Returns the number of associations stored within the gum::Bijection.
const_iterator cbegin() const
Returns an unsafe const_iterator pointing to the beginning of the hashtable.
std::pair< const Idx, const std::string ** > value_type
Definition: hashTable.h:682
bool operator!=(const TiXmlString &a, const TiXmlString &b)
Definition: tinystr.h:251
HashIter __iter
The hashTable iterator that actually does all the job.
Definition: bijection.h:1780
std::string toString() const
Returns a friendly representatin of the gum::Bijection.
bool resizePolicy() const noexcept
Returns true if the resize policy is automatic.
std::size_t Size
In aGrUM, hashed values are unsigned long int.
Definition: types.h:45
static const iterator & end4Statics()
Returns the unsafe end iterator for other classes&#39; statics.
Definition: bijection_tpl.h:47
HashTable21 __secondToFirst
The gum::HashTable associating T1 objects to T2 objects.
Definition: bijection.h:661
const_iterator_safe cbeginSafe() const
Returns the constant safe iterator at the begining of the gum::Bijection.
void setResizePolicy(const bool new_policy) noexcept
Change the gum::Bijection resizing policy.
Set of pairs of elements with fast search for both elements.
A non scalar implementation of a Bijection.
Definition: bijection.h:83
#define GUM_ERROR(type, msg)
Definition: exceptions.h:52