From aeced19b6148063b9c6cce4aecbd3150eb07b889 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Sun, 25 Nov 2007 18:38:02 +0000 Subject: [PATCH] Full merge from trunk at revision 41356 of entire boost-root tree. [SVN r41370] --- doc/acknowledgements.qbk | 75 + doc/bimap.hdf | 237 +++ doc/bimap.qbk | 166 ++ doc/bimap_and_boost.qbk | 477 ++++++ doc/compiler_specifics.qbk | 61 + doc/directdoxygen.jam | 13 + doc/examples.qbk | 236 +++ doc/future_work.qbk | 23 + doc/history.qbk | 450 ++++++ doc/html/boost_bimap/acknowledgements.html | 109 ++ doc/html/boost_bimap/bimap_and_boost.html | 174 ++ ...aries_that_work_well_with_boost_bimap.html | 1065 +++++++++++++ .../bimap_and_boost/dependencies.html | 417 +++++ doc/html/boost_bimap/compiler_specifics.html | 366 +++++ doc/html/boost_bimap/examples.html | 439 +++++ .../boost_bimap/examples/mighty_bimap.html | 148 ++ ...dex_to_bimap_path___bidirectional_map.html | 363 +++++ ...iindex_to_bimap_path___hashed_indices.html | 260 +++ .../boost_bimap/examples/simple_bimap.html | 223 +++ doc/html/boost_bimap/future_work.html | 49 + doc/html/boost_bimap/history.html | 111 ++ .../history/multiindex_and_bimap.html | 711 +++++++++ doc/html/boost_bimap/introduction.html | 201 +++ doc/html/boost_bimap/one_minute_tutorial.html | 497 ++++++ doc/html/boost_bimap/performance.html | 44 + doc/html/boost_bimap/rationale.html | 312 ++++ .../rationale/additional_features.html | 139 ++ doc/html/boost_bimap/rationale/code.html | 200 +++ .../rationale/the_student_and_the_mentor.html | 1396 ++++++++++++++++ doc/html/boost_bimap/reference.html | 179 +++ .../reference/bimap_reference.html | 990 ++++++++++++ .../reference/list_of_reference.html | 1337 ++++++++++++++++ .../reference/set_of_reference.html | 1333 ++++++++++++++++ .../unconstrained_set_of_reference.html | 201 +++ .../reference/unordered_set_of_reference.html | 1303 +++++++++++++++ .../reference/vector_of_reference.html | 1408 +++++++++++++++++ doc/html/boost_bimap/release_notes.html | 44 + doc/html/boost_bimap/test_suite.html | 457 ++++++ doc/html/boost_bimap/the_tutorial.html | 167 ++ .../bimaps_with_user_defined_names.html | 408 +++++ .../complete_instantiation_scheme.html | 253 +++ .../controlling_collection_types.html | 565 +++++++ .../differences_with_standard_maps.html | 481 ++++++ .../discovering_the_bimap_framework.html | 343 ++++ .../the_tutorial/hooking_information.html | 221 +++ .../the_collection_of_relations_type.html | 432 +++++ .../the_tutorial/unconstrained_sets.html | 195 +++ .../the_tutorial/useful_functions.html | 454 ++++++ doc/html/boostbook.css | 582 +++++++ doc/html/images/bimap/bimap.structures.png | Bin 0 -> 78200 bytes doc/html/images/bimap/boost.bimap.header.png | Bin 0 -> 10224 bytes doc/html/images/bimap/boost.bimap.logo.png | Bin 0 -> 21616 bytes .../bimap/collection.type.of.relation.png | Bin 0 -> 69430 bytes .../bimap/extended.mapping.framework.png | Bin 0 -> 82338 bytes doc/html/images/bimap/miBimapFramework.png | Bin 0 -> 39373 bytes .../images/bimap/more.bimap.structures.png | Bin 0 -> 69608 bytes doc/html/images/bimap/simple.bimap.png | Bin 0 -> 80168 bytes .../bimap/standard.mapping.framework.png | Bin 0 -> 54971 bytes doc/html/images/bimap/tagged.png | Bin 0 -> 27281 bytes doc/html/images/callouts/1.png | Bin 0 -> 391 bytes doc/html/images/callouts/10.png | Bin 0 -> 485 bytes doc/html/images/callouts/11.png | Bin 0 -> 410 bytes doc/html/images/callouts/12.png | Bin 0 -> 488 bytes doc/html/images/callouts/13.png | Bin 0 -> 509 bytes doc/html/images/callouts/14.png | Bin 0 -> 499 bytes doc/html/images/callouts/15.png | Bin 0 -> 507 bytes doc/html/images/callouts/2.png | Bin 0 -> 446 bytes doc/html/images/callouts/3.png | Bin 0 -> 431 bytes doc/html/images/callouts/4.png | Bin 0 -> 441 bytes doc/html/images/callouts/5.png | Bin 0 -> 423 bytes doc/html/images/callouts/6.png | Bin 0 -> 431 bytes doc/html/images/callouts/7.png | Bin 0 -> 397 bytes doc/html/images/callouts/8.png | Bin 0 -> 434 bytes doc/html/images/callouts/9.png | Bin 0 -> 420 bytes doc/html/images/caution.png | Bin 0 -> 4286 bytes doc/html/images/extern/boost.blade.logo.png | Bin 0 -> 25228 bytes doc/html/images/extern/googlesoc.png | Bin 0 -> 7535 bytes doc/html/images/home.png | Bin 0 -> 1105 bytes doc/html/images/important.png | Bin 0 -> 4666 bytes doc/html/images/next.png | Bin 0 -> 768 bytes doc/html/images/note.png | Bin 0 -> 4648 bytes doc/html/images/people/hector.png | Bin 0 -> 28047 bytes doc/html/images/people/joaquin.png | Bin 0 -> 22195 bytes doc/html/images/people/mafalda.png | Bin 0 -> 33491 bytes doc/html/images/people/matias.png | Bin 0 -> 23853 bytes doc/html/images/prev.png | Bin 0 -> 741 bytes doc/html/images/space.png | Bin 0 -> 75 bytes doc/html/images/tip.png | Bin 0 -> 3902 bytes doc/html/images/toc/acknowledgements.png | Bin 0 -> 8644 bytes doc/html/images/toc/bimap_and_boost.png | Bin 0 -> 8389 bytes doc/html/images/toc/compiler_specifics.png | Bin 0 -> 9429 bytes doc/html/images/toc/examples.png | Bin 0 -> 7792 bytes doc/html/images/toc/future_work.png | Bin 0 -> 7110 bytes doc/html/images/toc/history.png | Bin 0 -> 9114 bytes doc/html/images/toc/introduction.png | Bin 0 -> 8244 bytes doc/html/images/toc/one_minute_tutorial.png | Bin 0 -> 8902 bytes doc/html/images/toc/performance.png | Bin 0 -> 9305 bytes doc/html/images/toc/rationale.png | Bin 0 -> 7907 bytes doc/html/images/toc/reference.png | Bin 0 -> 8065 bytes doc/html/images/toc/release_notes.png | Bin 0 -> 10754 bytes doc/html/images/toc/test_suite.png | Bin 0 -> 9737 bytes doc/html/images/toc/the_tutorial.png | Bin 0 -> 8816 bytes doc/html/images/up.png | Bin 0 -> 766 bytes doc/html/images/warning.png | Bin 0 -> 3927 bytes doc/html/index.html | 160 ++ doc/introduction.qbk | 99 ++ doc/jamfile.v2 | 37 + doc/performance.qbk | 19 + doc/quick_tutorial.qbk | 182 +++ doc/rationale.qbk | 914 +++++++++++ doc/reference.qbk | 64 + doc/reference/bimap.qbk | 523 ++++++ doc/reference/list_of.qbk | 798 ++++++++++ doc/reference/set_of.qbk | 935 +++++++++++ doc/reference/unconstrained_set_of.qbk | 123 ++ doc/reference/unordered_set_of.qbk | 853 ++++++++++ doc/reference/vector_of.qbk | 843 ++++++++++ doc/release_notes.qbk | 19 + doc/test_suite.qbk | 147 ++ doc/toolbox.qbk | 75 + doc/tutorial.qbk | 1057 +++++++++++++ example/Jamfile.v2 | 50 + example/at_function_examples.cpp | 97 ++ example/bimap_and_boost/assign.cpp | 79 + example/bimap_and_boost/foreach.cpp | 106 ++ example/bimap_and_boost/lambda.cpp | 49 + example/bimap_and_boost/property_map.cpp | 59 + example/bimap_and_boost/range.cpp | 121 ++ example/bimap_and_boost/serialization.cpp | 89 ++ example/bimap_and_boost/typeof.cpp | 86 + example/bimap_and_boost/xpressive.cpp | 57 + example/mi_to_b_path/bidirectional_map.cpp | 87 + example/mi_to_b_path/hashed_indices.cpp | 94 ++ example/mi_to_b_path/mi_bidirectional_map.cpp | 107 ++ example/mi_to_b_path/mi_hashed_indices.cpp | 100 ++ .../mi_to_b_path/tagged_bidirectional_map.cpp | 90 ++ example/mighty_bimap.cpp | 109 ++ example/population_bimap.cpp | 121 ++ example/projection.cpp | 60 + example/repetitions_counter.cpp | 91 ++ example/simple_bimap.cpp | 82 + example/standard_map_comparison.cpp | 93 ++ example/step_by_step.cpp | 102 ++ example/tagged_simple_bimap.cpp | 86 + example/tutorial_info_hook.cpp | 163 ++ example/tutorial_modify_and_replace.cpp | 118 ++ example/tutorial_range.cpp | 100 ++ example/unconstrained_collection.cpp | 94 ++ example/user_defined_names.cpp | 142 ++ index.html | 9 + test/Jamfile.v2 | 80 + test/compile_fail/test_bimap_info_1.cpp | 49 + test/compile_fail/test_bimap_info_2.cpp | 48 + test/compile_fail/test_bimap_info_3.cpp | 48 + test/compile_fail/test_bimap_mutable_1.cpp | 49 + test/compile_fail/test_bimap_mutable_2.cpp | 49 + test/compile_fail/test_bimap_mutable_3.cpp | 48 + test/test_bimap.hpp | 488 ++++++ test/test_bimap_assign.cpp | 89 ++ test/test_bimap_convenience_header.cpp | 38 + test/test_bimap_extra.cpp | 89 ++ test/test_bimap_info.cpp | 126 ++ test/test_bimap_lambda.cpp | 47 + test/test_bimap_list_of.cpp | 32 + test/test_bimap_modify.cpp | 183 +++ test/test_bimap_multiset_of.cpp | 32 + test/test_bimap_mutable.cpp | 109 ++ test/test_bimap_operator_bracket.cpp | 193 +++ test/test_bimap_ordered.cpp | 176 +++ test/test_bimap_project.cpp | 143 ++ test/test_bimap_property_map.cpp | 76 + test/test_bimap_range.cpp | 134 ++ test/test_bimap_sequenced.cpp | 297 ++++ test/test_bimap_serialization.cpp | 114 ++ test/test_bimap_set_of.cpp | 32 + test/test_bimap_unconstrained.cpp | 109 ++ test/test_bimap_unordered.cpp | 167 ++ test/test_bimap_unordered_multiset_of.cpp | 34 + test/test_bimap_unordered_set_of.cpp | 32 + test/test_bimap_vector_of.cpp | 32 + test/test_mutant.cpp | 103 ++ test/test_mutant_relation.cpp | 241 +++ test/test_relation.hpp | 191 +++ test/test_structured_pair.cpp | 98 ++ test/test_tagged.cpp | 108 ++ 185 files changed, 33688 insertions(+) create mode 100755 doc/acknowledgements.qbk create mode 100755 doc/bimap.hdf create mode 100755 doc/bimap.qbk create mode 100755 doc/bimap_and_boost.qbk create mode 100755 doc/compiler_specifics.qbk create mode 100644 doc/directdoxygen.jam create mode 100755 doc/examples.qbk create mode 100755 doc/future_work.qbk create mode 100755 doc/history.qbk create mode 100644 doc/html/boost_bimap/acknowledgements.html create mode 100644 doc/html/boost_bimap/bimap_and_boost.html create mode 100644 doc/html/boost_bimap/bimap_and_boost/boost_libraries_that_work_well_with_boost_bimap.html create mode 100644 doc/html/boost_bimap/bimap_and_boost/dependencies.html create mode 100644 doc/html/boost_bimap/compiler_specifics.html create mode 100644 doc/html/boost_bimap/examples.html create mode 100644 doc/html/boost_bimap/examples/mighty_bimap.html create mode 100644 doc/html/boost_bimap/examples/multiindex_to_bimap_path___bidirectional_map.html create mode 100644 doc/html/boost_bimap/examples/multiindex_to_bimap_path___hashed_indices.html create mode 100644 doc/html/boost_bimap/examples/simple_bimap.html create mode 100644 doc/html/boost_bimap/future_work.html create mode 100644 doc/html/boost_bimap/history.html create mode 100644 doc/html/boost_bimap/history/multiindex_and_bimap.html create mode 100644 doc/html/boost_bimap/introduction.html create mode 100644 doc/html/boost_bimap/one_minute_tutorial.html create mode 100644 doc/html/boost_bimap/performance.html create mode 100644 doc/html/boost_bimap/rationale.html create mode 100644 doc/html/boost_bimap/rationale/additional_features.html create mode 100644 doc/html/boost_bimap/rationale/code.html create mode 100644 doc/html/boost_bimap/rationale/the_student_and_the_mentor.html create mode 100644 doc/html/boost_bimap/reference.html create mode 100644 doc/html/boost_bimap/reference/bimap_reference.html create mode 100644 doc/html/boost_bimap/reference/list_of_reference.html create mode 100644 doc/html/boost_bimap/reference/set_of_reference.html create mode 100644 doc/html/boost_bimap/reference/unconstrained_set_of_reference.html create mode 100644 doc/html/boost_bimap/reference/unordered_set_of_reference.html create mode 100644 doc/html/boost_bimap/reference/vector_of_reference.html create mode 100644 doc/html/boost_bimap/release_notes.html create mode 100644 doc/html/boost_bimap/test_suite.html create mode 100644 doc/html/boost_bimap/the_tutorial.html create mode 100644 doc/html/boost_bimap/the_tutorial/bimaps_with_user_defined_names.html create mode 100644 doc/html/boost_bimap/the_tutorial/complete_instantiation_scheme.html create mode 100644 doc/html/boost_bimap/the_tutorial/controlling_collection_types.html create mode 100644 doc/html/boost_bimap/the_tutorial/differences_with_standard_maps.html create mode 100644 doc/html/boost_bimap/the_tutorial/discovering_the_bimap_framework.html create mode 100644 doc/html/boost_bimap/the_tutorial/hooking_information.html create mode 100644 doc/html/boost_bimap/the_tutorial/the_collection_of_relations_type.html create mode 100644 doc/html/boost_bimap/the_tutorial/unconstrained_sets.html create mode 100644 doc/html/boost_bimap/the_tutorial/useful_functions.html create mode 100755 doc/html/boostbook.css create mode 100755 doc/html/images/bimap/bimap.structures.png create mode 100755 doc/html/images/bimap/boost.bimap.header.png create mode 100755 doc/html/images/bimap/boost.bimap.logo.png create mode 100755 doc/html/images/bimap/collection.type.of.relation.png create mode 100644 doc/html/images/bimap/extended.mapping.framework.png create mode 100755 doc/html/images/bimap/miBimapFramework.png create mode 100755 doc/html/images/bimap/more.bimap.structures.png create mode 100644 doc/html/images/bimap/simple.bimap.png create mode 100644 doc/html/images/bimap/standard.mapping.framework.png create mode 100755 doc/html/images/bimap/tagged.png create mode 100644 doc/html/images/callouts/1.png create mode 100644 doc/html/images/callouts/10.png create mode 100644 doc/html/images/callouts/11.png create mode 100644 doc/html/images/callouts/12.png create mode 100644 doc/html/images/callouts/13.png create mode 100644 doc/html/images/callouts/14.png create mode 100644 doc/html/images/callouts/15.png create mode 100644 doc/html/images/callouts/2.png create mode 100644 doc/html/images/callouts/3.png create mode 100644 doc/html/images/callouts/4.png create mode 100644 doc/html/images/callouts/5.png create mode 100644 doc/html/images/callouts/6.png create mode 100644 doc/html/images/callouts/7.png create mode 100644 doc/html/images/callouts/8.png create mode 100644 doc/html/images/callouts/9.png create mode 100755 doc/html/images/caution.png create mode 100755 doc/html/images/extern/boost.blade.logo.png create mode 100755 doc/html/images/extern/googlesoc.png create mode 100755 doc/html/images/home.png create mode 100755 doc/html/images/important.png create mode 100755 doc/html/images/next.png create mode 100755 doc/html/images/note.png create mode 100755 doc/html/images/people/hector.png create mode 100755 doc/html/images/people/joaquin.png create mode 100755 doc/html/images/people/mafalda.png create mode 100755 doc/html/images/people/matias.png create mode 100755 doc/html/images/prev.png create mode 100644 doc/html/images/space.png create mode 100755 doc/html/images/tip.png create mode 100755 doc/html/images/toc/acknowledgements.png create mode 100755 doc/html/images/toc/bimap_and_boost.png create mode 100755 doc/html/images/toc/compiler_specifics.png create mode 100755 doc/html/images/toc/examples.png create mode 100755 doc/html/images/toc/future_work.png create mode 100755 doc/html/images/toc/history.png create mode 100755 doc/html/images/toc/introduction.png create mode 100755 doc/html/images/toc/one_minute_tutorial.png create mode 100755 doc/html/images/toc/performance.png create mode 100755 doc/html/images/toc/rationale.png create mode 100755 doc/html/images/toc/reference.png create mode 100755 doc/html/images/toc/release_notes.png create mode 100755 doc/html/images/toc/test_suite.png create mode 100755 doc/html/images/toc/the_tutorial.png create mode 100755 doc/html/images/up.png create mode 100755 doc/html/images/warning.png create mode 100644 doc/html/index.html create mode 100755 doc/introduction.qbk create mode 100755 doc/jamfile.v2 create mode 100755 doc/performance.qbk create mode 100755 doc/quick_tutorial.qbk create mode 100755 doc/rationale.qbk create mode 100755 doc/reference.qbk create mode 100755 doc/reference/bimap.qbk create mode 100755 doc/reference/list_of.qbk create mode 100755 doc/reference/set_of.qbk create mode 100755 doc/reference/unconstrained_set_of.qbk create mode 100755 doc/reference/unordered_set_of.qbk create mode 100755 doc/reference/vector_of.qbk create mode 100755 doc/release_notes.qbk create mode 100755 doc/test_suite.qbk create mode 100755 doc/toolbox.qbk create mode 100755 doc/tutorial.qbk create mode 100755 example/Jamfile.v2 create mode 100755 example/at_function_examples.cpp create mode 100755 example/bimap_and_boost/assign.cpp create mode 100755 example/bimap_and_boost/foreach.cpp create mode 100755 example/bimap_and_boost/lambda.cpp create mode 100755 example/bimap_and_boost/property_map.cpp create mode 100755 example/bimap_and_boost/range.cpp create mode 100755 example/bimap_and_boost/serialization.cpp create mode 100755 example/bimap_and_boost/typeof.cpp create mode 100755 example/bimap_and_boost/xpressive.cpp create mode 100755 example/mi_to_b_path/bidirectional_map.cpp create mode 100755 example/mi_to_b_path/hashed_indices.cpp create mode 100755 example/mi_to_b_path/mi_bidirectional_map.cpp create mode 100755 example/mi_to_b_path/mi_hashed_indices.cpp create mode 100755 example/mi_to_b_path/tagged_bidirectional_map.cpp create mode 100755 example/mighty_bimap.cpp create mode 100755 example/population_bimap.cpp create mode 100755 example/projection.cpp create mode 100755 example/repetitions_counter.cpp create mode 100755 example/simple_bimap.cpp create mode 100755 example/standard_map_comparison.cpp create mode 100755 example/step_by_step.cpp create mode 100755 example/tagged_simple_bimap.cpp create mode 100755 example/tutorial_info_hook.cpp create mode 100755 example/tutorial_modify_and_replace.cpp create mode 100755 example/tutorial_range.cpp create mode 100755 example/unconstrained_collection.cpp create mode 100755 example/user_defined_names.cpp create mode 100755 index.html create mode 100755 test/Jamfile.v2 create mode 100755 test/compile_fail/test_bimap_info_1.cpp create mode 100755 test/compile_fail/test_bimap_info_2.cpp create mode 100755 test/compile_fail/test_bimap_info_3.cpp create mode 100755 test/compile_fail/test_bimap_mutable_1.cpp create mode 100755 test/compile_fail/test_bimap_mutable_2.cpp create mode 100755 test/compile_fail/test_bimap_mutable_3.cpp create mode 100755 test/test_bimap.hpp create mode 100755 test/test_bimap_assign.cpp create mode 100755 test/test_bimap_convenience_header.cpp create mode 100755 test/test_bimap_extra.cpp create mode 100755 test/test_bimap_info.cpp create mode 100755 test/test_bimap_lambda.cpp create mode 100755 test/test_bimap_list_of.cpp create mode 100755 test/test_bimap_modify.cpp create mode 100755 test/test_bimap_multiset_of.cpp create mode 100755 test/test_bimap_mutable.cpp create mode 100755 test/test_bimap_operator_bracket.cpp create mode 100755 test/test_bimap_ordered.cpp create mode 100755 test/test_bimap_project.cpp create mode 100755 test/test_bimap_property_map.cpp create mode 100755 test/test_bimap_range.cpp create mode 100755 test/test_bimap_sequenced.cpp create mode 100755 test/test_bimap_serialization.cpp create mode 100755 test/test_bimap_set_of.cpp create mode 100755 test/test_bimap_unconstrained.cpp create mode 100755 test/test_bimap_unordered.cpp create mode 100755 test/test_bimap_unordered_multiset_of.cpp create mode 100755 test/test_bimap_unordered_set_of.cpp create mode 100755 test/test_bimap_vector_of.cpp create mode 100755 test/test_mutant.cpp create mode 100755 test/test_mutant_relation.cpp create mode 100755 test/test_relation.hpp create mode 100755 test/test_structured_pair.cpp create mode 100755 test/test_tagged.cpp diff --git a/doc/acknowledgements.qbk b/doc/acknowledgements.qbk new file mode 100755 index 0000000..72b653e --- /dev/null +++ b/doc/acknowledgements.qbk @@ -0,0 +1,75 @@ +[/license + +Boost.Bimap + +Copyright (c) 2006-2007 Matias Capeletto + +Distributed under the Boost Software License, Version 1.0. +(See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt) + +] + +[/ QuickBook Document version 1.4 ] + +[section Acknowledgements] + +This library was developed in the context of the Google SoC 2006. I +first want to thank my mentor, Joaquin, for his friendship during this +project. Not only did he help me go through the process of creating this +library, but he also did his best so we could have a great time doing +it. Also, Boost.Bimap would not exist had Boost.MultiIndex, Joaquin's +masterpiece, not existed. Thanks a lot! + +__GOOGLE_SOC_2006__ + +I want to thank Google for this amazing ['boost] to the open-source +community and to Boost mentors for trusting in my proposal in the first +place. Next on the list are my colleagues from SoC that helped me not +get bored during the long hours of coding. + +Special acknowledgements to the developers of the Boost libraries that +Boost.Bimap has abused. See the dependencies section for a complete list. + +I want to thank the open-source developers who wrote the tools I used +during this project. The library was coded using Blade, a full +open-source development environment composed, in my opinion, of the best +tools for software building. The list of names is infinitely long, so I +give a general huge thanks here. + +__BOOST_BLADE_LOGO__ + +The icons in the TOC of the main page are from [@http://www.kde-look.org/kde-look.org kde-look.org]. +I want to thank them for their effort in making the open-source world a beautiful +place. When I find time, I will look for the authors' names. Please +forgive me for omitting them for the moment. + +Thanks to Paul Giaccone for proof-reading this documentation. (He has +not finished yet -- the remaining typos and spelling errors are mine and +will be corrected as soon as possible.) + +Finally, thanks to my family, who had to see me at home all day during +the SoC. Special thanks to my brother Agustin, future famous novelist +(at the present time he is 19 years old), who patiently read every word +of these docs and while correcting them, barked at me for my bad written +English. I have learned a lot from his sermons. I want to thank my dog, +Mafalda, too for barking all day from my window and for being such a +good company. + +Thanks to Alisdair Meredith, Fernando Cacciola, Jeff Garland, John Maddock, +Thorsten Ottosen, Tony and Giovanni Piero Deretta for participating in +the formal review and give me useful advices to improve this library. +And thanks a lot to Ion Gaztañaga for managing the review. + +[heading Boost.Bimap Team] + +From Argentina... Matias and Mafalda and from Spain... Joaquin and Hector + +__MATIAS_PHOTO__ +__MAFALDA_PHOTO__ +__JOAQUIN_PHOTO__ +__HECTOR_PHOTO__ + +Luckily, the distance helps team members avoid eating each other. + +[endsect] \ No newline at end of file diff --git a/doc/bimap.hdf b/doc/bimap.hdf new file mode 100755 index 0000000..2ab400b --- /dev/null +++ b/doc/bimap.hdf @@ -0,0 +1,237 @@ +# Doxyfile 1.4.7 + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +PROJECT_NAME = Boost.Bimap +PROJECT_NUMBER = +OUTPUT_DIRECTORY = html +CREATE_SUBDIRS = NO +OUTPUT_LANGUAGE = English +USE_WINDOWS_ENCODING = NO +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = YES +FULL_PATH_NAMES = YES +STRIP_FROM_PATH = ../../../boost/bimap +STRIP_FROM_INC_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +DETAILS_AT_TOP = NO +INHERIT_DOCS = YES +SEPARATE_MEMBER_PAGES = NO +TAB_SIZE = 4 +ALIASES = +OPTIMIZE_OUTPUT_FOR_C = NO +OPTIMIZE_OUTPUT_JAVA = NO +BUILTIN_STL_SUPPORT = YES +DISTRIBUTE_GROUP_DOC = YES +SUBGROUPING = YES +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = NO +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = NO +EXTRACT_LOCAL_METHODS = NO +HIDE_UNDOC_MEMBERS = YES +HIDE_UNDOC_CLASSES = YES +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = YES +SHOW_INCLUDE_FILES = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +SORT_BRIEF_DOCS = YES +SORT_BY_SCOPE_NAME = NO +GENERATE_TODOLIST = NO +GENERATE_TESTLIST = NO +GENERATE_BUGLIST = NO +GENERATE_DEPRECATEDLIST= NO +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +SHOW_DIRECTORIES = YES +FILE_VERSION_FILTER = +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = NO +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = NO +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = ../../../boost/bimap +FILE_PATTERNS = *.hpp +RECURSIVE = YES +EXCLUDE = ../../../boost/bimap/detail/test/check_metadata.hpp \ + ../../../boost/bimap/detail/test/check_size_of_pair.hpp +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = * +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = YES +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = NO +REFERENCED_BY_RELATION = YES +REFERENCES_RELATION = YES +REFERENCES_LINK_SOURCE = YES +USE_HTAGS = NO +VERBATIM_HEADERS = YES +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = NO +COLS_IN_ALPHA_INDEX = 3 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = doxydoc +HTML_FILE_EXTENSION = .html +HTML_HEADER = style/doxyheader.html +HTML_FOOTER = style/doxyfooter.html +HTML_STYLESHEET = style/template/doxydoc/doxygen.css +HTML_ALIGN_MEMBERS = YES +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +BINARY_TOC = NO +TOC_EXPAND = YES +DISABLE_INDEX = NO +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = NO +TREEVIEW_WIDTH = 250 +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = NO +USE_PDFLATEX = NO +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = NO +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = +XML_PROGRAMLISTING = YES +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = NO +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = BOOST_BIMAP_DOXYGEN_WILL_NOT_PROCESS_THE_FOLLOWING_LINES \ + BOOST_BIMAP_ONLY_DOXYGEN_WILL_PROCESS_THE_FOLLOWING_LINES +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /usr/bin/perl +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = YES +HIDE_UNDOC_RELATIONS = NO +HAVE_DOT = YES +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = YES +UML_LOOK = YES +TEMPLATE_RELATIONS = YES +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = YES +CALLER_GRAPH = YES +GRAPHICAL_HIERARCHY = YES +DIRECTORY_GRAPH = YES +DOT_IMAGE_FORMAT = png +DOT_PATH = +DOTFILE_DIRS = +MAX_DOT_GRAPH_WIDTH = 1024 +MAX_DOT_GRAPH_HEIGHT = 2046 +MAX_DOT_GRAPH_DEPTH = 1000 +DOT_TRANSPARENT = NO +DOT_MULTI_TARGETS = YES +GENERATE_LEGEND = NO +DOT_CLEANUP = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- +SEARCHENGINE = NO diff --git a/doc/bimap.qbk b/doc/bimap.qbk new file mode 100755 index 0000000..7091298 --- /dev/null +++ b/doc/bimap.qbk @@ -0,0 +1,166 @@ +[library Boost.Bimap + [quickbook 1.4] + [authors [Capeletto, Matias]] + [copyright 2006-2007 Matias Capeletto] + [category container] + [id bimap] + [dirname bimap] + [purpose + Bidirectional map + ] + [source-mode c++] + [license +Distributed under the Boost Software License, Version 1.0. +(See accompanying file LICENSE_1_0.txt or copy at +[@http://www.boost.org/LICENSE_1_0.txt]) + ] +] + +[/ QuickBook Document version 1.4 ] + +[/ Logos ] + +[def __BOOST_BIMAP_LOGO__ [$images/bimap/boost.bimap.logo.png]] +[def __BOOST_BLADE_LOGO__ [$images/extern/boost.blade.logo.png]] +[def __GOOGLE_SOC_2006__ [$images/extern/googlesoc.png]] + +[/ Helpers ] + +[def __MI_FRAMEWORK__ [$images/bimap/miBimapFramework.png]] +[def __SIMPLE_BIMAP__ [$images/bimap/simple.bimap.png]] +[def __STANDARD_MAPPING_FRAMEWORK__ [$images/bimap/standard.mapping.framework.png]] +[def __EXTENDED_MAPPING_FRAMEWORK__ [$images/bimap/extended.mapping.framework.png]] +[def __RELATION__ [$images/bimap/relation.png]] +[def __STD_PAIR__ [$images/bimap/std_pair.png]] +[def __COLLECTION_TYPE_OF_RELATION__ [$images/bimap/collection.type.of.relation.png]] +[def __BIMAP_STRUCTURES__ [$images/bimap/bimap.structures.png]] +[def __TAGGED__ [$images/bimap/tagged.png]] +[def __MORE_BIMAP_STRUCTURES__ [$images/bimap/more.bimap.structures.png]] +[def __RELATION_AND_PAIR__ [$images/bimap/relation.and.pair.png]] +[def __RELATION_AND_PAIR_WITH_INFO__ [$images/bimap/relation.and.pair.with.info.png]] + + +[/ People ] + +[def __MATIAS_PHOTO__ [$images/people/matias.png]] +[def __JOAQUIN_PHOTO__ [$images/people/joaquin.png]] +[def __MAFALDA_PHOTO__ [$images/people/mafalda.png]] +[def __HECTOR_PHOTO__ [$images/people/hector.png]] + +[/ Icons ] + +[def __NOTE__ [$images/note.png]] +[def __ALERT__ [$images/caution.png]] +[def __DETAIL__ [$images/note.png]] +[def __TIP__ [$images/tip.png]] +[def __QUESTION_MARK__ [$images/question.png]] + + +[/ Boost Libraries ] + +[def __BOOST_MULTI_INDEX__ [@http://www.boost.org/libs/multi_index/doc/index.html [*Boost.MultiIndex]]] +[def __BOOST_MPL__ [@http://www.boost.org/libs/mpl/doc/index.html [*Boost.MPL]]] +[def __BOOST_TYPE_TRAITS__ [@http://www.boost.org/doc/html/boost_typetraits.html [*Boost.TypeTraits]]] +[def __BOOST_ENABLE_IF__ [@http://www.boost.org/libs/utility/enable_if.html [*Boost.enable_if]]] +[def __BOOST_ITERATORS__ [@http://www.boost.org/libs/iterator/doc/index.html [*Boost.Iterators]]] +[def __BOOST_CALL_TRAITS__ [@http://www.boost.org/libs/utility/call_traits.htm [*Boost.call_traits]]] +[def __BOOST_STATIC_ASSERT__ [@http://www.boost.org/doc/html/boost_staticassert.html [*Boost.StaticAssert]]] + +[def __BOOST_SERIALIZATION__ [@http://www.boost.org/libs/serialization/doc/index.html [*Boost.Serialization]]] +[def __BOOST_HASH__ [@http://www.boost.org/doc/html/hash.html [*Boost.Hash]]] +[def __BOOST_ASSIGN__ [@http://www.boost.org/libs/assign/doc/index.html [*Boost.Assign]]] +[def __BOOST_LAMBDA__ [@http://www.boost.org/doc/html/lambda.html [*Boost.Lambda]]] +[def __BOOST_PROPERTY_MAP__ [@http://www.boost.org/doc/html/property_map.html [*Boost.PropertyMap]]] +[def __BOOST_RANGE__ [@http://www.boost.org/doc/html/range.html [*Boost.Range]]] +[def __BOOST_FOREACH__ [@http://www.boost.org/doc/html/foreach.html [*Boost.Foreach]]] +[def __BOOST_TEST__ [@http://www.boost.org/libs/test/doc/index.html [*Boost.Test]]] +[def __BOOST_TYPEOF__ [@http://www.boost.org/libs/typeof/doc/index.html [*Boost.Typeof]]] +[def __BOOST_XPRESSIVE__ [@http://www.boost.org/libs/xpressive/doc/index.html [*Boost.Xpressive]]] + + +[/ Extern Links ] + +[def __CPP_STANDARD_LIBRARY_TECHNICAL_REPORT__ [@http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1836.pdf C++ Standard Library Technical Report]] +[def __CPP_DEFECT_REPORT_130__ [@http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#130 Defect Report 130]] +[def __TR1_ISSUES_LIST__ [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1837.pdf Issues List]] + +[def __BOOST_HASH_FUNCTION__ [@http://www.boost.org/regression-logs/cs-win32_metacomm/doc/html/hash.html boost::hash]] + +[def __BOOST_PERMUTATION_ITERATOR__ [@http://www.boost.org/libs/iterator/doc/permutation_iterator.html `permutation_iterator`]] + +[def __BOOST_ASSERT_MACRO__ [@where_it_is `BOOST_ASSERT`]] +[def __BOOST_MPL_FORWARD_SEQUENCE__ [@http://www.boost.org/libs/mpl/doc/refmanual/forward-sequence.html MPL Forward Sequence]] +[def __BOOST_MPL_RANDOM_ACCESS_SEQUENCE__ [@http://www.boost.org/libs/mpl/doc/refmanual/random-access-sequence.html MPL Random Access Sequence]] +[def __BOOST_MPL_EXTENSIBLE_SEQUENCE__ [@http://www.boost.org/libs/mpl/doc/refmanual/extensible-sequence.html MPL Extensible Sequence]] + +[def __SGI_UNARY_FUNCTION__ [@http://www.sgi.com/tech/stl/UnaryFunction.html Unary Function]] +[def __SGI_BINARY_FUNCTION__ [@http://www.sgi.com/tech/stl/BinaryFunction.html Binary Function]] + +[def __SGI_ASSIGNABLE__ [@http://www.sgi.com/tech/stl/Assignable.html Assignable]] +[def __SGI_DEFAULT_CONSTRUCTIBLE__ [@http://www.sgi.com/tech/stl/DefaultConstructible.html Default Constructible]] +[def __SGI_BINARY_PREDICATE__ [@http://www.sgi.com/tech/stl/BinaryPredicate.html Binary Predicate]] +[def __SGI_CONTAINER__ [@http://www.sgi.com/tech/stl/Container.html Container]] +[def __SGI_SORTED_ASSOCIATIVE_CONTAINER__ [@http://www.sgi.com/tech/stl/SortedAssociativeContainer.html Sorted Associative Container]] +[def __SGI_UNIQUE_ASSOCIATIVE_CONTAINER__ [@http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html Unique Associative Container]] +[def __SGI_REVERSIBLE_CONTAINER__ [@http://www.sgi.com/tech/stl/ReversibleContainer.html Reversible Container]] +[def __SGI_RANDOM_ACCESS_CONTAINER__ [@http://www.sgi.com/tech/stl/RandomAccessContainer.html Random Access Container]] +[def __SGI_FRONT_INSERTION_SEQUENCE__ [@http://www.sgi.com/tech/stl/FrontInsertionSequence.html Front Insertion Sequence]] +[def __SGI_BACK_INSERTION_SEQUENCE__ [@http://www.sgi.com/tech/stl/BackInsertionSequence.html Back Insertion Sequence]] +[def __SGI_INPUT_ITERATOR__ [@http://www.sgi.com/tech/stl/InputIterator.html Input Iterator]] +[def __SGI_FORWARD_ITERATOR__ [@http://www.sgi.com/tech/stl/ForwardIterator.html Forward Iterator]] +[def __SGI_STRICT_WEAK_ORDERING__ [@http://www.sgi.com/tech/stl/StrictWeakOrdering.html Strict Weak Ordering]] + +[def __EIFFEL__ [@http://www.eiffel.com/ Eiffel]] +[def __SAFE_STL__ [@http://www.horstmann.com/safestl.html Safe STL]] +[def __STL_PORT_DEBUG_MODE__ [@http://www.stlport.com/doc/debug_mode.html STLport Debug Mode]] + +[def __CGAL__ [@http://www.cgal.org/ CGAL]] +[def __MYSQLPP__ [@http://tangentsoft.net/mysql++/ MySQL++]] + + +[def __STL_TREE_H__ [@http://www.sgi.com/tech/stl/stl_tree.h stl_tree.h]] +[def __ORDER_STATISTICS_TREE__ [@http://pine.cs.yale.edu/pinewiki/OrderStatisticsTree ['order-statistics trees]]] + +[def __GENERIC_PROGRAMMING_MOVE_CONSTRUCTORS__ [@http://www.ddj.com/dept/cpp/184403855 "Generic: Move Constructors]] +[def __CLARIFICATION_OF_INITIALIZATION__ [@http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2004/n1610.html "Clarification of Initialization of Class Objects by rvalues"]] + + +[/ Code snippets ] + +[import ../example/simple_bimap.cpp] +[import ../example/mighty_bimap.cpp] + +[section Preface] + +[heading Description] + +__BOOST_BIMAP_LOGO__ + +Boost.Bimap is a bidirectional maps library for C++. With Boost.Bimap you can create associative containers in which both types can be used as key. A `bimap` +can be thought of as a combination of a `std::map` and a `std::map`. +The learning curve of bimap is almost flat if you know how to use standard +containers. A great deal of effort has been put into mapping the naming scheme of the +STL in Boost.Bimap. The library is designed to match the common STL containers. + +[heading Influences and Related Work] + +The design of Boost.Bimap interface follows the standard template library. +It has been strongly influenced by Joaquin Lopez Muñoz's Boost.MultiIndex library +(the heart of bimaps) and codeproject::bimap library. + +[endsect] + +[include introduction.qbk] +[include quick_tutorial.qbk] +[include tutorial.qbk] +[include bimap_and_boost.qbk] +[include reference.qbk] +[include compiler_specifics.qbk] +[include performance.qbk] +[include examples.qbk] +[include test_suite.qbk] +[include future_work.qbk] +[include release_notes.qbk] +[include rationale.qbk] +[include history.qbk] +[include acknowledgements.qbk] diff --git a/doc/bimap_and_boost.qbk b/doc/bimap_and_boost.qbk new file mode 100755 index 0000000..747e575 --- /dev/null +++ b/doc/bimap_and_boost.qbk @@ -0,0 +1,477 @@ +[/license + +Boost.Bimap + +Copyright (c) 2006-2007 Matias Capeletto + +Distributed under the Boost Software License, Version 1.0. +(See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt) + +] + +[/ QuickBook Document version 1.4 ] + +[section Bimap and Boost] + +[section Bimap and MultiIndex] + +['MISC] - [*M]ulti-[*I]ndex [*S]pecialized [*C]ontainers + +[:[' +Let's be generic, construct frameworks, describe the world in an +unified way... +]] +[:[' +No!, it is better to be specialized, design easy-to-use components, +offer plug-and-play objects... +]] +[:[* +Why not take advantage of the best of both worlds? +]] + +__MI_FRAMEWORK__ + +With Boost.Bimap, you can build associative containers in which both +types can be used as key. There is a library in Boost that already +allows the creation of this kind of container: Boost.MultiIndex. It +offers great flexibility and lets you construct almost any container +that you could dream of. The framework is very clean. You migh want to +read this library's tutorial to learn about the power that has been +achieved. + + +But generality comes at a price: the interface that results might not be +the best for every specialization. People may end up wrapping a B.MI +container in its own class every time they want to use it as a +bidirectional map. Boost.Bimap takes advantage of the narrower scope to +produce a better interface for bidirectional maps +[footnote In the same fashion, Boost.MRU will allow the creation of ['most +recent updated] aware containers, hiding the complexity of Boost.MultiIndex.]. +There is no learning curve if you know how to use standard containers. +Great effort was put into mapping the naming scheme of the STL to Boost.Bimap. +The library is designed to match the common STL containers. + +Boost.MultiIndex is, in fact, the core of the bimap container. + +However, Boost.Bimap do not aim to tackle every problem with two indexed +types. There exist some problems that are better modelled with Boost.MultiIndex. + + +[blurb + +[*Problem I - An employee register] + +['Store an ID and a name for an employee, with fast search on each member.] + +This type of problem is better modelled as a database table, and +[*Boost.MultiIndex] is the preferred choice. It is possible that other data +will need to be indexed later. + +] + +[blurb + +[*Problem II - A partners container] + +['Store the names of couples and be able to get the name of a person's +partner.] + +This problem is better modelled as a collection of relations, and [*Boost.Bimap] +fits nicely here. + +] + +You can also read +[link boost_bimap.the_tutorial.additional_information Additional Information] for more +information about the relation of this two libraries. + +[endsect] + +[section Boost Libraries that work well with Boost.Bimap] + +[section Introduction] + +[table +[[Name][Description][author][Purpose]] + +[[ __BOOST_SERIALIZATION__ ][ +Serialization for persistence and marshalling] +[Robert Ramey] +[Serialization support for bimap containers and iterators]] + +[[ __BOOST_ASSIGN__ ][ +Filling containers with constant or generated data has never been easier] +[Thorsten Ottosen] +[Help to fill a bimap or views of it]] + +[[ __BOOST_HASH__ ][ +A TR1 hash function object that can be extended to hash user defined types] +[Daniel James] +[Default hashing function]] + +[[ __BOOST_LAMBDA__ ][ +Define small unnamed function objects at the actual call site, and more] +[from Jaakko Järvi, Gary Powell] +[Functors for modify, range, lower_bound and upper_bound]] + +[[ __BOOST_RANGE__ ][ +A new infrastructure for generic algorithms that builds on top of the new +iterator concepts] +[Thorsten Ottosen] +[Range based algorithms]] + +[[ __BOOST_FOREACH__ ][ +BOOST_FOREACH macro for easily iterating over the elements of a sequence] +[Eric Niebler] +[Iteration]] + +[[ __BOOST_TYPEOF__ ][ +Typeof operator emulation] +[Arkadiy Vertleyb, Peder Holt] +[Using BOOST_AUTO while we wait for C++0x]] + +[[ __BOOST_XPRESSIVE__ ][ +Regular expressions that can be written as strings or as expression templates] +[Eric Niebler] +[Help to fill a bimap from a string]] + +[[ __BOOST_PROPERTY_MAP__ ][ +Concepts defining interfaces which map key objects to value objects] +[Jeremy Siek] +[Integration with BGL]] +] + +[endsect] + +[section Boost.Serialization] + +A bimap can be archived and retrieved by means of the Boost.Serialization Library. +Both regular and XML archives are supported. The usage is straightforward and does +not differ from that of any other serializable type. For instance: + +[import ../example/bimap_and_boost/serialization.cpp] + +[@../../example/bimap_and_boost/serialization.cpp Go to source code] + +[code_bimap_and_boost_serialization] + +Serialization capabilities are automatically provided by just linking with the +appropriate Boost.Serialization library module: it is not necessary to explicitly +include any header from Boost.Serialization, apart from those declaring the type +of archive used in the process. If not used, however, serialization support can +be disabled by globally defining the macro BOOST_BIMAP_DISABLE_SERIALIZATION. +Disabling serialization for Boost.MultiIndex can yield a small improvement in +build times, and may be necessary in those defective compilers that fail to +correctly process Boost.Serialization headers. + +[warning Boost.Bimap and Boost.MultiIndex share a lot of serialization code. +The macro `BOOST_BIMAP_DISABLE_SERIALIZATION` disables serialization in *both* +libraries. The same happens when `BOOST_MULTI_INDEX_DISABLE_SERIALIZATION` is +defined. +] + +Retrieving an archived bimap restores not only the elements, but also the order +they were arranged in the views of the container. There is an exception to this rule, +though: for unordered sets, no guarantee is made about the order in which elements +will be iterated in the restored container; in general, it is unwise to rely on +the ordering of elements of a hashed view, since it can change in arbitrary ways +during insertion or rehashing --this is precisely the reason why hashed indices +and TR1 unordered associative containers do not define an equality operator. + +Iterators of a bimap can also be serialized. Serialization of an +iterator must be done only after serializing its corresponding container. + +[endsect] + +[section Boost.Assign] + +The purpose of this library is to make it easy to fill containers with data by +overloading operator,() and operator()(). These two operators make it possible +to construct lists of values that are then copied into a container. + +These lists are particularly useful in learning, testing, and prototyping +situations, but can also be handy otherwise. The library comes with predefined +operators for the containers of the standard library, but most functionality will +work with any standard compliant container. The library also makes it possible +to extend user defined types so for example a member function can be called for +a list of values instead of its normal arguments. + +Boost.Assign can be used with bimap containers. +The views of a bimap are signature-compatible with their standard +counterparts, so we can use other Boost.Assign utilities with them. + +[import ../example/bimap_and_boost/assign.cpp] + +[@../../example/bimap_and_boost/assign.cpp Go to source code] + +[code_bimap_and_boost_assign] + +[endsect] + +[section Boost.Hash] + +The hash function is the very core of the fast lookup capabilities of the +unordered sets: a hasher is just a Unary Function returning an std::size_t value +for any given key. In general, it is impossible that every key map to a +different hash value, for the space of keys can be greater than the number of permissible hash codes: what makes for a good hasher is that the probability of a collision (two different keys with the same hash value) is as close to zero as possible. + +This is a statistical property depending on the typical distribution of keys in a given application, so it is not feasible to have a general-purpose hash function with excellent results in every possible scenario; the default value for this parameter uses Boost.Hash, which often provides good enough results. + +Boost.Hash can be +[@http://www.boost.org/regression-logs/cs-win32_metacomm/doc/html/hash/custom.html +extended for custom data types], +enabling to use the default parameter of the unordered set types with any user types. + +[endsect] + +[section Boost.Lambda] + +The Boost Lambda Library (BLL in the sequel) is a C++ template library, which implements +form of lambda abstractions for C++. The term originates from functional programming and +lambda calculus, where a lambda abstraction defines an unnamed function. +Lambda expressions are very useful to construct the function objects required by some of +the functions in a bimap view. + +Boost.Bimap defines new placeholders in `` +to allow a sounder solution. The placeholders are named _key and _data and both +are equivalent to boost::lambda::_1. There are two reasons to include this placeholders: +the code looks better with them and they avoid the clash problem between lambda::_1 and +boost::_1 from Boost.Bind. + +[import ../example/bimap_and_boost/lambda.cpp] + +[@../../example/bimap_and_boost/lambda.cpp Go to source code] + +[code_bimap_and_boost_lambda] + +[endsect] + +[section Boost.Range] + +Boost.Range is a collection of concepts and utilities that are particularly useful +for specifying and implementing generic algorithms. +Generic algorithms have so far been specified in terms of two or more iterators. +Two iterators would together form a range of values that the algorithm could +work on. This leads to a very general interface, but also to a somewhat clumsy +use of the algorithms with redundant specification of container names. Therefore +we would like to raise the abstraction level for algorithms so they specify their +interface in terms of Ranges as much as possible. + +As Boost.Bimap views are signature-compatible with their standard +container counterparts, they are compatible with the concept of a range. +As an additional feature, ordered bimap views offer a function named +`range` that allows a range of values to be obtained. + +[import ../example/bimap_and_boost/range.cpp] + +If we have some generic functions that accepts ranges: + +[code_bimap_and_boost_range_functions] + +We can use them with Boost.Bimap with the help of the `range` function. + +[code_bimap_and_boost_range] + +[@../../example/bimap_and_boost/range.cpp Go to source code] + +[endsect] + +[section Boost.Foreach] + +In C++, writing a loop that iterates over a sequence is tedious. +We can either use iterators, which requires a considerable amount of +boiler-plate, or we can use the std::for_each() algorithm and move our +loop body into a predicate, which requires no less boiler-plate and forces +us to move our logic far from where it will be used. In contrast, some other +languages, like Perl, provide a dedicated "foreach" construct that automates +this process. BOOST_FOREACH is just such a construct for C++. It iterates +over sequences for us, freeing us from having to deal directly with iterators +or write predicates. + +You can use BOOST_FOREACH macro with Boost.Bimap views. The generated code will +be as efficient as a std::for_each iteration. +Here are some examples: + +[import ../example/bimap_and_boost/foreach.cpp] + +[code_bimap_and_boost_foreach] + +You can use it directly with ranges too: + +[code_bimap_and_boost_foreach_using_range] + +[@../../example/bimap_and_boost/foreach.cpp Go to source code] + +[endsect] + +[section Boost.Typeof] + +[import ../example/bimap_and_boost/typeof.cpp] + +Once C++0x is out we are going to be able to write code like: + + auto iter = bm.by().find("john"); + +instead of the more verbose + + bm_type::map_by::iterator iter = bm.by().find("john"); + +Boost.Typeof defines a macro BOOST_AUTO that can be used as a library +solution to the auto keyword while we wait for the next standard. + +If we have + +[code_bimap_and_boost_typeof_first] + +The following code snippet + +[code_bimap_and_boost_typeof_not_using_auto] + +can be rewrited as + +[code_bimap_and_boost_typeof_using_auto] + +[@../../example/bimap_and_boost/typeof.cpp Go to source code] + +[endsect] + +[section Boost.Xpressive] + +[import ../example/bimap_and_boost/xpressive.cpp] + +Using Boost.Xpressive we can parse a file and insert the relations in a bimap +in the same step. It is just amazing the power of four lines of code. +Here is an example (it is just beatifull) + +[code_bimap_and_boost_xpressive] + +[@../../example/bimap_and_boost/xpressive.cpp Go to source code] + +[endsect] + +[section Boost.Property_map] + +The Boost Property Map Library consists mainly of interface specifications in the form of +concepts (similar to the iterator concepts in the STL). These interface specifications +are intended for use by implementers of generic libraries in communicating requirements on +template parameters to their users. In particular, the Boost Property Map concepts define a +general purpose interface for mapping key objects to corresponding value objects, thereby +hiding the details of how the mapping is implemented from algorithms. + +The need for the property map interface came from the Boost Graph Library (BGL), which +contains many examples of algorithms that use the property map concepts to specify their +interface. For an example, note the ColorMap template parameter of the breadth_first_search. +In addition, the BGL contains many examples of concrete types that implement the property map +interface. The adjacency_list class implements property maps for accessing objects +(properties) that are attached to vertices and edges of the graph. + +The counterparts of two of the views of Boost.Bimap map, the `set` and +`unordered_set`, are read-write property maps. In order to use these, you +need to include one of the following headers: + + #include + #include + +The following is adapted from the example in the Boost.PropertyMap +documentation. + +[import ../example/bimap_and_boost/property_map.cpp] + +[@../../example/bimap_and_boost/property_map.cpp Go to source code] + +[code_bimap_and_boost_property_map] + +[endsect] + +[endsect] + +[section Dependencies] + +Boost.Bimap is built on top of several Boost libraries. The rationale +behind this decision is keeping the Boost code base small by reusing +existent code. The libraries used are well-established and have been +tested extensively, making this library easy to port since all the hard +work has already been done. The glue that holds everything together is +Boost.MPL. Clearly Boost.MultiIndex is the heart of this library. + +[table Boost Libraries needed by Boost.Bimap +[[Name][Description][author]] + +[[ __BOOST_MULTI_INDEX__ ][ +Containers with multiple STL-compatible access interfaces] +[Joaquín M López Muñoz]] + +[[ __BOOST_MPL__ ][ +Template metaprogramming framework of compile-time algorithms, sequences and metafunction classes] +[Aleksey Gurtovoy]] + +[[ __BOOST_TYPE_TRAITS__ ][ +Templates for fundamental properties of types.] +[John Maddock, Steve Cleary]] + +[[ __BOOST_ENABLE_IF__ ][ +Selective inclusion of function template overloads] +[Jaakko Järvi, Jeremiah Willcock, Andrew Lumsdaine]] + +[[ __BOOST_ITERATORS__ ][ +Iterator construction framework, adaptors, concepts, and more.] +[Dave Abrahams, Jeremy Siek, Thomas Witt]] + +[[ __BOOST_CALL_TRAITS__ ][ +Defines types for passing parameters.] +[John Maddock, Howard Hinnant]] + +[[ __BOOST_STATIC_ASSERT__ ][ +Static assertions (compile time assertions).] +[John Maddock]] + +] + +[table Optional Boost Libraries +[[Name][Description][author][Purpose]] + +[[ __BOOST_SERIALIZATION__ ][ +Serialization for persistence and marshalling] +[Robert Ramey] +[Serialization support for bimap containers and iterators]] + +[[ __BOOST_ASSIGN__ ][ +Filling containers with constant or generated data has never been easier] +[Thorsten Ottosen] +[Help to fill a bimap or views of it]] + +[[ __BOOST_HASH__ ][ +A TR1 hash function object that can be extended to hash user defined types] +[Daniel James] +[Default hashing function]] + +[[ __BOOST_LAMBDA__ ][ +Define small unnamed function objects at the actual call site, and more] +[from Jaakko Järvi, Gary Powell] +[Functors for modify, range, lower_bound and upper_bound]] + +[[ __BOOST_RANGE__ ][ +A new infrastructure for generic algorithms that builds on top of the new +iterator concepts] +[Thorsten Ottosen] +[Range based algorithms]] + +[[ __BOOST_PROPERTY_MAP__ ][ +Concepts defining interfaces which map key objects to value objects] +[Jeremy Siek] +[Integration with BGL]] +] + +[table Additional Boost Libraries needed to run the test-suite +[[Name][Description][author]] + +[[ __BOOST_TEST__ ][ +Support for simple program testing, full unit testing, and for program execution monitoring.] +[Gennadiy Rozental] +] +] + +[endsect] + +[endsect] \ No newline at end of file diff --git a/doc/compiler_specifics.qbk b/doc/compiler_specifics.qbk new file mode 100755 index 0000000..55dfda0 --- /dev/null +++ b/doc/compiler_specifics.qbk @@ -0,0 +1,61 @@ +[/license + +Boost.Bimap + +Copyright (c) 2006-2007 Matias Capeletto + +Distributed under the Boost Software License, Version 1.0. +(See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt) + +] + +[/ QuickBook Document version 1.4 ] + +[section Compiler specifics] + +[table +[[Compiler ][OS Tested ][State ]] +[[GCC 3.3 ][Linux ][Supported ]] +[[GCC 3.4 ][Linux ][Supported ]] +[[GCC 4.0 ][Linux, Mac][Supported ]] +[[GCC 4.1 ][Linux ][Supported ]] +[[GCC 4.2 ][Linux ][Supported ]] +[[ICC 8.0 ][Linux ][Supported ]] +[[ICC 9.0 ][Linux ][Supported ]] +[[ICC 9.1 ][Linux ][Supported ]] +[[GCC 4.2 ][Linux ][Supported ]] +[[GCC 4.2 ][Linux ][Supported ]] +[[VS 7.1 ][Windows ][Supported ]] +[[VS 8.0 ][Windows ][Supported ]] +[[ICC 7.1 ][Windows ][Not Supported ]] +[[ICC 8.0 ][Windows ][Supported ]] +[[ICC 9.1 ][Windows ][Supported ]] +[[CW 8.3 ][Windows ][Not Supported ]] +] + +[/ +[[Comeau C++][ ][Not yet tested (Will be supported) ]] +[[CW 8.3 ][Windows ][On going effort to support it ]] +] + +[h2 VS 7.1] + +If a .cpp file uses more than four differents bimaps the compiler will run +out of symbols and issue an internal compiler error. The official solution +in msdn is to split the .cpp in several files or upgrade your compiler. + +[h2 VS 8.0] + +VC++ 8.0 warns on usage of certain Standard Library and API functions that +can be cause buffer overruns or other possible security issues if misused. +See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +But the wording of the warning is misleading and unsettling, there are no +portable alternative functions, and VC++ 8.0's own libraries use the +functions in question. In order to turn off the warnings add the followings +defines at the begging of your .cpp files: + + #define _CRT_SECURE_NO_DEPRECATE + #define _SCL_SECURE_NO_DEPRECATE + +[endsect] \ No newline at end of file diff --git a/doc/directdoxygen.jam b/doc/directdoxygen.jam new file mode 100644 index 0000000..c674d93 --- /dev/null +++ b/doc/directdoxygen.jam @@ -0,0 +1,13 @@ +import type ; +import generators ; + +type.register HTML_DOXYFILE : hdf ; +type.register HTML_DOXYDOCS : hdt ; + +generators.register-standard directdoxygen.run : HTML_DOXYFILE : HTML_DOXYDOCS ; + +actions run +{ + "doxygen" $(>) + echo "Stamped" > "$(<)" +} diff --git a/doc/examples.qbk b/doc/examples.qbk new file mode 100755 index 0000000..5f05e2d --- /dev/null +++ b/doc/examples.qbk @@ -0,0 +1,236 @@ +[/license + +Boost.Bimap + +Copyright (c) 2006-2007 Matias Capeletto + +Distributed under the Boost Software License, Version 1.0. +(See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt) + +] + +[/ QuickBook Document version 1.4 ] + +[section Examples] + +[section Examples list] + +In the folder [@../../example libs/bimap/example] you can find all the examples +used in bimap documentation. Here is a list of them: + + +[table Tutorial examples +[[Program ][Description ]] + +[[[@../../example/simple_bimap.cpp + simple_bimap.cpp ]] + [Soccer world cup example ]] + +[[[@../../example/tagged_simple_bimap.cpp + tagged_simple_bimap.cpp ]] + [Soccer world cup example using user defined names ]] + +[[[@../../example/step_by_step.cpp + step_by_step.cpp ]] + [Basic example of the three views of bimap ]] + +[[[@../../example/population_bimap.cpp + population_bimap.cpp ]] + [Countries populations, using `unordered_set_of` and `multiset_of` ]] + +[[[@../../example/repetitions_counter.cpp + repetitions_counter.cpp ]] + [Word repetitions counter, using `unordered_set_of` and `list_of` ]] + +[[[@../../example/mighty_bimap.cpp + mighty_bimap.cpp ]] + [Dictionary using `list_of_relation` ]] + +[[[@../../example/user_defined_names.cpp + user_defined_names.cpp ]] + [Equivalence between code with tagged and untagged code ]] + +[[[@../../example/standard_map_comparison.cpp + standard_map_comparison.cpp ]] + [Comparison between standard maps and bimap map views ]] + +[[[@../../example/at_function_examples.cpp + at_function_examples.cpp ]] + [Functions `at(key)` and `operator[](key)` examples ]] + +[[[@../../example/tutorial_modify_and_replace.cpp + tutorial_modify_and_replace.cpp ]] + [`modify` and `replace` examples ]] + +[[[@../../example/tutorial_range.cpp + tutorial_range.cpp ]] + [`range()` tutorial ]] + +[[[@../../example/tutorial_info_hook.cpp + tutorial_info_hook.cpp ]] + [Additional information hooking ]] + +[[[@../../example/unconstrained_collection.cpp + unconstrained_collection.cpp ]] + [Using `unconstrained_set_of` collection type ]] +] + + +[table Bimap and Boost examples +[[Program ][Description ]] + +[[[@../../example/bimap_and_boost/assign.cpp + assign.cpp ]] + [Bimap and Boost.Assign: Methods to insert elements ]] + +[[[@../../example/bimap_and_boost/lambda.cpp + lambda.cpp ]] + [Bimap and Boost.Lambda: new lambda placeholders ]] + +[[[@../../example/bimap_and_boost/property_map.cpp + property_map.cpp ]] + [Bimap and Boost.PropertyMap: PropertyMap support ]] + +[[[@../../example/bimap_and_boost/range.cpp + range.cpp ]] + [Bimap and Boost.Range: Using bimaps in the new range framework ]] + +[[[@../../example/bimap_and_boost/foreach.cpp + foreach.cpp ]] + [Bimap and Boost.Foreach: Iterating over bimaps ]] + +[[[@../../example/bimap_and_boost/typeof.cpp + typeof.cpp ]] + [Bimap and Boost.Typeof: using BOOST_AUTO while we wait for C++0x ]] + +[[[@../../example/bimap_and_boost/xpressive.cpp + xpressive.cpp ]] + [Bimap and Boost.Xpressive: Inserting elements in a bimap ]] + +[[[@../../example/bimap_and_boost/serialization.cpp + serialization.cpp: ]] + [Bimap and Boost.Serialization: Load and save bimaps and iterators ]] +] + + +[table Boost.MultiIndex to Boost.Bimap path examples +[[Program ][Description ]] + +[[[@../../example/mi_to_b_path/bidirectional_map.cpp + bidirectional_map.cpp ]] + [Boost.MultiIndex to Boost.Bimap path example ]] + +[[[@../../example/mi_to_b_path/hashed_indices.cpp + hashed_indices.cpp ]] + [Boost.MultiIndex to Boost.Bimap path example ]] + +[[[@../../example/mi_to_b_path/tagged_bidirectional_map.cpp + tagged_bidirectional_map.cpp ]] + [Boost.MultiIndex to Boost.Bimap path example ]] + +] + +[endsect] + +[section Simple Bimap] + +This is the example from the one minute tutorial section. + +[@../../example/simple_bimap.cpp Go to source code] + +[code_simple_bimap] + +You can rewrite it using tags to gain readability. + +[@../../example/tagged_simple_bimap.cpp Go to source code] + +[import ../example/tagged_simple_bimap.cpp] + +[code_tagged_simple_bimap] + + +[endsect] + +[section Mighty Bimap] + +This is the translator example from the tutorial. +In this example the collection type of relation is changed to allow the iteration +of the container. + +[@../../example/mighty_bimap.cpp Go to source code] + +[code_mighty_bimap] + + +[endsect] + +[section MultiIndex to Bimap Path - Bidirectional Map] + +This is example 4 in Boost.MultiIndex documentation. + +[blurb +This example shows how to construct a bidirectional map with multi_index_container. +By a bidirectional map we mean a container of elements of +`std::pair` such that no two elements exists with the +same first or second value (`std::map` only guarantees uniqueness of the first member). +Fast look-up is provided for both keys. The program features a tiny Spanish-English +dictionary with on-line query of words in both languages. +] + +[heading Boost.MultiIndex] + +[@../../example/mi_to_b_path/mi_bidirectional_map.cpp Go to source code] + +[import ../example/mi_to_b_path/mi_bidirectional_map.cpp] + +[code_mi_to_b_path_mi_bidirectional_map] + +[heading Boost.Bimap] + +[@../../example/mi_to_b_path/bidirectional_map.cpp Go to source code] + +[import ../example/mi_to_b_path/bidirectional_map.cpp] + +[code_mi_to_b_path_bidirectional_map] + +Or better, using tags... + +[@../../example/mi_to_b_path/tagged_bidirectional_map.cpp Go to source code] + +[import ../example/mi_to_b_path/tagged_bidirectional_map.cpp] + +[code_mi_to_b_path_tagged_bidirectional_map] + +[endsect] + +[section MultiIndex to Bimap Path - Hashed indices] + +This is example 8 of Boost.MultiIndex. + +[blurb +Hashed indices can be used as an alternative to ordered indices when fast look-up is needed and sorting +information is of no interest. The example features a word counter where duplicate entries are checked by +means of a hashed index. +] + +[heading Boost.MultiIndex] + +[@../../example/mi_to_b_path/mi_hashed_indices.cpp Go to source code] + +[import ../example/mi_to_b_path/mi_hashed_indices.cpp] + +[code_mi_to_b_path_mi_hashed_indices] + +[heading Boost.Bimap] + +[@../../example/mi_to_b_path/hashed_indices.cpp Go to source code] + +[import ../example/mi_to_b_path/hashed_indices.cpp] + +[code_mi_to_b_path_hashed_indices] + + +[endsect] + +[endsect] \ No newline at end of file diff --git a/doc/future_work.qbk b/doc/future_work.qbk new file mode 100755 index 0000000..9118de5 --- /dev/null +++ b/doc/future_work.qbk @@ -0,0 +1,23 @@ +[/license + +Boost.Bimap + +Copyright (c) 2006-2007 Matias Capeletto + +Distributed under the Boost Software License, Version 1.0. +(See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt) + +] + +[/ QuickBook Document version 1.4 ] + +[section Future work] + + +[heading Rearrange Function] + +Boost.MultiIndex includes some others functions that can be included in the views. + + +[endsect] \ No newline at end of file diff --git a/doc/history.qbk b/doc/history.qbk new file mode 100755 index 0000000..5f3074b --- /dev/null +++ b/doc/history.qbk @@ -0,0 +1,450 @@ +[/license + +Boost.Bimap + +Copyright (c) 2006-2007 Matias Capeletto + +Distributed under the Boost Software License, Version 1.0. +(See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt) + +] + +[/ QuickBook Document version 1.4 ] + +[section History] + +[section The long path from Code Project to Boost] + +[variablelist +[[2002 - bimap at Code Project] +[ +Joaquin Lopez Muñoz posted his first +[@http://www.codeproject.com/vcpp/stl/bimap.asp#test_suite bimap library] +in 2002. Tons of users have been using it. He then +[@http://aspn.activestate.com/ASPN/Mail/Message/boost/1404881 asked the +list for interest] in his library in 2003. Luckily, there was a lot of +interest and Joaquin started to boostify the code. At some point all the +developers seemed to agree that, rather than a bidirectional map, it would +be better to work on an N-indexed set that contained Joaquin's library as a +particular case. +]] + +[[2003 - multiindex_set] +[ +The library grew enormously and was ready for a formal review in +2003. At this point, the container was a lot more powerful, but +everything comes with a price and this new beast lacked the simplicity +of the original bimap. +]] + +[[2004 - indexed_set] +[ +In 2004, the formal review ended well for the new multi-indexed +container. This Swiss army knife introduced several new features, such +as non-unique indexes, hashed indices and sequenced indices. In the list +of improvements to the library, it was mentioned that a bidirectional +map should be coded in top of this container. +]] + +[[2005 - multi_index_container] +[ +Once in Boost, the library switched to the now familiar name +"Boost.MultiIndex". Late in 2004, it formally became a member of Boost. +Joaquin continued to enchance the library and added new features such as +composite keys and random-access indices. +]] + +[[2006 - Multi Index Specialized Containers SoC project] +[ +In 2006, during the formal review of Boost.Property_tree, the need +for a bidirectional map container built on top of Boost.MultiIndex arose +again. Boost entered the Google SoC 2006 as a mentor organization at the +same time. Joaquin put himself forward as a mentor. He proposed to build +not only a bidirectional map, but a myriad multi-indexed specialized +containers. Matias Capeletto presented an application to code Boost.Misc +for the SoC and was elected, along with nine other students. Matias's and +Joaquin's SoC project ends with a working implementation of the bimap +library that was presented in an informal review. By the end of the year +the library was queued for a formal review. +]] + +[[2007 - Boost.Bimap] +[ +The formal review took place at the beggining of the year and Boost.Bimap +was accepted in Boost. +]] +] + +[endsect] + +[section MultiIndex and Bimap] + +This is the conversation thread that began during Boost.PropertyTree formal +review process. The review was very interesting and very deep topics were +addressed. It is quite interesting and it is now part of this library history. +Enjoy! + + +[*Marcin] +[:[' +The biggest virtue of property_tree is easy to use interface. +If we try to make generic tree of it, it will be compromised. +]] + +[*Gennadiy] +[:[' +IMO the same result (as library presents) could be achieved +just by using multi_index. +]] + +[*Marcin] +[:[' +Could you elaborate more on that? I considered use of +multi_index to implement indexing for properties, but it only affected the +implementation part of library, not interface, and because I already had a +working, exception safe solution, I didn't see the reason to dump it and add +another dependency on another library. +]] + +[*Gennadiy] +[:[' +I mean why do I need this half baked property_tree as another +data structure? Property tree supports nothing in itself. It's just a data +structure. You have parsers that produce property tree out of different sources. +But you mat as well produce maps or something else. Here for example All that +I need to do to "implement" similar functionality as your property tree: +]] + +`` +// Data structure itself +template +struct Node; +template +struct ptree_gen { + typedef std::pair > mi_value; + typedef multi_index_container > type; +}; +template +struct Node { + ValueType v; + ptree_gen::type children; +}; +// serialization support +template +void serialize(Archive & ar, Node& n, + const unsigned int version) +{ + ar & n.v; + ar & n.children; +} +// some access methods +template +ValueType const& +get( string const& keys, ptree_gen::type const& src ) +{ + std::pait sk = split( keys, "." ); + Node const& N = src.find( sk.first ); + return sk.second.empty() ? N.v : get( sk.second, N.children ); +} +`` + +[:[' +Use it like this: +]] + +`` +ptree_gen::type PT; +boost::archive::text_iarchive ia( std::ifstream ifs("filename") ); +ia >> PT; +string value = get( "a.b.c.d", PT ); +`` + +[:[' +Now tell me how property_tree interface is easier? And what is the value in +50k of Code you need to implement this data structure. +]] + +[*Thorsten] +[:[' +Seriously Gennadiy, do you really see newbies writing +the code you just did? +]] + +[*Marcin] +[:[' +What you just implemented is stripped down, bare bones version +of property_tree that, among other things, does not allow you to produce human +editable XML files. Now add more interface (aka get functions), add more +archives to serialization lib, add customization, add transparent +translation from strings to arbitrary types and vice versa. Spend some weeks +trying to get all the corner cases right, and then some more weeks trying to +smooth rough edges in the interface. Then write tests. Write docs. At the +end, I believe you will not get much less code than there is in the library +already. Maybe you get some savings by using multi_index instead of manual +indexing. +]] +[:[' +The reason why ptree does not use multi index is because implementation +existed long before I considered submitting to boost, probably before even I +knew of multi index existence. It was working well. Later, when I was +improving it during pre-review process, I seriously considered using +multi-index. But I decided it is not worth throwing everything out. +]] +[:[' +Although ptree has large interface with many functions modifying state of +the tree, it uses "single point of change" approach. Every insert eventually +goes through one function, which takes care of exception safety and keeping +index in sync with data. The same applies to erase. This function has 9 +lines of code in case of insert, and (by coincidence) also 9 in case of +erase. By using multi index these functions would obviously be simplified, +maybe to 4 lines each. Net gain: 10 lines of code (out of several hundred in +ptree_implementation.hpp). +]] +[:[' +I'm aware that there are performance gains to be reaped as well, but at that +time I was rather focusing on getting the interface right. +]] + +[*Dave] +[:[' +That's perfectly reasonable, but (through no fault of yours) +it misses the point I was trying to make. I guess I should have said, +"...that demonstrates it to be the best implementation." +]] +[:[' +All I'm saying is that the extent to which a Boost library +implementation should leverage other Boost libraries is not a question +that can always be decided based on following simple guidelines, and +that if this library is accepted, it's worth revisiting your decision. +]] + +[*Thorsten] +[:[' +I think it is important to focus on the interface in +the review, but I also see several benefits of an implementation that builds on +Boost.MultiIndex:' +]] +[:['- fewer bugs like the one Joaquin found]] +[:['- better space efficiency]] +[:['- exception-safety guarantees are immediately full-filled (I haven't +looked, but I suspect that there are several bugs in this area)]] + +[*Daniel] +[:[' +Multi_index supports everything a bimap would, but its +interface is more cumbersome. I for one won't use a W3DOM-like library +if we get one, but I would happily use property_tree. I've also only +used multi_index once, and that was to use it as a bidirectional map. +Property_tree covers other areas as well as being a potential subset of +an XML library, but I still hold there is value in such a subset. +]] + +[*Boris] +[:[' +I haven't used program_options yet. But if I understand +correctly both libraries seem to support storing and accessing data with +strings that might describe some kind of hierarchy. This seems to be the core +idea of both libraries - is this correct? +]] +[:[' +Then it wouldn't matter much what container is used. However a generic tree +which can store data hierarchically probably makes most sense. If I +understand correctly both libraries could make use of such a class? +]] + +[*Marcin] +[:[' +I think generic tree container is material for another library. +Whether property_tree should be based on it or not is a matter of internal +implementation, and generally of little interest to users. The biggest value +of property_tree is in its easy to use interface, that should not be +compromised, if at all possible. I have been already reassured in this view +by quite many people who took their time to review the library. +]] + +[*Boris] +[:[' +I was trying to see the big picture: I rather prefer a C++ +standard based on a few well-known concepts like containers, iterators, +algorithms etc. instead of having a C++ standard with hundreds of components +which are tailored for specific needs, collaborate with only a handful of other +components and think they provide an easy-to-use interface while all the +easy-to-use interfaces make the whole standard less easy-to-use. +]] +[:[' +That said I have used your property tree library myself to read and write a +configuration file. It was indeed very easy to use. However it would have +been even easier if it was something I had known before like eg. an +iterator. For now I will definitely use your property tree library but would +appreciate if existing concepts were reused many C++ developers are familiar +with. My opinion is that your library should be a part of Boost but should +be more generalized in the future. +]] + +[*Thorsten] +[:[' +Well, I think we need both. Boost.MultiIndex is a great +library and can do all kinds of wonderful things. But I would still like to see +a bidirectional map (boost::bimap) written as a wrapper around it to +get an easy and specialized interface. +]] + +[*Pavel] +[:[' +Bimap is available in libs/multi-index/examples/bimap.cpp. +]] + +[*Thorsten] +[:[' +Right, but the real value comes when somebody designs a nice +STL-like interface and write docs etc, at least that was my point. +]] + +[*Dave] +[:[' +IMO Thorsten is exactly right. This is precisely the sort of +thing that could be added to the library as part of its ongoing maintenance +and development (without review, of course). +]] + +[*Joaquin] +[:[' +Thorsten, we have talked about this privately in the past, +but I feel like bringing it to the list in the hope of getting the attention +of potential contributors: +]] +[:[' +There are some data structures buildable with B.MI which are regarded as +particularly useful or common, like for instance the bidirectional map or +bimap. A lean and mean implementation is provided in the aforementioned +example, but certainly a much carefully crafted interface can be provided +keeping B.MI as the implementation core: operator\[\], selection of +1-1/1-N/N-1/N-N variants, hashing/ordering, etc. +]] +[:[' +I'm afraid I don't have the time to pursue this, as the current roadmap for +core features of B.MI is taking all the spare time I can dedicate to the +library. For this reason, I would love to see some volunteer jumping in who +can develop this and other singular containers using B.MI (a cache container +comes to mind) and then propose the results here either as a stand alone +library of as part of B.MI --I'd prefer the former so as to keep the size +of B.MI bounded. +]] +[:[' +If there's such a volunteer I can provide her with some help/mentoring. I also +wonder whether this is a task suitable to be proposed for Google Summer of +Code. +]] + +[*Thorsten] +[:[' +I think it would be good for SOC. All the really hard things +are taken care of by B.MI, and so it seems reasonable for a student to be able +to fill in the details. +]] + +[*Dave] +[:[' +Great! +]] + +[*Jeff] +[:[' +Please write a proposal! +]] + +[*Joaquin] +[:[' +I've just done so: +]] + +[blurb *Specialized containers with Boost.MultiIndex* + + *Introduction* + + Boost.MultiIndex allows the construction of complex data structures involving + two or more indexing mechanisms on the same set of elements. Out of the + unlimited range of possible data structures specifiable within + Boost.MultiIndex, some particular configurations arise recurrently: + + *a.* A bidirectional map or bimap is a container of elements of type pair + where fast look up is provided both for the T and the Q field, + in contrast with a regular STL map which only allows for fast look up on T. + + *b.* An MRU (most recently used) list keeps the n last referenced elements: + when a new item is inserted and the list has reached its maximum length, the + oldest element is erased, whereas if an insertion is tried of a preexistence + element, this gets promoted to the first position. MRU lists can be used to + implement dynamic caches and the kind of behavior exhibited by programs + featuring a "Recent files" menu command, for instance. + + Although Boost.MultiIndex provides the mechanisms to build these common structures, + the resulting interface can be cumbersome and too general in comparison with + specialized containers focusing on such particular structures. + + *Goal* + + To write a library of specialized containers like the ones described above, using + Boost.MultiIndex as the implementation core. Besides bimap and MRU list, the student + can also propose other specialized containers of interest in the community. It is + expected that the library meets the standards of quality required by Boost for an + eventual inclusion in this project, which implies a strong emphasis on interface + design, documentation and unit testing; the mentor will be guiding the student + through the complete cycle from specification and requirements gathering to + documentation and actual coding. The final result of the project must then contain: + + *a.* Source code following + [@http://boost.org/more/lib_guide.htm#Guidelines Boost programming guidelines]. + + *b.* User documentation. Requirements on the format are loose, though the + [@http://www.boost.org/tools/quickbook/doc/html/index.html QuickBook] format is + gaining acceptance within Boost. + + *c.* Complete set of unit tests powered by + [@http://boost.sourceforge.net/boost-build2/ Boost Build System V2]. + + *Requirements* + + *a.* Intermediate-to-high level in C++, with emphasis in generic programming + (templates). + + *b.* Knowledge of the STL framework and design principles. Of course, knowledge + of Boost in general and Boost.MultiIndex in particular is a big plus. + + *c.* Acquaintance with at least two different C++ programming environments. + + *d.* Some fluency in the English language; subsequent reviews of the documentation + can help smooth rough edges here, though. + + *e.* A mathematical inclination and previous exposure to a formal Algorithms course + would help very much. + + *f.* A craving for extreme quality work. + + *Benefits for the student* + + The student taking on this project will have the opportunity to learn the complete + process of software production inside a highly regarded C++ open source institution, + and even see her work included in Boost eventually. The completion of the project + involves non-trivial problems in C++ interface design and so-called modern C++ + programming, high quality user documentation and unit testing. The student will + also learn, perhaps to her surprise, that most of the time will be spent gathering + and trying ideas and, in general, thinking, rather than writing actual code. +] + +[*Matias] +[:[' +I am planning to submit an application to SoC. I will love to make real +the specialized containers you mention and try to include some useful others. +]] + +[:[^ +And then... after long hours of coding (and fun) this library saw the light. +]] + +[:__BOOST_BIMAP_LOGO__] + +[endsect] + +[endsect] diff --git a/doc/html/boost_bimap/acknowledgements.html b/doc/html/boost_bimap/acknowledgements.html new file mode 100644 index 0000000..c74196f --- /dev/null +++ b/doc/html/boost_bimap/acknowledgements.html @@ -0,0 +1,109 @@ + + + +Acknowledgements + + + + + + + + + + + + + + +
+Boost C++ LibrariesChapter Logo +HomeLibrariesPeopleFAQMore
+
+
+PrevUpHome +
+
+ +

+ This library was developed in the context of the Google SoC 2006. I first want + to thank my mentor, Joaquin, for his friendship during this project. Not only + did he help me go through the process of creating this library, but he also + did his best so we could have a great time doing it. Also, Boost.Bimap would + not exist had Boost.MultiIndex, Joaquin's masterpiece, not existed. Thanks + a lot! +

+

+ googlesoc +

+

+ I want to thank Google for this amazing boost to the open-source + community and to Boost mentors for trusting in my proposal in the first place. + Next on the list are my colleagues from SoC that helped me not get bored during + the long hours of coding. +

+

+ Special acknowledgements to the developers of the Boost libraries that Boost.Bimap + has abused. See the dependencies section for a complete list. +

+

+ I want to thank the open-source developers who wrote the tools I used during + this project. The library was coded using Blade, a full open-source development + environment composed, in my opinion, of the best tools for software building. + The list of names is infinitely long, so I give a general huge thanks here. +

+

+ boost.blade.logo +

+

+ The icons in the TOC of the main page are from kde-look.org. + I want to thank them for their effort in making the open-source world a beautiful + place. When I find time, I will look for the authors' names. Please forgive + me for omitting them for the moment. +

+

+ Thanks to Paul Giaccone for proof-reading this documentation. (He has not finished + yet -- the remaining typos and spelling errors are mine and will be corrected + as soon as possible.) +

+

+ Finally, thanks to my family, who had to see me at home all day during the + SoC. Special thanks to my brother Agustin, future famous novelist (at the present + time he is 19 years old), who patiently read every word of these docs and while + correcting them, barked at me for my bad written English. I have learned a + lot from his sermons. I want to thank my dog, Mafalda, too for barking all + day from my window and for being such a good company. +

+

+ Thanks to Alisdair Meredith, Fernando Cacciola, Jeff Garland, John Maddock, + Thorsten Ottosen, Tony and Giovanni Piero Deretta for participating in the + formal review and give me useful advices to improve this library. And thanks + a lot to Ion Gaztañaga for managing the review. +

+

+ + Boost.Bimap Team +

+

+ From Argentina... Matias and Mafalda and from Spain... Joaquin and Hector +

+

+ matias mafalda joaquin hector +

+

+ Luckily, the distance helps team members avoid eating each other. +

+
+ + + +
Copyright © 2006 -2007 Matias Capeletto
+
+
+PrevUpHome +
+ + diff --git a/doc/html/boost_bimap/bimap_and_boost.html b/doc/html/boost_bimap/bimap_and_boost.html new file mode 100644 index 0000000..5ae0c43 --- /dev/null +++ b/doc/html/boost_bimap/bimap_and_boost.html @@ -0,0 +1,174 @@ + + + +Bimap and Boost + + + + + + + + + + + + + + + +
+Boost C++ LibrariesChapter Logo +HomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ MISC - Multi-Index Specialized + Containers +

+
+

+

+

+ Let's be generic, construct frameworks, describe the world + in an unified way... +

+

+

+
+
+

+

+

+ No!, it is better to be specialized, design easy-to-use components, + offer plug-and-play objects... +

+

+

+
+
+

+

+

+ Why not take advantage of the best of both worlds? + +

+

+

+
+

+ miBimapFramework +

+

+ With Boost.Bimap, you can build associative containers in which both types + can be used as key. There is a library in Boost that already allows the creation + of this kind of container: Boost.MultiIndex. It offers great flexibility + and lets you construct almost any container that you could dream of. The + framework is very clean. You migh want to read this library's tutorial to + learn about the power that has been achieved. +

+

+ But generality comes at a price: the interface that results might not be + the best for every specialization. People may end up wrapping a B.MI container + in its own class every time they want to use it as a bidirectional map. Boost.Bimap + takes advantage of the narrower scope to produce a better interface for bidirectional + maps + [2] + . There is no learning curve if you know how to use standard containers. + Great effort was put into mapping the naming scheme of the STL to Boost.Bimap. + The library is designed to match the common STL containers. +

+

+ Boost.MultiIndex is, in fact, the core of the bimap container. +

+

+ However, Boost.Bimap do not aim to tackle every problem with two indexed + types. There exist some problems that are better modelled with Boost.MultiIndex. +

+ + +

+ You can also read Additional + Information for more information about the relation of this two libraries. +

+
+
+

+

[2] + In the same fashion, Boost.MRU will allow the creation of most + recent updated aware containers, hiding the complexity of + Boost.MultiIndex. +

+
+
+ + + +
Copyright © 2006 -2007 Matias Capeletto
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_bimap/bimap_and_boost/boost_libraries_that_work_well_with_boost_bimap.html b/doc/html/boost_bimap/bimap_and_boost/boost_libraries_that_work_well_with_boost_bimap.html new file mode 100644 index 0000000..9065b97 --- /dev/null +++ b/doc/html/boost_bimap/bimap_and_boost/boost_libraries_that_work_well_with_boost_bimap.html @@ -0,0 +1,1065 @@ + + + +Boost + Libraries that work well with Boost.Bimap + + + + + + + + + + + + + + + +
+Boost C++ LibrariesChapter Logo +HomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ + +
+ +
++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Name +

+
+

+ Description +

+
+

+ author +

+
+

+ Purpose +

+
+

+ Boost.Serialization +

+
+

+ Serialization for persistence and marshalling +

+
+

+ Robert Ramey +

+
+

+ Serialization support for bimap containers and iterators +

+
+

+ Boost.Assign +

+
+

+ Filling containers with constant or generated data has never been + easier +

+
+

+ Thorsten Ottosen +

+
+

+ Help to fill a bimap or views of it +

+
+

+ Boost.Hash +

+
+

+ A TR1 hash function object that can be extended to hash user defined + types +

+
+

+ Daniel James +

+
+

+ Default hashing function +

+
+

+ Boost.Lambda +

+
+

+ Define small unnamed function objects at the actual call site, + and more +

+
+

+ from Jaakko Järvi, Gary Powell +

+
+

+ Functors for modify, range, lower_bound and upper_bound +

+
+

+ Boost.Range +

+
+

+ A new infrastructure for generic algorithms that builds on top + of the new iterator concepts +

+
+

+ Thorsten Ottosen +

+
+

+ Range based algorithms +

+
+

+ Boost.Foreach +

+
+

+ BOOST_FOREACH macro for easily iterating over the elements of a + sequence +

+
+

+ Eric Niebler +

+
+

+ Iteration +

+
+

+ Boost.Typeof +

+
+

+ Typeof operator emulation +

+
+

+ Arkadiy Vertleyb, Peder Holt +

+
+

+ Using BOOST_AUTO while we wait for C++0x +

+
+

+ Boost.Xpressive +

+
+

+ Regular expressions that can be written as strings or as expression + templates +

+
+

+ Eric Niebler +

+
+

+ Help to fill a bimap from a string +

+
+

+ Boost.PropertyMap +

+
+

+ Concepts defining interfaces which map key objects to value objects +

+
+

+ Jeremy Siek +

+
+

+ Integration with BGL +

+
+
+
+ +

+ A bimap can be archived and retrieved by means of the Boost.Serialization + Library. Both regular and XML archives are supported. The usage is straightforward + and does not differ from that of any other serializable type. For instance: +

+

+ Go to source + code +

+

+

+

+ +

+
+typedef bimap< std::string, int > bm_type;
+
+// Create a bimap and serialize it to a file
+{
+    bm_type bm;
+    bm.insert( bm_type::value_type("one",1) );
+    bm.insert( bm_type::value_type("two",2) );
+
+    std::ofstream ofs("data");
+    boost::archive::text_oarchive oa(ofs);
+
+    oa << const_cast<const bm_type&>(bm); 1
+
+    2const bm_type::left_iterator left_iter = bm.left.find("two");
+    oa << left_iter;
+
+    const bm_type::right_iterator right_iter = bm.right.find(1);
+    oa << right_iter;
+}
+
+// Load the bimap back
+{
+    bm_type bm;
+
+    std::ifstream ifs("data", std::ios::binary);
+    boost::archive::text_iarchive ia(ifs);
+
+    ia >> bm;
+
+    assert( bm.size() == 2 );
+
+    bm_type::left_iterator left_iter;
+    ia >> left_iter;
+
+    assert( left_iter->first == "two" );
+
+    bm_type::right_iterator right_iter;
+    ia >> right_iter;
+
+    assert( right_iter->first == 1 );
+}
+
+

+

+

+

+

+

+
+ + + + + + + + +
+1

+ We must do a const cast because Boost.Serialization archives only save + const objects. Read Boost.Serializartion docs for the rationale behind + this decision

+2

We can only serialize iterators if the bimap was serialized + first. Note that the const cast is not requiered here because we create + our iterators as const.

+

+

+

+

+

+ Serialization capabilities are automatically provided by just linking with + the appropriate Boost.Serialization library module: it is not necessary + to explicitly include any header from Boost.Serialization, apart from those + declaring the type of archive used in the process. If not used, however, + serialization support can be disabled by globally defining the macro BOOST_BIMAP_DISABLE_SERIALIZATION. + Disabling serialization for Boost.MultiIndex can yield a small improvement + in build times, and may be necessary in those defective compilers that + fail to correctly process Boost.Serialization headers. +

+
+ + + + + +
[Warning]Warning
+

+

+

+ Boost.Bimap and Boost.MultiIndex share a lot of serialization code. + The macro BOOST_BIMAP_DISABLE_SERIALIZATION + disables serialization in both libraries. + The same happens when BOOST_MULTI_INDEX_DISABLE_SERIALIZATION + is defined. +

+

+

+
+

+ Retrieving an archived bimap restores not only the elements, but also the + order they were arranged in the views of the container. There is an exception + to this rule, though: for unordered sets, no guarantee is made about the + order in which elements will be iterated in the restored container; in + general, it is unwise to rely on the ordering of elements of a hashed view, + since it can change in arbitrary ways during insertion or rehashing --this + is precisely the reason why hashed indices and TR1 unordered associative + containers do not define an equality operator. +

+

+ Iterators of a bimap can also be serialized. Serialization of an iterator + must be done only after serializing its corresponding container. +

+
+
+ +

+ The purpose of this library is to make it easy to fill containers with + data by overloading operator,() and operator()(). These two operators make + it possible to construct lists of values that are then copied into a container. +

+

+ These lists are particularly useful in learning, testing, and prototyping + situations, but can also be handy otherwise. The library comes with predefined + operators for the containers of the standard library, but most functionality + will work with any standard compliant container. The library also makes + it possible to extend user defined types so for example a member function + can be called for a list of values instead of its normal arguments. +

+

+ Boost.Assign can be used with bimap containers. The views of a bimap are + signature-compatible with their standard counterparts, so we can use other + Boost.Assign utilities with them. +

+

+ Go to source code +

+

+

+

+ +

+
+ typedef bimap< multiset_of< int >, list_of< std::string > > bm_type;
+
+ // We can use assign::list_of to initialize the container.
+
+ bm_type bm = assign::list_of< bm_type::relation > 1
+     ( 1, "one"   )
+     ( 2, "two"   )
+     ( 3, "three" );
+
+ // The left map view is a multiset, again we use insert
+
+ assign::insert( bm.left )
+     ( 4, "four" )
+     ( 5, "five" )
+     ( 6, "six"  );
+
+ // The right map view is a list so we use push_back here
+ // Note the order of the elements in the list!
+
+ assign::push_back( bm.right )
+     ( "seven" , 7 )
+     ( "eight" , 8 );
+
+ assign::push_front( bm.right )
+     ( "nine"  ,  9 )
+     ( "ten"   , 10 )
+     ( "eleven", 11 );
+
+// Since it is left_based the main view is a multiset, so we use insert
+
+ assign::insert( bm )
+     ( 12, "twelve"   )
+     ( 13, "thirteen" );
+ 
+

+

+

+

+

+

+
+ + +
+1

+ Note that bm_type::relation has to be used instead of + bm_type::value_type. Contrary to value_type, relation + type stores the elements as non const, a requirement of assign::list_of

+

+

+

+

+
+
+ +

+ The hash function is the very core of the fast lookup capabilities of the + unordered sets: a hasher is just a Unary Function returning an std::size_t + value for any given key. In general, it is impossible that every key map + to a different hash value, for the space of keys can be greater than the + number of permissible hash codes: what makes for a good hasher is that + the probability of a collision (two different keys with the same hash value) + is as close to zero as possible. +

+

+ This is a statistical property depending on the typical distribution of + keys in a given application, so it is not feasible to have a general-purpose + hash function with excellent results in every possible scenario; the default + value for this parameter uses Boost.Hash, which often provides good enough + results. +

+

+ Boost.Hash can be extended + for custom data types, enabling to use the default parameter of + the unordered set types with any user types. +

+
+
+ +

+ The Boost Lambda Library (BLL in the sequel) is a C++ template library, + which implements form of lambda abstractions for C++. The term originates + from functional programming and lambda calculus, where a lambda abstraction + defines an unnamed function. Lambda expressions are very useful to construct + the function objects required by some of the functions in a bimap view. +

+

+ Boost.Bimap defines new placeholders in <boost/bimap/support/lambda.hpp> + to allow a sounder solution. The placeholders are named _key and _data + and both are equivalent to boost::lambda::_1. There are two reasons to + include this placeholders: the code looks better with them and they avoid + the clash problem between lambda::_1 and boost::_1 from Boost.Bind. +

+

+ Go to source code +

+

+

+

+ +

+
+typedef bimap< std::string, int > bm_type;
+
+bm_type bm;
+bm.insert( bm_type::value_type("one",1) );
+bm.insert( bm_type::value_type("two",2) );
+
+bm.right.range( 5 < _key, _key < 10 );
+
+bm.left.modify_key( bm.left.find("one"), _key = "1" );
+
+bm.left.modify_data( bm.left.begin(), _data *= 10 );
+
+

+

+

+

+

+

+
+

+

+

+

+
+
+ +

+ Boost.Range is a collection of concepts and utilities that are particularly + useful for specifying and implementing generic algorithms. Generic algorithms + have so far been specified in terms of two or more iterators. Two iterators + would together form a range of values that the algorithm could work on. + This leads to a very general interface, but also to a somewhat clumsy use + of the algorithms with redundant specification of container names. Therefore + we would like to raise the abstraction level for algorithms so they specify + their interface in terms of Ranges as much as possible. +

+

+ As Boost.Bimap views are signature-compatible with their standard container + counterparts, they are compatible with the concept of a range. As an additional + feature, ordered bimap views offer a function named range + that allows a range of values to be obtained. +

+

+ If we have some generic functions that accepts ranges: +

+

+

+

+ +

+
+template< class ForwardReadableRange, class UnaryFunctor >
+UnaryFunctor for_each(const ForwardReadableRange & r, UnaryFunctor func)
+{
+    typedef typename 
+    boost::range_const_iterator<ForwardReadableRange>::type const_iterator;
+
+    for(const_iterator i= boost::begin(r), iend= boost::end(r); i!=iend; ++i )
+    {
+        func(*i);
+    }
+
+    return func;
+}
+
+template< class ForwardReadableRange, class Predicate >
+typename boost::range_difference<ForwardReadableRange>::type
+    count_if(const ForwardReadableRange & r, Predicate pred)
+{
+    typedef typename
+    boost::range_const_iterator<ForwardReadableRange>::type const_iterator;
+
+    typename boost::range_difference<ForwardReadableRange>::type c = 0;
+
+    for( const_iterator i = boost::begin(r), iend = boost::end(r); i != iend; ++i )
+    {
+        if( pred(*i) ) ++c;
+    }
+
+    return c;
+}
+
+

+

+

+

+

+

+
+

+

+

+

+

+ We can use them with Boost.Bimap with the help of the range + function. +

+

+

+

+ +

+
+struct pair_printer
+{
+    pair_printer(std::ostream & o) : os(o) {}
+    template< class Pair >
+    void operator()(const Pair & p)
+    {
+        os << "(" << p.first << "," << p.second << ")";
+    }
+    private:
+    std::ostream & os;
+};
+
+struct second_extractor
+{
+    template< class Pair >
+    const typename Pair::second_type & operator()(const Pair & p)
+    {
+        return p.second;
+    }
+};
+
+int main()
+{
+    typedef bimap< double, multiset_of<int> > bm_type;
+
+    bm_type bm;
+    bm.insert( bm_type::value_type(2.5 , 1) );
+    bm.insert( bm_type::value_type(3.1 , 2) );
+    //...
+    bm.insert( bm_type::value_type(6.4 , 4) );
+    bm.insert( bm_type::value_type(1.7 , 2) );
+
+    // Print all the elements of the left map view
+
+    for_each( bm.left, pair_printer(std::cout) );
+
+    // Print a range of elements of the right map view
+
+    for_each( bm.right.range( 2 <= _key, _key < 6 ), pair_printer(std::cout) );
+
+    // Count the number of elements where the data is equal to 2 from a
+    // range of elements of the left map view
+
+    count_if( bm.left.range( 2.3 < _key, _key < 5.4 ),
+              bind<int>( second_extractor(), _1 ) == 2 );
+
+    return 0;
+}
+
+

+

+

+

+

+

+
+

+

+

+

+

+ Go to source code +

+
+
+ +

+ In C++, writing a loop that iterates over a sequence is tedious. We can + either use iterators, which requires a considerable amount of boiler-plate, + or we can use the std::for_each() algorithm and move our loop body into + a predicate, which requires no less boiler-plate and forces us to move + our logic far from where it will be used. In contrast, some other languages, + like Perl, provide a dedicated "foreach" construct that automates + this process. BOOST_FOREACH is just such a construct for C++. It iterates + over sequences for us, freeing us from having to deal directly with iterators + or write predicates. +

+

+ You can use BOOST_FOREACH macro with Boost.Bimap views. The generated code + will be as efficient as a std::for_each iteration. Here are some examples: +

+

+

+

+ +

+
+typedef bimap< std::string, list_of<int> > bm_type;
+
+bm_type bm;
+bm.insert( bm_type::value_type("1", 1) );
+bm.insert( bm_type::value_type("2", 2) );
+bm.insert( bm_type::value_type("3", 4) );
+bm.insert( bm_type::value_type("4", 2) );
+
+BOOST_FOREACH( bm_type::left_reference p, bm.left )
+{
+    ++p.second; 1
+}
+
+BOOST_FOREACH( bm_type::right_const_reference p, bm.right )
+{
+    std::cout << p.first << "-->" << p.second << std::endl;
+}
+
+
+

+

+

+

+

+

+
+ + +
+1

We can modify the right element because we have use a mutable collection + type in the right side.

+

+

+

+

+

+ You can use it directly with ranges too: +

+

+

+

+ +

+
+BOOST_FOREACH( bm_type::left_reference p,
+             ( bm.left.range( "1" <= _key, _key < "3" ) ))
+{
+    ++p.second;
+}
+
+BOOST_FOREACH( bm_type::left_const_reference p,
+             ( bm.left.range( "1" <= _key, _key < "3" ) ))
+{
+    std::cout << p.first << "-->" << p.second << std::endl;
+}
+
+

+

+

+

+

+

+
+

+

+

+

+

+ Go to source code +

+
+
+ +

+ Once C++0x is out we are going to be able to write code like: +

+
+auto iter = bm.by<name>().find("john");
+
+

+ instead of the more verbose +

+
+bm_type::map_by<name>::iterator iter = bm.by<name>().find("john");
+
+

+ Boost.Typeof defines a macro BOOST_AUTO that can be used as a library solution + to the auto keyword while we wait for the next standard. +

+

+ If we have +

+

+

+

+ +

+
+typedef bimap< tagged<std::string,name>, tagged<int,number> > bm_type;
+bm_type bm;
+bm.insert( bm_type::value_type("one"  ,1) );
+bm.insert( bm_type::value_type("two"  ,2) );
+
+

+

+

+

+

+

+
+

+

+

+

+

+ The following code snippet +

+

+

+

+ +

+
+for( bm_type::map_by<name>::iterator iter = bm.by<name>().begin();
+     iter!=bm.by<name>().end(); ++iter)
+{
+    std::cout << iter->first << " --> " << iter->second << std::endl;
+}
+
+bm_type::map_by<number>::iterator iter = bm.by<number>().find(2);
+std::cout << "2: " << iter->get<name>();
+
+

+

+

+

+

+

+
+

+

+

+

+

+ can be rewrited as +

+

+

+

+ +

+
+for( BOOST_AUTO(iter, bm.by<name>().begin()); iter!=bm.by<name>().end(); ++iter)
+{
+    std::cout << iter->first << " --> " << iter->second << std::endl;
+}
+
+BOOST_AUTO( iter, bm.by<number>().find(2) );
+std::cout << "2: " << iter->get<name>();
+
+

+

+

+

+

+

+
+

+

+

+

+

+ Go to source code +

+
+
+ +

+ Using Boost.Xpressive we can parse a file and insert the relations in a + bimap in the same step. It is just amazing the power of four lines of code. + Here is an example (it is just beatifull) +

+

+

+

+ +

+
+typedef bimap< std::string, int > bm_type;
+bm_type bm;
+
+std::string rel_str("one <--> 1     two <--> 2      three <--> 3");
+
+sregex rel = ( (s1= +_w) >> " <--> " >> (s2= +_d) )
+[
+    xp::ref(bm)->*insert( construct<bm_type::value_type>(s1, as<int>(s2)) )
+];
+
+sregex relations = rel >> *(+_s >> rel);
+
+regex_match(rel_str, relations);
+
+assert( bm.size() == 3 );
+
+

+

+

+

+

+

+
+

+

+

+

+

+ Go to source code +

+
+
+ +

+ The Boost Property Map Library consists mainly of interface specifications + in the form of concepts (similar to the iterator concepts in the STL). + These interface specifications are intended for use by implementers of + generic libraries in communicating requirements on template parameters + to their users. In particular, the Boost Property Map concepts define a + general purpose interface for mapping key objects to corresponding value + objects, thereby hiding the details of how the mapping is implemented from + algorithms. +

+

+ The need for the property map interface came from the Boost Graph Library + (BGL), which contains many examples of algorithms that use the property + map concepts to specify their interface. For an example, note the ColorMap + template parameter of the breadth_first_search. In addition, the BGL contains + many examples of concrete types that implement the property map interface. + The adjacency_list class implements property maps for accessing objects + (properties) that are attached to vertices and edges of the graph. +

+

+ The counterparts of two of the views of Boost.Bimap map, the set and unordered_set, + are read-write property maps. In order to use these, you need to include + one of the following headers: +

+
+#include <boost/bimap/property_map/set_support.hpp>
+#include <boost/bimap/property_map/unordered_set_support.hpp>
+
+

+ The following is adapted from the example in the Boost.PropertyMap documentation. +

+

+ Go to source + code +

+

+

+

+ +

+
+template <typename AddressMap>
+void foo(AddressMap & address_map)
+{
+    typedef typename boost::property_traits<AddressMap>::value_type value_type;
+    typedef typename boost::property_traits<AddressMap>::key_type key_type;
+
+    value_type address;
+    key_type fred = "Fred";
+    std::cout << get(address_map, fred);
+}
+
+int main()
+{
+    typedef bimap<std::string, multiset_of<std::string> > Name2Address;
+    typedef Name2Address::value_type location;
+
+    Name2Address name2address;
+    name2address.insert( location("Fred", "710 West 13th Street") );
+    name2address.insert( location( "Joe", "710 West 13th Street") );
+
+    foo( name2address.left );
+
+    return 0;
+}
+
+

+

+

+

+

+

+
+

+

+

+

+
+
+ + + +
Copyright © 2006 -2007 Matias Capeletto
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_bimap/bimap_and_boost/dependencies.html b/doc/html/boost_bimap/bimap_and_boost/dependencies.html new file mode 100644 index 0000000..0c00672 --- /dev/null +++ b/doc/html/boost_bimap/bimap_and_boost/dependencies.html @@ -0,0 +1,417 @@ + + + +Dependencies + + + + + + + + + + + + + + + +
+Boost C++ LibrariesChapter Logo +HomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ Boost.Bimap is built on top of several Boost libraries. The rationale behind + this decision is keeping the Boost code base small by reusing existent code. + The libraries used are well-established and have been tested extensively, + making this library easy to port since all the hard work has already been + done. The glue that holds everything together is Boost.MPL. Clearly Boost.MultiIndex + is the heart of this library. +

+
+

Table 1.4. Boost Libraries needed by Boost.Bimap

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Name +

+
+

+ Description +

+
+

+ author +

+
+

+ Boost.MultiIndex +

+
+

+ Containers with multiple STL-compatible access interfaces +

+
+

+ Joaquín M López Muñoz +

+
+

+ Boost.MPL +

+
+

+ Template metaprogramming framework of compile-time algorithms, sequences + and metafunction classes +

+
+

+ Aleksey Gurtovoy +

+
+

+ Boost.TypeTraits +

+
+

+ Templates for fundamental properties of types. +

+
+

+ John Maddock, Steve Cleary +

+
+

+ Boost.enable_if +

+
+

+ Selective inclusion of function template overloads +

+
+

+ Jaakko Järvi, Jeremiah Willcock, Andrew Lumsdaine +

+
+

+ Boost.Iterators +

+
+

+ Iterator construction framework, adaptors, concepts, and more. +

+
+

+ Dave Abrahams, Jeremy Siek, Thomas Witt +

+
+

+ Boost.call_traits +

+
+

+ Defines types for passing parameters. +

+
+

+ John Maddock, Howard Hinnant +

+
+

+ Boost.StaticAssert +

+
+

+ Static assertions (compile time assertions). +

+
+

+ John Maddock +

+
+
+
+

Table 1.5. Optional Boost Libraries

+
++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Name +

+
+

+ Description +

+
+

+ author +

+
+

+ Purpose +

+
+

+ Boost.Serialization +

+
+

+ Serialization for persistence and marshalling +

+
+

+ Robert Ramey +

+
+

+ Serialization support for bimap containers and iterators +

+
+

+ Boost.Assign +

+
+

+ Filling containers with constant or generated data has never been easier +

+
+

+ Thorsten Ottosen +

+
+

+ Help to fill a bimap or views of it +

+
+

+ Boost.Hash +

+
+

+ A TR1 hash function object that can be extended to hash user defined + types +

+
+

+ Daniel James +

+
+

+ Default hashing function +

+
+

+ Boost.Lambda +

+
+

+ Define small unnamed function objects at the actual call site, and + more +

+
+

+ from Jaakko Järvi, Gary Powell +

+
+

+ Functors for modify, range, lower_bound and upper_bound +

+
+

+ Boost.Range +

+
+

+ A new infrastructure for generic algorithms that builds on top of the + new iterator concepts +

+
+

+ Thorsten Ottosen +

+
+

+ Range based algorithms +

+
+

+ Boost.PropertyMap +

+
+

+ Concepts defining interfaces which map key objects to value objects +

+
+

+ Jeremy Siek +

+
+

+ Integration with BGL +

+
+
+
+

Table 1.6. Additional Boost Libraries needed to run + the test-suite

+
+++++ + + + + + + + + + + +
+

+ Name +

+
+

+ Description +

+
+

+ author +

+
+

+ Boost.Test +

+
+

+ Support for simple program testing, full unit testing, and for program + execution monitoring. +

+
+

+ Gennadiy Rozental +

+
+
+
+
+ + + +
Copyright © 2006 -2007 Matias Capeletto
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_bimap/compiler_specifics.html b/doc/html/boost_bimap/compiler_specifics.html new file mode 100644 index 0000000..8395e60 --- /dev/null +++ b/doc/html/boost_bimap/compiler_specifics.html @@ -0,0 +1,366 @@ + + + +Compiler specifics + + + + + + + + + + + + + + + +
+Boost C++ LibrariesChapter Logo +HomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Compiler +

+
+

+ OS Tested +

+
+

+ State +

+
+

+ GCC 3.3 +

+
+

+ Linux +

+
+

+ Supported +

+
+

+ GCC 3.4 +

+
+

+ Linux +

+
+

+ Supported +

+
+

+ GCC 4.0 +

+
+

+ Linux, Mac +

+
+

+ Supported +

+
+

+ GCC 4.1 +

+
+

+ Linux +

+
+

+ Supported +

+
+

+ GCC 4.2 +

+
+

+ Linux +

+
+

+ Supported +

+
+

+ ICC 8.0 +

+
+

+ Linux +

+
+

+ Supported +

+
+

+ ICC 9.0 +

+
+

+ Linux +

+
+

+ Supported +

+
+

+ ICC 9.1 +

+
+

+ Linux +

+
+

+ Supported +

+
+

+ GCC 4.2 +

+
+

+ Linux +

+
+

+ Supported +

+
+

+ GCC 4.2 +

+
+

+ Linux +

+
+

+ Supported +

+
+

+ VS 7.1 +

+
+

+ Windows +

+
+

+ Supported +

+
+

+ VS 8.0 +

+
+

+ Windows +

+
+

+ Supported +

+
+

+ ICC 7.1 +

+
+

+ Windows +

+
+

+ Not Supported +

+
+

+ ICC 8.0 +

+
+

+ Windows +

+
+

+ Supported +

+
+

+ ICC 9.1 +

+
+

+ Windows +

+
+

+ Supported +

+
+

+ CW 8.3 +

+
+

+ Windows +

+
+

+ Not Supported +

+
+

+ + VS 7.1 +

+

+ If a .cpp file uses more than four differents bimaps the compiler will run + out of symbols and issue an internal compiler error. The official solution + in msdn is to split the .cpp in several files or upgrade your compiler. +

+

+ + VS 8.0 +

+

+ VC++ 8.0 warns on usage of certain Standard Library and API functions that + can be cause buffer overruns or other possible security issues if misused. + See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx But + the wording of the warning is misleading and unsettling, there are no portable + alternative functions, and VC++ 8.0's own libraries use the functions in question. + In order to turn off the warnings add the followings defines at the begging + of your .cpp files: +

+
+#define _CRT_SECURE_NO_DEPRECATE
+#define _SCL_SECURE_NO_DEPRECATE
+
+
+ + + +
Copyright © 2006 -2007 Matias Capeletto
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_bimap/examples.html b/doc/html/boost_bimap/examples.html new file mode 100644 index 0000000..61d3362 --- /dev/null +++ b/doc/html/boost_bimap/examples.html @@ -0,0 +1,439 @@ + + + +Examples + + + + + + + + + + + + + + + +
+Boost C++ LibrariesChapter Logo +HomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ In the folder libs/bimap/example you can + find all the examples used in bimap documentation. Here is a list of them: +

+
+

Table 1.7. Tutorial examples

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Program +

+
+

+ Description +

+
+

+ simple_bimap.cpp +

+
+

+ Soccer world cup example +

+
+

+ tagged_simple_bimap.cpp + +

+
+

+ Soccer world cup example using user defined names +

+
+

+ step_by_step.cpp +

+
+

+ Basic example of the three views of bimap +

+
+

+ population_bimap.cpp + +

+
+

+ Countries populations, using unordered_set_of + and multiset_of +

+
+

+ repetitions_counter.cpp + +

+
+

+ Word repetitions counter, using unordered_set_of + and list_of +

+
+

+ mighty_bimap.cpp +

+
+

+ Dictionary using list_of_relation +

+
+

+ user_defined_names.cpp + +

+
+

+ Equivalence between code with tagged and untagged code +

+
+

+ standard_map_comparison.cpp + +

+
+

+ Comparison between standard maps and bimap map views +

+
+

+ at_function_examples.cpp + +

+
+

+ Functions at(key) + and operator[](key) + examples +

+
+

+ tutorial_modify_and_replace.cpp + +

+
+

+ modify and replace examples +

+
+

+ tutorial_range.cpp +

+
+

+ range() + tutorial +

+
+

+ tutorial_info_hook.cpp + +

+
+

+ Additional information hooking +

+
+

+ unconstrained_collection.cpp + +

+
+

+ Using unconstrained_set_of + collection type +

+
+
+
+

Table 1.8. Bimap and Boost examples

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Program +

+
+

+ Description +

+
+

+ assign.cpp +

+
+

+ Bimap and Boost.Assign: Methods to insert elements +

+
+

+ lambda.cpp +

+
+

+ Bimap and Boost.Lambda: new lambda placeholders +

+
+

+ property_map.cpp + +

+
+

+ Bimap and Boost.PropertyMap: PropertyMap support +

+
+

+ range.cpp +

+
+

+ Bimap and Boost.Range: Using bimaps in the new range framework +

+
+

+ foreach.cpp + +

+
+

+ Bimap and Boost.Foreach: Iterating over bimaps +

+
+

+ typeof.cpp +

+
+

+ Bimap and Boost.Typeof: using BOOST_AUTO while we wait for C++0x +

+
+

+ xpressive.cpp + +

+
+

+ Bimap and Boost.Xpressive: Inserting elements in a bimap +

+
+

+ serialization.cpp: + +

+
+

+ Bimap and Boost.Serialization: Load and save bimaps and iterators +

+
+
+
+

Table 1.9. Boost.MultiIndex to Boost.Bimap path examples

+
++++ + + + + + + + + + + + + + + + + + + +
+

+ Program +

+
+

+ Description +

+
+

+ bidirectional_map.cpp + +

+
+

+ Boost.MultiIndex to Boost.Bimap path example +

+
+

+ hashed_indices.cpp + +

+
+

+ Boost.MultiIndex to Boost.Bimap path example +

+
+

+ tagged_bidirectional_map.cpp + +

+
+

+ Boost.MultiIndex to Boost.Bimap path example +

+
+
+
+
+
+ + + +
Copyright © 2006 -2007 Matias Capeletto
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_bimap/examples/mighty_bimap.html b/doc/html/boost_bimap/examples/mighty_bimap.html new file mode 100644 index 0000000..fc7b5fb --- /dev/null +++ b/doc/html/boost_bimap/examples/mighty_bimap.html @@ -0,0 +1,148 @@ + + + +Mighty Bimap + + + + + + + + + + + + + + + +
+Boost C++ LibrariesChapter Logo +HomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ This is the translator example from the tutorial. In this example the collection + type of relation is changed to allow the iteration of the container. +

+

+ Go to source code +

+

+

+

+ +

+
+#include <iostream>
+#include <string>
+#include <boost/bimap/bimap.hpp>
+#include <boost/bimap/list_of.hpp>
+#include <boost/bimap/unordered_set_of.hpp>
+
+struct english {};
+struct spanish {};
+
+int main()
+{
+    using namespace boost::bimaps;
+
+    typedef bimap
+    <
+        unordered_set_of< tagged< std::string, spanish > >,
+        unordered_set_of< tagged< std::string, english > >,
+        list_of_relation
+
+    > translator;
+
+    translator trans;
+
+    // We have to use `push_back` because the collection of relations is
+    // a `list_of_relation`
+
+    trans.push_back( translator::value_type("hola"  ,"hello"   ) );
+    trans.push_back( translator::value_type("adios" ,"goodbye" ) );
+    trans.push_back( translator::value_type("rosa"  ,"rose"    ) );
+    trans.push_back( translator::value_type("mesa"  ,"table"   ) );
+
+    std::cout << "enter a word" << std::endl;
+    std::string word;
+    std::getline(std::cin,word);
+
+    // Search the queried word on the from index (Spanish)
+
+    translator::map_by<spanish>::const_iterator is
+        = trans.by<spanish>().find(word);
+
+    if( is != trans.by<spanish>().end() )
+    {
+        std::cout << word << " is said "
+                  << is->get<english>()
+                  << " in English" << std::endl;
+    }
+    else
+    {
+        // Word not found in Spanish, try our luck in English
+
+        translator::map_by<english>::const_iterator ie
+            = trans.by<english>().find(word);
+
+        if( ie != trans.by<english>().end() )
+        {
+            std::cout << word << " is said "
+                      << ie->get<spanish>()
+                      << " in Spanish" << std::endl;
+        }
+        else
+        {
+            // Word not found, show the possible translations
+
+            std::cout << "No such word in the dictionary"      << std::endl;
+            std::cout << "These are the possible translations" << std::endl;
+
+            for( translator::const_iterator
+                    i = trans.begin(),
+                    i_end = trans.end();
+
+                    i != i_end ; ++i )
+            {
+                std::cout << i->get<spanish>()
+                          << " <---> "
+                          << i->get<english>()
+                          << std::endl;
+            }
+        }
+    }
+    return 0;
+}
+
+

+

+

+

+

+

+
+

+

+

+

+
+ + + +
Copyright © 2006 -2007 Matias Capeletto
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_bimap/examples/multiindex_to_bimap_path___bidirectional_map.html b/doc/html/boost_bimap/examples/multiindex_to_bimap_path___bidirectional_map.html new file mode 100644 index 0000000..8274f8c --- /dev/null +++ b/doc/html/boost_bimap/examples/multiindex_to_bimap_path___bidirectional_map.html @@ -0,0 +1,363 @@ + + + +MultiIndex + to Bimap Path - Bidirectional Map + + + + + + + + + + + + + + + +
+Boost C++ LibrariesChapter Logo +HomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ This is example 4 in Boost.MultiIndex documentation. +

+ +
+ + Boost.MultiIndex +
+

+ Go to source + code +

+

+

+

+ +

+
+#include <iostream>
+#include <boost/tokenizer.hpp>
+
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/key_extractors.hpp>
+#include <boost/multi_index/ordered_index.hpp>
+
+using namespace boost;
+using namespace boost::multi_index;
+
+// tags for accessing both sides of a bidirectional map
+
+struct from {};
+struct to   {};
+
+// The class template bidirectional_map wraps the specification
+// of a bidirectional map based on multi_index_container.
+
+template<typename FromType,typename ToType>
+struct bidirectional_map
+{
+    typedef std::pair<FromType,ToType> value_type;
+
+    typedef multi_index_container<
+        value_type,
+        indexed_by
+        <
+            ordered_unique
+            <
+                tag<from>, member<value_type,FromType,&value_type::first>
+            >,
+            ordered_unique
+            <
+                tag<to>, member<value_type,ToType,&value_type::second>
+            >
+        >
+
+  > type;
+
+};
+
+// A dictionary is a bidirectional map from strings to strings
+
+typedef bidirectional_map<std::string,std::string>::type dictionary;
+
+int main()
+{
+    dictionary d;
+
+    // Fill up our microdictionary.
+    // first members Spanish, second members English.
+
+    d.insert(dictionary::value_type("hola","hello"));
+    d.insert(dictionary::value_type("adios","goodbye"));
+    d.insert(dictionary::value_type("rosa","rose"));
+    d.insert(dictionary::value_type("mesa","table"));
+
+    std::cout << "enter a word" << std::endl;
+    std::string word;
+    std::getline(std::cin,word);
+
+    // search the queried word on the from index (Spanish)
+
+    dictionary::iterator it = d.get<from>().find(word);
+
+    if( it != d.end() )
+    {
+        // the second part of the element is the equivalent in English
+
+        std::cout << word << " is said "
+                  << it->second << " in English" << std::endl;
+    }
+    else
+    {
+        // word not found in Spanish, try our luck in English
+
+        dictionary::index_iterator<to>::type it2 = d.get<to>().find(word);
+        if( it2 != d.get<to>().end() )
+        {
+            std::cout << word << " is said "
+                      << it2->first << " in Spanish" << std::endl;
+        }
+        else
+        {
+            std::cout << "No such word in the dictionary" << std::endl;
+        }
+    }
+
+    return 0;
+}
+
+

+

+

+

+

+

+
+

+

+

+

+
+ + Boost.Bimap +
+

+ Go to source + code +

+

+

+

+ +

+
+#include <iostream>
+#include <boost/tokenizer.hpp>
+#include <boost/bimap/bimap.hpp>
+
+using namespace boost::bimaps;
+
+// A dictionary is a bidirectional map from strings to strings
+
+typedef bimap<std::string,std::string> dictionary;
+typedef dictionary::value_type translation;
+
+int main()
+{
+    dictionary d;
+
+    // Fill up our microdictionary.
+    // first members Spanish, second members English.
+
+    d.insert( translation("hola" ,"hello"  ));
+    d.insert( translation("adios","goodbye"));
+    d.insert( translation("rosa" ,"rose"   ));
+    d.insert( translation("mesa" ,"table"  ));
+
+    std::cout << "enter a word" << std::endl;
+    std::string word;
+    std::getline(std::cin,word);
+
+    // search the queried word on the from index (Spanish)
+
+    dictionary::left_const_iterator it = d.left.find(word);
+
+    if( it != d.left.end() )
+    {
+        // the second part of the element is the equivalent in English
+
+        std::cout << word << " is said "
+                  << it->second 1
+                  << " in English" << std::endl;
+    }
+    else
+    {
+        // word not found in Spanish, try our luck in English
+
+        dictionary::right_const_iterator it2 = d.right.find(word);
+        if( it2 != d.right.end() )
+        {
+            std::cout << word << " is said "
+                      << it2->second 2
+                      << " in Spanish" << std::endl;
+        }
+        else
+        {
+            std::cout << "No such word in the dictionary" << std::endl;
+        }
+    }
+
+    return 0;
+}
+
+

+

+

+

+

+

+
+ + + + + + + + +
+1

it is an iterator of the + left view, so it->second refers to the right element of + the relation, the word in english

+2

it2 + is an iterator of the right view, so it2->second + refers to the left element of the relation, the word in spanish

+

+

+

+

+

+ Or better, using tags... +

+

+ Go to + source code +

+

+

+

+ +

+
+#include <iostream>
+
+#include <boost/bimap/bimap.hpp>
+
+using namespace boost::bimaps;
+
+// tags
+
+struct spanish {};
+struct english {};
+
+// A dictionary is a bidirectional map from strings to strings
+
+typedef bimap
+<
+    tagged< std::string,spanish >, tagged< std::string,english >
+
+> dictionary;
+
+typedef dictionary::value_type translation;
+
+int main()
+{
+    dictionary d;
+
+    // Fill up our microdictionary. 
+    // first members Spanish, second members English.
+
+    d.insert( translation("hola" ,"hello"  ));
+    d.insert( translation("adios","goodbye"));
+    d.insert( translation("rosa" ,"rose"   ));
+    d.insert( translation("mesa" ,"table"  ));
+
+    std::cout << "enter a word" << std::endl;
+    std::string word;
+    std::getline(std::cin,word);
+
+    // search the queried word on the from index (Spanish) */
+
+    dictionary::map_by<spanish>::const_iterator it =
+        d.by<spanish>().find(word);
+
+    if( it != d.by<spanish>().end() )
+    {
+        std::cout << word << " is said " 
+                  << it->get<english>() << " in English" << std::endl;
+    }
+    else
+    {
+        // word not found in Spanish, try our luck in English
+
+        dictionary::map_by<english>::const_iterator it2 =
+            d.by<english>().find(word);
+
+        if( it2 != d.by<english>().end() )
+        {
+            std::cout << word << " is said "
+                      << it2->get<spanish>() << " in Spanish" << std::endl;
+        }
+        else
+        {
+            std::cout << "No such word in the dictionary" << std::endl;
+        }
+    }
+
+    return 0;
+}
+
+

+

+

+

+

+

+
+

+

+

+

+
+ + + +
Copyright © 2006 -2007 Matias Capeletto
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_bimap/examples/multiindex_to_bimap_path___hashed_indices.html b/doc/html/boost_bimap/examples/multiindex_to_bimap_path___hashed_indices.html new file mode 100644 index 0000000..1bbbe68 --- /dev/null +++ b/doc/html/boost_bimap/examples/multiindex_to_bimap_path___hashed_indices.html @@ -0,0 +1,260 @@ + + + +MultiIndex + to Bimap Path - Hashed indices + + + + + + + + + + + + + + + +
+Boost C++ LibrariesChapter Logo +HomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ This is example 8 of Boost.MultiIndex. +

+ +
+ + Boost.MultiIndex +
+

+ Go to source + code +

+

+

+

+ +

+
+#include <iostream>
+#include <iomanip>
+
+#include <boost/tokenizer.hpp>
+
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/key_extractors.hpp>
+#include <boost/multi_index/ordered_index.hpp>
+#include <boost/multi_index/hashed_index.hpp>
+#include <boost/lambda/lambda.hpp>
+
+using namespace boost::multi_index;
+namespace bl = boost::lambda;
+
+// word_counter keeps the ocurrences of words inserted. A hashed
+// index allows for fast checking of preexisting entries.
+
+struct word_counter_entry
+{
+    std::string  word;
+    unsigned int occurrences;
+
+    word_counter_entry( std::string word_ ) : word(word_), occurrences(0) {}
+};
+
+typedef multi_index_container
+<
+    word_counter_entry,
+    indexed_by
+    <
+        ordered_non_unique
+        <
+            BOOST_MULTI_INDEX_MEMBER(
+                word_counter_entry,unsigned int,occurrences),
+            std::greater<unsigned int>
+        >,
+        hashed_unique
+        <
+            BOOST_MULTI_INDEX_MEMBER(word_counter_entry,std::string,word)
+        >
+  >
+
+> word_counter;
+
+typedef boost::tokenizer<boost::char_separator<char> > text_tokenizer;
+
+int main()
+{
+    std::string text=
+        "En un lugar de la Mancha, de cuyo nombre no quiero acordarme... "
+        "...snip..."
+        "...no se salga un punto de la verdad.";
+
+    // feed the text into the container
+
+    word_counter   wc;
+    text_tokenizer tok(text,boost::char_separator<char>(" \t\n.,;:!?'\"-"));
+    unsigned int   total_occurrences = 0;
+
+    for( text_tokenizer::iterator it = tok.begin(), it_end = tok.end();
+         it != it_end ; ++it )
+    {
+        ++total_occurrences;
+        word_counter::iterator wit = wc.insert(*it).first;
+        wc.modify_key( wit, ++ bl::_1 );
+    }
+
+    // list words by frequency of appearance
+
+    std::cout << std::fixed << std::setprecision(2);
+
+    for( word_counter::iterator wit = wc.begin(), wit_end=wc.end();
+         wit != wit_end; ++wit )
+    {
+        std::cout << std::setw(11) << wit->word << ": "
+                  << std::setw(5)
+                  << 100.0 * wit->occurrences / total_occurrences << "%"
+                  << std::endl;
+    }
+
+    return 0;
+}
+
+

+

+

+

+

+

+
+

+

+

+

+
+ + Boost.Bimap +
+

+ Go to source code +

+

+

+

+ +

+
+#include <iostream>
+#include <iomanip>
+
+#include <boost/tokenizer.hpp>
+
+#include <boost/bimap/bimap.hpp>
+#include <boost/bimap/unordered_set_of.hpp>
+#include <boost/bimap/multiset_of.hpp>
+#include <boost/bimap/support/lambda.hpp>
+
+using namespace boost::bimaps;
+
+struct word        {};
+struct occurrences {};
+
+typedef bimap
+<
+    
+     multiset_of< tagged<unsigned int,occurrences>, std::greater<unsigned int> >, 
+unordered_set_of< tagged< std::string,       word>                             >
+
+> word_counter;
+
+typedef boost::tokenizer<boost::char_separator<char> > text_tokenizer;
+
+int main()
+{
+
+    std::string text=
+        "Relations between data in the STL are represented with maps."
+        "A map is a directed relation, by using it you are representing "
+        "a mapping. In this directed relation, the first type is related to "
+        "the second type but it is not true that the inverse relationship "
+        "holds. This is useful in a lot of situations, but there are some "
+        "relationships that are bidirectional by nature.";
+
+    // feed the text into the container
+
+    word_counter   wc;
+    text_tokenizer tok(text,boost::char_separator<char>(" \t\n.,;:!?'\"-"));
+    unsigned int   total_occurrences = 0;
+
+    for( text_tokenizer::const_iterator it = tok.begin(), it_end = tok.end();
+         it != it_end ; ++it )
+    {
+        ++total_occurrences;
+
+        word_counter::map_by<occurrences>::iterator wit =
+            wc.by<occurrences>().insert(
+                 word_counter::map_by<occurrences>::value_type(0,*it)
+            ).first;
+
+        wc.by<occurrences>().modify_key( wit, ++_key);
+    }
+
+    // list words by frequency of appearance
+
+    std::cout << std::fixed << std::setprecision(2);
+
+    for( word_counter::map_by<occurrences>::const_iterator
+            wit     = wc.by<occurrences>().begin(),
+            wit_end = wc.by<occurrences>().end();
+
+         wit != wit_end; ++wit )
+    {
+        std::cout << std::setw(15) << wit->get<word>() << ": "
+                  << std::setw(5)
+                  << 100.0 * wit->get<occurrences>() / total_occurrences << "%"
+                  << std::endl;
+    }
+
+    return 0;
+}
+
+

+

+

+

+

+

+
+

+

+

+

+
+ + + +
Copyright © 2006 -2007 Matias Capeletto
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_bimap/examples/simple_bimap.html b/doc/html/boost_bimap/examples/simple_bimap.html new file mode 100644 index 0000000..98bcafa --- /dev/null +++ b/doc/html/boost_bimap/examples/simple_bimap.html @@ -0,0 +1,223 @@ + + + +Simple Bimap + + + + + + + + + + + + + + + +
+Boost C++ LibrariesChapter Logo +HomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ This is the example from the one minute tutorial section. +

+

+ Go to source code +

+

+

+

+ +

+
+#include <string>
+#include <iostream>
+
+#include <boost/bimap.hpp>
+
+template< class MapType >
+void print_map(const MapType & map,
+               const std::string & separator,
+               std::ostream & os )
+{
+    typedef typename MapType::const_iterator const_iterator;
+
+    for( const_iterator i = map.begin(), iend = map.end(); i != iend; ++i )
+    {
+        os << i->first << separator << i->second << std::endl;
+    }
+}
+
+int main()
+{
+    // Soccer World cup
+
+    typedef boost::bimap< std::string, int > results_bimap;
+    typedef results_bimap::value_type position;
+
+    results_bimap results;
+    results.insert( position("Argentina"    ,1) );
+    results.insert( position("Spain"        ,2) );
+    results.insert( position("Germany"      ,3) );
+    results.insert( position("France"       ,4) );
+
+    std::cout << "The number of countries is " << results.size()
+              << std::endl;
+
+    std::cout << "The winner is " << results.right.at(1)
+              << std::endl
+              << std::endl;
+
+    std::cout << "Countries names ordered by their final position:"
+              << std::endl;
+
+    // results.right works like a std::map< int, std::string >
+
+    print_map( results.right, ") ", std::cout );
+
+    std::cout << std::endl
+              << "Countries names ordered alphabetically along with"
+                    "their final position:"
+              << std::endl;
+
+    // results.left works like a std::map< std::string, int >
+
+    print_map( results.left, " ends in position ", std::cout );
+
+    return 0;
+}
+
+

+

+

+

+

+

+
+

+

+

+

+

+ You can rewrite it using tags to gain readability. +

+

+ Go to source code +

+

+

+

+ +

+
+#include <iostream>
+
+#include <boost/bimap.hpp>
+
+struct country  {};
+struct place    {};
+
+int main()
+{
+    using namespace boost::bimaps;
+
+    // Soccer World cup.
+
+    typedef bimap
+    <
+        tagged< std::string, country >,
+        tagged< int        , place   >
+
+    > results_bimap;
+
+    typedef results_bimap::value_type position;
+
+    results_bimap results;
+    results.insert( position("Argentina"    ,1) );
+    results.insert( position("Spain"        ,2) );
+    results.insert( position("Germany"      ,3) );
+    results.insert( position("France"       ,4) );
+
+    std::cout << "Countries names ordered by their final position:"
+                << std::endl;
+
+    1for( results_bimap::map_by<place>::const_iterator
+            i    = results.by<place>().begin(),
+            iend = results.by<place>().end() ;
+            i != iend; ++i )
+    {
+        2std::cout << i->get<place  >() << ") "
+                  << i->get<country>() << std::endl;
+    }
+
+    std::cout << std::endl
+              << "Countries names ordered alfabetically along with"
+                 "their final position:"
+              << std::endl;
+
+    3for( results_bimap::map_by<country>::const_iterator
+            i    = results.by<country>().begin(),
+            iend = results.by<country>().end() ;
+            i != iend; ++i )
+    {
+        std::cout << i->get<country>() << " ends "
+                  << i->get<place  >() << "º"
+                  << std::endl;
+    }
+
+    return 0;
+}
+
+

+

+

+

+

+

+
+ + + + + + + + + + + + +
+1

results.by<place>() + is equivalent to results.right +

+2

get<Tag> + works for each view of the bimap

+3

results.by<country>() + is equivalent to results.left +

+

+

+

+

+
+ + + +
Copyright © 2006 -2007 Matias Capeletto
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_bimap/future_work.html b/doc/html/boost_bimap/future_work.html new file mode 100644 index 0000000..4075174 --- /dev/null +++ b/doc/html/boost_bimap/future_work.html @@ -0,0 +1,49 @@ + + + +Future work + + + + + + + + + + + + + + + +
+Boost C++ LibrariesChapter Logo +HomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ + Rearrange Function +

+

+ Boost.MultiIndex includes some others functions that can be included in the + views. +

+
+ + + +
Copyright © 2006 -2007 Matias Capeletto
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_bimap/history.html b/doc/html/boost_bimap/history.html new file mode 100644 index 0000000..e3a8d15 --- /dev/null +++ b/doc/html/boost_bimap/history.html @@ -0,0 +1,111 @@ + + + +History + + + + + + + + + + + + + + + +
+Boost C++ LibrariesChapter Logo +HomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ + +
+ +
+

+
+
2002 - bimap at Code Project
+
+ Joaquin Lopez Muñoz posted his first bimap + library in 2002. Tons of users have been using it. He then asked + the list for interest in his library in 2003. Luckily, there was + a lot of interest and Joaquin started to boostify the code. At some point + all the developers seemed to agree that, rather than a bidirectional map, + it would be better to work on an N-indexed set that contained Joaquin's + library as a particular case. +
+
2003 - multiindex_set
+
+ The library grew enormously and was ready for a formal review in 2003. + At this point, the container was a lot more powerful, but everything comes + with a price and this new beast lacked the simplicity of the original bimap. +
+
2004 - indexed_set
+
+ In 2004, the formal review ended well for the new multi-indexed container. + This Swiss army knife introduced several new features, such as non-unique + indexes, hashed indices and sequenced indices. In the list of improvements + to the library, it was mentioned that a bidirectional map should be coded + in top of this container. +
+
2005 - multi_index_container
+
+ Once in Boost, the library switched to the now familiar name "Boost.MultiIndex". + Late in 2004, it formally became a member of Boost. Joaquin continued to + enchance the library and added new features such as composite keys and + random-access indices. +
+
2006 - Multi Index Specialized Containers + SoC project
+
+ In 2006, during the formal review of Boost.Property_tree, the need for + a bidirectional map container built on top of Boost.MultiIndex arose again. + Boost entered the Google SoC 2006 as a mentor organization at the same + time. Joaquin put himself forward as a mentor. He proposed to build not + only a bidirectional map, but a myriad multi-indexed specialized containers. + Matias Capeletto presented an application to code Boost.Misc for the SoC + and was elected, along with nine other students. Matias's and Joaquin's + SoC project ends with a working implementation of the bimap library that + was presented in an informal review. By the end of the year the library + was queued for a formal review. +
+
2007 - Boost.Bimap
+
+ The formal review took place at the beggining of the year and Boost.Bimap + was accepted in Boost. +
+
+
+
+
+ + + +
Copyright © 2006 -2007 Matias Capeletto
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_bimap/history/multiindex_and_bimap.html b/doc/html/boost_bimap/history/multiindex_and_bimap.html new file mode 100644 index 0000000..e77dde0 --- /dev/null +++ b/doc/html/boost_bimap/history/multiindex_and_bimap.html @@ -0,0 +1,711 @@ + + + +MultiIndex + and Bimap + + + + + + + + + + + + + + + +
+Boost C++ LibrariesChapter Logo +HomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ This is the conversation thread that began during Boost.PropertyTree formal + review process. The review was very interesting and very deep topics were + addressed. It is quite interesting and it is now part of this library history. + Enjoy! +

+

+ Marcin +

+
+

+

+

+ The biggest virtue of property_tree is easy to use interface. + If we try to make generic tree of it, it will be compromised. +

+

+

+
+

+ Gennadiy +

+
+

+

+

+ IMO the same result (as library presents) could be achieved + just by using multi_index. +

+

+

+
+

+ Marcin +

+
+

+

+

+ Could you elaborate more on that? I considered use of multi_index + to implement indexing for properties, but it only affected the implementation + part of library, not interface, and because I already had a working, + exception safe solution, I didn't see the reason to dump it and add another + dependency on another library. +

+

+

+
+

+ Gennadiy +

+
+

+

+

+ I mean why do I need this half baked property_tree as another + data structure? Property tree supports nothing in itself. It's just a + data structure. You have parsers that produce property tree out of different + sources. But you mat as well produce maps or something else. Here for + example All that I need to do to "implement" similar functionality + as your property tree: +

+

+

+
+

+ +

+
+// Data structure itself
+template<typename ValueType,typename KeyType>
+struct Node;
+template<typename ValueType,typename KeyType>
+struct ptree_gen {
+    typedef std::pair<KeyType,Node<ValueType,KeyType> > mi_value;
+    typedef multi_index_container<mi_value, indexed_by<...> > type;
+};
+template<typename ValueType,typename KeyType>
+struct Node {
+    ValueType v;
+    ptree_gen<ValueType,KeyType>::type children;
+};
+// serialization support
+template<class Archive,typename ValueType,typename KeyType>
+void serialize(Archive & ar, Node<ValueType,KeyType>& n,
+               const unsigned int version)
+{
+    ar & n.v;
+    ar & n.children;
+}
+// some access methods
+template<typename ValueType,typename KeyType>
+ValueType const&
+get( string const& keys, ptree_gen<ValueType,KeyType>::type const& src )
+{
+    std::pait<string,string> sk = split( keys, "." );
+    Node const& N = src.find( sk.first );
+    return sk.second.empty() ? N.v : get( sk.second, N.children );
+}
+
+

+

+
+

+

+

+ Use it like this: +

+

+

+
+

+ +

+
+ptree_gen<string,string>::type PT;
+boost::archive::text_iarchive ia( std::ifstream ifs("filename") );
+ia >> PT;
+string value = get( "a.b.c.d", PT );
+
+

+

+
+

+

+

+ Now tell me how property_tree interface is easier? And what + is the value in 50k of Code you need to implement this data structure. + +

+

+

+
+

+ Thorsten +

+
+

+

+

+ Seriously Gennadiy, do you really see newbies writing the + code you just did? +

+

+

+
+

+ Marcin +

+
+

+

+

+ What you just implemented is stripped down, bare bones version + of property_tree that, among other things, does not allow you to produce + human editable XML files. Now add more interface (aka get functions), + add more archives to serialization lib, add customization, add transparent + translation from strings to arbitrary types and vice versa. Spend some + weeks trying to get all the corner cases right, and then some more weeks + trying to smooth rough edges in the interface. Then write tests. Write + docs. At the end, I believe you will not get much less code than there + is in the library already. Maybe you get some savings by using multi_index + instead of manual indexing. +

+

+

+
+
+

+

+

+ The reason why ptree does not use multi index is because implementation + existed long before I considered submitting to boost, probably before + even I knew of multi index existence. It was working well. Later, when + I was improving it during pre-review process, I seriously considered + using multi-index. But I decided it is not worth throwing everything + out. +

+

+

+
+
+

+

+

+ Although ptree has large interface with many functions modifying + state of the tree, it uses "single point of change" approach. + Every insert eventually goes through one function, which takes care of + exception safety and keeping index in sync with data. The same applies + to erase. This function has 9 lines of code in case of insert, and (by + coincidence) also 9 in case of erase. By using multi index these functions + would obviously be simplified, maybe to 4 lines each. Net gain: 10 lines + of code (out of several hundred in ptree_implementation.hpp). +

+

+

+
+
+

+

+

+ I'm aware that there are performance gains to be reaped as + well, but at that time I was rather focusing on getting the interface + right. +

+

+

+
+

+ Dave +

+
+

+

+

+ That's perfectly reasonable, but (through no fault of yours) + it misses the point I was trying to make. I guess I should have said, + "...that demonstrates it to be the best implementation." +

+

+

+
+
+

+

+

+ All I'm saying is that the extent to which a Boost library + implementation should leverage other Boost libraries is not a question + that can always be decided based on following simple guidelines, and + that if this library is accepted, it's worth revisiting your decision. + +

+

+

+
+

+ Thorsten +

+
+

+

+

+ I think it is important to focus on the interface in the review, + but I also see several benefits of an implementation that builds on Boost.MultiIndex:' + +

+

+

+
+
+

+

+

+ - fewer bugs like the one Joaquin found +

+

+

+
+
+

+

+

+ - better space efficiency +

+

+

+
+
+

+

+

+ - exception-safety guarantees are immediately full-filled (I + haven't looked, but I suspect that there are several bugs in this area) +

+

+

+
+

+ Daniel +

+
+

+

+

+ Multi_index supports everything a bimap would, but its interface + is more cumbersome. I for one won't use a W3DOM-like library if we get + one, but I would happily use property_tree. I've also only used multi_index + once, and that was to use it as a bidirectional map. Property_tree covers + other areas as well as being a potential subset of an XML library, but + I still hold there is value in such a subset. +

+

+

+
+

+ Boris +

+
+

+

+

+ I haven't used program_options yet. But if I understand correctly + both libraries seem to support storing and accessing data with strings + that might describe some kind of hierarchy. This seems to be the core + idea of both libraries - is this correct? +

+

+

+
+
+

+

+

+ Then it wouldn't matter much what container is used. However + a generic tree which can store data hierarchically probably makes most + sense. If I understand correctly both libraries could make use of such + a class? +

+

+

+
+

+ Marcin +

+
+

+

+

+ I think generic tree container is material for another library. + Whether property_tree should be based on it or not is a matter of internal + implementation, and generally of little interest to users. The biggest + value of property_tree is in its easy to use interface, that should not + be compromised, if at all possible. I have been already reassured in + this view by quite many people who took their time to review the library. + +

+

+

+
+

+ Boris +

+
+

+

+

+ I was trying to see the big picture: I rather prefer a C++ + standard based on a few well-known concepts like containers, iterators, + algorithms etc. instead of having a C++ standard with hundreds of components + which are tailored for specific needs, collaborate with only a handful + of other components and think they provide an easy-to-use interface while + all the easy-to-use interfaces make the whole standard less easy-to-use. + +

+

+

+
+
+

+

+

+ That said I have used your property tree library myself to + read and write a configuration file. It was indeed very easy to use. + However it would have been even easier if it was something I had known + before like eg. an iterator. For now I will definitely use your property + tree library but would appreciate if existing concepts were reused many + C++ developers are familiar with. My opinion is that your library should + be a part of Boost but should be more generalized in the future. +

+

+

+
+

+ Thorsten +

+
+

+

+

+ Well, I think we need both. Boost.MultiIndex is a great library + and can do all kinds of wonderful things. But I would still like to see + a bidirectional map (boost::bimap) written as a wrapper around it to + get an easy and specialized interface. +

+

+

+
+

+ Pavel +

+
+

+

+

+ Bimap is available in libs/multi-index/examples/bimap.cpp. + +

+

+

+
+

+ Thorsten +

+
+

+

+

+ Right, but the real value comes when somebody designs a nice + STL-like interface and write docs etc, at least that was my point. +

+

+

+
+

+ Dave +

+
+

+

+

+ IMO Thorsten is exactly right. This is precisely the sort + of thing that could be added to the library as part of its ongoing maintenance + and development (without review, of course). +

+

+

+
+

+ Joaquin +

+
+

+

+

+ Thorsten, we have talked about this privately in the past, + but I feel like bringing it to the list in the hope of getting the attention + of potential contributors: +

+

+

+
+
+

+

+

+ There are some data structures buildable with B.MI which are + regarded as particularly useful or common, like for instance the bidirectional + map or bimap. A lean and mean implementation is provided in the aforementioned + example, but certainly a much carefully crafted interface can be provided + keeping B.MI as the implementation core: operator[], selection of 1-1/1-N/N-1/N-N + variants, hashing/ordering, etc. +

+

+

+
+
+

+

+

+ I'm afraid I don't have the time to pursue this, as the current + roadmap for core features of B.MI is taking all the spare time I can + dedicate to the library. For this reason, I would love to see some volunteer + jumping in who can develop this and other singular containers using B.MI + (a cache container comes to mind) and then propose the results here either + as a stand alone library of as part of B.MI --I'd prefer the former so + as to keep the size of B.MI bounded. +

+

+

+
+
+

+

+

+ If there's such a volunteer I can provide her with some help/mentoring. + I also wonder whether this is a task suitable to be proposed for Google + Summer of Code. +

+

+

+
+

+ Thorsten +

+
+

+

+

+ I think it would be good for SOC. All the really hard things + are taken care of by B.MI, and so it seems reasonable for a student to + be able to fill in the details. +

+

+

+
+

+ Dave +

+
+

+

+

+ Great! +

+

+

+
+

+ Jeff +

+
+

+

+

+ Please write a proposal! +

+

+

+
+

+ Joaquin +

+
+

+

+

+ I've just done so: +

+

+

+
+ +

+ Matias +

+
+

+

+

+ I am planning to submit an application to SoC. I will love + to make real the specialized containers you mention and try to include + some useful others. +

+

+

+
+
+

+

+

+ And then... after long hours of coding (and fun) this library + saw the light. +

+

+

+
+
+

+

+

+ boost.bimap.logo +

+

+

+
+
+ + + +
Copyright © 2006 -2007 Matias Capeletto
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_bimap/introduction.html b/doc/html/boost_bimap/introduction.html new file mode 100644 index 0000000..4f76abb --- /dev/null +++ b/doc/html/boost_bimap/introduction.html @@ -0,0 +1,201 @@ + + + +Introduction + + + + + + + + + + + + + + + +
+Boost C++ LibrariesChapter Logo +HomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ + How to use + this document +

+

+ This documentation contains a large amount of information. Whereas it may be + worth reading it all, this documentation is intended for programmers with various + motives: +

+
+

+
+
I have to finished this today, I just want + a bidirectional map!
+
+ If your boss will kill you if the project is not finished by the end of the + day, just read the One-minute + tutorial. If you have a background in STL, you can be testing a bimap + within ten minutes. +
+
I am a serious programmer and want to learn + Boost.Bimap
+
+ Boost.Bimap has a lot to offer if you are prepared to spend some time reading + this documentation. You will need to read The + tutorial and skim through some of the Examples. + The best way to read this documentation is in the order given here. Just + click on the arrow at the right bottom corner as you finish each page. You + may skip the reference section, and return to it later to look up a function + signature or to find a specific metafunction. +
+
I just love C++, I want to see the inner + workings of Boost.Bimap.
+
+ If you are a library developer, this documentation is the best place to learn + how Boost.Bimap is implemented. It is strongly recommended that you first + learn to use the library as if you were the second type of programmer above. + This library was developed in the Google SoC 2006, and the mentor and student + generated a great deal of documentation in the building process. The rationale + section is very large and contains a lot of information. There is a history + section for those who might find it useful. Finally, in the reference section, + each entity of the library is documented and its source code is presented. +
+
+
+
+ + + + + +
[Note]Note
+

+

+

+ If anything in the documentation is unclear, please email me at matias + {dot} capeletto {at} gmail {dot} com, telling me which of the + three types of programmer above you are and which section needs improvement. + Please use the following notation for the subject: [boost][bimap] + Your problem as this will help me to identify it more easily. + If appropriate, I will act on your advice to improve the documentation. + Thanks and enjoy! +

+

+

+
+
+ + + + + +
[Important]Important
+

+

+

+ If you should find a bug or would like to see an additional feature in + the library, please use the standard Boost methods of dealing with this + kind of issue rather than emailing me directly. Boost has a very good system + to track bugs and + features + requests, and using it is the best way of dealing with them as + soon as possible. +

+

+

+
+

+ + Navigation +

+

+ Used in combination with the configured browser key (usually Alt), the following + keys act as handy shortcuts for common navigation tasks. +

+
    +
  • +General
      +
    • +p - Previous page +
    • +
    • +n - Next page +
    • +
    • +h - home +
    • +
    • +u - Up +
    • +
    +
  • +
  • +Main TOC
      +
    • +i - Introduction +
    • +
    • +o - One minute tutorial +
    • +
    • +t - The tutorial +
    • +
    • +b - Bimap and Boost +
    • +
    • +r - Reference +
    • +
    • +c - Compiler specifics +
    • +
    • +v - Performance +
    • +
    • +e - Examples +
    • +
    • +s - Test Suite +
    • +
    • +f - Future work +
    • +
    • +m - Release notes +
    • +
    • +w - Rationale +
    • +
    • +y - History +
    • +
    • +a - Acknowledgements +
    • +
    +
  • +
+
+ + + +
Copyright © 2006 -2007 Matias Capeletto
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_bimap/one_minute_tutorial.html b/doc/html/boost_bimap/one_minute_tutorial.html new file mode 100644 index 0000000..5a4f964 --- /dev/null +++ b/doc/html/boost_bimap/one_minute_tutorial.html @@ -0,0 +1,497 @@ + + + +One minute tutorial + + + + + + + + + + + + + + + +
+Boost C++ LibrariesChapter Logo +HomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ + What is a + bimap? +

+

+ A Bimap is a data structure that represents bidirectional relations between + elements of two collections. The container is designed to work as two opposed + STL maps. A bimap between a collection X + and a collection Y can be viewed + as a map from X to Y (this view will be called the left + map view) or as a map from Y + to X (known as the right + map view). Additionally, the bimap can also be viewed as a set of + relations between X and Y (named the collection of relations + view). +

+

+ The following code creates an empty bimap container: +

+
+typedef bimap<X,Y> bm_type;
+bm_type bm;
+
+

+ Given this code, the following is the complete description of the resulting + bimap. + [1] +

+
    +
  • +bm.left is signature-compatible with std::map<X,Y> +
  • +
  • +bm.right is signature-compatible with std::map<Y,X> +
  • +
  • +bm is signature-compatible + with std::set< relation<X,Y> > +
  • +
+

+ simple.bimap +

+

+ You can see how a bimap container offers three views over the same collection + of bidirectional relations. +

+

+ If we have any generic function that work with maps +

+
+template< class MapType >
+void print_map(const MapType & m)
+{
+    typedef typename MapType::const_iterator const_iterator;
+    for( const_iterator iter = m.begin(), iend = m.end(); iter != iend; ++iter )
+    {
+        std::cout << iter->first << "-->" << iter->second << std::endl;
+    }
+}
+
+

+ We can use the left map view and the right map + view with it +

+
+bimap< int, std::string > bm;
+...
+print_map( bm.left  );
+print_map( bm.right );
+
+

+ And the output will be +

+
1 --> one
+2 --> two
+...
+one --> 1
+two --> 2
+...
+
+

+ + Layout + of the relation and the pairs of a bimap +

+

+ The relation class represents + two related elements. The two values are named left and right to express the + symmetry of this type. The bimap pair classes are signature-compatible with + std::pairs. +

+

+ relation.and.pair +

+

+ + Step by step +

+

+ A convinience header is avaiable in the boost directory: +

+
+#include <boost/bimap.hpp>
+
+

+ Lets define a bidirectional map between integers and strings: +

+

+

+

+ +

+
+typedef boost::bimap< int, std::string > bm_type;
+bm_type bm;
+
+

+

+

+

+

+

+
+

+

+

+

+

+ + The + collection of relations view +

+

+ Remember that bm alone can + be used as a set of relations. We can insert elements or iterate over them + using this view. +

+

+

+

+ +

+
+bm.insert( bm_type::value_type(1, "one" ) );
+bm.insert( bm_type::value_type(2, "two" ) );
+
+std::cout << "There are " << bm.size() << "relations" << std::endl;
+
+for( bm_type::const_iterator iter = bm.begin(), iend = bm.end(); 
+    iter != iend; ++iter )
+{
+    // iter->left  : data : int
+    // iter->right : data : std::string
+
+    std::cout << iter->left << " <--> " << iter->right << std::endl;
+}
+
+

+

+

+

+

+

+
+

+

+

+

+

+ + The left + map view +

+

+ bm.left works like a std::map< + int, std::string + >. We use it in the same way we will + use a standard map. +

+

+

+

+ +

+
+1typedef bm_type::left_map::const_iterator left_const_iterator;
+
+for( left_const_iterator left_iter = bm.left.begin(), iend = bm.left.end();
+     left_iter != iend; ++left_iter )
+{
+    // left_iter->first  : key  : int
+    // left_iter->second : data : std::string
+
+    std::cout << left_iter->first << " --> " << left_iter->second << std::endl;
+}
+
+2bm_type::left_const_iterator left_iter = bm.left.find(2);
+assert( left_iter->second ==  "two" );
+
+3bm.left.insert( bm_type::left_value_type( 3, "three" ) );
+
+

+

+

+

+

+

+
+ + + + + + + + + + + + +
+1

The type of bm.left is bm_type::left_map + and the type of bm.right is bm_type::right_map +

+2

bm_type::left_-type- can be used as a shortcut for + the more verbose bm_type::left_map::-type-

+3

This line produces the same effect + of bm.insert( bm_type::value_type(3,"three") );

+

+

+

+

+

+ + The right + map view +

+

+ bm.right works like a std::map< + std::string, int >. It + is important to note that the key is the first type and the data is the second + one, exactly as with standard maps. +

+

+

+

+ +

+
+bm_type::right_const_iterator right_iter = bm.right.find("two");
+
+// right_iter->first  : key  : std::string
+// right_iter->second : data : int
+
+assert( right_iter->second ==  2 );
+
+assert( bm.right.at("one") == 1 );
+
+bm.right.erase("two");
+
+1bm.right.insert( bm_type::right_value_type( "four", 4 ) );
+
+

+

+

+

+

+

+
+ + +
+1

This line produces the same effect of bm.insert( bm_type::value_type(4,"four") + );

+

+

+

+

+

+ + Differences + with std::map +

+

+ The main difference between bimap views and their standard containers counterparts + is that, because of the bidirectional nature of a bimap, the values stored + in it can not be modified directly using iterators. For example, when a std::map<X,Y> iterator + is dereferenced the return type is std::pair<const X, + Y>, + so the following code is valid: m.begin()->second = new_value;. + However dereferencing a bimap<X,Y>::left_iterator + returns a type that is signature-compatible with a std::pair<const X, const Y> +

+
+bm.left.find(1)->second = "1"; // Compilation error
+
+

+ If you insert (1,"one") and (1,"1") in a std::map<int,std::string> the second insertion will have no effect. + In a bimap<X,Y> both keys have to remain unique. The insertion + may fail in other situtions too. Lets see an example +

+
+bm.clear();
+
+bm.insert( bm_type::value_type( 1, "one" ) );
+
+bm.insert( bm_type::value_type( 1, "1"   ) ); // No effect!
+bm.insert( bm_type::value_type( 2, "one" ) ); // No effect!
+
+assert( bm.size() == 1 );
+
+

+ + A simple example +

+

+ Look how you can reuse code that is intend to be used with std::maps, like + the print_map function in this example. +

+

+ Go to source code +

+

+

+

+ +

+
+#include <string>
+#include <iostream>
+
+#include <boost/bimap.hpp>
+
+template< class MapType >
+void print_map(const MapType & map,
+               const std::string & separator,
+               std::ostream & os )
+{
+    typedef typename MapType::const_iterator const_iterator;
+
+    for( const_iterator i = map.begin(), iend = map.end(); i != iend; ++i )
+    {
+        os << i->first << separator << i->second << std::endl;
+    }
+}
+
+int main()
+{
+    // Soccer World cup
+
+    typedef boost::bimap< std::string, int > results_bimap;
+    typedef results_bimap::value_type position;
+
+    results_bimap results;
+    results.insert( position("Argentina"    ,1) );
+    results.insert( position("Spain"        ,2) );
+    results.insert( position("Germany"      ,3) );
+    results.insert( position("France"       ,4) );
+
+    std::cout << "The number of countries is " << results.size()
+              << std::endl;
+
+    std::cout << "The winner is " << results.right.at(1)
+              << std::endl
+              << std::endl;
+
+    std::cout << "Countries names ordered by their final position:"
+              << std::endl;
+
+    // results.right works like a std::map< int, std::string >
+
+    print_map( results.right, ") ", std::cout );
+
+    std::cout << std::endl
+              << "Countries names ordered alphabetically along with"
+                    "their final position:"
+              << std::endl;
+
+    // results.left works like a std::map< std::string, int >
+
+    print_map( results.left, " ends in position ", std::cout );
+
+    return 0;
+}
+
+

+

+

+

+

+

+
+

+

+

+

+

+ The output of this program will be the following: +

+
The number of countries is 4
+
+The winner is Argentina
+
+Countries names ordered by their final position:
+1) Argentina
+2) Spain
+3) Germany
+4) France
+
+Countries names ordered alphabetically along with their final position:
+Argentina ends in position 1
+France ends in position 4
+Germany ends in position 3
+Spain ends in position 2
+
+

+ + Continuing + the journey +

+

+ For information on function signatures, see any standard library documentation + or read the reference section + of this documentation. +

+
+ + + + + +
[Caution]Caution
+

+

+

+ Be aware that a bidirectional map is only signature-compatible with standard + containers. Some functions may give different results, such as in the case + of inserting a pair into the left map where the second value conflicts + with a stored relation in the container. The functions may be slower in + a bimap because of the duplicated constraints. It is strongly recommended + that you read The full tutorial + if you intend to use a bimap in a serious project. +

+

+

+
+
+

+

[1] + A type is signature-compatible with other type if + it has the same signature for functions and metadata. Preconditions, postconditions + and the order of operations need not be the same. +

+
+
+ + + +
Copyright © 2006 -2007 Matias Capeletto
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_bimap/performance.html b/doc/html/boost_bimap/performance.html new file mode 100644 index 0000000..04c5e2b --- /dev/null +++ b/doc/html/boost_bimap/performance.html @@ -0,0 +1,44 @@ + + + +Performance + + + + + + + + + + + + + + + +
+Boost C++ LibrariesChapter Logo +HomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ Section under construction. +

+
+ + + +
Copyright © 2006 -2007 Matias Capeletto
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_bimap/rationale.html b/doc/html/boost_bimap/rationale.html new file mode 100644 index 0000000..a7b7f15 --- /dev/null +++ b/doc/html/boost_bimap/rationale.html @@ -0,0 +1,312 @@ + + + +Rationale + + + + + + + + + + + + + + + +
+Boost C++ LibrariesChapter Logo +HomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ + +

+ This section assumes that you have read all other sections, the most of important + of which being tutorial, std::set theory + and the reference, and that you have tested the library. + A lot of effort was invested in making the interface as intuitive and clean + as possible. If you understand, and hopefully like, the interface of this library, + it will be a lot easier to read this rationale. The following section is little + more than a rationale. This library was coded in the context of the Google + SoC 2006 and the student and mentor were in different continents. A great deal + of email flowed between Joaquin and Matias. The juiciest parts of the conversations + where extracted and rearranged here. +

+
+ + + + + +
[Note]Note
+

+

+

+ To browse the code, you can use the Bimap + Complete Reference, a doxygen-powered document targeted + at developers. +

+

+

+
+
+ +

+ The initial explanation includes few features. This section aims to describe + the general design of the library and excludes details of those features + that are of lesser importance; these features will be introduced later. +

+

+ The design of the library is divided into two parts. The first is the construction + of a relation class. This will be the object stored and + managed by the multi_index_container core. The idea is + to make this class as easy as possible to use, while making it efficient + in terms of memory and access time. This is a cornerstone in the design of + Boost.Bimap and, as you will see in this + rationale, the rest of the design follows easily. +

+

+ The following interface is necessary for the relation + class: +

+
+typedef -unspecified- TA; typedef -unspecified- TB;
+
+TA a, ai; TB b, bi;
+
+typedef relation< TA, TB > rel;
+STATIC_ASSERT( is_same< rel::left_type , TA >::value );
+STATIC_ASSERT( is_same< rel::right_type, TB >::value );
+
+rel r(ai,bi);
+assert( r.left == ai && r.right == bi );
+
+r.left  = a; r.right = b;
+assert( r.left  == a && r.right == b );
+
+typedef pair_type_by< member_at::left , rel >::type pba_type;
+STATIC_ASSERT( is_same< pba_type::first_type , TA >::value );
+STATIC_ASSERT( is_same< pba_type::second_type, TB >::value );
+
+typedef pair_type_by< member_at::right, rel >::type pbb_type;
+STATIC_ASSERT( is_same< pbb_type::first_type , TB >::value );
+STATIC_ASSERT( is_same< pbb_type::second_type, TA >::value );
+
+pba_type pba = pair_by< member_at::left  >(r);
+assert( pba.first == r.left  && pba.second == r.right );
+
+pbb_type pbb = pair_by< member_at::right >(r);
+assert( pbb.first == r.right && pbb.second == r.left  );
+
+

+ relation +

+

+ Although this seems straightforward, as will be seen later, it is the most + difficult code hack of the library. It is indeed very easy if we relax some + of the efficiency constraints. For example, it is trivial if we allow a relation + to have greater size than the the sum of those of its components. It is equally + simple if access speed is not important. One of the first decisions made + about Boost.Bimap was, however, that, in + order to be useful, it had to achieve zero overhead over the wrapped Boost.MultiIndex container. Finally, there is another + constraint that can be relaxed: conformance to C++ standards, but this is + quite unacceptable. Let us now suppose that we have coded this class, and + it conforms to what was required. +

+

+ The second part is based on this relation class. We can + now view the data in any of three ways: pair<A,B>, + relation<A,B> and pair<B,A>. + Suppose that our bimap supports only one-to-one relations. (Other relation + types are considered additional features in this design.) The proposed interface + is very simple, and it is based heavily on the concepts of the STL. Given + a bimap<A,B> bm: +

+
    +
  1. +bm.left is signature-compatible with a + std::map<A,B> +
  2. +
  3. +bm.right is signature-compatible with a + std::map<B,A> +
  4. +
  5. +bm is signature-compatible + with a std::set<relation<A,B> > +
  6. +
+

+ simple.bimap +

+

+ This interface is easily learned by users who have a STL background, as well + as being simple and powerful. This is the general design. +

+
+ + Relation + Implementation +
+

+ This section explains the details of the actual relation + class implementation. +

+

+ The first thing that we can imagine is the use of an union. + Regrettably, the current C++ standard only allows unions of POD types. For + the views, we can try a wrapper around a relation<A,B> that + has two references named first and second that bind to A + and B, or to B and A. +

+
+relation<TA,TB> r;
+
+const_reference_pair<A,B> pba(r);
+const_reference_pair<B,A> pbb(r);
+
+

+ It is not difficult to code the relation class using this, but two references + are initialized at every access and using of pba.first + will be slower in most compilers than using r.left directly + . There is another hidden drawback of using this scheme: it is not iterator-friendly, + since the map views iterators must be degraded to Read Write + instead of LValue. This will be explained later. +

+

+ At first, this seems to be the best we can do with the current C++ standard. + However there is a solution to this problem that does not conform very well + to C++ standards but does achieve zero overhead in terms of access time and + memory, and additionally allows the view iterators to be upgraded to LValue + again. +

+

+ In order to use this, the compiler must conform to a layout-compatibility + clause that is not currently in the standard but is very natural. The additional + clause imposes that if we have two classes: +

+
+struct class_a_b
+{
+    Type1 name_a;
+    Type2 name_b;
+};
+
+struct class_b_a
+{
+    Type1 name_b;
+    Type2 name_a;
+};
+
+

+ then the storage layout of class_a_b is equal to the storage + layout of class_b_a. If you are surprised to learn that + this does not hold in a standards-compliant C++ compiler, welcome to the + club. It is the natural way to implement it from the point of view of the + compiler's vendor and is very useful for the developer. Maybe it will be + included in the standard some day. Every current compiler conforms to this. +

+

+ If we are able to count on this, then we can implement an idiom called mutant. + The idea is to provide a secure wrapper around reinterpret_cast. + A class can declare that it can be viewed using different view classes that + are storage-compatible with it. Then we use the free function mutate<view>(mutant) + to get the view. The mutate + function checks at compile time that the requested view is declared in the + mutant views list. We implement a class name structured_pair + that is signature-compatible with a std::pair, + while the storage layout is configured with a third template parameter. Two + instances of this template class will provide the views of the relation. +

+

+ The thing is that if we want to be standards-compliant, we cannot use this + approach. It is very annoying not to be able to use something that we know + will work with every compiler and that is far better than alternatives. So + -- and this is an important decision -- we have to find a way to use it and + still make the library standards-compliant. +

+

+ The idea is very simple. We code both approaches: the const_reference_pair-based + and the mutant-based, and use the mutant approach if the compiler is compliant + with our new layout-compatible clause. If the compiler really messes things + up, we degrade the performance of the bimap a little. The only drawback here + is that, while the mutant approach allows to make LValue + iterators, we have to degrade them to Read Write in + both cases, because we require that the same code be compilable by any standards-compliant + compiler. +

+
+ + + + + +
[Note]Note
+

+

+

+ Testing this approach in all the supported compilers indicated that the + mutant idiom was always supported. The strictly compliant version was + removed from the code because it was never used. +

+

+

+
+
+ + Bimap + Implementation +
+

+ The core of bimap will be obviously a multi_index_container. + The basic idea to tackle the implementation of the bimap class is to use + iterator_adaptor to convert the iterators from Boost.MultiIndex + to the std::map and std::set behaviour. + The map_view and the set_view can be implemented directly using + this new transformed iterators and a wrapper around each index of the core + container. However, there is a hidden idiom here, that, once coded, will + be very useful for other parts of this library and for Boost.MRU library. + Following the ideas from iterator_adaptor, + Boost.Bimap views are implemented using a container_adaptor. + There are several template classes (for example map_adaptor + and set_adaptor) that take + a std::map signature-conformant class and new + iterators, and adapt the container so it now uses this iterators instead + of the originals. For example, if you have a std::set<int*>, + you can build other container that behaves exactly as a std::set<int> using + set_adaptor and iterator_adaptor. + The combined use of this two tools is very powerful. A container_adaptor + can take classes that do not fulfil all the requirements of the adapted container. + The new container must define these missing functions. +

+
+
+ + + +
Copyright © 2006 -2007 Matias Capeletto
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_bimap/rationale/additional_features.html b/doc/html/boost_bimap/rationale/additional_features.html new file mode 100644 index 0000000..7c09b39 --- /dev/null +++ b/doc/html/boost_bimap/rationale/additional_features.html @@ -0,0 +1,139 @@ + + + +Additional + Features + + + + + + + + + + + + + + + +
+Boost C++ LibrariesChapter Logo +HomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
+ + N-1, + N-N, hashed maps +
+

+ This is a very interesting point of the design. The framework introduced + in std::set theory permits the management of the different + constraints with a very simple and conceptual approach. It is easy both to + remember and to learn. The idea here is to allow the user to specify the + collection type of each key directly. In order to implement this feature, + we have to solve two problems: +

+
    +
  • + The index types of the multi_index_container + core now depends on the collection type used for each key. +
  • +
  • + The map views now change their semantics according to the collection type + chosen. +
  • +
+

+ Boost.Bimap relies heavily on Boost.MPL to implement all of the metaprogramming + necessary to make this framework work. By default, if the user does not specify + the kind of the set, a std::set type + is used. +

+

+ bimap.structures +

+
+ + Collection + type of relation constraints +
+

+ The constraints of the bimap set view are another very important feature. + In general, Boost.Bimap users will base the set view type on one of the two + collection types of their keys. It may be useful however to give this set + other constraints or simply to order it differently. By default, Boost.Bimap + bases the collection type of relations on the left collection type, but the + user may choose between: +

+
    +
  • + left_based +
  • +
  • + right_based +
  • +
  • + set_of_relation<> +
  • +
  • + multiset_of_relation<> +
  • +
  • + unordered_set_of_relation<> +
  • +
  • + unordered_multiset_of_relation<> +
  • +
  • + list_of +
  • +
  • + vector_of +
  • +
+

+ In the first two cases, there are only two indices in the multi_index_core, + and for this reason, these are the preferred options. The implementation + uses further metaprogramming to define a new index if necessary. +

+
+ + Tagged +
+

+ The idea of using tags instead of the member_at::side + idiom is very appealing since code that uses it is more readable. The only + cost is compile time. boost/bimap/tagged is the implementation + of a non-invasive tagged idiom. The relation class is + built in such a way that even when the user uses tags, the member_at::side + idiom continues to work. This is good since an user can start tagging even + before completing the coding of the algorithm, and the untagged code continues + to work. The development becomes a little more complicated when user-defined + tags are included, but there are many handy metafunctions defined in the + tagged idiom that help to keep things simple enough. +

+

+ tagged +

+
+ + + +
Copyright © 2006 -2007 Matias Capeletto
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_bimap/rationale/code.html b/doc/html/boost_bimap/rationale/code.html new file mode 100644 index 0000000..9a795c8 --- /dev/null +++ b/doc/html/boost_bimap/rationale/code.html @@ -0,0 +1,200 @@ + + + +Code + + + + + + + + + + + + + + + +
+Boost C++ LibrariesChapter Logo +HomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+

+Code +

+

+ You can browse the code using the Boost.Bimap doxygen docs. +

+

+ The code follows the Boost + Library Requirement and Guidelines as closely as possible. +

+
+

Table 1.10. folders in boost/bimap

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ name +

+
+

+ what is inside? +

+
+

+ user level header files +

+
 
+

+ tagged/ +

+
+

+ tagged idiom +

+
+

+ relation/ +

+
+

+ the bimap data +

+
+

+ container_adaptor/ +

+
+

+ easy way of adapting containers +

+
+

+ views/ +

+
+

+ bimap views +

+
+

+ property_map/ +

+
+

+ support for property map concept +

+
+
+
+

Table 1.11. folders in each folder

+
++++ + + + + + + + + + + + + + + + + + + +
+

+ name +

+
+

+ what is inside? +

+
+

+

+
+

+ class definitions +

+
+

+ support/ +

+
+

+ optional metafunctions and free functions +

+
+

+ detail/ +

+
+

+ things not intended for the user's eyes +

+
+
+
+
+ + + +
Copyright © 2006 -2007 Matias Capeletto
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_bimap/rationale/the_student_and_the_mentor.html b/doc/html/boost_bimap/rationale/the_student_and_the_mentor.html new file mode 100644 index 0000000..ebd0aab --- /dev/null +++ b/doc/html/boost_bimap/rationale/the_student_and_the_mentor.html @@ -0,0 +1,1396 @@ + + + +The + student and the mentor + + + + + + + + + + + + + + + +
+Boost C++ LibrariesChapter Logo +HomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
+ + + + + +
[Tip]Tip
+

+

+

+ It is a good idea to read the original Boost.Misc + SoC proposal first. +

+

+

+
+
+

+

+

+ - The discussion starts with Joaquin trying to strip out the + "misc" name out of the library - +

+

+

+
+

+ joaquin +

+

+ Joaquin +

+
+

+

+

+ Thinking about it, the unifying principle of MISC containers + is perhaps misleading: certainly all miscs use multi-indexing internally, + but this does not reflect much in the external interface (as it should + be, OTOH). So, from the user's point of view, miscs are entirely heterogeneous + beasts. Moreover, there isn't in your proposal any kind of global facility + common to all miscs. What about dropping the misc principle and working + on each container as a separate library, then? You'd have boost::bimap, + boost::mru, etc, and no common intro to them. This also opens up the + possibility to add other containers to the suite which aren't based on + B.MI. What's your stance on this? Do you see a value in keeping miscs + conceptually together? +

+

+

+
+

+ matias +

+

+ Matias +

+
+

+

+

+ As the original proposal states only two containers (bimap + and mru set) both based in B.MI, it was straight forward to group them + together. When I was writing the SoC proposal I experienced a similar + feeling when the two families begin to grow. As you say, the only common + denominator is their internal implementation. I thought a bit about a + more general framework to join this two families (and other internally + related ones) and finally came up with an idea: Boost.MultiIndex! So + I think that it is not a good idea to try to unify the two families and + I voted in favor of get rid of the misc part of boost::misc::bimap and + boost::misc::mru. Anyway, for my SoC application it seems OK to put the + two families in the same project because although from the outside they + are completely unrelated, the work I will have to do in order to build + the libraries will be consistent and what I will learn coding the bimap + family will be used when I start to code the mru family. When the mru + family is in place, I will surely have learnt other things to improve + the bimap group. +

+

+

+
+
+

+

+

+ On the other hand, I think it will be useful for the general + user to have at least some document linked in the B.MI documentation + that enumerates the most common cases of uses (a bimap and an mru set + for example) and points where to find clean implementation for this useful + containers. For now, a link to boost::bimap and other one to boost::mru + will suffice. If you think about the title of such a document, you will + probably come up with something like: Common Multi Index Specialized + Containers, and we are back to our misc proposal. So, to order some ideas: + +

+

+

+
+
+

+

+

+ - A new family of containers that can be accessed by both key + will be created. (boost::bimap) +

+

+

+
+
+

+

+

+ - A new family of time aware containers will see the light. + (boost::mru) +

+

+

+
+
+

+

+

+ - A page can be added to B.MI documentation, titled misc that + links this new libraries. +

+

+

+
+
+

+

+

+ This is a clearer framework for the user. They can use a mru + container without hearing about Boost.MultiIndex at all. And B.MI users + will get some of their common containers already implemented with an + STL friendly interface in other libraries. And as you stated this is + more extensible because opens the door to use other libraries in bimap + and mru families than just Boost.MultiIndex without compromising the + more general boost framework. The word "misc" it is going to + disappear from the code and the documentation of bimap and mru. From + now on the only use for it will be to identify our SoC project. I am + thinking in a name for the bimap library. What about Boost.BidirectionalMap? + Ideas? +

+

+

+
+

+ Joaquin +

+
+

+

+

+ Yes, Boost.Bimap. In my opinion, bimap is a well known name + in the Boost and even in the C++ community. It sounds and is short. Why + not to vindicate yourself as the owner of this name? +

+

+

+
+

+ - Then after a week of work - +

+

+ Matias +

+
+

+

+

+ Now that Boost.Bimap is getting some shape, I see that as + you have told me, we must offer a "one_to_many_map" and a "multi_bimap" + as part of the library. The framework I am actually working allowed to + construct this kind of bidirectional maps and it is easy to understand + from the user side. +

+

+

+
+

+ Joaquin +

+
+

+

+

+ OK, I am glad we agree on this point. +

+

+

+
+

+ Matias +

+
+

+

+

+ With respect to the symmetry of the key access names, I have + to agree that there is not much a difference between the following ones: + +

+

+

+
+
+

+

+

+ - to - from +

+

+

+
+
+

+

+

+ - to - b +

+

+

+
+
+

+

+

+ - 0 - 1 +

+

+

+
+
+

+

+

+ - left - right +

+

+

+
+
+

+

+

+ In my opinion it is a matter of taste, but left/right sounds + more symmetrical than the others. +

+

+

+
+

+ Joaquin +

+
+

+

+

+ I like very much the left/right notation, it is very simple + to remember and it is a lot more symmetrical than to/from. +

+

+

+
+

+ Matias +

+
+

+

+

+ At first my idea was to obtain ease of use hiding the B.MI + core, making it more STL-intuitive. Nevertheless I have realized that + B.MI is a lot more coherent and easy to use that I had imagined. This + makes me think again in the problem. In the design that I am coding now, + bimap is-a multi_index_container specializes + with a data type very comfortable called bipair, that can be seen like + any of the two maps that integrates it using map views. This scheme has + great benefits for users: +

+

+

+
+
+

+

+

+ - If the user already knows B.MI, he can take advantage of + the tools that it provides and that are not present in the STL containers. + In addition, in some cases the use to indices to see the data can be + very useful. +

+

+

+
+
+

+

+

+ - If the user does not know anything about B.MI but have an + STL framework, the learning curve is reduced to understand the bimap + instantiation and how a is obtained the desired map view. +

+

+

+
+
+

+

+

+ Another very important benefit holds: All the algorithms done + for B.MI continues to work with Boost.Bimap and if B.MI continues growing, + bimap grow automatically. +

+

+

+
+

+ Joaquin +

+
+

+

+

+ Umm... This is an interesting design decision, but controversial + in my opinion. Basically you decide to expose the implementation of bimap; + that has advantages, as you stated, but also a nonsmall disadvantage: + once you have documented the implementation, + it is not possible to change it anymore. It is a marriage with B.MI without + the chance of divorce. The other possibility, to hide the implementation + and to duplicate and document the provided functionality, explicitly + or implicitly due to the same characteristics of the implementation, + is of course heavier to maintain, but it gives a degree of freedom to + change the guts of your software if you need to. Do not take this like + a frontal objection, but I think that it is quite important design decision, + not only in the context of bimap but in general. +

+

+

+
+

+ Matias +

+
+

+

+

+ You are quite right here. I think we have to choose the hardest + path and hide the B.MI core from the user. I am sending you the first + draft of bimap along with some documentation. +

+

+

+
+

+ - This completes the second week, the documentation was basically + the first section of this rationale - +

+

+ Joaquin +

+
+

+

+

+ I must confess that I am beginning to like what I see. I am + mathematical by vocation, and when I see symmetry in a formulation I + believe that it is in the right track. +

+

+

+
+

+ Matias +

+
+

+

+

+ We are two mathematicians by vocation then. +

+

+

+
+

+ Joaquin +

+
+

+

+

+ I think that the part of std::set theory is very clear. To + me, it turns out to me somewhat strange to consider the rank of a map + (values X) like a std::set, but of course the formulation is consistent. + +

+

+

+
+

+ Matias +

+
+

+

+

+ I like it very much, it can be a little odd at first, but + now that I have get used to it, it is very easy to express in the code + my contrains on the data, and I believe that if somebody reads the code + and sees the bimap instantiation he is not going to have problems understanding + it. Perhaps it is easier to understand it if we use your notation: ordered_nonunique, + unordered_unique, but this goes against our STL facade. In my opinion + the user that comes from STL must have to learn as less as possible. + +

+

+

+
+

+ Joaquin +

+
+

+

+

+ Considering a relation like a struct + {left, right} is clean and clear. If I understand + it well, one relation has views of type pair{first, second}, is this correct? +

+

+

+
+

+ Matias +

+
+

+

+

+ Yes, I believe that the left/right notation to express symmetry + is great. I believe that to people is going to love it. +

+

+

+
+

+ Joaquin +

+
+

+

+

+ OK, perfect. I likes this very much: +

+

+

+
+
+

+

+

+ - bm.left is compatible with std::map<A,B> +

+

+

+
+
+

+

+

+ - bm.right is compatible with std::map<B,A> +

+

+

+
+
+

+

+

+ - bm is compatible with std::set<relation<A,B>> +

+

+

+
+
+

+

+

+ It is elegant and symmetric. I feel good vibrations here. + +

+

+

+
+

+ Matias +

+
+

+

+

+ Great! +

+

+

+
+

+ Joaquin +

+
+

+

+

+ Moving on, the support for N-1, N-N, and hashed index is very + easy to grasp, and it fits well in framework. However I do not finish + to understand very well the "set<relation> constraints" + section. Will you came up with some examples of which is the meaning + of the different cases that you enumerate? +

+

+

+
+

+ Matias - +

+
+

+

+

+ Yes, I mean: +

+

+

+
+
+

+

+

+ - based on the left +

+

+

+
+
+

+

+

+ - based on the right +

+

+

+
+
+

+

+

+ The bimap core must be based on some index of multi index. + If the index of the left is of the type hash, then in fact the main view + is going to be an unordered_set< relation<A,B> >. Perhaps + this is not what the user prefers and he wants to base its main view + on the right index. +

+

+

+
+
+

+

+

+ - set_of_relation +

+

+

+
+
+

+

+

+ - multiset_of_relation +

+

+

+
+
+

+

+

+ - unordered_set_of_relation +

+

+

+
+
+

+

+

+ - unordered_multiset_of_relation +

+

+

+
+
+

+

+

+ However, if both of them are hash indexes, the user may want + the main view to be ordered. As we have a B.MI core this is very easy + to support, we just have to add another index to it. +

+

+

+
+

+ Joaquin +

+
+

+

+

+ I understand it now. OK, I do not know if we have to include + this in the first version, is going to be a functionality avalanche! + +

+

+

+
+

+ Matias +

+
+

+

+

+ The user is not affected by the addition of this functionality, + because by default it will be based on the left index that is a very + natural behaviour. I do not think that this is functionality bloat, but + I agree with you that it is a functionality avalanche. +

+

+

+
+

+ Joaquin +

+
+

+

+

+ There are restrictions between the left and right set types + and the possible main view set types. For example if some of the index + is of unique type, then the main view cannot be of type multiset_of_relation. + To the inverse one, if the main view is of type set_of_relation the left + and the right index cannot be of type multi_set. All this subject of + the unicity constrictions and the resulting interactions between indexes + is one of the subtle subjects of B.MI. +

+

+

+
+

+ Matias +

+
+

+

+

+ This can be checked at compile time and informed as an error + in compile time. +

+

+

+
+

+ Joaquin +

+
+

+

+

+ It can be interesting. +

+

+

+
+

+ - And right when everything seems to be perfect... - +

+

+ Joaquin +

+
+

+

+

+ I have some worse news with respect to mutant, it is very + a well designed and manageable class, unfortunately, C++ does not guarantee + layout-compatibility almost in any case. For example, the C++ standard + does not guarantee that the classes struct{T1 a; T2 b;} and struct{T1 b; T2 a;} are layout-compatible, and therefore + the trick of reinterpret_cast is an undefined behavior. I am with you + in which that in the 100% of the cases this scheme will really work, + but the standard is the standard. If you can look the layout-compatibility + subject in it (http://www.kuzbass.ru/docsisocpp). + As you see, sometimes the standard is cruel. Although mutant seems a + lost case, please do not hurry to eliminate it. We will see what can + be done for it. +

+

+

+
+

+ Matias +

+
+

+

+

+ I read the standard, and you were right about it. Mutant was + an implementation detail. It is a pity because I am sure that it will + work perfect in any compiler. Perhaps the standard becomes more strict + some day and mutant returns to life... We can then try a wrapper around + a relation<A,B> that have two references named first and second + that bind to A and B, or B and A. +

+

+

+
+

+ +

+
+relation<TA,TB> r;
+const_reference_pair<A,B> pba(r);
+const_reference_pair<B,A> pbb(r);
+
+

+

+
+

+

+

+ It is not difficult to code the relation class in this way + but two references are initialized with every access and the use of + pba.first will be slower than r.left in most compilers. It is very + difficult to optimize this kind of references. +

+

+

+
+

+ Joaquin +

+
+

+

+

+ This workaround is not possible, due to technical problems + with the expected behavior of the iterators. If the iterators of bm.left + are of bidirectional type, then standard stated that it have to return + an object of type const value_type& when dereferenced. You will have + to return a const_reference_pair created in the flight, making it impossible + to return a reference. +

+

+

+
+

+ Matias +

+
+

+

+

+ I understand... I have workaround for that also but surely + the standard will attack me again! We must manage to create the class + relation that responds as we want, the rest of the code will flow from + this point. This clear separation between the relation class and the + rest of the library, is going to help to us to separate the problems + and to attack them better. +

+

+

+
+

+ Joaquin +

+
+

+

+

+ What workaround? It already pricks my curiosity,I have dedicated + a long time to the subject and I do not find any solution except that + we allow the relation class to occupy more memory. +

+

+

+
+

+ Matias +

+
+

+

+

+ We must achieve that the relation<A,B> size equals the + pair<A,B> size if we want this library to be really useful. I was + going to write my workaround and I realized that It does not work. Look + at this: http://www.boost.org/libs/iterator/doc/new-iter-concepts.html + Basically the problem that we are dealing is solved if we based our iterators + on this proposal. The present standard forces that the bidirectional + iterators also are of the type input and output. Using the new concepts + there is no inconvenient in making our iterators "Readable Writable + Swappable Bidirectional Traversal". Therefore the const_reference_pair + returns to be valid. +

+

+

+
+

+ Joaquin +

+
+

+

+

+ It is correct in the sense that you simply say that your iterators + are less powerful than those of the std::map. It is not that it is wrong, + simply that instead of fixing the problem, you confess it. +

+

+

+
+

+ Matias +

+
+

+

+

+ OK, but in our particular case; What are the benefits of offering + a LValue iterator against a Read Write iterator? It does not seem to + me that it is less powerful in this case. +

+

+

+
+

+ Joaquin +

+
+

+

+

+ The main problem with a ReadWrite is that the following thing: + value_type * + p=&(*it); + fails or stores a transitory direction in p. Is this important in the + real life? I do not know. How frequently you store the direction of the + elements of a map? Perhaps it is not very frequent, since the logical + thing is to store the iterators instead of the directions of the elements. + Let us review our options: +

+

+

+
+
+

+

+

+ 1. We used mutant knowing that is not standard, but of course + it is supported in the 100% of the cases. +

+

+

+
+
+

+

+

+ 2. We used const_reference_pair and we declared the iterators + not LValue. +

+

+

+
+
+

+

+

+ 3. We found some trick that still we do not know. I have thus + been playing with unions and things, without much luck. +

+

+

+
+
+

+

+

+ 4. We leverage the restriction that views have to support + the first, second notation. If we made this decision, there are several + possibilities: +

+

+

+
+
+

+

+

+ a. The left map has standard semantics first/second while + the right map has the inverse semantics. +

+

+

+
+
+

+

+

+ b. Instead of first and second we provide first() and second(), + with which the problem is trivial. +

+

+

+
+
+

+

+

+ c. The map view do not support first/second but left/right + as the father relation +

+

+

+
+
+

+

+

+ 5. We solve the problem using more memory than sizeof(pair<A,B>). + +

+

+

+
+
+

+

+

+ In any case, I would say that the only really unacceptable + option is the last one. +

+

+

+
+

+ Matias +

+
+

+

+

+ Lets see. +

+

+

+
+
+

+

+

+ 1. I want the "standard compliant" label in the + library. +

+

+

+
+
+

+

+

+ 2. This is the natural choice, but knowing that there is another + option that always works and it is more efficient is awful. +

+

+

+
+
+

+

+

+ 3. I have also tried to play with unions, the problem is that + the union members must be POD types. +

+

+

+
+
+

+

+

+ 4. This option implies a big lost to the library. +

+

+

+
+
+

+

+

+ 5. Totally agree. +

+

+

+
+
+

+

+

+ I want to add another option to this list. Using metaprogramming, + the relation class checks if the compiler supports the mutant idiom. + If it supports it then it uses it and obtains zero overhead plus LValue + iterators, but if it do not supports it then uses const_reference_pair + and obtains minimum overhead with ReadWrite iterators. This might be + controversial but the advantages that mutant offers are very big and + the truth is that I do not believe that in any actual compiler this idiom + is not supported. This scheme would adjust perfectly to the present standard + since we are not supposing anything. The only drawback here is that although + the mutant approach allows to make LValue iterators we have to degrade + they to Read Write in both cases, because we want that the same code + can be compiled in any standard compliant compiler. +

+

+

+
+

+ - Hopefully we find our way out of the problem - +

+

+ Joaquin +

+
+

+

+

+ Changing the subject, I believe that the general concept of + hooking data is good, but I do not like the way you implement it. It + has to be easy to migrate to B.MI to anticipate the case in that Boost.Bimap + becomes insufficient. It is more natural for a B.MI user that the data + is accessed without the indirection of .data. I do not know how this can be + articulated in your framework. +

+

+

+
+

+ Matias +

+
+

+

+

+ I have a technical problem to implement the data_hook in this + way. If the standard would let us use the mutant idiom directly, I can + implement it using multiple inheritance. But as we must use const_reference_pair + too, It becomes impossible for me to support it. We have three options + here: +

+

+

+
+
+

+

+

+ 1) relation { left, right, data } and pair_view { first, second, + data } +

+

+

+
+
+

+

+

+ - This is more intuitive within the bimap framework, since + it does not mix the data with the index, as a table in a data base does, + but gives more importance to the index. +

+

+

+
+
+

+

+

+ - It is not necessary that the user puts the mutable keyword + in each member of the data class. +

+

+

+
+
+

+

+

+ - This moves away just a little bit from B.MI because the + model of it is similar to a table, but it continues to exist a clear + path of migration. +

+

+

+
+
+

+

+

+ 2) relation { left,right, d1,d2... dn } and pair_view { first, + second, data } +

+

+

+
+
+

+

+

+ - The path to B.MI is the one you have proposed. +

+

+

+
+
+

+

+

+ - It is very asymmetric. It is necessary to explain that the + views are handled different that the relation. +

+

+

+
+
+

+

+

+ - The user must place the mutable keyboards in the data class. + +

+

+

+
+
+

+

+

+ 3) Only relation { left,right, d1,d2... dn } +

+

+

+
+
+

+

+

+ - Simple migration path to B.MI. +

+

+

+
+
+

+

+

+ - You are not able to access the hooked data from the views. + +

+

+

+
+
+

+

+

+ My vote goes to the first proposal. +

+

+

+
+

+ Joaquin +

+
+

+

+

+ Yes, the first option is the one that less surprises hold + to the user. I also vote for 1. +

+

+

+
+

+ - The third week was over - +

+

+ Matias +

+
+

+

+

+ There is still one problem that I have to solve. I need to + know if it is necessary to create a map_view associated to nothing. If + it is necessary there are two options: that it behaves as an empty container + or that it throws an exception or assert when trying to use it. If it + is not necessary, the map_view is going to keep a reference instead of + a pointer. To me, the map_view always must be viewing something. In the + case of the iterators being able to create them empty, makes them easy + to use in contexts that require constructors by default, like being the + value_type of a container, but I do not believe that this is the case + of map_view. +

+

+

+
+

+ Joaquin +

+
+

+

+

+ How would an empty map_view be useful? My intuition is like + yours, map_view would have to be always associate to something. If we + wished to obtain the semantics "is associated or not" we can + use a pointer to a map_view. +

+

+

+
+

+ Matias +

+
+

+

+

+ OK, then you agree to that map_views stores a reference instead + of a pointer? +

+

+

+
+

+ Joaquin +

+
+

+

+

+ It depends on the semantics you want to give to map_views, + and in concrete to the copy of map_views. +

+

+

+
+

+ +

+
+map_view x=...;
+map_view y=...;
+x=y;
+
+

+

+
+

+

+

+ What is supposed to do this last line? +

+

+

+
+
+

+

+

+ 1. Rebinding of x, that is to say, x points at the same container + that y. +

+

+

+
+
+

+

+

+ 2. Copy of the underlying container. +

+

+

+
+
+

+

+

+ If you want to implement 1, you cannot use references internally. + If you want to implement 2, it is almost the same to use a reference + or a pointer. +

+

+

+
+

+ Matias +

+
+

+

+

+ If I want that they behave exactly as std::maps then I must + go for 2. But if I think they as "views" of something, I like + 1. The question is complicated. I add another option: +

+

+

+
+
+

+

+

+ 3. Error: operator= is declare as private in boost::bimap::map_view + std_container +

+

+

+
+
+

+

+

+ Also What happens with std_container + = view;? and with view + = std_container;? +

+

+

+
+
+ + + +
Copyright © 2006 -2007 Matias Capeletto
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_bimap/reference.html b/doc/html/boost_bimap/reference.html new file mode 100644 index 0000000..9626a31 --- /dev/null +++ b/doc/html/boost_bimap/reference.html @@ -0,0 +1,179 @@ + + + +Reference + + + + + + + + + + + + + + + +
+Boost C++ LibrariesChapter Logo +HomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ The following are the interface headers of Boost.Bimap: +

+

+ Convenience +

+
  • + "boost/bimap.hpp" (includes "boost/bimap/bimap.hpp" + and imports the bimap class to boost namespace) +
+

+ Container +

+
  • + "boost/bimap/bimap.hpp" (includes "boost/bimap/set_of.hpp" + and "boost/bimap/unconstrained_set_of.hpp") +
+

+ Set Types +

+
    +
  • + "boost/bimap/set_of.hpp" +
  • +
  • + "boost/bimap/multiset_of.hpp" +
  • +
  • + "boost/bimap/unordered_set_of.hpp" +
  • +
  • + "boost/bimap/unordered_multiset_of.hpp" +
  • +
  • + "boost/bimap/list_of.hpp" +
  • +
  • + "boost/bimap/vector_of.hpp" +
  • +
  • + "boost/bimap/unconstrained_set_of.hpp" +
  • +
+

+ Boost Integration +

+
    +
  • + "boost/bimap/support/lambda.hpp" +
  • +
  • + "boost/bimap/property_map/set_support.hpp" +
  • +
  • + "boost/bimap/property_map/unordered_set_support.hpp" +
  • +
+

+ A program using Boost.Bimap must therefore include "boost/bimap/bimap.hpp" + and the headers defining the collection types to be used. +

+

+ Additional headers allow the integration of Boost.Bimap with other boost + libraries, like Boost.Lambda and Boost.Property_map. +

+

+ In order to use the serialization capabilities of Boost.Bimap, the appropriate + Boost.Serialization library module must be linked. Other than that, Boost.Bimap + is a header-only library, requiring no additional object modules. +

+
+
+ + + +
Copyright © 2006 -2007 Matias Capeletto
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_bimap/reference/bimap_reference.html b/doc/html/boost_bimap/reference/bimap_reference.html new file mode 100644 index 0000000..72a2382 --- /dev/null +++ b/doc/html/boost_bimap/reference/bimap_reference.html @@ -0,0 +1,990 @@ + + + +Bimap Reference + + + + + + + + + + + + + + + +
+Boost C++ LibrariesChapter Logo +HomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ bimap instantiations comprise + two side views and an view of the relation specified at compile time. Each + view allows read-write access to the elements contained in a definite manner, + mathing an STL container signature. +

+

+ Views are not isolated objects and so cannot be constructed on their own; + rather they are an integral part of a bimap. + The name of the view class implementation proper is never directly exposed + to the user, who has access only to the associated view type specifier. +

+

+ Insertion and deletion of elements are always performed through the appropriate + interface of any of the three views of the bimap; + these operations do, however, have an impact on all other views as well: + for instance, insertion through a given view may fail because there exists + another view that forbids the operation in order to preserve its invariant + (such as uniqueness of elements). The global operations performed jointly + in the any view can be reduced to six primitives: +

+
    +
  • + copying +
  • +
  • + insertion of an element +
  • +
  • + hinted insertion, where a pre-existing element is suggested in order + to improve the efficiency of the operation +
  • +
  • + deletion of an element +
  • +
  • + replacement of the value of an element, which may trigger the rearrangement + of this element in one or more views, or may forbid the replacement +
  • +
  • + modification of an element, and its subsequent rearrangement/banning + by the various views +
  • +
+

+ The last two primitives deserve some further explanation: in order to guarantee + the invariants associated to each view (e.g. some definite ordering) elements + of a bimap are not mutable. + To overcome this restriction, the views expose member functions for updating + and modifying, which allows for the mutation of elements in a controlled + fashion. +

+
+

+

+
+ +

+ Some member functions of a view interface are implemented by global primitives + from the above list. The complexity of these operations thus depends on + all views of a given bimap, + not just the currently used view. +

+

+ In order to establish complexity estimates, a view is characterised by + its complexity signature, consisting of the following associated functions + on the number of elements: +

+
    +
  • +c(n): + copying +
  • +
  • +i(n): + insertion +
  • +
  • +h(n): + hinted insertion +
  • +
  • +d(n): + deletion +
  • +
  • +r(n): + replacement +
  • +
  • +m(n): + modifying +
  • +
+

+ If the collection type of the relation is left_based + or right_based, and we + use an l subscript to denote + the left view and an r + for the right view, then the insertion of an element in such a container + is of complexity O(i_l(n)+i_r(n)), + where n is the number of elements. If the collection type of relation is + not side-based, then there is an additional term to add that is contributed + by the collection type of relation view. Using a + to denote the above view, the complexity of insertion will now be O(i_l(n)+i_r(n)+i_a(n)). + To abbreviate the notation, we adopt the following definitions: +

+
    +
  • C(n) = c_l(n) + c_r(n) [ + + c_a(n) ]
  • +
  • I(n) = i_l(n) + i_r(n) [ + + i_a(n) ]
  • +
  • H(n) = h_l(n) + h_r(n) [ + + h_a(n) ]
  • +
  • D(n) = d_l(n) + d_r(n) [ + + d_a(n) ]
  • +
  • R(n) = r_l(n) + r_r(n) [ + + r_a(n) ]
  • +
  • M(n) = m_l(n) + m_r(n) [ + + m_a(n) ]
  • +
+
+
+ +

+ Set type specifiers are passed as instantiation arguments to bimap and provide the information needed + to incorporate the corresponding views. Currently, Boost.Bimap provides + the collection type specifiers. The side collection type + specifiers define the constraints of the two map views of the bimap. The + collection type of relation specifier defines the + main set view constraints. If left_based + (the default parameter) or right_based + is used, then the collection type of relation will be based on the left + or right collection type correspondingly. +

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Side collection type +

+
+

+ Collection type of relation +

+
+

+ Include +

+
+

+ set_of +

+
+

+ set_of_relation +

+
+

+ boost/bimap/set_of.hpp +

+
+

+ multiset_of +

+
+

+ multiset_of_relation +

+
+

+ boost/bimap/multiset_of.hpp +

+
+

+ unordered_set_of +

+
+

+ unordered_set_of_relation +

+
+

+ boost/bimap/unordered_set_of.hpp +

+
+

+ unordered_multiset_of +

+
+

+ unordered_multiset_of_relation +

+
+

+ boost/bimap/unordered_multiset_of.hpp +

+
+

+ list_of +

+
+

+ list_of_relation +

+
+

+ boost/bimap/list_of.hpp +

+
+

+ vector_of +

+
+

+ vector_of_relation +

+
+

+ boost/bimap/vector_of.hpp +

+
+

+ unconstrained_set_of +

+
+

+ unconstrained_set_of_relation +

+
+

+ boost/bimap/unconstrained_set_of.hpp +

+
+

+

+
+

+ left_based +

+
+

+ boost/bimap/bimap.hpp +

+
+

+

+
+

+ right_based +

+
+

+ boost/bimap/bimap.hpp +

+
+
+
+

+Tags +

+

+ Tags are just conventional types used as mnemonics for the types stored + in a bimap. Boost.Bimap + uses the tagged idiom to let the user specify this tags. +

+
+
+ +
+namespace boost {
+namespace bimaps {
+
+template< class Type, typename Tag >
+struct tagged;
+
+// bimap template class
+
+template
+<
+    class LeftCollectionType, class RightCollectionType,
+
+    class AdditionalParameter_1 = detail::not_specified,
+    class AdditionalParameter_2 = detail::not_specified
+>
+class bimap - implementation defined { : public SetView } -
+{
+    public:
+
+    // Metadata
+
+    typedef -unspecified- left_tag;
+    typedef -unspecified- left_map;
+
+    typedef -unspecified- right_tag;
+    typedef -unspecified- right_map;
+
+    // Shortcuts
+    // typedef -side-_map::-type- -side-_-type-;
+
+    typedef -unspecified- info_type;
+
+    // Map views
+
+     left_map  left;
+    right_map right;
+
+    // Constructors
+
+    bimap();
+
+    template< class InputIterator >
+    bimap(InputIterator first,InputIterator last);
+
+    bimap(const bimap &);
+
+    bimap& operator=(const bimap& b);
+
+    // Projection of iterators
+
+    template< class IteratorType >
+    left_iterator project_left(IteratorType iter);
+
+    template< class IteratorType >
+    left_const_iterator project_left(IteratorType iter) const;
+
+    template< class IteratorType >
+    right_iterator project_right(IteratorType iter);
+
+    template< class IteratorType >
+    right_const_iterator project_right(IteratorType iter) const;
+
+    template< class IteratorType >
+    iterator project_up(IteratorType iter);
+
+    template< class IteratorType >
+    const_iterator project_up(IteratorType iter) const;
+
+    // Support for tags
+
+    template< class Tag >
+    struct map_by;
+
+    template< class Tag >
+    map_by<Tag>::type by();
+
+    template< class Tag >
+    const map_by<Tag>::type & by() const;
+
+    template< class Tag, class IteratorType >
+    map_by<Tag>::iterator project(IteratorType iter);
+
+    template< class Tag, class IteratorType >
+    map_by<Tag>::const_iterator project(IteratorType iter) const
+
+};
+
+
+} // namespace bimap
+} // namespace boost
+
+
+
+ + +

+ This is the main component of Boost.Bimap. +

+
+ +

+ In the descriptions of the operations of bimap, + we adopt the scheme outlined in the complexity signature section. +

+
+
+ +

+ bimap is instantiated + with the following types: +

+
    +
  1. + LeftCollectionType and RightCollectionType are collection type specifications + optionally tagged, or any type optionally tagged, in which case that + side acts as a set. +
  2. +
  3. + AdditionalParameter_{1/2} can be any ordered subset of: +
      +
    • + CollectionTypeOfRelation specification +
    • +
    • + Allocator +
    • +
    +
  4. +
+
+
+ +
+left_tag, right_tag
+
+
+

+

+

+ Tags for each side of the bimap. If the user has not specified any + tag the tags default to member_at::left + and member_at::right. +

+

+

+
+
+left_key_type, right_key_type
+
+
+

+

+

+ Key type of each side. In a bimap<A,B> left_key_type + is A and right_key_type is B. If there are tags, it is better + to use: Bimap::map_by<Tag>::key_type. +

+

+

+
+
+left_data_type, right_data_type
+
+
+

+

+

+ Data type of each side. In a bimap<A,B> left_key_type is B + and right_key_type is A. If there are tags, it is better to use: + Bimap::map_by<Tag>::data_type. +

+

+

+
+
+left_value_type, right_value_type
+
+
+

+

+

+ Value type used for the views. If there are tags, it is better to + use: Bimap::map_by<Tag>::value_type. +

+

+

+
+
+left_iterator, right_iterator
+left_const_iterator, right_const_iterator
+
+
+

+

+

+ Iterators of the views. If there are tags, it is better to use: + Bimap::map_by<Tag>::iterator and Bimap::map_by<Tag>::const_iterator +

+

+

+
+
+left_map, right_map
+
+
+

+

+

+ Map view type of each side. If there are tags, it is better to use: + Bimap::map_by<Tag>::type. +

+

+

+
+
+
+ +
+bimap();
+
+
    +
  • +Effects: Constructs an empty bimap. +
  • +
  • +Complexity: Constant. +
  • +
+
+template<typename InputIterator>
+bimap(InputIterator first,InputIterator last);
+
+
    +
  • +Requires: InputIterator + is a model of Input Iterator over elements of type relation + or a type convertible to relation. + last is reachable from first. +
  • +
  • +Effects: Constructs an empty bimap and fills it with the elements + in the range [first,last). Insertion of each element may or + may not succeed depending on acceptance by the collection types of + the bimap. +
  • +
  • +Complexity: + O(m*H(m)), where m is the number of elements in [first,last). +
  • +
+
+bimap(const bimap & x);
+
+
    +
  • +Effects: Constructs a copy of x, copying + its elements as well as its internal objects (key extractors, comparison + objects, allocator.) +
  • +
  • +Postconditions:*this == x. The order of the views of the + bimap is preserved + as well. +
  • +
  • +Complexity: O(x.size()*log(x.size()) + + C(x.size())) +
  • +
+
+~bimap()
+
+
    +
  • +Effects: Destroys the bimap and all the elements contained. + The order in which the elements are destroyed is not specified. +
  • +
  • +Complexity: O(n). +
  • +
+
+bimap& operator=(const bimap& x);
+
+
    +
  • +Effects: Replaces the elements and + internal objects of the bimap + with copies from x. +
  • +
  • +Postconditions:*this==x. The order on the views of the + bimap is preserved + as well. +
  • +
  • +Returns: *this. +
  • +
  • +Complexity: O(n + x.size()*log(x.size()) + + C(x.size())). +
  • +
  • +Exception safety: Strong, provided + the copy and assignment operations of the types of ctor_args_list + do not throw. +
  • +
+
+

+

+
+ +

+ Given a bimap with views + v1 and v2, we say than an v1-iterator it1 and an v2-iterator it2 are + equivalent if: +

+
    +
  • +it1 == + i1.end() + AND it2 == + i2.end(), +
  • +
  • + OR it1 and it2 point to the same element. +
  • +
+
+template< class IteratorType >
+left_iterator project_left(IteratorType iter);
+
+template< class IteratorType >
+left_const_iterator project_left(IteratorType iter) const;
+
+
    +
  • +Requires:IteratorType + is a bimap view iterator. it is a valid iterator of some view of *this + (i.e. does not refer to some other bimap.) +
  • +
  • +Effects: Returns a left map view iterator + equivalent to it. +
  • +
  • +Complexity: Constant. +
  • +
  • +Exception safety: nothrow. +
  • +
+
+template< class IteratorType >
+right_iterator project_right(IteratorType iter);
+
+template< class IteratorType >
+right_const_iterator project_right(IteratorType iter) const;
+
+
    +
  • +Requires:IteratorType + is a bimap view iterator. it is a valid iterator of some view of *this + (i.e. does not refer to some other bimap.) +
  • +
  • +Effects: Returns a right map view + iterator equivalent to it. +
  • +
  • +Complexity: Constant. +
  • +
  • +Exception safety: nothrow. +
  • +
+
+template< class IteratorType >
+iterator project_up(IteratorType iter);
+
+template< class IteratorType >
+const_iterator project_up(IteratorType iter) const;
+
+
    +
  • +Requires:IteratorType + is a bimap view iterator. it is a valid iterator of some view of *this + (i.e. does not refer to some other bimap.) +
  • +
  • +Effects: Returns a collection of relations + view iterator equivalent to it. +
  • +
  • +Complexity: Constant. +
  • +
  • +Exception safety: nothrow. +
  • +
+
+

+

+
+ +
+template< class Tag >
+struct map_by;
+
+
    +
  • +map_by<Tag>::type yields the type of the map view + tagged with Tag. map_by<Tag>::-type + name- is the same as map_by<Tag>::type::-type name-. +
  • +
  • +Requires: Tag + is a valid user defined name of the bimap. +
  • +
+
+template< class Tag >
+map_by<Tag>::type by();
+
+template< class Tag >
+const map_by<Tag>::type & by() const;
+
+
    +
  • +Requires: Tag + is a valid user defined name of the bimap. +
  • +
  • +Effects: Returns a reference to the + map view tagged with Tag + held by *this. +
  • +
  • +Complexity: Constant. +
  • +
  • +Exception safety: nothrow. +
  • +
+
+template< class Tag, class IteratorType >
+map_by<Tag>::iterator project(IteratorType iter);
+
+template< class Tag, class IteratorType >
+map_by<Tag>::const_iterator project(IteratorType iter) const
+
+
    +
  • +Requires: Tag + is a valid user defined name of the bimap. IteratorType + is a bimap view iterator. it is a valid iterator of some view of *this + (i.e. does not refer to some other bimap.) +
  • +
  • +Effects: Returns a reference to the + map view tagged with Tag + held by *this. +
  • +
  • +Complexity: Constant. +
  • +
  • +Exception safety: nothrow. +
  • +
+
+
+ +

+ A bimap can be archived + and retrieved by means of Boost.Serialization. Boost.Bimap does + not expose a public serialisation interface, as this is provided by Boost.Serialization + itself. Both regular and XML archives are supported. +

+

+ Each of the set specifications comprising a given bimap + contributes its own preconditions as well as guarantees on the retrieved + containers. In describing these, the following concepts are used. A type + T is serializable + (resp. XML-serializable) if any object of type T + can be saved to an output archive (XML archive) and later retrieved from + an input archive (XML archive) associated to the same storage. If x' of type T + is loaded from the serialization information saved from another object + x, we say that x' is a restored copy of x. Given + a Binary + Predicate Pred + over (T, T), and objects p + and q of type Pred, we say that q + is serialization-compatible with p + if +

+
  • +p(x,y) == q(x',y') +
+

+ for every x and y of type T + and x' and y' being restored copies of x and y, + respectively. +

+ +
    +
  • +Requires: Value is serializable (XML-serializable). + Additionally, each of the views of b can impose other requirements. +
  • +
  • +Exception safety: Strong with respect + to b. If an exception + is thrown, ar may be left in an inconsistent state. +
  • +
+ +
    +
  • +Requires: Value is serializable (XML-serializable). + Additionally, each of the views of b' + can impose other requirements. +
  • +
  • +Exception safety: Basic. If an exception + is thrown, ar may be left in an inconsistent state. +
  • +
+
+
+
+ + + +
Copyright © 2006 -2007 Matias Capeletto
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_bimap/reference/list_of_reference.html b/doc/html/boost_bimap/reference/list_of_reference.html new file mode 100644 index 0000000..7cf7458 --- /dev/null +++ b/doc/html/boost_bimap/reference/list_of_reference.html @@ -0,0 +1,1337 @@ + + + +list_of Reference + + + + + + + + + + + + + + + +
+Boost C++ LibrariesChapter Logo +HomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ + +
+ +
+namespace boost {
+namespace bimaps {
+
+
+template< class KeyType >
+struct list_of;
+
+struct list_of_relation;
+
+
+} // namespace bimap
+} // namespace boost
+
+
+
+ + +

+ A list_of set view is a std::list signature compatible interface to the + underlying heap of elements contained in a bimap. +

+

+ If you look the bimap by a side, you will use a map view and if you looked + it as a whole you will be using a set view. +

+

+ Elements in a list_of view are by default sorted according to their order + of insertion: this means that new elements inserted through a different + view of the bimap are appended + to the end of the list_of view. Additionally, the view allows for free + reordering of elements in the same vein as std::list + does. Validity of iterators and references to elements is preserved in + all operations. +

+

+ There are a number of differences with respect to std::lists: +

+
    +
  • + list_of views are not Assignable + (like any other view.) +
  • +
  • + Unlike as in std::list, insertions into a list_of view + may fail due to clashings with other views. This alters the semantics + of the operations provided with respect to their analogues in std::list. +
  • +
  • + Elements in a list_of view are not mutable, and can only be changed by + means of replace and + modify member functions. +
  • +
+

+ Having these restrictions into account, list_of views are models of Reversible Container, + Front + Insertion Sequence and Back + Insertion Sequence. We only provide descriptions of those types + and operations that are either not present in the concepts modeled or do + not exactly conform to the requirements for these types of containers. +

+
+namespace boost {
+namespace bimaps {
+namespace views {
+
+template< -implementation defined parameter list- >
+class -implementation defined view name-
+{
+    public:
+
+    // types
+
+    typedef -unspecified- value_type;
+    typedef -unspecified- allocator_type;
+    typedef -unspecified- reference;
+    typedef -unspecified- const_reference;
+    typedef -unspecified- iterator;
+    typedef -unspecified- const_iterator;
+    typedef -unspecified- size_type;
+    typedef -unspecified- difference_type;
+    typedef -unspecified- pointer;
+    typedef -unspecified- const_pointer;
+    typedef -unspecified- reverse_iterator;
+    typedef -unspecified- const_reverse_iterator;
+
+    typedef -unspecified- info_type;
+
+    // construct/copy/destroy
+
+    this_type & operator=(const this_type & x);
+
+    template< class InputIterator >
+    void assign(InputIterator first, InputIterator last);
+
+    void assign(size_type n, const value_type & value);
+
+    allocator_type get_allocator() const;
+
+    // iterators
+
+    iterator               begin();
+    const_iterator         begin() const;
+
+    iterator               end();
+    const_iterator         end() const;
+
+    reverse_iterator       rbegin();
+    const_reverse_iterator rbegin() const;
+
+    reverse_iterator       rend();
+    const_reverse_iterator rend() const;
+
+    // capacity
+
+    bool      empty() const;
+
+    size_type size() const;
+
+    size_type max_size() const;
+
+    void resize(size_type n, const value_type & x = value_type());
+
+    // access
+
+    const_reference front() const;
+    const_reference back() const;
+
+    // modifiers
+
+    std::pair<iterator,bool> push_front(const value_type & x);
+    void                     pop_front();
+
+    std::pair<iterator,bool> push_back(const value_type & x);
+    void                     pop_back();
+
+    std::pair<iterator,bool> insert(iterator position, const value_type & x);
+
+    void insert(iterator position, size_type n, const value_type & x);
+
+    template< class InputIterator >
+    void insert(iterator position, InputIterator first, InputIterator last);
+
+    iterator erase(iterator position);
+    iterator erase(iterator first, iterator last);
+
+    bool replace(iterator position, const value_type & x);
+
+    // Only in map views
+    // {
+
+      template< class CompatibleKey >
+      bool replace_key(iterator position, const CompatibleKey & x);
+
+      template< class CompatibleData >
+      bool replace_data(iterator position, const CompatibleData & x);
+
+      template< class KeyModifier >
+      bool modify_key(iterator position, KeyModifier mod);
+
+      template< class DataModifier >
+      bool modify_data(iterator position, DataModifier mod);
+
+    // }
+
+
+    void clear();
+
+    // list operations
+
+    void splice(iterator position, this_type & x);
+    void splice(iterator position, this_type & x, iterator i);
+    void splice(
+        iterator position, this_type & x, iterator first, iterator last);
+
+    void remove(const value_type & value);
+
+    template< class Predicate >
+    void remove_if(Predicate pred);
+
+    void unique();
+
+    template< class BinaryPredicate >
+    void unique(BinaryPredicate binary_pred);
+
+    void merge(this_type & x);
+
+    template< class Compare >
+    void merge(this_type & x,Compare comp);
+
+    void sort();
+
+    template< class Compare >
+    void sort(Compare comp);
+
+    void reverse();
+
+    // rearrange operations
+
+    void relocate(iterator position, iterator i);
+    void relocate(iterator position, iterator first, iterator last);
+
+}
+
+// view comparison
+
+bool operator==(const this_type & v1, const this_type & v2 );
+bool operator< (const this_type & v1, const this_type & v2 );
+bool operator!=(const this_type & v1, const this_type & v2 );
+bool operator> (const this_type & v1, const this_type & v2 );
+bool operator>=(const this_type & v1, const this_type & v2 );
+bool operator<=(const this_type & v1, const this_type & v2 );
+
+} // namespace views
+} // namespace bimap
+} // namespace boost
+
+

+ In the case of a bimap< list_of<Left>, ... > +

+

+ In the set view: +

+
+typedef signature-compatible with relation< Left, ... > key_type;
+typedef signature-compatible with relation< Left, ... > value_type;
+
+

+ In the left map view: +

+
+typedef  Left  key_type;
+typedef  ...   data_type;
+
+typedef signature-compatible with std::pair< Left, ... > value_type;
+
+

+ In the right map view: +

+
+typedef  ...  key_type;
+typedef  Left data_type;
+
+typedef signature-compatible with std::pair< ... , Left > value_type;
+
+

+

+
+ +

+ Here and in the descriptions of operations of list_of + views, we adopt the scheme outlined in the complexity + signature section. The complexity signature of a list_of view is: +

+
    +
  • + copying: c(n) = n * log(n), +
  • +
  • + insertion: i(n) = 1 (constant), +
  • +
  • + hinted insertion: h(n) = 1 (constant), +
  • +
  • + deletion: d(n) = 1 (constant), +
  • +
  • + replacement: r(n) = 1 (constant), +
  • +
  • + modifying: m(n) = 1 (constant). +
  • +
+
+
+ +

+ list_of views are instantiated + internally to bimap and + specified by means of the collection type specifiers and the bimap itself. + Instantiations are dependent on the following types: +

+
    +
  • +Value from list_of, +
  • +
  • +Allocator from bimap, +
  • +
+
+
+ +

+ As explained in the view concepts section, views do not have public constructors + or destructors. Assignment, on the other hand, is provided. +

+
+this_type & operator=(const this_type & x);
+
+
    +
  • +Effects: a + = b; where a and b are the bimap objects to which *this + and x belong, respectively. +
  • +
  • +Returns: *this. +
  • +
+

+

+
+template< class InputIterator >
+void assign(InputIterator first, InputIterator last);
+
+
    +
  • +Requires: InputIterator + is a model of Input + Iterator over elements of type value_type + or a type convertible to value_type. + first and last are not iterators into any views of the bimap to which this view belongs. + last is reachable from + first. +
  • +
  • +Effects: clear(); insert(end(),first,last); +
  • +
+

+

+
+void assign(size_type n, const value_type & value);
+
+
  • +Effects: clear(); for(size_type + i = + 0; + i < + n ; + ++n) push_back(v); +
+
+
+ +

+

+
+void resize(size_type n,const value_type& x=value_type()); 
+
+
    +
  • +Effects: if( n > size() ) insert(end(), + n - + size(), + x);else if( n < size() ) { iterator + it = + begin(); std::advance(it, n); erase(it, end());} +
  • +
  • +Note: If an expansion is requested, + the size of the view is not guaranteed to be n after this operation + (other views may ban insertions.) +
  • +
+
+
+ +

+

+
+std::pair<iterator,bool> push_front(const value_type& x);
+
+
    +
  • +Effects: Inserts x + at the beginning of the sequence if no other views of the bimap bans the insertion. +
  • +
  • +Returns: The return value is a pair + p. p.second + is true if and only if + insertion took place. On successful insertion, p.first + points to the element inserted; otherwise, p.first + points to an element that caused the insertion to be banned. Note that + more than one element can be causing insertion not to be allowed. +
  • +
  • +Complexity: + O(I(n)). +
  • +
  • +Exception safety: Strong. +
  • +
+

+

+
+std::pair<iterator,bool> push_back(const value_type & x);
+
+
    +
  • +Effects: Inserts x + at the end of the sequence if no other views of the bimap + bans the insertion. +
  • +
  • +Returns: The return value is a pair + p. p.second + is true if and only if + insertion took place. On successful insertion, p.first + points to the element inserted; otherwise, p.first + points to an element that caused the insertion to be banned. Note that + more than one element can be causing insertion not to be allowed. +
  • +
  • +Complexity: + O(I(n)). +
  • +
  • +Exception safety: Strong. +
  • +
+

+

+
+std::pair<iterator,bool> insert(iterator position, const value_type & x);
+
+
    +
  • +Requires: position + is a valid iterator + of the view. +
  • +
  • +Effects: Inserts x + before position if insertion is allowed by all other views of the + bimap. +
  • +
  • +Returns: The return value is a pair + p. p.second + is true if and only if + insertion took place. On successful insertion, p.first + points to the element inserted; otherwise, p.first + points to an element that caused the insertion to be banned. Note that + more than one element can be causing insertion not to be allowed. +
  • +
  • +Complexity: + O(I(n)). +
  • +
  • +Exception safety: Strong. +
  • +
+

+

+
+void insert(iterator position, size_type n, const value_type & x);
+
+
    +
  • +Requires: position + is a valid iterator + of the view. +
  • +
  • +Effects: for(size_type + i = + 0; + i < + n; + ++i) insert(position, x); +
  • +
+

+

+
+template< class InputIterator>
+void insert(iterator position,InputIterator first,InputIterator last);
+
+
    +
  • +Requires: position + is a valid iterator + of the view. InputIterator + is a model of Input + Iterator over elements of type value_type. + first and last are not iterators into any view + of the bimap to which + this view belongs. last + is reachable from first. +
  • +
  • +Effects: while(first + != last) insert(position, *first++); +
  • +
  • +Complexity: + O(m*I(n+m)), where m is the number of elements in [first,last). +
  • +
  • +Exception safety: Basic. +
  • +
+

+

+
+iterator erase(iterator position);
+
+
    +
  • +Requires: position + is a valid dereferenceable iterator + of the view. +
  • +
  • +Effects: Deletes the element pointed + to by position. +
  • +
  • +Returns: An iterator pointing to the + element immediately following the one that was deleted, or end() + if no such element exists. +
  • +
  • +Complexity: + O(D(n)). +
  • +
  • +Exception safety: nothrow. +
  • +
+

+

+
+iterator erase(iterator first, iterator last); 
+
+
    +
  • +Requires: [first,last) + is a valid range of the view. +
  • +
  • +Effects: Deletes the elements in + [first,last). +
  • +
  • +Returns: last. +
  • +
  • +Complexity: + O(m*D(n)), where m is the number of elements in [first,last). +
  • +
  • +Exception safety: nothrow. +
  • +
+

+

+
+bool replace(iterator position,const value_type& x);
+
+
    +
  • +Requires: position + is a valid dereferenceable iterator of the view. +
  • +
  • +Effects: Assigns the value x to the element pointed to by position into the bimap + to which the view belongs if replacing is allowed by all other views + of the bimap. +
  • +
  • +Postconditions: Validity of position is preserved in all cases. +
  • +
  • +Returns: true + if the replacement took place, false + otherwise. +
  • +
  • +Complexity: + O(R(n)). +
  • +
  • +Exception safety: Strong. If an exception + is thrown by some user-provided operation the bimap + to which the view belongs remains in its original state. +
  • +
+

+

+
+template< class CompatibleKey >
+bool replace_key(iterator position, const CompatibleKey & x);
+
+
    +
  • +Requires: position + is a valid dereferenceable iterator of the set view. CompatibleKey can be assigned to + key_type. +
  • +
  • +Effects: Assigns the value x to e.first, + where e is the element + pointed to by position + into the bimap to which + the set view belongs if replacing is allowed by all other views of + the bimap. +
  • +
  • +Postconditions: Validity of position + is preserved in all cases. +
  • +
  • +Returns: true + if the replacement took place, false + otherwise. +
  • +
  • +Complexity: + O(R(n)). +
  • +
  • +Exception safety: Strong. If an exception + is thrown by some user-provided operation, the bimap + to which the set view belongs remains in its original state. +
  • +
+

+

+
+template< class CompatibleData >
+bool replace_data(iterator position, const CompatibleData & x);
+
+
    +
  • +Requires: position + is a valid dereferenceable iterator of the set view. CompatibleKey can be assigned to + data_type. +
  • +
  • +Effects: Assigns the value x to e.second, + where e is the element + pointed to by position + into the bimap to which + the set view belongs if replacing is allowed by all other views of + the bimap. +
  • +
  • +Postconditions: Validity of position + is preserved in all cases. +
  • +
  • +Returns: true + if the replacement took place, false + otherwise. +
  • +
  • +Complexity: + O(R(n)). +
  • +
  • +Exception safety: Strong. If an exception + is thrown by some user-provided operation, the bimap + to which the set view belongs remains in its original state. +
  • +
+

+

+
+template< class KeyModifier >
+bool modify_key(iterator position, KeyModifier mod);
+
+
    +
  • +Requires: KeyModifier + is a model of Unary + Function accepting arguments of type: key_type&; position + is a valid dereferenceable iterator of the view. +
  • +
  • +Effects: Calls mod(e.first) where e is the element pointed to + by position and rearranges *position into all the views of the + bimap. If the rearrangement + fails, the element is erased. It is successful if the rearrangement + is allowed by all other views of the bimap. +
  • +
  • +Postconditions: Validity of position is preserved if the operation + succeeds. +
  • +
  • +Returns: true + if the operation succeeded, false + otherwise. +
  • +
  • +Complexity: + O(M(n)). +
  • +
  • +Exception safety: Basic. If an exception + is thrown by some user-provided operation (except possibly mod), then + the element pointed to by position is erased. +
  • +
  • +Note: Only provided for map views. +
  • +
+

+

+
+template< class DataModifier >
+bool modify_data(iterator position, DataModifier mod);
+
+
    +
  • +Requires: DataModifier + is a model of Unary + Function accepting arguments of type: data_type&; position + is a valid dereferenceable iterator of the view. +
  • +
  • +Effects: Calls mod(e.second) where e is the element pointed to + by position and rearranges *position into all the views of the + bimap. If the rearrangement + fails, the element is erased. It is successful if the rearrangement + is allowed by all other views of the bimap. +
  • +
  • +Postconditions: Validity of position is preserved if the operation + succeeds. +
  • +
  • +Returns: true + if the operation succeeded, false + otherwise. +
  • +
  • +Complexity: + O(M(n)). +
  • +
  • +Exception safety: Basic. If an exception + is thrown by some user-provided operation (except possibly mod), then + the element pointed to by position is erased. +
  • +
  • +Note: Only provided for map views. +
  • +
+
+
+ +

+ list_of views provide + the full set of list operations found in std::list; + the semantics of these member functions, however, differ from that of + std::list in some cases as insertions might + not succeed due to banning by other views. Similarly, the complexity + of the operations may depend on the other views belonging to the same + bimap. +

+

+

+
+void splice(iterator position, this_type & x);
+
+
    +
  • +Requires: position + is a valid iterator of the view. &x!=this. +
  • +
  • +Effects: Inserts the contents of + x before position, + in the same order as they were in x. + Those elements successfully inserted are erased from x. +
  • +
  • +Complexity: + O(x.size()*I(n+x.size()) + + x.size()*D(x.size())). +
  • +
  • +Exception safety: Basic. +
  • +
+

+

+
+void splice(iterator position, this_type & x,iterator i);
+
+
    +
  • +Requires: position + is a valid iterator of the view. i + is a valid dereferenceable iterator x. +
  • +
  • +Effects: Inserts the element pointed + to by i before position: + if insertion is successful, the element is erased from x. In the special case &x==this, + no copy or deletion is performed, and the operation is always successful. + If position==i, no operation is performed. +
  • +
  • +Postconditions: If &x==this, no iterator or reference is invalidated. +
  • +
  • +Complexity: + If &x==this, + constant; otherwise O(I(n) + D(n)). +
  • +
  • +Exception safety: If &x==this, + nothrow; otherwise, strong. +
  • +
+

+

+
+void splice(iterator position, this_type & x, iterator first, iterator last);
+
+
    +
  • +Requires: position + is a valid iterator of the view. first + and last are valid + iterators of x. last + is reachable from first. + position is not in the range [first,last). +
  • +
  • +Effects: For each element in the range + [first,last), insertion is tried before position; + if the operation is successful, the element is erased from x. In the + special case &x==this, + no copy or deletion is performed, and insertions are always successful. +
  • +
  • +Postconditions: If &x==this, no iterator or reference is invalidated. +
  • +
  • +Complexity: + If &x==this, + constant; otherwise O(m*I(n+m) + m*D(x.size())) where m is the number + of elements in [first,last). +
  • +
  • +Exception safety: If &x==this, + nothrow; otherwise, basic. +
  • +
+

+

+
+void remove(const value_type & value);
+
+
    +
  • +Effects: Erases all elements of the + view which compare equal to value. +
  • +
  • +Complexity: + O(n + m*D(n)), where m is the number of elements erased. +
  • +
  • +Exception safety: Basic. +
  • +
+

+

+
+template< class Predicate >
+void remove_if(Predicate pred);
+
+
    +
  • +Effects: Erases all elements x of the view for which pred(x) + holds. +
  • +
  • +Complexity: + O(n + m*D(n)), where m is the number of elements erased. +
  • +
  • +Exception safety: Basic. +
  • +
+

+

+
+void unique();
+
+
    +
  • +Effects: Eliminates all but the first + element from every consecutive group of equal elements referred to + by the iterator i in + the range [first+1,last) + for which *i==*(i-1). +
  • +
  • +Complexity: + O(n + m*D(n)), where m is the number of elements erased. +
  • +
  • +Exception safety: Basic. +
  • +
+

+

+
+template< class BinaryPredicate >
+void unique(BinaryPredicate binary_pred);
+
+
    +
  • +Effects: Eliminates all but the first + element from every consecutive group of elements referred to by the + iterator i in the range [first+1,last) for which binary_pred(*i,*(i-1)) + holds. +
  • +
  • +Complexity: + O(n + m*D(n)), where m is the number of elements erased. +
  • +
  • +Exception safety: Basic. +
  • +
+

+

+
+void merge(this_type & x);
+
+
    +
  • +Requires: std::less<value_type> is a Strict + Weak Ordering over value_type. + Both the view and x + are sorted according to std::less<value_type>. +
  • +
  • +Effects: Attempts to insert every + element of x into the + corresponding position of the view (according to the order). Elements + successfully inserted are erased from x. + The resulting sequence is stable, i.e. equivalent elements of either + container preserve their relative position. In the special case &x==this, + no operation is performed. +
  • +
  • +Postconditions: Elements in the view + and remaining elements in x + are sorted. Validity of iterators to the view and of non-erased elements + of x references is + preserved. +
  • +
  • +Complexity: + If &x==this, + constant; otherwise O(n + x.size()*I(n+x.size()) + x.size()*D(x.size())). +
  • +
  • +Exception safety: If &x==this, + nothrow; otherwise, basic. +
  • +
+

+

+
+template< class Compare >
+void merge(this_type & x, Compare comp);
+
+
    +
  • +Requires: Compare is a Strict + Weak Ordering over value_type. + Both the view and x + are sorted according to comp. +
  • +
  • +Effects: Attempts to insert every + element of x into the + corresponding position of the view (according to comp). + Elements successfully inserted are erased from x. + The resulting sequence is stable, i.e. equivalent elements of either + container preserve their relative position. In the special case &x==this, + no operation is performed. +
  • +
  • +Postconditions: Elements in the view + and remaining elements in x + are sorted according to comp. + Validity of iterators to the view and of non-erased elements of x references is preserved. +
  • +
  • +Complexity: + If &x==this, + constant; otherwise O(n + x.size()*I(n+x.size()) + x.size()*D(x.size())). +
  • +
  • +Exception safety: If &x==this, + nothrow; otherwise, basic. +
  • +
+

+

+
+void sort();
+
+
    +
  • +Requires: std::less<value_type> is a Strict + Weak Ordering over value_type. +
  • +
  • +Effects: Sorts the view according + to std::less<value_type>. + The sorting is stable, i.e. equivalent elements preserve their relative + position. +
  • +
  • +Postconditions: Validity of iterators + and references is preserved. +
  • +
  • +Complexity: O(n*log(n)). +
  • +
  • +Exception safety: nothrow if std::less<value_type> + does not throw; otherwise, basic. +
  • +
+

+

+
+template< typename Compare >
+void sort(Compare comp);
+
+
    +
  • +Requires: Compare is a Strict + Weak Ordering over value_type. +
  • +
  • +Effects: Sorts the view according + to comp. The sorting is stable, i.e. equivalent elements preserve their + relative position. +
  • +
  • +Postconditions: Validity of iterators + and references is preserved. +
  • +
  • +Complexity: O(n*log(n)). +
  • +
  • +Exception safety: nothrow if comp + does not throw; otherwise, basic. +
  • +
+

+

+
+void reverse();
+
+
    +
  • +Effects: Reverses the order of the + elements in the view. +
  • +
  • +Postconditions: Validity of iterators + and references is preserved. +
  • +
  • +Complexity: O(n). +
  • +
  • +Exception safety: nothrow. +
  • +
+
+
+ +

+ These operations, without counterpart in std::list + (although splice provides partially overlapping functionality), perform + individual and global repositioning of elements inside the index. +

+

+

+
+void relocate(iterator position, iterator i);
+
+
    +
  • +Requires: position + is a valid iterator of the view. i + is a valid dereferenceable iterator of the view. +
  • +
  • +Effects: Inserts the element pointed + to by i before position. If position==i, + no operation is performed. +
  • +
  • +Postconditions: No iterator or reference + is invalidated. +
  • +
  • +Complexity: Constant. +
  • +
  • +Exception safety: nothrow. +
  • +
+

+

+
+void relocate(iterator position, iterator first, iterator last);
+
+
    +
  • +Requires: position + is a valid iterator of the view. first + and last are valid + iterators of the view. last + is reachable from first. + position is not in + the range [first,last). +
  • +
  • +Effects: The range of elements [first,last) is repositioned just before position. +
  • +
  • +Postconditions: No iterator or reference + is invalidated. +
  • +
  • +Complexity: Constant. +
  • +
  • +Exception safety: nothrow. +
  • +
+
+
+ +

+ Views cannot be serialized on their own, but only as part of the bimap into which they are embedded. + In describing the additional preconditions and guarantees associated + to list_of views with + respect to serialization of their embedding containers, we use the concepts + defined in the bimap + serialization section. +

+ +
  • +Requires: No additional requirements + to those imposed by the container. +
+ +
  • +Requires: No additional requirements + to those imposed by the container. Postconditions: + On successful loading, each of the elements of [begin(), + end()) + is a restored copy of the corresponding element in [m.get<i>().begin(), + m.get<i>().end()), + where i is the position + of the list_of view + in the container. +
+ +
  • +Requires: it + is a valid iterator of the view. The associated bimap + has been previously saved. +
+ +
    +
  • +Postconditions: On successful loading, + if it was dereferenceable then *it' is the restored copy of *it, + otherwise it' + == end(). +
  • +
  • +Note: It is allowed that it be a const_iterator + and the restored it' + an iterator, or viceversa. +
  • +
+
+
+
+ + + +
Copyright © 2006 -2007 Matias Capeletto
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_bimap/reference/set_of_reference.html b/doc/html/boost_bimap/reference/set_of_reference.html new file mode 100644 index 0000000..fa411e7 --- /dev/null +++ b/doc/html/boost_bimap/reference/set_of_reference.html @@ -0,0 +1,1333 @@ + + + +set_of Reference + + + + + + + + + + + + + + + +
+Boost C++ LibrariesChapter Logo +HomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ + +
+ +
+namespace boost {
+namespace bimaps {
+
+
+template
+<
+    class KeyType,
+    class KeyCompare = std::less< KeyType >
+>
+struct set_of;
+
+
+template
+<
+    class KeyCompare = std::less< _relation >
+>
+struct set_of_relation;
+
+
+} // namespace bimap
+} // namespace boost
+
+
+
+ +
+namespace boost {
+namespace bimaps {
+
+
+template
+<
+    class KeyType,
+    class KeyCompare = std::less< KeyType >
+>
+struct multiset_of;
+
+
+template
+<
+    class KeyCompare = std::less< _relation >
+>
+struct multiset_of_relation;
+
+
+} // namespace bimap
+} // namespace boost
+
+
+
+ +

+ These collection type specifiers allow for insertion of sets disallowing + or allowing duplicate elements, respectively. The syntaxes of set_of and multiset_of + coincide, so they are described together. +

+
+
+ + +

+ A [multi]set_of set view is a std::[multi]set signature-compatible interface + to the underlying heap of elements contained in a bimap. +

+

+ There are two variants: set_of, which does not allow duplicate elements + (with respect to its associated comparison predicate) and multiset_of, + which does accept those duplicates. The interface of these two variants + is largely the same, so they are documented together with their differences + explicitly noted where they exist. +

+

+ If you look the bimap from a side, you will use a map view, and if you + look at it as a whole, you will be using a set view. +

+
+namespace boost {
+namespace bimaps {
+namespace views {
+
+template< -implementation defined parameter list- >
+class -implementation defined view name-
+{
+    public:
+
+    typedef -unspecified- key_type;
+    typedef -unspecified- value_type;
+    typedef -unspecified- key_compare;
+    typedef -unspecified- value_compare;
+    typedef -unspecified- allocator_type;
+    typedef -unspecified- reference;
+    typedef -unspecified- const_reference;
+    typedef -unspecified- iterator;
+    typedef -unspecified- const_iterator;
+    typedef -unspecified- size_type;
+    typedef -unspecified- difference_type;
+    typedef -unspecified- pointer;
+    typedef -unspecified- const_pointer;
+    typedef -unspecified- reverse_iterator;
+    typedef -unspecified- const_reverse_iterator;
+
+    typedef -unspecified- info_type;
+
+    this_type & operator=(const this_type & x);
+
+    allocator_type get_allocator() const;
+
+    // iterators
+
+    iterator               begin();
+    const_iterator         begin() const;
+
+    iterator               end();
+    const_iterator         end() const;
+
+    reverse_iterator       rbegin();
+    const_reverse_iterator rbegin() const;
+
+    reverse_iterator       rend();
+    const_reverse_iterator rend() const;
+
+    // capacity
+
+    bool      empty() const;
+
+    size_type size() const;
+
+    size_type max_size() const;
+
+    // modifiers
+
+    std::pair<iterator,bool> insert(const value_type & x);
+
+    iterator insert(iterator position, const value_type & x);
+
+    template< class InputIterator>
+    void insert(InputIterator first,  InputIterator last);
+
+    iterator erase(iterator position);
+
+    template< class CompatibleKey >
+    size_type erase(const CompatibleKey & x);
+
+    iterator erase(iterator first,  iterator last);
+
+    bool replace(iterator position, const value_type& x);
+
+    // Only in map views
+    // {
+
+      template< class CompatibleKey >
+      bool replace_key(iterator position, const CompatibleKey & x);
+
+      template< class CompatibleData >
+      bool replace_data(iterator position, const CompatibleData & x);
+
+      template< class KeyModifier >
+      bool modify_key(iterator position, KeyModifier mod);
+
+      template< class DataModifier >
+      bool modify_data(iterator position, DataModifier mod);
+
+    // }
+
+    void swap(this_type & x);
+
+    void clear();
+
+    // observers
+
+    key_compare    key_comp() const;
+
+    value_compare  value_comp() const;
+
+    // set operations
+
+    template< class CompatibleKey >
+    iterator find(const CompatibleKey & x);
+
+    template< class CompatibleKey >
+    const_iterator find(const CompatibleKey & x) const;
+
+
+    template< class CompatibleKey >
+    size_type count(const CompatibleKey & x) const;
+
+
+    template< class CompatibleKey >
+    iterator lower_bound(const CompatibleKey & x);
+
+    template< class CompatibleKey >
+    const_iterator lower_bound(const CompatibleKey & x) const;
+
+
+    template< class CompatibleKey >
+    iterator upper_bound(const CompatibleKey & x);
+
+    template< class CompatibleKey >
+    const_iterator upper_bound(const CompatibleKey & x) const;
+
+
+    template< class CompatibleKey >
+    std::pair<iterator,iterator>
+        equal_range(const CompatibleKey & x);
+
+    template< class CompatibleKey >
+    std::pair<const_iterator,const_iterator>
+        equal_range(const CompatibleKey & x) const;
+
+    // Only in maps views
+    // {
+
+    template< class LowerBounder, class UpperBounder>
+    std::pair<iterator,iterator> range(
+        LowerBounder lower, UpperBounder upper);
+
+    template< class LowerBounder, class UpperBounder>
+    std::pair<const_iterator,const_iterator> range(
+        LowerBounder lower, UpperBounder upper) const;
+
+    typedef -unspecified- data_type;
+
+      // Only in for `set_of` collection type
+      // {
+
+      template< class CompatibleKey >
+      const data_type & at(const CompatibleKey & k) const;
+
+        // Only if the other collection type is mutable
+        // {
+
+        template< class CompatibleKey >
+        data_type & operator[](const CompatibleKey & k);
+
+        template< class CompatibleKey >
+        data_type & at(const CompatibleKey & k);
+
+        // }
+
+        // Only if info_hook is used
+        // {
+
+        template< class CompatibleKey >
+        info_type & info_at(const CompatibleKey & k);
+
+        template< class CompatibleKey >
+        const info_type & info_at(const CompatibleKey & k) const;
+
+        // }
+
+      // }
+
+    // }
+};
+
+// view comparison
+
+bool operator==(const this_type & v1, const this_type & v2 );
+bool operator< (const this_type & v1, const this_type & v2 );
+bool operator!=(const this_type & v1, const this_type & v2 );
+bool operator> (const this_type & v1, const this_type & v2 );
+bool operator>=(const this_type & v1, const this_type & v2 );
+bool operator<=(const this_type & v1, const this_type & v2 );
+
+} // namespace views
+} // namespace bimap
+} // namespace boost
+
+

+ In the case of a bimap< {multi}set_of<Left>, ... > +

+

+ In the set view: +

+
+typedef signature-compatible with relation<       Left, ... > key_type;
+typedef signature-compatible with relation< const Left, ... > value_type;
+
+

+ In the left map view: +

+
+typedef  Left  key_type;
+typedef  ...   data_type;
+
+typedef signature-compatible with std::pair< const Left, ... > value_type;
+
+

+ In the right map view: +

+
+typedef  ...  key_type;
+typedef  Left data_type;
+
+typedef signature-compatible with std::pair< ... ,const Left > value_type;
+
+

+

+
+ +

+ Here and in the descriptions of operations of this view, we adopt the + scheme outlined in the complexity + signature section. The complexity signature of [multi]set_of view + is: +

+
    +
  • + copying: c(n) = n * log(n), +
  • +
  • + insertion: i(n) = log(n), +
  • +
  • + hinted insertion: h(n) = 1 (constant) if the hint element precedes + the point of insertion, h(n) = log(n) + otherwise, +
  • +
  • + deletion: d(n) = 1 (amortized + constant), +
  • +
  • + replacement: r(n) = 1 (constant) + if the element position does not change, r(n) = log(n) + otherwise, +
  • +
  • + modifying: m(n) = 1 (constant) + if the element position does not change, m(n) = log(n) + otherwise. +
  • +
+
+
+ +

+ Set views are instantiated internally to a bimap. + Instantiations are dependent on the following types: +

+
    +
  • +Value from the set + specifier, +
  • +
  • +Allocator from bimap, +
  • +
  • +Compare from the set + specifier. +
  • +
+

+ Compare is a Strict + Weak Ordering on elements of Value. +

+
+
+ +

+ Set views do not have public constructors or destructors. Assignment, + on the other hand, is provided. +

+
+this_type & operator=(const this_type & x);
+
+
    +
  • +Effects: a + = b; where a and b are the bimap objects to which *this + and x belong, respectively. +
  • +
  • +Returns: *this. +
  • +
+
+
+ +

+

+
+std::pair<iterator,bool> insert(const value_type & x);
+
+
    +
  • +Effects: Inserts x + into the bimap to which + the set view belongs if +
      +
    • + the set view is non-unique OR no other element with equivalent + key exists, +
    • +
    • + AND insertion is allowed by the other set specifications the bimap. +
    • +
    +
  • +
  • +Returns: The return value is a pair + p. p.second + is true if and only if + insertion took place. On successful insertion, p.first + points to the element inserted; otherwise, p.first + points to an element that caused the insertion to be banned. Note that + more than one element can be causing insertion not to be allowed. +
  • +
  • +Complexity: + O(I(n)). +
  • +
  • +Exception safety: Strong. +
  • +
+

+

+
+iterator insert(iterator position, const value_type & x);
+
+
    +
  • +Requires: position + is a valid iterator of the view. +
  • +
  • +Effects: position + is used as a hint to improve the efficiency of the operation. Inserts + x into the bimap to which the view belongs if +
      +
    • + the set view is non-unique OR no other element with equivalent + key exists, +
    • +
    • + AND insertion is allowed by all other views of the bimap. +
    • +
    +
  • +
  • +Returns: On successful insertion, + an iterator to the newly inserted element. Otherwise, an iterator to + an element that caused the insertion to be banned. Note that more than + one element can be causing insertion not to be allowed. +
  • +
  • +Complexity: + O(H(n)). +
  • +
  • +Exception safety: Strong. +
  • +
+

+

+
+template< class InputIterator >
+void insert(InputIterator first, InputIterator last);
+
+
    +
  • +Requires: InputIterator + is a model of Input + Iterator over elements of type value_type + or a type convertible to value_type. first + and last are not iterators + into any view of the bimap + to which this index belongs. last + is reachable from first. +
  • +
  • +Effects: iterator + hint = + end(); + while( + first != + last ) + hint = + insert( + hint, + *first++ ); +
  • +
  • +Complexity: + O(m*H(n+m)), where m is the number of elements in [first, + last). +
  • +
  • +Exception safety: Basic. +
  • +
+

+

+
+iterator erase(iterator position);
+
+
    +
  • +Requires: position + is a valid dereferenceable iterator if the set view. +
  • +
  • +Effects: Deletes the element pointed + to by position. +
  • +
  • +Returns: An iterator pointing to the + element immediately following the one that was deleted, or end() + if no such element exists. +
  • +
  • +Complexity: + O(D(n)). +
  • +
  • +Exception safety: nothrow. +
  • +
+

+

+
+template< class CompatibleKey >
+size_type erase(const CompatibleKey & x);
+
+
    +
  • +Requires: CompatibleKey + is a compatible key of key_compare. +
  • +
  • +Effects: Deletes the elements with + key equivalent to x. +
  • +
  • +Returns: Number of elements deleted. +
  • +
  • +Complexity: + O(log(n) + m*D(n)), where m is the number of elements deleted. +
  • +
  • +Exception safety: Basic. +
  • +
+

+

+
+iterator erase(iterator first, iterator last);
+
+
    +
  • +Requires: [first,last) + is a valid range of the view. +
  • +
  • +Effects: Deletes the elements in + [first,last). +
  • +
  • +Returns: last. +
  • +
  • +Complexity: + O(log(n) + m*D(n)), where m is the number of elements in [first,last). +
  • +
  • +Exception safety: nothrow. +
  • +
+

+

+
+bool replace(iterator position, const value_type& x);
+
+
    +
  • +Requires: position + is a valid dereferenceable iterator of the set view. +
  • +
  • +Effects: Assigns the value x to the element pointed to by position into the bimap + to which the set view belongs if, for the value x
      +
    • + the set view is non-unique OR no other element with equivalent + key exists (except possibly *position), +
    • +
    • + AND replacing is allowed by all other views of the bimap. +
    • +
    +
  • +
  • +Postconditions: Validity of position + is preserved in all cases. +
  • +
  • +Returns: true + if the replacement took place, false + otherwise. +
  • +
  • +Complexity: + O(R(n)). +
  • +
  • +Exception safety: Strong. If an exception + is thrown by some user-provided operation, the bimap + to which the set view belongs remains in its original state. +
  • +
+

+

+
+template< class CompatibleKey >
+bool replace_key(iterator position, const CompatibleKey & x);
+
+
    +
  • +Requires: position + is a valid dereferenceable iterator of the set view. CompatibleKey can be assigned to + key_type. +
  • +
  • +Effects: Assigns the value x to e.first, + where e is the element + pointed to by position + into the bimap to which + the set view belongs if, +
      +
    • + the map view is non-unique OR no other element with equivalent + key exists (except possibly *position), +
    • +
    • + AND replacing is allowed by all other views of the bimap. +
    • +
    +
  • +
  • +Postconditions: Validity of position + is preserved in all cases. +
  • +
  • +Returns: true + if the replacement took place, false + otherwise. +
  • +
  • +Complexity: + O(R(n)). +
  • +
  • +Exception safety: Strong. If an exception + is thrown by some user-provided operation, the bimap + to which the set view belongs remains in its original state. +
  • +
+

+

+
+template< class CompatibleData >
+bool replace_data(iterator position, const CompatibleData & x);
+
+
    +
  • +Requires: position + is a valid dereferenceable iterator of the set view. CompatibleKey can be assigned to + data_type. +
  • +
  • +Effects: Assigns the value x to e.second, + where e is the element + pointed to by position + into the bimap to which + the set view belongs if, +
      +
    • + the map view is non-unique OR no other element with equivalent + key exists (except possibly *position), +
    • +
    • + AND replacing is allowed by all other views of the bimap. +
    • +
    +
  • +
  • +Postconditions: Validity of position + is preserved in all cases. +
  • +
  • +Returns: true + if the replacement took place, false + otherwise. +
  • +
  • +Complexity: + O(R(n)). +
  • +
  • +Exception safety: Strong. If an exception + is thrown by some user-provided operation, the bimap + to which the set view belongs remains in its original state. +
  • +
+

+

+
+template< class KeyModifier >
+bool modify_key(iterator position, KeyModifier mod);
+
+
    +
  • +Requires: KeyModifier + is a model of Unary + Function accepting arguments of type: key_type&; position + is a valid dereferenceable iterator of the view. +
  • +
  • +Effects: Calls mod(e.first) where e is the element pointed to + by position and rearranges *position into all the views of the + bimap. If the rearrangement + fails, the element is erased. Rearrangement is successful if +
      +
    • + the map view is non-unique OR no other element with equivalent + key exists, +
    • +
    • + AND rearrangement is allowed by all other views of the bimap. +
    • +
    +
  • +
  • +Postconditions: Validity of position is preserved if the operation + succeeds. +
  • +
  • +Returns: true + if the operation succeeded, false + otherwise. +
  • +
  • +Complexity: + O(M(n)). +
  • +
  • +Exception safety: Basic. If an exception + is thrown by some user-provided operation (except possibly mod), then + the element pointed to by position is erased. +
  • +
  • +Note: Only provided for map views. +
  • +
+

+

+
+template< class DataModifier >
+bool modify_data(iterator position, DataModifier mod);
+
+
    +
  • +Requires: DataModifier + is a model of Unary + Function accepting arguments of type: data_type&; position + is a valid dereferenceable iterator of the view. +
  • +
  • +Effects: Calls mod(e.second) where e is the element pointed to + by position and rearranges *position into all the views of the + bimap. If the rearrangement + fails, the element is erased. Rearrangement is successful if +
      +
    • + the oppositte map view is non-unique OR no other element with equivalent + key in that view exists, +
    • +
    • + AND rearrangement is allowed by all other views of the bimap. +
    • +
    +
  • +
  • +Postconditions: Validity of position is preserved if the operation + succeeds. +
  • +
  • +Returns: true + if the operation succeeded, false + otherwise. +
  • +
  • +Complexity: + O(M(n)). +
  • +
  • +Exception safety: Basic. If an exception + is thrown by some user-provided operation (except possibly mod), then + the element pointed to by position is erased. +
  • +
  • +Note: Only provided for map views. +
  • +
+
+
+ +

+ [multi]set_of + views provide the full lookup functionality required by Sorted + Associative Container and Unique + Associative Container, namely find, + count, lower_bound, upper_bound + and equal_range. Additionally, + these member functions are templatized to allow for non-standard arguments, + so extending the types of search operations allowed. +

+

+ A type CompatibleKey + is said to be a compatible key of Compare if (CompatibleKey, + Compare) + is a compatible extension of Compare. + This implies that Compare, + as well as being a strict weak ordering, accepts arguments of type CompatibleKey, which usually means + it has several overloads of operator(). +

+

+

+
+template< class CompatibleKey >
+iterator find(const CompatibleKey & x);
+
+template< class CompatibleKey >
+const_iterator find(const CompatibleKey & x) const;
+
+
    +
  • +Requires: CompatibleKey + is a compatible key of key_compare. +
  • +
  • +Effects: Returns a pointer to an element + whose key is equivalent to x, + or end() + if such an element does not exist. +
  • +
  • +Complexity: O(log(n)). +
  • +
+

+

+
+template< class CompatibleKey >
+size_type count(const key_type & x) const;
+
+
    +
  • +Requires: CompatibleKey + is a compatible key of key_compare. +
  • +
  • +Effects: Returns the number of elements + with key equivalent to x. +
  • +
  • +Complexity: O(log(n) + count(x)). +
  • +
+

+

+
+template< class CompatibleKey >
+iterator lower_bound(const key_type & x);
+
+template< class CompatibleKey >
+const_iterator lower_bound(const key_type & x) const;
+
+
    +
  • +Requires: CompatibleKey + is a compatible key of key_compare. +
  • +
  • +Effects: Returns an iterator pointing + to the first element with key not less than x, + or end() + if such an element does not exist. +
  • +
  • +Complexity: O(log(n)). +
  • +
+

+

+
+template< class CompatibleKey >
+iterator upper_bound(const key_type & x);
+
+template< class CompatibleKey >
+const_iterator upper_bound(const key_type & x) const;
+
+
    +
  • +Requires: CompatibleKey + is a compatible key of key_compare. +
  • +
  • +Effects: Returns an iterator pointing + to the first element with key greater than x, + or end() + if such an element does not exist. +
  • +
  • +Complexity: O(log(n)). +
  • +
+

+

+
+template< class CompatibleKey >
+std::pair<iterator,iterator>
+    equal_range(const key_type & x);
+
+template< class CompatibleKey >
+std::pair<const_iterator,const_iterator> 
+    equal_range(const key_type & x) const;
+
+
    +
  • +Requires: CompatibleKey + is a compatible key of key_compare. +
  • +
  • +Effects: Equivalent to make_pair(lower_bound(x),upper_bound(x)). +
  • +
  • +Complexity: O(log(n)). +
  • +
+
+
+ +

+ The member function range is not defined for sorted associative containers, + but [multi]set_of + map views provide it as a convenient utility. A range or interval is + defined by two conditions for the lower and upper bounds, which are modelled + after the following concepts. +

+

+ Consider a Strict + Weak Ordering Compare + over values of type Key. A type LowerBounder + is said to be a lower bounder of Compare + if +

+
    +
  • +LowerBounder is a + Predicate over Key, +
  • +
  • + if lower(k1) + and !comp(k2,k1) then lower(k2), +
  • +
+

+ for every lower of type + LowerBounder, comp of type Compare, + and k1, k2 of type Key. + Similarly, an upper bounder is a type UpperBounder + such that +

+
    +
  • +UpperBounder is a + Predicate over Key, +
  • +
  • + if upper(k1) + and !comp(k1,k2) then upper(k2), +
  • +
+

+ for every upper of type + UpperBounder, comp of type Compare, + and k1, k2 of type Key. +

+

+

+
+template< class LowerBounder, class UpperBounder>
+std::pair<const_iterator,const_iterator> range(
+    LowerBounder lower, UpperBounder upper) const;
+
+
    +
  • +Requires: LowerBounder + and UpperBounder are + a lower and upper bounder of key_compare, + respectively. +
  • +
  • +Effects: Returns a pair of iterators + pointing to the beginning and one past the end of the subsequence of + elements satisfying lower and upper simultaneously. If no such elements + exist, the iterators both point to the first element satisfying lower, + or else are equal to end() if this latter element does not exist. +
  • +
  • +Complexity: O(log(n)). +
  • +
  • +Variants: In place of lower or upper + (or both), the singular value boost::bimap::unbounded + can be provided. This acts as a predicate which all values of type + key_type satisfy. +
  • +
  • +Note: Only provided for map views. +
  • +
+
+
+ +

+

+
+template< class CompatibleKey >
+const data_type & at(const CompatibleKey & k) const;
+
+
    +
  • +Requires: CompatibleKey + is a compatible key of key_compare. +
  • +
  • +Effects: Returns the data_type reference that is associated + with k, or throws + std::out_of_range if such key does not + exist. +
  • +
  • +Complexity: O(log(n)). +
  • +
  • +Note: Only provided when set_of is used. +
  • +
+

+ The symmetry of bimap imposes some constraints on operator[] and the non constant version of at() + that are not found in std::maps. + Tey are only provided if the other collection type is mutable (list_of, vector_of + and unconstrained_set_of). +

+

+

+
+template< class CompatibleKey >
+data_type & operator[](const CompatibleKey & k);
+
+
    +
  • +Requires: CompatibleKey + is a compatible key of key_compare. +
  • +
  • +Effects: return + insert(value_type(k,data_type()))->second; +
  • +
  • +Complexity: O(log(n)). +
  • +
  • +Note: Only provided when set_of is used and the other collection + type is mutable. +
  • +
+

+

+
+template< class CompatibleKey >
+data_type & at(const CompatibleKey & k);
+
+
    +
  • +Requires: CompatibleKey + is a compatible key of key_compare. +
  • +
  • +Effects: Returns the data_type reference that is associated + with k, or throws + std::out_of_range if such key does not + exist. +
  • +
  • +Complexity: O(log(n)). +
  • +
  • +Note: Only provided when set_of is used and the other collection + type is mutable. +
  • +
+

+

+
+template< class CompatibleKey >
+info_type & info_at(const CompatibleKey & k);
+
+template< class CompatibleKey >
+const info_type & info_at(const CompatibleKey & k) const;
+
+
    +
  • +Requires: CompatibleKey + is a compatible key of key_compare. +
  • +
  • +Effects: Returns the info_type reference that is associated + with k, or throws + std::out_of_range if such key does not + exist. +
  • +
  • +Complexity: O(log(n)). +
  • +
  • +Note: Only provided when set_of and info_hook + are used +
  • +
+
+
+ +

+ Views cannot be serialized on their own, but only as part of the bimap into which they are embedded. + In describing the additional preconditions and guarantees associated + to [multi]set_of + views with respect to serialization of their embedding containers, we + use the concepts defined in the bimap + serialization section. +

+ +
  • +Requires: No additional requirements + to those imposed by the container. +
+ +
    +
  • +Requires: In addition to the general + requirements, value_comp() must be serialization-compatible + with m.get<i>().value_comp(), + where i is the position of the ordered view in the container. +
  • +
  • +Postconditions: On successful loading, + each of the elements of [begin(), + end()) + is a restored copy of the corresponding element in [m.get<i>().begin(), + m.get<i>().end()). +
  • +
+ +
  • +Requires: it + is a valid iterator of the view. The associated bimap + has been previously saved. +
+ +
    +
  • +Postconditions: On successful loading, + if it was dereferenceable then *it' is the restored copy of *it, + otherwise it' + == end(). +
  • +
  • +Note: It is allowed that it be a + const_iterator and + the restored it' an + iterator, or viceversa. +
  • +
+
+
+
+ + + +
Copyright © 2006 -2007 Matias Capeletto
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_bimap/reference/unconstrained_set_of_reference.html b/doc/html/boost_bimap/reference/unconstrained_set_of_reference.html new file mode 100644 index 0000000..18a8e76 --- /dev/null +++ b/doc/html/boost_bimap/reference/unconstrained_set_of_reference.html @@ -0,0 +1,201 @@ + + + +unconstrained_set_of + Reference + + + + + + + + + + + + + + + +
+Boost C++ LibrariesChapter Logo +HomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ + +
+ +
+namespace boost {
+namespace bimaps {
+
+
+template< class KeyType >
+struct unconstrained_set_of;
+
+struct unconstrained_set_of_relation;
+
+
+} // namespace bimap
+} // namespace boost
+
+
+
+ + +

+ An unconstrained_set_of set view is a view with no constraints. The use + of these kind of view boost the bimap performance but the view can not + be accessed. An unconstrained view is an empty class. +

+
+namespace boost {
+namespace bimaps {
+namespace views {
+
+template< -implementation defined parameter list- >
+class -implementation defined view name-
+{
+    // Empty view
+};
+
+} // namespace views
+} // namespace bimap
+} // namespace boost
+
+

+ In the case of a bimap< unconstrained_set_of<Left>, ... > +

+

+ In the set view: +

+
+typedef signature-compatible with relation< Left, ... > key_type;
+typedef signature-compatible with relation< Left, ... > value_type;
+
+

+ In the left map view: +

+
+typedef  Left  key_type;
+typedef  ...   data_type;
+
+typedef signature-compatible with std::pair< Left, ... > value_type;
+
+

+ In the right map view: +

+
+typedef  ...  key_type;
+typedef  Left data_type;
+
+typedef signature-compatible with std::pair< ... , Left > value_type;
+
+

+

+
+ +

+ We adopt the scheme outlined in the complexity + signature section. An unconstrained view can not be accessed by + the user, but the formulas to find the order of an operation for a bimap + hold with the following definitions. The complexity signature of a unconstrained_set_of view is: +

+
    +
  • + copying: c(n) = 0 +
  • +
  • + insertion: i(n) = 0 +
  • +
  • + hinted insertion: h(n) = 0 +
  • +
  • + deletion: d(n) = 0 +
  • +
  • + replacement: r(n) = 0 +
  • +
  • + modifying: m(n) = 0 +
  • +
+
+
+ +

+ Views cannot be serialized on their own, but only as part of the bimap into which they are embedded. + In describing the additional preconditions and guarantees associated + to list_of views with + respect to serialization of their embedding containers, we use the concepts + defined in the bimap + serialization section. +

+ +
  • +Requires: No additional requirements + to those imposed by the container. +
+ +
  • +Requires: No additional requirements + to those imposed by the container. +
+
+
+
+ + + +
Copyright © 2006 -2007 Matias Capeletto
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_bimap/reference/unordered_set_of_reference.html b/doc/html/boost_bimap/reference/unordered_set_of_reference.html new file mode 100644 index 0000000..e99e639 --- /dev/null +++ b/doc/html/boost_bimap/reference/unordered_set_of_reference.html @@ -0,0 +1,1303 @@ + + + +unordered_set_of + Reference + + + + + + + + + + + + + + + +
+Boost C++ LibrariesChapter Logo +HomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ + +
+ +
+namespace boost {
+namespace bimaps {
+
+
+template
+<
+    class KeyType,
+    class HashFunctor   = hash< KeyType >,
+    class EqualKey      = std::equal_to< KeyType >
+>
+struct unordered_set_of;
+
+
+template
+<
+    class HashFunctor   = hash< _relation >,
+    class EqualKey      = std::equal_to< _relation >
+>
+struct unordered_set_of_relation;
+
+
+} // namespace bimap
+} // namespace boost
+
+
+
+ +
+namespace boost {
+namespace bimaps {
+
+
+template
+<
+    class KeyType,
+    class HashFunctor   = hash< KeyType >,
+    class EqualKey      = std::equal_to< KeyType >
+>
+struct unordered_multiset_of;
+
+
+template
+<
+    class HashFunctor   = hash< _relation >,
+    class EqualKey      = std::equal_to< _relation >
+>
+struct unordered_multiset_of_relation;
+
+
+} // namespace bimap
+} // namespace boost
+
+
+
+ +

+ These collection types specifiers allow for set views without and with + allowance of duplicate elements, respectively. The syntax of set_of and multiset_of + coincide, thus we describe them in a grouped manner. +

+
+
+ + +

+ An unordered_[multi]set_of set view is a tr1::unordered[multi]set signature + compatible interface to the underlying heap of elements contained in a + bimap. +

+

+ The interface and semantics of unordered_[multi]set_of + views are modeled according to the proposal for unordered associative containers + given in the C++ + Standard Library Technical Report, also known as TR1. An unordered_[multi]set_of view is particularized according + to a given Hash function + object which returns hash values for the keys and a binary predicate Pred acting as an equivalence relation + on values of Key. +

+

+ There are two variants: unordered_set_of, which do not allow duplicate + elements (with respect to its associated comparison predicate) and unordered_multiset_of, + which accept those duplicates. The interface of these two variants is the + same to a great extent, so they are documented together with their differences + explicitly noted when they exist. +

+

+ If you look the bimap by a side, you will use a map view and if you looked + it as a whole you will be using a set view. +

+

+ Except where noted, unordered_[multi]set_of + views (both unique and non-unique) are models of Unordered Associative + Container. Validity of iterators and references to elements is + preserved in all cases. Occasionally, the exception safety guarantees provided + are actually stronger than required by the extension draft. We only provide + descriptions of those types and operations that are either not present + in the concepts modeled or do not exactly conform to the requirements for + unordered associative containers. +

+
+namespace boost {
+namespace bimap {
+namespace views {
+
+template< -implementation defined parameter list- >
+class -implementation defined view name-
+{
+    public:
+
+    // types
+
+    typedef -unspecified- key_type;
+    typedef -unspecified- value_type;
+    typedef -unspecified- key_compare;
+    typedef -unspecified- value_compare;
+    typedef -unspecified- hasher;
+    typedef -unspecified- key_equal;
+    typedef -unspecified- allocator_type;
+    typedef -unspecified- reference;
+    typedef -unspecified- const_reference;
+    typedef -unspecified- iterator;
+    typedef -unspecified- const_iterator;
+    typedef -unspecified- size_type;
+    typedef -unspecified- difference_type;
+    typedef -unspecified- pointer;
+    typedef -unspecified- const_pointer;
+    typedef -unspecified- local_iterator;
+    typedef -unspecified- const_local_iterator;
+
+    typedef -unspecified- info_type;
+
+    // construct/destroy/copy:
+
+    this_type & operator=(const this_type & x);
+
+    allocator_type get_allocator() const;
+
+    // size and capacity
+
+    bool      empty() const;
+    size_type size() const;
+    size_type max_size() const;
+
+    // iterators
+
+    iterator       begin();
+    const_iterator begin() const;
+    iterator       end();
+    const_iterator end() const;
+
+    // modifiers
+
+    std::pair< iterator, bool > insert(const value_type & x);
+
+    iterator insert(iterator position, const value_type & x);
+
+    template< class InputIterator >
+    void insert(InputIterator first, InputIterator last);
+
+    iterator erase(iterator position);
+
+    template< class CompatibleKey >
+    size_type erase(const CompatibleKey & x);
+
+    iterator erase(iterator first, iterator last);
+
+    bool replace(iterator position, const value_type & x);
+
+    // Only in map views
+    // {
+
+      template< class CompatibleKey >
+      bool replace_key(iterator position, const CompatibleKey & x);
+
+      template< class CompatibleData >
+      bool replace_data(iterator position, const CompatibleData & x);
+
+      template< class KeyModifier >
+      bool modify_key(iterator position, KeyModifier mod);
+
+      template< class DataModifier >
+      bool modify_data(iterator position, DataModifier mod);
+
+    // }
+
+
+    void clear();
+
+    // observers
+
+    key_from_value key_extractor() const;
+    hasher         hash_function() const;
+    key_equal      key_eq() const;
+
+    // lookup
+
+    template< class CompatibleKey >
+    iterator find(const CompatibleKey & x);
+
+    template< class CompatibleKey >
+    const_iterator find(const CompatibleKey & x) const;
+
+    template< class CompatibleKey >
+    size_type count(const CompatibleKey & x) const;
+
+    template< class CompatibleKey >
+    std::pair<iterator,iterator>
+        equal_range(const CompatibleKey & x);
+
+    template< class CompatibleKey >
+    std::pair<const_iterator,const_iterator>
+        equal_range(const CompatibleKey & x) const;
+
+    // bucket interface
+
+    size_type bucket_count() const;
+    size_type max_bucket_count() const;
+    size_type bucket_size(size_type n) const;
+    size_type bucket(const key_type & k) const;
+
+    local_iterator       begin(size_type n);
+    const_local_iterator begin(size_type n) const;
+    local_iterator       end(size_type n);
+    const_local_iterator end(size_type n) const;
+
+    // hash policy
+
+    float load_factor() const;
+    float max_load_factor() const;
+    void  max_load_factor(float z);
+    void  rehash(size_type n);
+
+    // Only in maps views
+    // {
+
+    typedef -unspecified- data_type;
+
+      // Only in for `unordered_set_of` collection type
+      // {
+
+      template<class CompatibleKey>
+      const data_type & at(const CompatibleKey & k) const;
+
+        // Only if the other collection type is mutable
+        // {
+
+        template<class CompatibleKey>
+        data_type & operator[](const CompatibleKey & k);
+
+        template<class CompatibleKey>
+        data_type & at(const CompatibleKey & k);
+
+        // }
+
+        // Only if info_hook is used
+        // {
+
+        template< class CompatibleKey >
+        info_type & info_at(const CompatibleKey & k);
+
+        template< class CompatibleKey >
+        const info_type & info_at(const CompatibleKey & k) const;
+
+      // }
+
+    // }
+
+};
+
+} // namespace views
+} // namespace bimap
+} // namespace boost
+
+

+ In the case of a bimap< unordered_{multi}set_of<Left>, ... > +

+

+ In the set view: +

+
+typedef signature-compatible with relation<       Left, ... > key_type;
+typedef signature-compatible with relation< const Left, ... > value_type;
+
+

+ In the left map view: +

+
+typedef  Left  key_type;
+typedef  ...   data_type;
+
+typedef signature-compatible with std::pair< const Left, ... > value_type;
+
+

+ In the right map view: +

+
+typedef  ...  key_type;
+typedef  Left data_type;
+
+typedef signature-compatible with std::pair< ... ,const Left > value_type;
+
+

+

+
+ +

+ Here and in the descriptions of operations of unordered_[multi]set_of + views, we adopt the scheme outlined in the complexity + signature section. The complexity signature of unordered_[multi]set_of + view is: +

+
    +
  • + copying: c(n) = n * log(n), +
  • +
  • + insertion: average case i(n) = 1 (constant), worst case i(n) = n, +
  • +
  • + hinted insertion: average case h(n) = 1 (constant), worst case h(n) = n, +
  • +
  • + deletion: average case d(n) = 1 (constant), worst case d(n) = n, +
  • +
  • + replacement: +
      +
    • + if the new element key is equivalent to the original, r(n) + = 1 + (constant), +
    • +
    • + otherwise, average case r(n) = 1 (constant), worst case r(n) + = n, +
    • +
    +
  • +
  • + modifying: average case m(n) = 1 (constant), worst case m(n) = n. +
  • +
+
+
+ +

+ unordered_[multi]set_of views are instantiated internally + to bimap specified by + means of the collection type specifiers and the bimap + itself. Instantiations are dependent on the following types: +

+
    +
  • +Value from bimap, +
  • +
  • +Allocator from bimap, +
  • +
  • +Hash from the collection + type specifier, +
  • +
  • +Pred from the collection + type specifier. +
  • +
+

+ Hash is a Unary + Function taking a single argument of type key_type + and returning a value of type std::size_t + in the range [0, std::numeric_limits<std::size_t>::max()). Pred is a Binary + Predicate inducing an equivalence relation on elements of key_type. It is required that the + Hash object return the + same value for keys equivalent under Pred. +

+
+
+ +
+iterator
+const_iterator
+local_iterator
+const_local_iterator
+
+
+

+

+

+ These types are models of Forward + Iterator. +

+

+

+
+
+
+ +

+ As explained in the concepts section, views do not have public constructors + or destructors. Assignment, on the other hand, is provided. Upon construction, + max_load_factor() + is 1.0. +

+
+this_type & operator=(const this_type & x);
+
+
    +
  • +Effects: a + = b; + where a and b are the bimap + objects to which *this + and x belong, respectively. +
  • +
  • +Returns: *this. +
  • +
+
+
+ +

+

+
+std::pair<iterator,bool> insert(const value_type & x);
+
+
    +
  • +Effects: Inserts x + into the bimap to which + the view belongs if +
      +
    • + the view is non-unique OR no other element with equivalent key + exists, +
    • +
    • + AND insertion is allowed by all other views of the bimap. +
    • +
    +
  • +
  • +Returns: The return value is a pair + p. p.second + is true if and only if + insertion took place. On successful insertion, p.first + points to the element inserted; otherwise, p.first + points to an element that caused the insertion to be banned. Note that + more than one element can be causing insertion not to be allowed. +
  • +
  • +Complexity: + O(I(n)). +
  • +
  • +Exception safety: Strong. +
  • +
+

+

+
+iterator insert(iterator position, const value_type & x);
+
+
    +
  • +Requires: position + is a valid iterator of the view. +
  • +
  • +Effects: position + is used as a hint to improve the efficiency of the operation. Inserts + x into the bimap to which the view belongs if +
      +
    • + the view is non-unique OR no other element with equivalent key + exists, +
    • +
    • + AND insertion is allowed by all other views of the bimap. +
    • +
    +
  • +
  • +Returns: On successful insertion, + an iterator to the newly inserted element. Otherwise, an iterator to + an element that caused the insertion to be banned. Note that more than + one element can be causing insertion not to be allowed. +
  • +
  • +Complexity: + O(H(n)). +
  • +
  • +Exception safety: Strong. +
  • +
+

+

+
+template< class InputIterator>
+void insert(InputIterator first, InputIterator last);
+
+
    +
  • +Requires: InputIterator + is a model of Input + Iterator over elements of type value_type. + first and last are not iterators into any views + of the bimap to which + this view belongs. last + is reachable from first. +
  • +
  • +Effects: iterator + hint = + end();while(first != + last) + hint = + insert(hint, *first++); +
  • +
  • +Complexity: + O(m*H(n+m)), where m is the number of elements in [first, + last). +
  • +
  • +Exception safety: Basic. +
  • +
+

+

+
+iterator erase(iterator position);
+
+
    +
  • +Requires: position + is a valid dereferenceable iterator + of the view. +
  • +
  • +Effects: Deletes the element pointed + to by position. +
  • +
  • +Returns: An iterator + pointing to the element immediately following the one that was deleted, + or end() + if no such element exists. +
  • +
  • +Complexity: + O(D(n)). +
  • +
  • +Exception safety: nothrow. +
  • +
+

+

+
+template< class CompatibleKey >
+size_type erase(const CompatibleKey & x);
+
+
    +
  • +Effects: Deletes the elements with + key equivalent to x. +
  • +
  • +Returns: Number of elements deleted. +
  • +
  • +Complexity: + Average case, O(1 + m*D(n)), worst case O(n + m*D(n)), where m is the + number of elements deleted. +
  • +
  • +Exception safety: Basic. +
  • +
+

+

+
+iterator erase(iterator first, iterator last);
+
+
    +
  • +Requires: [first,last) + is a valid range of the view. +
  • +
  • +Effects: Deletes the elements in + [first,last). +
  • +
  • +Returns: last. +
  • +
  • +Complexity: + O(m*D(n)), where m is the number of elements in [first,last). +
  • +
  • +Exception safety: nothrow. +
  • +
+

+

+
+bool replace(iterator position, const value_type & x);
+
+
    +
  • +Requires: position + is a valid dereferenceable iterator + of the view. +
  • +
  • +Effects: Assigns the value x to the element pointed to by position into the bimap + to which the view belongs if, for the value x
      +
    • + the view is non-unique OR no other element with equivalent key + exists (except possibly *position), +
    • +
    • + AND replacing is allowed by all other views of the bimap. +
    • +
    +
  • +
  • +Postconditions: Validity of position + is preserved in all cases. +
  • +
  • +Returns: true + if the replacement took place, false + otherwise. +
  • +
  • +Complexity: + O(R(n)). +
  • +
  • +Exception safety: Strong. If an exception + is thrown by some user-provided operation the bimap + to which the view belongs remains in its original state. +
  • +
+

+

+
+template< class CompatibleKey >
+bool replace_key(iterator position, const CompatibleKey & x);
+
+
    +
  • +Requires: position + is a valid dereferenceable iterator of the set view. CompatibleKey can be assigned to + key_type. +
  • +
  • +Effects: Assigns the value x to e.first, + where e is the element + pointed to by position + into the bimap to which + the set view belongs if, +
      +
    • + the map view is non-unique OR no other element with equivalent + key exists (except possibly *position), +
    • +
    • + AND replacing is allowed by all other views of the bimap. +
    • +
    +
  • +
  • +Postconditions: Validity of position + is preserved in all cases. +
  • +
  • +Returns: true + if the replacement took place, false + otherwise. +
  • +
  • +Complexity: + O(R(n)). +
  • +
  • +Exception safety: Strong. If an exception + is thrown by some user-provided operation, the bimap + to which the set view belongs remains in its original state. +
  • +
+

+

+
+template< class CompatibleData >
+bool replace_data(iterator position, const CompatibleData & x);
+
+
    +
  • +Requires: position + is a valid dereferenceable iterator of the set view. CompatibleKey can be assigned to + data_type. +
  • +
  • +Effects: Assigns the value x to e.second, + where e is the element + pointed to by position + into the bimap to which + the set view belongs if, +
      +
    • + the map view is non-unique OR no other element with equivalent + key exists (except possibly *position), +
    • +
    • + AND replacing is allowed by all other views of the bimap. +
    • +
    +
  • +
  • +Postconditions: Validity of position + is preserved in all cases. +
  • +
  • +Returns: true + if the replacement took place, false + otherwise. +
  • +
  • +Complexity: + O(R(n)). +
  • +
  • +Exception safety: Strong. If an exception + is thrown by some user-provided operation, the bimap + to which the set view belongs remains in its original state. +
  • +
+

+

+
+template< class KeyModifier >
+bool modify_key(iterator position, KeyModifier mod);
+
+
    +
  • +Requires: KeyModifier + is a model of Unary + Function accepting arguments of type: key_type&; position + is a valid dereferenceable iterator of the view. +
  • +
  • +Effects: Calls mod(e.first) where e is the element pointed to + by position and rearranges *position into all the views of the + bimap. If the rearrangement + fails, the element is erased. Rearrangement is successful if +
      +
    • + the map view is non-unique OR no other element with equivalent + key exists, +
    • +
    • + AND rearrangement is allowed by all other views of the bimap. +
    • +
    +
  • +
  • +Postconditions: Validity of position is preserved if the operation + succeeds. +
  • +
  • +Returns: true + if the operation succeeded, false + otherwise. +
  • +
  • +Complexity: + O(M(n)). +
  • +
  • +Exception safety: Basic. If an exception + is thrown by some user-provided operation (except possibly mod), then + the element pointed to by position is erased. +
  • +
  • +Note: Only provided for map views. +
  • +
+

+

+
+template< class DataModifier >
+bool modify_data(iterator position, DataModifier mod);
+
+
    +
  • +Requires: DataModifier + is a model of Unary + Function accepting arguments of type: data_type&; position + is a valid dereferenceable iterator of the view. +
  • +
  • +Effects: Calls mod(e.second) where e is the element pointed to + by position and rearranges *position into all the views of the + bimap. If the rearrangement + fails, the element is erased. Rearrangement is successful if +
      +
    • + the oppositte map view is non-unique OR no other element with equivalent + key in that view exists, +
    • +
    • + AND rearrangement is allowed by all other views of the bimap. +
    • +
    +
  • +
  • +Postconditions: Validity of position is preserved if the operation + succeeds. +
  • +
  • +Returns: true + if the operation succeeded, false + otherwise. +
  • +
  • +Complexity: + O(M(n)). +
  • +
  • +Exception safety: Basic. If an exception + is thrown by some user-provided operation (except possibly mod), then + the element pointed to by position is erased. +
  • +
  • +Note: Only provided for map views. +
  • +
+
+
+
+Lookup +
+

+ unordered_[multi]set_of views provide the full lookup + functionality required by unordered associative containers, namely find, count, + and equal_range. Additionally, + these member functions are templatized to allow for non-standard arguments, + so extending the types of search operations allowed. The kind of arguments + permissible when invoking the lookup member functions is defined by the + following concept. +

+

+ A type CompatibleKey + is said to be a compatible key of (Hash, Pred) if (CompatibleKey, + Hash, + Pred) + is a compatible extension of (Hash, Pred). + This implies that Hash + and Pred accept arguments + of type CompatibleKey, + which usually means they have several overloads of their corresponding + operator() + member functions. +

+

+

+
+template< class CompatibleKey >
+iterator find(const CompatibleKey & x);
+
+template< class CompatibleKey >
+const_iterator find(const CompatibleKey & x) const;
+
+
    +
  • +Effects: Returns a pointer to an element + whose key is equivalent to x, + or end() + if such an element does not exist. +
  • +
  • +Complexity: Average case O(1) (constant), + worst case O(n). +
  • +
+

+

+
+template< class CompatibleKey >
+size_type count(const CompatibleKey & x) const;
+
+
    +
  • +Effects: Returns the number of elements + with key equivalent to x. +
  • +
  • +Complexity: Average case O(count(x)), + worst case O(n). +
  • +
+

+

+
+template< class CompatibleKey >
+std::pair<iterator,iterator>
+    equal_range(const CompatibleKey & x);
+
+template< class CompatibleKey >
+std::pair<const_iterator,const_iterator>
+    equal_range(const CompatibleKey & x) const;
+
+
    +
  • +Effects: Returns a range containing + all elements with keys equivalent to x + (and only those). +
  • +
  • +Complexity: Average case O(count(x)), + worst case O(n). +
  • +
+
+
+ +

+

+
+template< class CompatibleKey >
+const data_type & at(const CompatibleKey & k) const;
+
+
    +
  • +Requires: CompatibleKey + is a compatible key of key_compare. +
  • +
  • +Effects: Returns the data_type reference that is associated + with k, or throws + std::out_of_range if such key does not + exist. +
  • +
  • +Complexity: Average case O(1) (constant), + worst case O(n). +
  • +
  • +Note: Only provided when unordered_set_of is used. +
  • +
+

+ The symmetry of bimap imposes some constraints on operator[] and the non constant version of at() + that are not found in std::maps. + Tey are only provided if the other collection type is mutable (list_of, vector_of + and unconstrained_set_of). +

+

+

+
+template< class CompatibleKey >
+data_type & operator[](const CompatibleKey & k);
+
+
    +
  • +Requires: CompatibleKey + is a compatible key of key_compare. +
  • +
  • +Effects: return + insert(value_type(k,data_type()))->second; +
  • +
  • +Complexity: If the insertion is performed + O(I(n)), else: Average case O(1) (constant), worst case O(n). +
  • +
  • +Note: Only provided when unordered_set_of is used and the + other collection type is mutable. +
  • +
+

+

+
+template< class CompatibleKey >
+data_type & at(const CompatibleKey & k);
+
+
    +
  • +Requires: CompatibleKey + is a compatible key of key_compare. +
  • +
  • +Effects: Returns the data_type reference that is associated + with k, or throws + std::out_of_range if such key does not + exist. +
  • +
  • +Complexity: Average case O(1) (constant), + worst case O(n). +
  • +
  • +Note: Only provided when unordered_set_of is used and the + other collection type is mutable. +
  • +
+

+

+
+template< class CompatibleKey >
+info_type & info_at(const CompatibleKey & k);
+
+template< class CompatibleKey >
+const info_type & info_at(const CompatibleKey & k) const;
+
+
    +
  • +Requires: CompatibleKey + is a compatible key of key_compare. +
  • +
  • +Effects: Returns the info_type reference that is associated + with k, or throws + std::out_of_range if such key does not + exist. +
  • +
  • +Complexity: Average case O(1) (constant), + worst case O(n). +
  • +
  • +Note: Only provided when unordered_set_of and info_hook are used +
  • +
+
+
+ +

+

+
+void rehash(size_type n);
+
+
    +
  • +Effects: Increases if necessary the + number of internal buckets so that size()/bucket_count() does not exceed the maximum load + factor, and bucket_count()>=n. +
  • +
  • +Postconditions: Validity of iterators + and references to the elements contained is preserved. +
  • +
  • +Complexity: Average case O(size()), + worst case O(size(n)2). +
  • +
  • +Exception safety: Strong. +
  • +
+
+
+ +

+ Views cannot be serialized on their own, but only as part of the bimap into which they are embedded. + In describing the additional preconditions and guarantees associated + to unordered_[multi]set_of views with respect to serialization + of their embedding containers, we use the concepts defined in the bimap serialization section. +

+ +
  • +Requires: No additional requirements + to those imposed by the container. +
+ +
    +
  • +Requires: Additionally to the general + requirements, key_eq() must be serialization-compatible + with m.get<i>().key_eq(), + where i is the position of the unordered_[multi]set_of + view in the container. +
  • +
  • +Postconditions: On successful loading, + the range [begin(), end()) contains restored copies of every + element in [m.get<i>().begin(), m.get<i>().end()), though not necessarily in the same + order. +
  • +
+ +
  • +Requires: it + is a valid iterator + of the view. The associated bimap + has been previously saved. +
+ +
    +
  • +Postconditions: On successful loading, + if it was dereferenceable + then *it' + is the restored copy of *it, otherwise it' + == end(). +
  • +
  • +Note: It is allowed that it be a const_iterator + and the restored it' + an iterator, or viceversa. +
  • +
+ +
  • +Requires: it + is a valid local iterator of the view. The associated bimap has been previously saved. +
+ +
    +
  • +Postconditions: On successful loading, + if it was dereferenceable + then *it' + is the restored copy of *it; if it + was m.get<i>().end(n) + for some n, then it' + == m'.get<i>().end(n) (where b + is the original bimap, + b' its restored copy + and i is the ordinal + of the index.) +
  • +
  • +Note: It is allowed that it be a const_local_iterator + and the restored it' + a local_iterator, or + viceversa. +
  • +
+
+
+
+ + + +
Copyright © 2006 -2007 Matias Capeletto
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_bimap/reference/vector_of_reference.html b/doc/html/boost_bimap/reference/vector_of_reference.html new file mode 100644 index 0000000..bc43ffc --- /dev/null +++ b/doc/html/boost_bimap/reference/vector_of_reference.html @@ -0,0 +1,1408 @@ + + + +vector_of + Reference + + + + + + + + + + + + + + + +
+Boost C++ LibrariesChapter Logo +HomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ + +
+ +
+namespace boost {
+namespace bimaps {
+
+
+template< class KeyType >
+struct vector_of;
+
+struct vector_of_relation;
+
+
+} // namespace bimap
+} // namespace boost
+
+
+
+ + +

+ vector_of views are free-order sequences with constant time positional + access and random access iterators. Elements in a vector_of view are by + default sorted according to their order of insertion: this means that new + elements inserted through a different view of the bimap + are appended to the end of the vector_of view; additionally, facilities + are provided for further rearrangement of the elements. The public interface + of vector_of views includes that of list_of views, with differences in + the complexity of the operations, plus extra operations for positional + access (operator[] + and at()) + and for capacity handling. Validity of iterators and references to elements + is preserved in all operations, regardless of the capacity status. +

+

+ As is the case with list_of views, vector_of views have the following limitations + with respect to STL sequence containers: +

+
    +
  • + vector_of views are not Assignable + (like any other view.) +
  • +
  • + Insertions into a vector_of view may fail due to clashings with other + views. This alters the semantics of the operations provided with respect + to their analogues in STL sequence containers. +
  • +
  • + Elements in a vector_of view are not mutable, and can only be changed + by means of replace and modify member functions. +
  • +
+

+ Having these restrictions into account, vector of views are models of + Random + Access Container and Back + Insertion Sequence. Although these views do not model Front + Insertion Sequence, because front insertion and deletion take linear + time, front operations are nonetheless provided to match the interface + of list_of views. We only describe those types and operations that are + either not present in the concepts modeled or do not exactly conform to + the requirements for these types of containers. +

+
+namespace boost {
+namespace bimaps {
+namespace views {
+
+template< -implementation defined parameter list- >
+class -implementation defined view name-
+{
+    public:
+
+    // types
+
+    typedef -unspecified- value_type;
+    typedef -unspecified- allocator_type;
+    typedef -unspecified- reference;
+    typedef -unspecified- const_reference;
+    typedef -unspecified- iterator;
+    typedef -unspecified- const_iterator;
+    typedef -unspecified- size_type;
+    typedef -unspecified- difference_type;
+    typedef -unspecified- pointer;
+    typedef -unspecified- const_pointer;
+    typedef -unspecified- reverse_iterator;
+    typedef -unspecified- const_reverse_iterator;
+
+    typedef -unspecified- info_type;
+
+    // construct / copy / destroy
+
+    this_type & operator=(this_type & x);
+
+    template< class InputIterator >
+    void assign(InputIterator first, InputIterator last);
+
+    void assign(size_type n, const value_type & value);
+
+    allocator_type get_allocator() const;
+
+    // iterators
+
+    iterator               begin();
+    const_iterator         begin() const;
+
+    iterator               end();
+    const_iterator         end() const;
+
+    reverse_iterator       rbegin();
+    const_reverse_iterator rbegin() const;
+
+    reverse_iterator       rend();
+    const_reverse_iterator rend() const;
+
+    // capacity
+
+    bool      empty() const;
+
+    size_type size() const;
+
+    size_type max_size() const;
+
+    size_type capacity() const;
+
+    void reserve(size_type m);
+
+    void resize(size_type n, const value_type & x = value_type());
+
+    // access
+
+    const_reference operator[](size_type n) const;
+
+    const_reference at(size_type n) const;
+
+    const_reference front() const;
+
+    const_reference back() const;
+
+    // modifiers
+
+    std::pair<iterator,bool> push_front(const value_type & x);
+    void                     pop_front();
+
+    std::pair<iterator,bool> push_back(const value_type & x);
+    void                     pop_back();
+
+    std::pair<iterator,bool> insert(iterator position, const value_type & x);
+
+    void insert(iterator position, size_type m, const value_type & x);
+
+    template< class InputIterator>
+    void insert(iterator position, InputIterator first, InputIterator last);
+
+    iterator erase(iterator position);
+    iterator erase(iterator first, iterator last);
+
+    bool replace(iterator position, const value_type & x);
+
+    // Only in map views
+    // {
+
+      template< class CompatibleKey >
+      bool replace_key(iterator position, const CompatibleKey & x);
+
+      template< class CompatibleData >
+      bool replace_data(iterator position, const CompatibleData & x);
+
+      template< class KeyModifier >
+      bool modify_key(iterator position, KeyModifier mod);
+
+      template< class DataModifier >
+      bool modify_data(iterator position, DataModifier mod);
+
+    // }
+
+
+    void clear();
+
+    // list operations
+
+    void splice(iterator position, this_type & x);
+    void splice(iterator position, this_type & x, iterator i);
+    void splice(
+        iterator position, this_type & x, iterator first, iterator last);
+
+    void remove(const value_type & value);
+
+    template< class Predicate >
+    void remove_if(Predicate pred);
+
+    void unique();
+
+    template< class BinaryPredicate >
+    void unique(BinaryPredicate binary_pred);
+
+    void merge(this_type & x);
+
+    template< typename Compare >
+    void merge(this_type & x, Compare comp);
+
+    void sort();
+
+    template< typename Compare >
+    void sort(Compare comp);
+
+    void reverse();
+
+    // rearrange operations
+
+    void relocate(iterator position, iterator i);
+    void relocate(iterator position, iterator first, iterator last);
+};
+
+// view comparison
+
+bool operator==(const this_type & v1, const this_type & v2 );
+bool operator< (const this_type & v1, const this_type & v2 );
+bool operator!=(const this_type & v1, const this_type & v2 );
+bool operator> (const this_type & v1, const this_type & v2 );
+bool operator>=(const this_type & v1, const this_type & v2 );
+bool operator<=(const this_type & v1, const this_type & v2 );
+
+} // namespace views
+} // namespace bimap
+} // namespace boost
+
+

+ In the case of a bimap< vector_of<Left>, ... > +

+

+ In the set view: +

+
+typedef signature-compatible with relation< Left, ... > key_type;
+typedef signature-compatible with relation< Left, ... > value_type;
+
+

+ In the left map view: +

+
+typedef  Left  key_type;
+typedef  ...   data_type;
+
+typedef signature-compatible with std::pair< Left, ... > value_type;
+
+

+ In the right map view: +

+
+typedef  ...  key_type;
+typedef  Left data_type;
+
+typedef signature-compatible with std::pair< ... , Left > value_type;
+
+

+

+
+ +

+ Here and in the descriptions of operations of vector_of + views, we adopt the scheme outlined in the complexity + signature section. The complexity signature of vector_of + view is: +

+
    +
  • + copying: c(n) = n * log(n), +
  • +
  • + insertion: i(n) = 1 (amortized + constant), +
  • +
  • + hinted insertion: h(n) = 1 (amortized constant), +
  • +
  • + deletion: d(n) = m, + where m is the distance from the deleted element to the end of the + sequence, +
  • +
  • + replacement: r(n) = 1 (constant), +
  • +
  • + modifying: m(n) = 1 (constant). +
  • +
+

+ The following expressions are also used as a convenience for writing + down some of the complexity formulas: +

+ +

+ (shl and rel stand for shift left + and relocate, respectively.) +

+
+
+ +

+ vector_of views are instantiated + internally to bimap and + specified by means of the collection type specifiers and the bimap itself. + Instantiations are dependent on the following types: +

+
    +
  • +Value from vector_of, +
  • +
  • +Allocator from bimap, +
  • +
+
+
+ +

+ As explained in the views concepts section, views do not have public + constructors or destructors. Assignment, on the other hand, is provided. +

+
+this_type & operator=(const this_type & x);
+
+
    +
  • +Effects: a=b; where a and b are the bimap objects to which *this + and x belong, respectively. +
  • +
  • +Returns: *this. +
  • +
+

+

+
+template< class InputIterator >
+void assign(InputIterator first, InputIterator last);
+
+
    +
  • +Requires: InputIterator + is a model of Input + Iterator over elements of type value_type + or a type convertible to value_type. + first and last are not iterators into any view + of the bimap to which + this view belongs. last + is reachable from first. +
  • +
  • +Effects: clear(); insert(end(),first,last); +
  • +
+

+

+
+void assign(size_type n, const value_type & value);
+
+
  • +Effects: clear(); for(size_type + i = + 0; + i < + n; + ++n) push_back(v); +
+
+
+ +

+

+
+size_type capacity() const;
+
+
    +
  • +Returns: The total number of elements + c such that, when + size() + < c, + back insertions happen in constant time (the general case as described + by i(n) is amortized constant time.) +
  • +
  • +Note: Validity of iterators and references + to elements is preserved in all insertions, regardless of the capacity + status. +
  • +
+

+

+
+void reserve(size_type m);
+
+
    +
  • +Effects: If the previous value of + capacity() + was greater than or equal to m, + nothing is done; otherwise, the internal capacity is changed so that + capacity()>=m. +
  • +
  • +Complexity: If the capacity is not + changed, constant; otherwise O(n). +
  • +
  • +Exception safety: If the capacity + is not changed, nothrow; otherwise, strong. +
  • +
+

+

+
+void resize(size_type n, const value_type & x = value_type());
+
+
    +
  • +Effects: if( n > size() ) insert(end(), + n-size(), + x);else if( n<size() ) erase(begin()+n,end()); +
  • +
  • +Note: If an expansion is requested, + the size of the view is not guaranteed to be n after this operation + (other views may ban insertions.) +
  • +
+
+
+ +

+

+
+std::pair<iterator,bool> push_front(const value_type & x);
+
+
    +
  • +Effects: Inserts x at the beginning + of the sequence if no other view of the bimap + bans the insertion. +
  • +
  • +Returns: The return value is a pair + p. p.second + is true if and only if + insertion took place. On successful insertion, p.first + points to the element inserted; otherwise, p.first + points to an element that caused the insertion to be banned. Note that + more than one element can be causing insertion not to be allowed. +
  • +
  • +Complexity: + O(n+I(n)). +
  • +
  • +Exception safety: Strong. +
  • +
+

+

+
+std::pair<iterator,bool> push_back(const value_type & x);
+
+
    +
  • +Effects: Inserts x + at the end of the sequence if no other view of the bimap + bans the insertion. +
  • +
  • +Returns: The return value is a pair + p. p.second + is true if and only if + insertion took place. On successful insertion, p.first + points to the element inserted; otherwise, p.first + points to an element that caused the insertion to be banned. Note that + more than one element can be causing insertion not to be allowed. +
  • +
  • +Complexity: + O(I(n)). +
  • +
  • +Exception safety: Strong. +
  • +
+

+

+
+std::pair<iterator,bool> insert(iterator position, const value_type & x);
+
+
    +
  • +Requires: position + is a valid iterator of the view. +
  • +
  • +Effects: Inserts x + before position if insertion is allowed by all other views of the + bimap. +
  • +
  • +Returns: The return value is a pair + p. p.second + is true if and only if + insertion took place. On successful insertion, p.first + points to the element inserted; otherwise, p.first + points to an element that caused the insertion to be banned. Note that + more than one element can be causing insertion not to be allowed. +
  • +
  • +Complexity: + O(shl(end()-position,1) + I(n)). +
  • +
  • +Exception safety: Strong. +
  • +
+

+

+
+void insert(iterator position, size_type m, const value_type & x);
+
+
    +
  • +Requires: position + is a valid iterator of the view. +
  • +
  • +Effects: for(size_type + i = + 0; + i < + m; + ++i) insert(position, x); +
  • +
  • +Complexity: + O(shl(end()-position,m) + m*I(n+m)). +
  • +
+

+

+
+template< class InputIterator >
+void insert(iterator position, InputIterator first, InputIterator last);
+
+
    +
  • +Requires: position + is a valid iterator of the view. InputIterator + is a model of Input + Iterator over elements of type value_type + or a type convertible to value_type. + first and last are not iterators into any view + of the bimap to which + this view belongs. last + is reachable from first. +
  • +
  • +Effects: while(first!=last)insert(position,*first++); +
  • +
  • +Complexity: + O(shl(end()-position,m) + m*I(n+m)), where m is the number of elements + in [first,last). +
  • +
  • +Exception safety: Basic. +
  • +
+

+

+
+iterator erase(iterator position);
+
+
    +
  • +Requires: position + is a valid dereferenceable iterator of the view. +
  • +
  • +Effects: Deletes the element pointed + to by position. +
  • +
  • +Returns: An iterator pointing to the + element immediately following the one that was deleted, or end() + if no such element exists. +
  • +
  • +Complexity: + O(D(n)). +
  • +
  • +Exception safety: nothrow. +
  • +
+

+

+
+iterator erase(iterator first, iterator last);
+
+
    +
  • +Requires: [first,last) + is a valid range of the view. +
  • +
  • +Effects: Deletes the elements in + [first,last). +
  • +
  • +Returns: last. +
  • +
  • +Complexity: + O(m*D(n)), where m is the number of elements in [first,last). +
  • +
  • +Exception safety: nothrow. +
  • +
+

+

+
+bool replace(iterator position, const value_type & x);
+
+
    +
  • +Requires: position + is a valid dereferenceable iterator of the view. +
  • +
  • +Effects: Assigns the value x to the + element pointed to by position into the bimap + to which the view belongs if replacing is allowed by all other views + of the bimap. +
  • +
  • +Postconditions: Validity of position + is preserved in all cases. +
  • +
  • +Returns: true + if the replacement took place, false + otherwise. +
  • +
  • +Complexity: + O(R(n)). +
  • +
  • +Exception safety: Strong. If an exception + is thrown by some user-provided operation the bimap + to which the view belongs remains in its original state. +
  • +
+

+

+
+template< class CompatibleKey >
+bool replace_key(iterator position, const CompatibleKey & x);
+
+
    +
  • +Requires: position + is a valid dereferenceable iterator of the set view. CompatibleKey can be assigned to + key_type. +
  • +
  • +Effects: Assigns the value x to e.first, + where e is the element + pointed to by position + into the bimap to which + the set view belongs if replacing is allowed by all other views of + the bimap. +
  • +
  • +Postconditions: Validity of position + is preserved in all cases. +
  • +
  • +Returns: true + if the replacement took place, false + otherwise. +
  • +
  • +Complexity: + O(R(n)). +
  • +
  • +Exception safety: Strong. If an exception + is thrown by some user-provided operation, the bimap + to which the set view belongs remains in its original state. +
  • +
+

+

+
+template< class CompatibleData >
+bool replace_data(iterator position, const CompatibleData & x);
+
+
    +
  • +Requires: position + is a valid dereferenceable iterator of the set view. CompatibleKey can be assigned to + data_type. +
  • +
  • +Effects: Assigns the value x to e.second, + where e is the element + pointed to by position + into the bimap to which + the set view belongs if replacing is allowed by all other views of + the bimap. +
  • +
  • +Postconditions: Validity of position + is preserved in all cases. +
  • +
  • +Returns: true + if the replacement took place, false + otherwise. +
  • +
  • +Complexity: + O(R(n)). +
  • +
  • +Exception safety: Strong. If an exception + is thrown by some user-provided operation, the bimap + to which the set view belongs remains in its original state. +
  • +
+

+

+
+template< class KeyModifier >
+bool modify_key(iterator position, KeyModifier mod);
+
+
    +
  • +Requires: KeyModifier + is a model of Unary + Function accepting arguments of type: key_type&; position + is a valid dereferenceable iterator of the view. +
  • +
  • +Effects: Calls mod(e.first) where e is the element pointed to + by position and rearranges *position into all the views of the + bimap. If the rearrangement + fails, the element is erased. It is successful if the rearrangement + is allowed by all other views of the bimap. +
  • +
  • +Postconditions: Validity of position is preserved if the operation + succeeds. +
  • +
  • +Returns: true + if the operation succeeded, false + otherwise. +
  • +
  • +Complexity: + O(M(n)). +
  • +
  • +Exception safety: Basic. If an exception + is thrown by some user-provided operation (except possibly mod), then + the element pointed to by position is erased. +
  • +
  • +Note: Only provided for map views. +
  • +
+

+

+
+template< class DataModifier >
+bool modify_data(iterator position, DataModifier mod);
+
+
    +
  • +Requires: DataModifier + is a model of Unary + Function accepting arguments of type: data_type&; position + is a valid dereferenceable iterator of the view. +
  • +
  • +Effects: Calls mod(e.second) where e is the element pointed to + by position and rearranges *position into all the views of the + bimap. If the rearrangement + fails, the element is erased. It is successful if the rearrangement + is allowed by all other views of the bimap. +
  • +
  • +Postconditions: Validity of position is preserved if the operation + succeeds. +
  • +
  • +Returns: true + if the operation succeeded, false + otherwise. +
  • +
  • +Complexity: + O(M(n)). +
  • +
  • +Exception safety: Basic. If an exception + is thrown by some user-provided operation (except possibly mod), then + the element pointed to by position is erased. +
  • +
  • +Note: Only provided for map views. +
  • +
+
+
+ +

+ vector_of views replicate + the interface of list_of + views, which in turn includes the list operations provided by std::list. The syntax and behavior of these + operations exactly matches those of list_of + views, but the associated complexity bounds differ in general. +

+

+

+
+void splice(iterator position, this_type & x);
+
+
    +
  • +Requires: position + is a valid iterator of the view. &x!=this. +
  • +
  • +Effects: Inserts the contents of + x before position, + in the same order as they were in x. + Those elements successfully inserted are erased from x. +
  • +
  • +Complexity: + O(shl(end()-position,x.size()) + x.size()*I(n+x.size()) + x.size()*D(x.size())). +
  • +
  • +Exception safety: Basic. +
  • +
+

+

+
+void splice(iterator position, this_type & x,iterator i);
+
+
    +
  • +Requires: position + is a valid iterator of the view. i + is a valid dereferenceable iterator x. +
  • +
  • +Effects: Inserts the element pointed + to by i before position: if insertion is successful, + the element is erased from x. + In the special case &x==this, no copy or deletion is performed, + and the operation is always successful. If position==i, + no operation is performed. +
  • +
  • +Postconditions: If &x==this, no iterator or reference is invalidated. +
  • +
  • +Complexity: + If &x==this, + O(rel(position,i,i+1)); otherwise O(shl(end()-position,1) + I(n) + + D(n)). +
  • +
  • +Exception safety: If &x==this, + nothrow; otherwise, strong. +
  • +
+

+

+
+void splice(iterator position, this_type & x, iterator first, iterator last);
+
+
    +
  • +Requires: position + is a valid iterator of the view. first + and last are valid + iterators of x. last is reachable from first. position + is not in the range [first,last). +
  • +
  • +Effects: For each element in the range + [first,last), insertion is tried before position; if the operation is successful, + the element is erased from x. + In the special case &x==this, no copy or deletion is performed, + and insertions are always successful. +
  • +
  • +Postconditions: If &x==this, no iterator or reference is invalidated. +
  • +
  • +Complexity: + If &x==this, + O(rel(position,first,last)); otherwise O(shl(end()-position,m) + m*I(n+m) + + m*D(x.size())) where m is the number of elements in [first,last). +
  • +
  • +Exception safety: If &x==this, + nothrow; otherwise, basic. +
  • +
+

+

+
+void remove(const value_type & value);
+
+
    +
  • +Effects: Erases all elements of the + view which compare equal to value. +
  • +
  • +Complexity: + O(n + m*D(n)), where m is the number of elements erased. +
  • +
  • +Exception safety: Basic. +
  • +
+

+

+
+template< class Predicate >
+void remove_if(Predicate pred);
+
+
    +
  • +Effects: Erases all elements x of the view for which pred(x) + holds. +
  • +
  • +Complexity: + O(n + m*D(n)), where m is the number of elements erased. +
  • +
  • +Exception safety: Basic. +
  • +
+

+

+
+void unique();
+
+
    +
  • +Effects: Eliminates all but the first + element from every consecutive group of equal elements referred to + by the iterator i in + the range [first+1,last) + for which *i==*(i-1). +
  • +
  • +Complexity: + O(n + m*D(n)), where m is the number of elements erased. +
  • +
  • +Exception safety: Basic. +
  • +
+

+

+
+template< class BinaryPredicate >
+void unique(BinaryPredicate binary_pred); 
+
+
    +
  • +Effects: Eliminates all but the first + element from every consecutive group of elements referred to by the + iterator i in the range [first+1,last) for which binary_pred(*i, *(i-1)) holds. +
  • +
  • +Complexity: + O(n + m*D(n)), where m is the number of elements erased. +
  • +
  • +Exception safety: Basic. +
  • +
+

+

+
+void merge(this_type & x);
+
+
    +
  • +Requires: std::less<value_type> is a Strict + Weak Ordering over value_type. + Both the view and x + are sorted according to std::less<value_type>. +
  • +
  • +Effects: Attempts to insert every + element of x into the corresponding position of the view (according + to the order). Elements successfully inserted are erased from x. The resulting sequence is stable, + i.e. equivalent elements of either container preserve their relative + position. In the special case &x==this, no operation is performed. +
  • +
  • +Postconditions: Elements in the view + and remaining elements in x + are sorted. Validity of iterators to the view and of non-erased elements + of x references is + preserved. +
  • +
  • +Complexity: + If &x==this, + constant; otherwise O(n + x.size()*I(n+x.size()) + x.size()*D(x.size())). +
  • +
  • +Exception safety: If &x==this, + nothrow; otherwise, basic. +
  • +
+

+

+
+template< class Compare >
+void merge(this_type & x, Compare comp);
+
+
    +
  • +Requires: Compare + is a Strict + Weak Ordering over value_type. + Both the view and x + are sorted according to comp. +
  • +
  • +Effects: Attempts to insert every + element of x into the + corresponding position of the view (according to comp). + Elements successfully inserted are erased from x. + The resulting sequence is stable, i.e. equivalent elements of either + container preserve their relative position. In the special case &x==this, + no operation is performed. +
  • +
  • +Postconditions: Elements in the view + and remaining elements in x + are sorted according to comp. + Validity of iterators to the view and of non-erased elements of x references is preserved. +
  • +
  • +Complexity: + If &x==this, + constant; otherwise O(n + x.size()*I(n+x.size()) + x.size()*D(x.size())). +
  • +
  • +Exception safety: If &x==this, + nothrow; otherwise, basic. +
  • +
+

+

+
+void sort();
+
+
    +
  • +Requires: std::less<value_type> is a Strict + Weak Ordering over value_type. +
  • +
  • +Effects: Sorts the view according + to std::less<value_type>. + The sorting is stable, i.e. equivalent elements preserve their relative + position. +
  • +
  • +Postconditions: Validity of iterators + and references is preserved. +
  • +
  • +Complexity: O(n*log(n)). +
  • +
  • +Exception safety: Basic. +
  • +
+

+

+
+template< class Compare >
+void sort(Compare comp);
+
+
    +
  • +Requires: Compare is a Strict + Weak Ordering over value_type. +
  • +
  • +Effects: Sorts the view according + to comp. The sorting + is stable, i.e. equivalent elements preserve their relative position. +
  • +
  • +Postconditions: Validity of iterators + and references is preserved. +
  • +
  • +Complexity: O(n*log(n)). +
  • +
  • +Exception safety: Basic. +
  • +
+

+

+
+void reverse();
+
+
    +
  • +Effects: Reverses the order of the + elements in the view. +
  • +
  • +Postconditions: Validity of iterators + and references is preserved. +
  • +
  • +Complexity: O(n). +
  • +
  • +Exception safety: nothrow. +
  • +
+
+
+ +

+ These operations, without counterpart in std::list + (although splice provides partially overlapping functionality), perform + individual and global repositioning of elements inside the index. +

+

+

+
+void relocate(iterator position, iterator i);
+
+
    +
  • +Requires: position + is a valid iterator of the view. i + is a valid dereferenceable iterator of the view. +
  • +
  • +Effects: Inserts the element pointed + to by i before position. If position==i, + no operation is performed. +
  • +
  • +Postconditions: No iterator or reference + is invalidated. +
  • +
  • +Complexity: Constant. +
  • +
  • +Exception safety: nothrow. +
  • +
+

+

+
+void relocate(iterator position, iterator first, iterator last);
+
+
    +
  • +Requires: position + is a valid iterator of the view. first + and last are valid + iterators of the view. last + is reachable from first. + position is not in + the range [first,last). +
  • +
  • +Effects: The range of elements [first,last) is repositioned just before position. +
  • +
  • +Postconditions: No iterator or reference + is invalidated. +
  • +
  • +Complexity: Constant. +
  • +
  • +Exception safety: nothrow. +
  • +
+
+
+ +

+ Views cannot be serialized on their own, but only as part of the bimap into which they are embedded. + In describing the additional preconditions and guarantees associated + to vector_of views with + respect to serialization of their embedding containers, we use the concepts + defined in the bimap + serialization section. +

+ +
  • +Requires: No additional requirements + to those imposed by the container. +
+ +
    +
  • +Requires: No additional requirements + to those imposed by the container. +
  • +
  • +Postconditions: On successful loading, + each of the elements of [begin(), + end()) + is a restored copy of the corresponding element in [m.get<i>().begin(), + m.get<i>().end()), + where i is the position + of the vector_of view + in the container. +
  • +
+ +
  • +Requires: it + is a valid iterator of the view. The associated bimap + has been previously saved. +
+ +
    +
  • +Postconditions: On successful loading, + if it was dereferenceable then *it' is the restored copy of *it, + otherwise it'==end(). +
  • +
  • +Note: It is allowed that it be a + const_iterator and + the restored it' an + iterator, or viceversa. +
  • +
+
+
+
+ + + +
Copyright © 2006 -2007 Matias Capeletto
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_bimap/release_notes.html b/doc/html/boost_bimap/release_notes.html new file mode 100644 index 0000000..77eec38 --- /dev/null +++ b/doc/html/boost_bimap/release_notes.html @@ -0,0 +1,44 @@ + + + +Release notes + + + + + + + + + + + + + + + +
+Boost C++ LibrariesChapter Logo +HomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ Not yet released. +

+
+ + + +
Copyright © 2006 -2007 Matias Capeletto
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_bimap/test_suite.html b/doc/html/boost_bimap/test_suite.html new file mode 100644 index 0000000..a7238c6 --- /dev/null +++ b/doc/html/boost_bimap/test_suite.html @@ -0,0 +1,457 @@ + + + +Test suite + + + + + + + + + + + + + + + +
+Boost C++ LibrariesChapter Logo +HomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ The Boost.Bimap test suite exercises the whole spectrum of functionalities + provided by the library. Although the tests are not meant to serve as a learning + guide, the interested reader may find it useful to inspect the source code + to gain familiarity with some of the least common features offered by Boost.Bimap. +

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Program +

+
+

+ Description +

+
+

+ test_tagged.cpp +

+
+

+ Tagged idiom checks +

+
+

+ test_mutant.cpp +

+
+

+ Test the mutant idiom +

+
+

+ test_structured_pair.cpp + +

+
+

+ Test structured pair class +

+
+

+ test_mutant_relation.cpp + +

+
+

+ Test the relation class +

+
+

+ test_bimap_set_of.cpp + +

+
+

+ Library interface check +

+
+

+ test_bimap_multiset_of.cpp + +

+
+

+ Library interface check +

+
+

+ test_bimap_unordered_set_of.cpp + +

+
+

+ Library interface check +

+
+

+ test_bimap_unordered_multiset_of.cpp + +

+
+

+ Library interface check +

+
+

+ test_bimap_list_of.cpp + +

+
+

+ Library interface check +

+
+

+ test_bimap_vector_of.cpp + +

+
+

+ Library interface check +

+
+

+ test_bimap_convenience_header.cpp + +

+
+

+ Library interface check +

+
+

+ test_bimap_ordered.cpp + +

+
+

+ Test set and multiset based bimaps +

+
+

+ test_bimap_unordered.cpp + +

+
+

+ Test unordered_set and unordered_multiset based bimaps +

+
+

+ test_bimap_sequenced.cpp + +

+
+

+ Test list and vector based bimaps +

+
+

+ test_bimap_unconstrained.cpp + +

+
+

+ Test bimaps with unconstrained views +

+
+

+ test_bimap_serialization.cpp + +

+
+

+ Serialization support checks +

+
+

+ test_bimap_property_map.cpp + +

+
+

+ Property map concepts for the set and unordered set views +

+
+

+ test_bimap_modify.cpp + +

+
+

+ replace, modify and operator[] +

+
+

+ test_bimap_lambda.cpp + +

+
+

+ Test lambda modified idom support +

+
+

+ test_bimap_assign.cpp + +

+
+

+ Test Boost.Assign support +

+
+

+ test_bimap_project.cpp + +

+
+

+ Projection of iterators support +

+
+

+ test_bimap_operator_bracket.cpp + +

+
+

+ operator[] + and at() + functions +

+
+

+ test_bimap_info.cpp +

+
+

+ Information hooking support +

+
+

+ test_bimap_extra.cpp + +

+
+

+ Additional checks +

+
+

+ test_bimap_info_1.cpp + +

+
+

+ Information hooking compilation fail test +

+
+

+ test_bimap_info_2.cpp + +

+
+

+ Information hooking compilation fail test +

+
+

+ test_bimap_info_3.cpp + +

+
+

+ Information hooking compilation fail test +

+
+

+ test_bimap_mutable_1.cpp + +

+
+

+ Mutable members compilation fail test +

+
+

+ test_bimap_mutable_2.cpp + +

+
+

+ Mutable members compilation fail test +

+
+

+ test_bimap_mutable_3.cpp + +

+
+

+ Mutable members compilation fail test +

+
+
+ + + +
Copyright © 2006 -2007 Matias Capeletto
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_bimap/the_tutorial.html b/doc/html/boost_bimap/the_tutorial.html new file mode 100644 index 0000000..2c5ff76 --- /dev/null +++ b/doc/html/boost_bimap/the_tutorial.html @@ -0,0 +1,167 @@ + + + +The tutorial + + + + + + + + + + + + + + + +
+Boost C++ LibrariesChapter Logo +HomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ + +
+ +
    +
  1. + Boost.Bimap is intuitive because it is based on the standard template library. + New concepts are however presented to extend the standard maps to bidirectional + maps. The first step is to gain a firm grasp of the bimap framework. The + first section (Discovering + the bimap framework) aims to explain this. +
  2. +
  3. + Boost.Bimap offers much more than just a one-to-one ordered unique bidirectional + map. It is possible to control the collection type of each side of the + relationship that the bimap represents, giving one-to-many containers, + hashed bidirectional containers and others that may be more suitable to + the the task at hand. The second section (Controlling + collection types) explains how to instantiate a bimap with different + collection constraints. +
  4. +
  5. + The section (The + "collection of relations" type) explains how to create + new types of bidirectional maps using custom collection types. +
  6. +
  7. + In the section Differences + with standard maps we will learn about the subtle differences between + a bimap map view and a standard map. +
  8. +
  9. + The section Useful + functions provides information about functions of a bimap that are + not found in the STL. +
  10. +
  11. + The types of a bimap can be tagged so that each side is accessible by something + closer to the problem than left and right. This leads to more readable, + self-documenting code. The fourth section (Bimaps + with user defined names) shows how to use this feature. +
  12. +
  13. + The bimap mapping framework allows to disable a view of a bimap, including + the standard mapping containers as a particular case. The section Unconstrained Sets + explains how they work. +
  14. +
  15. + The section Additional + information explains how to attach information to each relation + of a bimap. +
  16. +
  17. + The final section (Complete + Instantiation Scheme) summarizes bimap instantiation and explains + how change the allocator type to be used. +
  18. +
+
+
+ + + +
Copyright © 2006 -2007 Matias Capeletto
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_bimap/the_tutorial/bimaps_with_user_defined_names.html b/doc/html/boost_bimap/the_tutorial/bimaps_with_user_defined_names.html new file mode 100644 index 0000000..8147ffa --- /dev/null +++ b/doc/html/boost_bimap/the_tutorial/bimaps_with_user_defined_names.html @@ -0,0 +1,408 @@ + + + +Bimaps + with user defined names + + + + + + + + + + + + + + + +
+Boost C++ LibrariesChapter Logo +HomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ In the following example, the library user inserted comments to guide future + programmers: +

+

+ Go to source code +

+

+

+

+ +

+
+typedef bimap
+<
+    multiset_of<std::string>,
+    int
+
+> People;
+
+People people;
+
+// ...
+
+int user_id;
+std::cin >> user_id;
+
+// people.right : map<id,name>
+
+People::right_const_iterator id_iter = people.right.find(user_id);
+if( id_iter != people.right.end() )
+{
+    // first  : id
+    // second : name
+
+    std::cout << "name: " << id_iter->second << std::endl
+              << "id:   " << id_iter->first  << std::endl;
+}
+else
+{
+    std::cout << "Unknown id, users are:" << std::endl;
+
+    // people.left : map<name,id>
+
+    for( People::left_const_iterator
+            name_iter = people.left.begin(),
+            iend      = people.left.end();
+
+         name_iter != iend; ++name_iter )
+    {
+        // first  : name
+        // second : id
+
+        std::cout << "name: " << name_iter->first  << std::endl
+                  << "id:   " << name_iter->second << std::endl;
+    }
+}
+
+

+

+

+

+

+

+
+

+

+

+

+

+ In Boost.Bimap there is a better way to document the code and in the meantime + helping you to write more mantainable and readable code. You can tag the + two collections of the bimap so they can be accessed by more descriptive + names. +

+

+ tagged +

+

+ A tagged type is a type that has been labelled using a tag. A tag is any + valid C++ type. In a bimap, the types are always tagged. If you do not specify + your own tag, the container uses member_at::left + and member_at::right to tag the left and right sides respectively. + In order to specify a custom tag, the type of each side has to be tagged. + Tagging a type is very simple: +

+
+typedef tagged< int, a_tag > tagged_int;
+
+

+ Now we can rewrite the example: +

+

+ Go to source code +

+

+

+

+ +

+
+struct id   {}; // Tag for the identification number
+struct name {}; // Tag for the name of the person
+
+typedef bimap
+<
+	 tagged< int        , id   >  ,
+    multiset_of< tagged< std::string, name > >
+
+> People;
+
+People people;
+
+// ...
+
+int user_id;
+std::cin >> user_id;
+
+People::map_by<id>::const_iterator id_iter = people.by<id>().find(user_id);
+if( id_iter != people.by<id>().end() )
+{
+    std::cout << "name: " << id_iter->get<name>() << std::endl
+              << "id:   " << id_iter->get<id>()   << std::endl;
+}
+else
+{
+    std::cout << "Unknown id, users are:" << std::endl;
+
+    for( People::map_by<name>::const_iterator
+            name_iter = people.by<name>().begin(),
+            iend      = people.by<name>().end();
+
+        name_iter != iend; ++name_iter )
+    {
+        std::cout << "name: " << name_iter->get<name>() << std::endl
+                  << "id:   " << name_iter->get<id>()   << std::endl;
+    }
+}
+
+

+

+

+

+

+

+
+

+

+

+

+

+ Here is a list of common structures in both tagged and untagged versions. + Remember that when the bimap has user defined tags you can still use the + untagged version structures. +

+
+struct Left  {};
+struct Right {};
+typedef bimap< 
+         multiset_of< tagged< int, Left  > >,
+    unordered_set_of< tagged< int, Right > >
+> bm_type;
+
+bm_type bm;
+
+//...
+
+bm_type::iterator       iter       = bm.begin();
+bm_type::left_iterator  left_iter  = bm.left.begin();
+bm_type::right_iterator right_iter = bm.right.begin();
+
+
+

Table 1.3. Equivalence of expresions using user defined names

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Untagged version +

+
+

+ Tagged version +

+
+

+ bm.left +

+
+

+ bm.by<Left>() +

+
+

+ bm.right +

+
+

+ bm.by<Right>() +

+
+

+ bm_type::left_map +

+
+

+ bm::map_by<Left>::type +

+
+

+ bm_type::right_value_type +

+
+

+ bm::map_by<Right>::value_type +

+
+

+ bm_type::left_iterator +

+
+

+ bm::map_by<Left>::iterator +

+
+

+ bm_type::right_const_iterator +

+
+

+ bm::map_by<Right>::const_iterator +

+
+

+ iter->left +

+
+

+ iter->get<Left>() +

+
+

+ iter->right +

+
+

+ iter->get<Right>() +

+
+

+ left_iter->first +

+
+

+ left_iter->get<Left>() +

+
+

+ left_iter->second +

+
+

+ left_iter->get<Right>() +

+
+

+ right_iter->first +

+
+

+ right_iter->get<Right>() +

+
+

+ right_iter->second +

+
+

+ right_iter->get<Left>() +

+
+

+ bm.project_left(iter) +

+
+

+ bm.project<Left>(iter) +

+
+

+ bm.project_right(iter) +

+
+

+ bm.project<Right>(iter) +

+
+
+
+
+ + + +
Copyright © 2006 -2007 Matias Capeletto
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_bimap/the_tutorial/complete_instantiation_scheme.html b/doc/html/boost_bimap/the_tutorial/complete_instantiation_scheme.html new file mode 100644 index 0000000..87bf1d5 --- /dev/null +++ b/doc/html/boost_bimap/the_tutorial/complete_instantiation_scheme.html @@ -0,0 +1,253 @@ + + + +Complete + instantiation scheme + + + + + + + + + + + + + + + +
+Boost C++ LibrariesChapter Logo +HomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ To summarize, this is the complete instantiation scheme. +

+
+typedef bimap
+<
+    LeftCollectionType, RightCollectionType
+
+    [ , SetTypeOfRelation  ]  // Default to left_based
+    [ , with_info< Info >  ]  // Default to no info
+    [ , Allocator          ]  // Default to std::allocator<>
+
+> bm;
+
+

+ {Side}CollectionType + can directly be a type. This defaults to set_of<Type>, or can be a {CollectionType}_of<Type> + specification. Additionally, the type of this two parameters can be tagged + to specify user defined names instead of the usual member_at::-Side- tags. +

+

+ The possibles way to use the first parameter are: +

+
+bimap< Type, R >
+
+
    +
  • + Left type: Type +
  • +
  • + Left collection type: set_of< Type > +
  • +
  • + Left tag: member_at::left +
  • +
+
+bimap< #[#CollectionType]#_of< Type >, R >
+
+
    +
  • + Left type: Type +
  • +
  • + Left collection type: CollectionType_of< LeftType > +
  • +
  • + Left tag: member_at::left +
  • +
+
+bimap< tagged< Type, Tag >, R >
+
+
    +
  • + Left type: Type +
  • +
  • + Left collection type: set_of< LeftType + > +
  • +
  • + Left tag: Tag +
  • +
+
+bimap< #[#CollectionType]#_of< tagged< Type, Tag > >, R >
+
+
    +
  • + Left type: Type +
  • +
  • + Left collection type: CollectionType_of< LeftType > +
  • +
  • + Left tag: Tag +
  • +
+

+ The same options are available for the second parameter. +

+

+ The last three parameters are used to specify the collection type of the + relation, the information member and the allocator type. +

+

+ If you want to specify a custom allocator type while relying on the default + value of CollectionTypeOfRelation, you can do so by simply writing bimap<LeftKeyType, + RightKeyType, + Allocator>. + Boost.Bimap's internal machinery detects that the third parameter in this + case does not refer to the relation type but rather to an allocator. +

+

+ The following are the possible ways of instantiating the last three parameters + of a bimap. You can ignore some of the parameter but the order must be respected. +

+
+bimap< L, R >
+
+
    +
  • + set_of_relation_type: based on the left key type +
  • +
  • + info: no info +
  • +
  • + allocator: std::allocator +
  • +
+
+bimap< L, R ,SetOfRelationType>
+
+
    +
  • + set_of_relation_type: SetOfRelationType +
  • +
  • + info: no info +
  • +
  • + allocator: std::allocator +
  • +
+
+bimap< L, R , SetOfRelationType, with_info<Info> >
+
+
    +
  • + set_of_relation_type: SetOfRelationType +
  • +
  • + info: Info +
  • +
  • + allocator: std::allocator +
  • +
+
+bimap< L, R , SetOfRelationType, with_info<Info>, Allocator>
+
+
    +
  • + set_of_relation_type: SetOfRelationType +
  • +
  • + info: Info +
  • +
  • + allocator: Allocator +
  • +
+
+bimap< L, R , SetOfRelationType, Allocator>
+
+
    +
  • + set_of_relation_type: SetOfRelationType +
  • +
  • + info: no info +
  • +
  • + allocator: Allocator +
  • +
+
+bimap< L, R , with_info<Info> >
+
+
    +
  • + set_of_relation_type: based on the left key type +
  • +
  • + info: Info +
  • +
  • + allocator: std::allocator +
  • +
+
+bimap< L, R , with_info<Info>, Allocator>
+
+
    +
  • + set_of_relation_type: based on the left key type +
  • +
  • + allocator: Allocator +
  • +
+
+bimap< L, R , Allocator>
+
+
    +
  • + set_of_relation_type: based on the left key type +
  • +
  • + info: no info +
  • +
  • + allocator: Allocator +
  • +
+
+ + + +
Copyright © 2006 -2007 Matias Capeletto
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_bimap/the_tutorial/controlling_collection_types.html b/doc/html/boost_bimap/the_tutorial/controlling_collection_types.html new file mode 100644 index 0000000..f178e49 --- /dev/null +++ b/doc/html/boost_bimap/the_tutorial/controlling_collection_types.html @@ -0,0 +1,565 @@ + + + +Controlling + collection types + + + + + + + + + + + + + + + +
+Boost C++ LibrariesChapter Logo +HomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ As has already been said, in STL maps, you can only control the constraints + from one of the collections, namely the one that you are viewing. In Boost.Bimap, + you can control both and it is as easy as using the STL. +

+

+ extended.mapping.framework +

+

+ The idea is to use the same constraint names that are used in the standard. + If you don't specify the collection type, Boost.Bimap assumes that the + collection is a set. The instantiation of a bimap with custom collection + types looks like this: +

+
+typedef bimap< CollectionType_of<A>, CollectionType_of<B> > bm_type;
+
+

+ The following is the list of all supported collection types. +

+
+

Table 1.2. Collection of Key Types

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ name +

+
+

+ Features +

+
+

+ map view type +

+
+

+ set_of +

+
+

+ ordered, unique +

+
+

+ map +

+
+

+ multiset_of +

+
+

+ ordered +

+
+

+ multimap +

+
+

+ unordered_set_of +

+
+

+ hashed, unique +

+
+

+ unordered_map +

+
+

+ unordered_multiset_of +

+
+

+ hashed +

+
+

+ unordered_multimap +

+
+

+ list_of +

+
+

+ sequenced +

+
+

+ list_map +

+
+

+ vector_of +

+
+

+ random access +

+
+

+ vector_map +

+
+

+ unconstrained_set_of +

+
+

+ unconstrained +

+
+

+ can not be viewed +

+
+
+

+ list_of and vector_of map views are not associated + with any existing STL associative containers. They are two examples of + unsorted associative containers. unconstrained_set_of + allow the user to ignore a view. This will be explained later. +

+

+ bimap.structures +

+

+ The selection of the collection type affects the possible operations that + you can perform with each side of the bimap and the time it takes to do + each. If we have: +

+
+typedef bimap< CollectionType_of<A>, CollectionType_of<B> > bm_type;
+bm_type bm;
+
+

+ The following now describes the resulting map views of the bidirectional + map. +

+
    +
  • +bm.left is signature-compatible with + LeftMapType<A,B> +
  • +
  • +bm.right is signature-compatible with + RightMapType<B,A> +
  • +
+
+
+ +

+ Each collection type template has different parameters to control its behaviour. + For example, in set_of + specification, you can pass a Functor type that compares two types. All + of these parameters are exactly the same as those of the standard library + container, except for the allocator type. You will learn later how to change + the allocator for a bimap. +

+

+ The following table lists the meanings of each collection type's parameters. +

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ name +

+
+

+ Additional Parameters +

+
+

+ set_of<T,KeyComp> +

+

+ multiset_of<T,KeyComp> +

+
+

+ KeyComp is a Functor that compares + two types using a less-than operator. By default, this is std::less<T>. +

+
+

+ unordered_set_of<T,HashFunctor,EqualKey> +

+

+ unordered_multiset_of<T,HashFunctor,EqualKey> +

+
+

+ HashFunctor converts a T object into an std::size_t value. By default it is + boost::hash<T>. +

+

+ EqualKey is a Functor that tests + two types for equality. By default, the equality operator is std::equal_to<T>. +

+
+

+ list_of<T> +

+
+

+ No additional parameters. +

+
+

+ vector_of<T> +

+
+

+ No additional parameters. +

+
+

+ unconstrained_set_of<T> +

+
+

+ No additional parameters. +

+
+
+
+ +
+ + Countries + Populations +
+

+ We want to store countries populations. The requeriments are: +

+
    +
  1. + Get a list of countries in decresing order of their populations. +
  2. +
  3. + Given a countrie, get their population. +
  4. +
+

+ Lets create the appropiate bimap. +

+
+typedef bimap<
+
+    unordered_set_of< std::string >,
+    multiset_of< long, std::greater<long> >
+
+> populations_bimap;
+
+

+ First of all countries names are unique identifiers, while two countries + may have the same population. This is why we choose multiset_of for populations. +

+

+ Using a multiset_of for + population allow us to iterate over the data. Since listing countries ordered + by their names is not a requisite, we can use an unordered_set_of + that allows constant order look up. +

+

+ And now lets use it in a complete example +

+

+ Go to source code +

+

+

+

+ +

+
+typedef bimap<
+
+    unordered_set_of< std::string >,
+    multiset_of< long, std::greater<long> >
+
+> population_bimap;
+
+typedef population_bimap::value_type population;
+
+population_bimap pop;
+pop.insert( population("China",          1321000000) );
+pop.insert( population("India",          1129000000) );
+pop.insert( population("United States",   301950000) );
+pop.insert( population("Indonesia",       234950000) );
+pop.insert( population("Brazil",          186500000) );
+pop.insert( population("Pakistan",        163630000) );
+
+std::cout << "Countries by their population:" << std::endl;
+
+// First requirement
+1for( population_bimap::right_const_iterator
+        i = pop.right.begin(), iend = pop.right.end();
+        i != iend ; ++i )
+{
+    std::cout << i->second << " with " << i->first << std::endl;
+}
+
+// Second requirement
+2std::cout << "Population of China: " << pop.left.at("China") << std::endl;
+
+

+

+

+

+

+

+
+ + + + + + + + +
+1

The right map view works like a std::multimap< long, std::string, std::greater<long> >, + We can iterate over it to print the results in the required order.

+2

The + left map view works like a std::unordered_map< std::string, long >, given the name of the country we + can use it to search for the population in constant time

+

+

+

+

+
+ + Repetitions + counter +
+

+ We want to count the repetitions for each word in a text and print them + in order of appearance. +

+

+ Go to source code +

+

+

+

+ +

+
+typedef bimap
+<
+    unordered_set_of< std::string >,
+    list_of< counter > 1
+
+> word_counter;
+
+typedef boost::tokenizer<boost::char_separator<char> > text_tokenizer;
+
+std::string text=
+    "Relations between data in the STL are represented with maps."
+    "A map is a directed relation, by using it you are representing "
+    "a mapping. In this directed relation, the first type is related to "
+    "the second type but it is not true that the inverse relationship "
+    "holds. This is useful in a lot of situations, but there are some "
+    "relationships that are bidirectional by nature.";
+
+// feed the text into the container
+word_counter   wc;
+text_tokenizer tok(text,boost::char_separator<char>(" \t\n.,;:!?'\"-"));
+
+for( text_tokenizer::const_iterator it = tok.begin(), it_end = tok.end();
+     it != it_end ; ++it )
+{
+    2++ wc.left[*it];
+}
+
+// list words with counters by order of appearance
+3for( word_counter::right_const_iterator
+        wit = wc.right.begin(), wit_end = wc.right.end();
+
+     wit != wit_end; ++wit )
+{
+    std::cout << wit->second << ": " << wit->first;
+}
+
+

+

+

+

+

+

+
+ + + + + + + + + + + + +
+1

counter is an integer + that is initialized in zero in the constructor

+2

Because the right collection + type is list_of, the + right data is not used a key and can be modified in the same way as with + standard maps.

+3

When we insert the elements using the left map view, the + element is inserted at the end of the list.

+

+

+

+

+
+
+ + + +
Copyright © 2006 -2007 Matias Capeletto
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_bimap/the_tutorial/differences_with_standard_maps.html b/doc/html/boost_bimap/the_tutorial/differences_with_standard_maps.html new file mode 100644 index 0000000..d24aa84 --- /dev/null +++ b/doc/html/boost_bimap/the_tutorial/differences_with_standard_maps.html @@ -0,0 +1,481 @@ + + + +Differences + with standard maps + + + + + + + + + + + + + + + +
+Boost C++ LibrariesChapter Logo +HomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ Remember that a map can be interpreted as a relation between two collections. + In bimaps we have the freedom to change both collection types, imposing + constrains in each of them. Some insertions that we give for granted to + success in standard maps fails with bimaps. For example: +

+
+bimap<int,std::string> bm;
+
+bm.left.insert(1,"orange");
+bm.left.insert(2,"orange"); // No effect! returns make_pair(iter,false)
+
+

+ The insertion will only succeed if it is allowed by all views of the bimap. In the next snippet we define + the right collection as a multiset, when we try to insert the same two + elements the second insertion is allowed by the left map view because both + values are different and it is allowed by the right map view because it + is a non-unique collection type. +

+
+bimap<int, multiset_of<std::string> > bm;
+
+bm.left.insert(1,"orange");
+bm.left.insert(2,"orange"); // Insertion succeed!
+
+

+ If we use a custom collection of relation type, the insertion has to be + allowed by it too. +

+
+
+ +

+ The relations stored in the Bimap will not be in most cases modifiable + directly by iterators because both sides are used as keys of key-based + sets. When a bimap<A,B> left view iterator is dereferenced + the return type is signature-compatible with a std::pair< const A, const B >. + However there are some collection types that are not key_based, + for example list_of. If a Bimap uses one of these collection types there + is no problem with modifying the data of that side. The following code + is valid: +

+
+typedef bimap< int, list_of< std::string > > bm_type;
+bm_type bm;
+bm.insert( bm_type::relation( 1, "one" ) );
+...
+bm.left.find(1)->second = "1"; // Valid
+
+

+ In this case, when the iterator is dereferenced the return type is signature-compatible + with a std::pair<const int, std::string>. +

+

+ The following table shows the constness of the dereferenced data of each + collection type of: +

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Side collection type +

+
+

+ Dereferenced data +

+
+

+ set_of +

+
+

+ constant +

+
+

+ multiset_of +

+
+

+ constant +

+
+

+ unordered_set_of +

+
+

+ constant +

+
+

+ unordered_multiset_of +

+
+

+ constant +

+
+

+ list_of +

+
+

+ mutable +

+
+

+ vector_of +

+
+

+ mutable +

+
+

+ unconstrained_set_of +

+
+

+ mutable +

+
+

+ Here are some examples. When dereferenced the iterators returns a type + that is signature-compatible with these types. +

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ Bimap type +

+
+

+ Signature-compatible types +

+
+

+ bimap<A,B> +

+
+

+ iterator -> relation<const + A,const B> +

+

+ left_iterator + -> pair<const + A,const B> +

+

+ right_iterator + -> pair<const + B,const A> +

+
+

+ bimap<multiset_of<A>,unordered_set_of<B> + > +

+
+

+ iterator -> relation<const + A,const B> +

+

+ left_iterator + -> pair<const + A,const B> +

+

+ right_iterator + -> pair<const + B,const A> +

+
+

+ bimap<set_of<A>,list_of<B> + > +

+
+

+ iterator -> relation<const + A,B> +

+

+ left_iterator + -> pair<const + A,B> +

+

+ right_iterator + -> pair<B,const + A> +

+
+

+ bimap<vector_of<A>,set_of<B> + > +

+
+

+ iterator -> relation<A,const + B> +

+

+ left_iterator + -> pair<A,const + B> +

+

+ right_iterator + -> pair<const + B,A> +

+
+

+ bimap<list_of<A>,unconstrained_set_of<B> + > +

+
+

+ iterator -> relation<A,B> +

+

+ left_iterator + -> pair<A,B> +

+

+ right_iterator + -> pair<B,A> +

+
+
+
+ +

+ set_of and unordered_set_of map views overload + operator[] + to retrieve the associated data of a given key only when the other collection + type is a mutable one. In these cases it works in the same way as the standard. +

+
+bimap< unorderd_set_of< std::string>, list_of<int> > bm;
+
+bm.left["one"] = 1; // Ok
+
+

+ The standard defines an access function for map + and unordered_map: +

+
+const data_type & at(const key_type & k) const;
+      data_type & at(const key_type & k);
+
+

+ These functions look for a key and returns the associated data value, but + throws a std::out_of_range exception if the key is + not found. +

+

+ In bimaps the constant version of these functions is given for set_of and unorderd_set_of + map views independently of the other collection type. The mutable version + is only provided when the other collection type is mutable. +

+

+ The following examples shows the behaviour of at(key) +

+

+ Go to source code +

+

+

+

+ +

+
+typedef bimap< set_of< std::string >, list_of< int > > bm_type;
+bm_type bm;
+
+try
+{
+    bm.left.at("one") = 1; // throws std::out_of_range
+}
+catch( std::out_of_range & e ) {}
+
+assert( bm.empty() );
+
+bm.left["one"] = 1; // Ok
+
+assert( bm.left.at("one") == 1 ); // Ok
+
+

+

+

+

+

+

+
+

+

+

+

+

+

+

+ +

+
+typedef bimap< multiset_of<std::string>, unordered_set_of<int> > bm_type;
+bm_type bm;
+
+bm.right[1] = "one"; // compilation error
+
+bm.right.insert( bm_type::right_value_type(1,"one") );
+
+assert( bm.right.at(1) == "one" ); // Ok
+
+try
+{
+    std::cout << bm.right.at(2); // throws std::out_of_range
+}
+catch( std::out_of_range & e ) {}
+
+bm.right.at(1) = "1"; // compilation error
+
+
+

+

+

+

+

+

+
+

+

+

+

+
+
+ +

+ The complexity of some operations is different in bimaps. Read the + reference to find the complexity of each function. +

+
+
+ + + +
Copyright © 2006 -2007 Matias Capeletto
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_bimap/the_tutorial/discovering_the_bimap_framework.html b/doc/html/boost_bimap/the_tutorial/discovering_the_bimap_framework.html new file mode 100644 index 0000000..16362b0 --- /dev/null +++ b/doc/html/boost_bimap/the_tutorial/discovering_the_bimap_framework.html @@ -0,0 +1,343 @@ + + + +Discovering + the bimap framework + + + + + + + + + + + + + + + +
+Boost C++ LibrariesChapter Logo +HomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ One way to interpret bidirectional maps is as a function between two collections + of data, lets call them the left and the right collection. An element in + this bimap is a relation between an element from the left collection and + an element from the right collection. The types of both collections defines + the bimap behaviour. We can view the stored data from the left side, as + a mapping between keys from the left collection and data from the right + one, or from the right side, as a mapping between keys from the right collection + and data from the left collection. +

+
+
+ +

+ Relationships between data in the STL are represented by maps. A standard + map is a directed relation of keys from a left collection and data from + a right unconstrained collection. The following diagram shows the relationship + represented and the user's viewpoint. +

+

+ standard.mapping.framework +

+

+ The left collection type depends on the selected map type. For example + if the the map type is std::multimap + the collection type of X is a multiset_of. + The following table shows the equivalent types for the std associative + containers. +

+
+

Table 1.1. std associative containers

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ container +

+
+

+ left collection type +

+
+

+ right collection type +

+
+

+ map +

+
+

+ set_of +

+
+

+ no constraints +

+
+

+ multimap +

+
+

+ multiset_of +

+
+

+ no constraints +

+
+

+ unordered_map +

+
+

+ unordered_set_of +

+
+

+ no constraints +

+
+

+ unordered_multimap +

+
+

+ unordered_multiset_of +

+
+

+ no constraints +

+
+
+
+
+
+ +

+ Boost.Bimap design is based on the STL, and extends the framework in a + natural way. The following diagram represents the new situation. +

+

+ extended.mapping.framework +

+

+ Notice that now the std::maps + are a particular case of a Boost.Bimap container, where you can view only + one side of the relationship and can control the constraints of only one + of the collections. Boost.Bimap allows the user to view the relationship + from three viewpoints. You can view it from one side, obtaining a std::map compatible container, or you can + work directly with the whole relation. +

+

+ The next diagram shows the layout of the relation and pairs of a bimap. + It is the one from the one minute tutorial +

+

+ relation.and.pair +

+

+ Bimap pairs are signature-compatible with standard pairs but are different + from them. As you will see in other sections they can be tagged with user + defined names and additional information can be attached to them. You can + convert from std::pairs to bimap pairs directly but the + reverse conversion is not provided. This mean that you can insert elements + in a bimap using algorithms like std::copy + from containers like std::map, + or use std::make_pair to add new elements. However + it is best to use bm.left.insert( bm_type::left_value_type(f,s) ) instead + of bm.insert( std::make_pair(f,s) ) to avoid + an extra call to the copy constructor of each type. +

+

+ The following code snippet shows the relation between a bimap and standard + maps. +

+
+ + + + + +
[Note]Note
+

+

+

+ You have to used references to views, and not directly views object. + Views cannot be constructed as separate objects from the container + they belong to, so the following: +

+
+// Wrong: we forgot the & after bm_type::left_type
+bm_type::left_map lm = bm.left;
+
+

+ does not compile, since it is trying to construct the view object + lm. This is a common + source of errors in user code. +

+

+

+
+

+ Go to source code +

+

+

+

+ +

+
+template< class Map, class CompatibleKey, class CompatibleData >
+void use_it( Map & m,
+             const CompatibleKey  & key,
+             const CompatibleData & data )
+{
+    typedef typename Map::value_type value_type;
+    typedef typename Map::const_iterator const_iterator;
+
+    m.insert( value_type(key,data) );
+    const_iterator iter = m.find(key);
+    if( iter != m.end() )
+    {
+        assert( iter->first  == key  );
+        assert( iter->second == data );
+
+        std::cout << iter->first << " --> " << iter->second;
+    }
+    m.erase(key);
+}
+
+int main()
+{
+    typedef bimap< set_of<std::string>, set_of<int> > bimap_type;
+    bimap_type bm;
+
+    // Standard map
+    {
+        typedef std::map< std::string, int > map_type;
+        map_type m;
+
+        use_it( m, "one", 1 );
+    }
+
+    // Left map view
+    {
+        typedef bimap_type::left_map map_type;
+        map_type & m = bm.left;
+
+        use_it( m, "one", 1 );
+    }
+
+    // Reverse standard map
+    {
+        typedef std::map< int, std::string > reverse_map_type;
+        reverse_map_type rm;
+
+        use_it( rm, 1, "one" );
+    }
+
+    // Right map view
+    {
+        typedef bimap_type::right_map reverse_map_type;
+        reverse_map_type & rm = bm.right;
+
+        use_it( rm, 1, "one" );
+    }
+
+    return 0;
+}
+
+

+

+

+

+

+

+
+

+

+

+

+
+
+ + + +
Copyright © 2006 -2007 Matias Capeletto
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_bimap/the_tutorial/hooking_information.html b/doc/html/boost_bimap/the_tutorial/hooking_information.html new file mode 100644 index 0000000..41df430 --- /dev/null +++ b/doc/html/boost_bimap/the_tutorial/hooking_information.html @@ -0,0 +1,221 @@ + + + +Hooking + Information + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ Bidirectional maps may have associated information about each relation. Suppose + we want to represent a books and author bidirectional map. +

+

+

+

+ +

+
+typedef bimap<
+
+    multiset_of< std::string >, // author
+         set_of< std::string >  // book name
+
+> bm_type;
+typedef bm_type::value_type book;
+
+bm_type bm;
+
+bm.insert( book( "Bjarne Stroustrup"   , "The C++ Programming Language" ) );
+bm.insert( book( "Scott Meyers"        , "Effective C++"                ) );
+bm.insert( book( "Andrei Alexandrescu" , "Modern C++ Design"            ) );
+
+// Print the author of Modern C++
+std::cout << bm.right.at( "Modern C++ Design" );
+
+

+

+

+

+

+

+
+

+

+

+

+

+ Suppose now that we want to store abstract of each book. We have two options: +

+
    +
  1. + Books name are unique identifiers, so we can create a separate std::map< string, string > + that relates books names with abstracts. +
  2. +
  3. + We can use Boost.MultiIndex for the new beast. +
  4. +
+

+ Option 1 is the wrong approach, if we go this path we lost what bimap has + won us. We now have to maintain the logic of two interdependent containers, + there is an extra string stored for each book name, and the performance will + be worse. This is far away from being a good solution. +

+

+ Option 2 is correct. We start thinking books as entries in a table. So it + makes sense to start using Boost.MultiIndex. We can then add the year of + publication, the price, etc... and we can index this new items too. So Boost.MultiIndex + is a sound solution for our problem. +

+

+ The thing is that there are cases where we want to maintain bimap semantics + (use at() + to find an author given a book name and the other way around) and add information + about the relations that we are sure we will not want to index later (like + the abstracts). Option 1 is not possible, option 2 neither. +

+

+ Boost.Bimap provides support for this kind of situations by means of information + hooking. You can pass an extra parameter to a bimap with the type info_hook< + InfoType > + and an info member of type + InfoType will appear in the + relation and bimap pairs. +

+

+ Relations and bimap pairs constructors can take an extra argument. If only + two arguments are used, the information will be initialized with their default + constructor. +

+

+

+

+ +

+
+typedef bimap<
+
+    multiset_of< std::string >, // author
+         set_of< std::string >, // book name
+
+      with_info< std::string >  // abstract
+
+> bm_type;
+typedef bm_type::value_type book;
+
+bm_type bm;
+
+bm.insert(
+
+    book( "Bjarne Stroustrup"   , "The C++ Programming Language",
+
+          "For C++ old-timers, the first edition of this book is"
+          "the one that started it all—the font of our knowledge." )
+);
+
+
+// Print the abstract of the bible
+std::cout << bm.right.at("The C++ Programming Language");
+
+// Print the abstract of this book
+bm_type::left_iterator i = bm.left.find("Bjarne Stroustrup");
+std::cout << i->info;
+
+

+

+

+

+

+

+
+

+

+

+

+

+ Contrary to the two key types, the information will be mutable using iterators. +

+

+

+

+ +

+
+i->info += "More details about this book";
+
+

+

+

+

+

+

+
+

+

+

+

+

+ A new function is included in unique map views: info_at(key), that + mimics the standard at(key) function + but returned the associated information instead of the data. +

+

+

+

+ +

+
+// Print the new abstract
+std::cout << bm.right.info_at("The C++ Programming Language");
+
+

+

+

+

+

+

+
+

+

+

+

+

+ Go to source code +

+
+ + + +
Copyright © 2006 -2007 Matias Capeletto
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_bimap/the_tutorial/the_collection_of_relations_type.html b/doc/html/boost_bimap/the_tutorial/the_collection_of_relations_type.html new file mode 100644 index 0000000..01a7363 --- /dev/null +++ b/doc/html/boost_bimap/the_tutorial/the_collection_of_relations_type.html @@ -0,0 +1,432 @@ + + + +The + collection of relations type + + + + + + + + + + + + + + + +
+Boost C++ LibrariesChapter Logo +HomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ Being able to change the collection type of the bimap relation view is + another very important feature. Remember that this view allows the user + to see the container as a group of the stored relations. This view has + set semantics instead of map semantics. +

+

+ collection.type.of.relation +

+

+ By default, Boost.Bimap will base the collection type of the relation on + the type of the left collection. If the left collection type is a set, + then the collection type of the relation will be a set with the same order + as the left view. +

+

+ In general, Boost.Bimap users will base the collection type of a relation + on the type of the collection on one of the two sides. However there are + times where it is useful to give this collection other constraints or simply + to order it differently. The user is allowed to choose between: +

+
    +
  • + left_based +
  • +
  • + right_based +
  • +
  • + set_of_relation<> +
  • +
  • + multiset_of_relation<> +
  • +
  • + unordered_set_of_relation<> +
  • +
  • + unordered_multiset_of_relation<> +
  • +
  • + list_of_relation +
  • +
  • + vector_of_relation +
  • +
  • + unconstrained_set_of_relation +
  • +
+
+ + + + + +
[Tip]Tip
+

+

+

+ The first two options and the last produce faster bimaps, so prefer + these where possible. +

+

+

+
+

+ more.bimap.structures +

+

+ The collection type of relation can be used to create powerful containers. + For example, if you need to maximize search speed, then the best bidirectional + map possible is one that relates elements from an unordered_set + to another unordered_set. + The problem is that this container cannot be iterated. If you need to know + the list of relations inside the container, you need another collection + type of relation. In this case, a list_of_relation + is a good choice. The resulting container trades insertion and deletion + time against fast search capabilities and the possibility of bidirectional + iteration. +

+

+ Go to source code +

+

+

+

+ +

+
+#include <iostream>
+#include <string>
+#include <boost/bimap/bimap.hpp>
+#include <boost/bimap/list_of.hpp>
+#include <boost/bimap/unordered_set_of.hpp>
+
+struct english {};
+struct spanish {};
+
+int main()
+{
+    using namespace boost::bimaps;
+
+    typedef bimap
+    <
+        unordered_set_of< tagged< std::string, spanish > >,
+        unordered_set_of< tagged< std::string, english > >,
+        list_of_relation
+
+    > translator;
+
+    translator trans;
+
+    // We have to use `push_back` because the collection of relations is
+    // a `list_of_relation`
+
+    trans.push_back( translator::value_type("hola"  ,"hello"   ) );
+    trans.push_back( translator::value_type("adios" ,"goodbye" ) );
+    trans.push_back( translator::value_type("rosa"  ,"rose"    ) );
+    trans.push_back( translator::value_type("mesa"  ,"table"   ) );
+
+    std::cout << "enter a word" << std::endl;
+    std::string word;
+    std::getline(std::cin,word);
+
+    // Search the queried word on the from index (Spanish)
+
+    translator::map_by<spanish>::const_iterator is
+        = trans.by<spanish>().find(word);
+
+    if( is != trans.by<spanish>().end() )
+    {
+        std::cout << word << " is said "
+                  << is->get<english>()
+                  << " in English" << std::endl;
+    }
+    else
+    {
+        // Word not found in Spanish, try our luck in English
+
+        translator::map_by<english>::const_iterator ie
+            = trans.by<english>().find(word);
+
+        if( ie != trans.by<english>().end() )
+        {
+            std::cout << word << " is said "
+                      << ie->get<spanish>()
+                      << " in Spanish" << std::endl;
+        }
+        else
+        {
+            // Word not found, show the possible translations
+
+            std::cout << "No such word in the dictionary"      << std::endl;
+            std::cout << "These are the possible translations" << std::endl;
+
+            for( translator::const_iterator
+                    i = trans.begin(),
+                    i_end = trans.end();
+
+                    i != i_end ; ++i )
+            {
+                std::cout << i->get<spanish>()
+                          << " <---> "
+                          << i->get<english>()
+                          << std::endl;
+            }
+        }
+    }
+    return 0;
+}
+
+

+

+

+

+

+

+
+

+

+

+

+
+
+ +

+ Each collection type of relation has different parameters to control its + behaviour. For example, in the set_of_relation + specification, you can pass a Functor type that compares two types. All + of the parameters are exactly as in the standard library containers, except + for the type, which is set to the bimap relation and the allocator type. + To help users in the creation of each functor, the collection type of relation + templates takes an mpl lambda expression where the relation type will be + evaluated later. A placeholder named _relation + is available to bimap users. +

+

+ The following table lists the meaning of the parameters for each collection + type of relations. +

+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

+ name +

+
+

+ Additional Parameters +

+
+

+ left_based +

+
+

+ Not a template. +

+
+

+ right_based +

+
+

+ Not a template. +

+
+

+ set_of_relation<KeyComp> +

+

+ multiset_of_relation<KeyComp> +

+
+

+ KeyComp is a Functor that compares + two types using less than. By default, the less-than operator is + std::less<_relation>. +

+
+

+ unordered_set_of_relation<HashFunctor,EqualKey> +

+

+ unordered_multiset_of_relation<HashFunctor,EqualKey> +

+
+

+ HashFunctor converts the relation into an std::size_t value. By default it is + boost::hash<_relation>. +

+

+ EqualKey is a Functor that tests + two relations for equality. By default, the equality operator is + std::equal_to<_relation>. +

+
+

+ list_of_relation +

+
+

+ Not a template. +

+
+

+ vector_of_relation +

+
+

+ Not a template. +

+
+

+ unconstrained_set_of_relation +

+
+

+ Not a template. +

+
+
+
+ +

+ Consider this example: +

+
+template< class Rel >
+struct RelOrder
+{
+    bool operator()(Rel ra, Rel rb) const
+    {
+        return (ra.left+ra.right) < (rb.left+rb.right);
+    }
+};
+
+typedef bimap
+<
+        multiset_of< int >,
+        multiset_of< int >,
+        set_of_relation< RelOrder<_relation> >
+
+> bimap_type;
+
+

+ Here the bimap relation view is ordered using the information of both sides. + This container will only allow unique relations because set_of_relation + has been used but the elements in each side of the bimap can be repeated. +

+
+struct name         {};
+struct phone_number {};
+
+typedef bimap
+<
+    tagged< unordered_multiset_of< string >, name         >,
+    tagged< unordered_set_of     < int    >, phone_number >,
+    set_of_relation<>
+
+> bimap_type;
+
+

+ In this other case the bimap will relate names to phone numbers. Names + can be repeated and phone numbers are unique. You can perform quick searches + by name or phone number and the container can be viewed ordered using the + relation view. +

+
+
+ + + +
Copyright © 2006 -2007 Matias Capeletto
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_bimap/the_tutorial/unconstrained_sets.html b/doc/html/boost_bimap/the_tutorial/unconstrained_sets.html new file mode 100644 index 0000000..12244b2 --- /dev/null +++ b/doc/html/boost_bimap/the_tutorial/unconstrained_sets.html @@ -0,0 +1,195 @@ + + + +Unconstrained + Sets + + + + + + + + + + + + + + + +
+Boost C++ LibrariesChapter Logo +HomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ Unconstrained sets allow the user to disable one of the views of a bimap. + Doing so makes the bimap operations execute faster and reduces memory consumption. + This completes the bidirectional mapping framework by including unidirectional + mappings as a particular case. +

+

+ Unconstrained sets are useful for the following reasons: +

+
    +
  • + A bimap type has stronger guarantees than its standard equivalent, and + includes some useful functions (replace, modify) that the standard does + not have. +
  • +
  • + You can view the mapping as a collection of relations. +
  • +
  • + Using this kind of map makes the code very extensible. If, at any moment + of the development, the need to perform searches from the right side of + the mapping arises, the only necessary change is to the typedef. +
  • +
+

+ Given this bimap instance, +

+

+

+

+ +

+
+typedef bimap< std::string, unconstrained_set_of<int> > bm_type;
+typedef bm_type::left_map map_type;
+
+bm_type bm;
+map_type & m = bm.left;
+
+

+

+

+

+

+

+
+

+

+

+

+

+ or this standard map one +

+

+

+

+ +

+
+typedef std::map< std::string, int > map_type;
+
+map_type m;
+
+

+

+

+

+

+

+
+

+

+

+

+

+ The following code snippet is valid +

+

+

+

+ +

+
+m["one"] = 1;
+
+assert( m.find("one") != m.end() );
+
+for( map_type::iterator i = m.begin(), iend = m.end(); i != iend; ++i )
+{
+    1++(i->second);
+}
+
+m.erase("one");
+
+

+

+

+

+

+

+
+ + +
+1

The right collection of the bimap is mutable so its elements can be modified + using iterators.

+

+

+

+

+

+ But using a bimap has some benefits +

+

+

+

+ +

+
+typedef map_type::const_iterator const_iterator;
+typedef std::pair<const_iterator,const_iterator> const_range;
+
+1const_range r = m.range( "one" <= _key, _key <= "two" );
+for( const_iterator i = r.first; i != r.second; ++i )
+{
+    std::cout << i->first << "-->" << i->second << std::endl;
+}
+
+m.modify_key( m.begin(), _key = "1" );
+
+

+

+

+

+

+

+
+ + +
+1

This range is a model of BidirectionalRange, read the docs of Boost.Range + for more information.

+

+

+

+

+

+ Go to source code +

+
+ + + +
Copyright © 2006 -2007 Matias Capeletto
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_bimap/the_tutorial/useful_functions.html b/doc/html/boost_bimap/the_tutorial/useful_functions.html new file mode 100644 index 0000000..f40a862 --- /dev/null +++ b/doc/html/boost_bimap/the_tutorial/useful_functions.html @@ -0,0 +1,454 @@ + + + +Useful functions + + + + + + + + + + + + + + + +
+Boost C++ LibrariesChapter Logo +HomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ + +
+ +

+ Iterators can be projected to any of the three views of the bimap. A bimap + provides three member functions to cope with projection: project_left, project_right + and project_up, with projects + iterators to the left map view, the right + map view and the collection of relations view. + These functions take any iterator from the bimap and retrieve an iterator + over the projected view pointing to the same element. +

+

+ Here is an example that uses projection: +

+

+ Go to source code +

+

+

+

+ +

+
+typedef bimap<std::string,multiset_of<int,std::greater<int> > > bm_type;
+
+bm_type bm;
+bm.insert( bm_type::value_type("John" ,34) );
+bm.insert( bm_type::value_type("Peter",24) );
+bm.insert( bm_type::value_type("Mary" ,12) );
+
+// Find the name of the next younger person after Peter
+
+bm_type::left_const_iterator name_iter = bm.left.find("Peter");
+
+bm_type::right_const_iterator years_iter = bm.project_right(name_iter);
+
+++years_iter;
+
+std::cout << "The next younger person after Peter is " << years_iter->second;
+
+

+

+

+

+

+

+
+

+

+

+

+
+
+ +

+ These functions are members of the views of a bimap that are not founded + in their standard counterparts. +

+

+ The replace family member + functions performs in-place replacement of a given element as the following + example shows: +

+

+ Go to source + code +

+

+

+

+ +

+
+typedef bimap< int, std::string > bm_type;
+bm_type bm;
+
+bm.insert( bm_type::value_type(1,"one") );
+
+// Replace (1,"one") with (1,"1") using the right map view
+{
+    bm_type::right_iterator it = bm.right.find("one");
+
+    bool successful_replace = bm.right.replace_key( it, "1" );
+
+    assert( successful_replace );
+}
+
+bm.insert( bm_type::value_type(2,"two") );
+
+// Fail to replace (1,"1") with (1,"two") using the left map view
+{
+    assert( bm.size() == 2 );
+
+    bm_type::left_iterator it = bm.left.find(1);
+
+    bool successful_replace = bm.left.replace_data( it, "two" );
+
+    1assert( ! successful_replace );
+    assert( bm.size() == 2 );
+}
+
+

+

+

+

+

+

+
+ + +
+1

it is still valid here, + and the bimap was left unchanged

+

+

+

+

+

+ replace functions performs + this substitution in such a manner that: +

+
    +
  • + The complexity is constant time if the changed element retains its original + order with respect to all views; it is logarithmic otherwise. +
  • +
  • + Iterator and reference validity are preserved. +
  • +
  • + The operation is strongly exception-safe, i.e. the bimap + remains unchanged if some exception (originated by the system or the + user's data types) is thrown. +
  • +
+

+ replace functions are powerful + operations not provided by standard STL containers, and one that is specially + handy when strong exception-safety is required. +

+

+ The observant reader might have noticed that the convenience of replace + comes at a cost: namely the whole element has to be copied twice + to do the updating (when retrieving it and inside replace). + If elements are expensive to copy, this may be quite a computational cost + for the modification of just a tiny part of the object. To cope with this + situation, Boost.Bimap provides an alternative updating mechanism: modify functions. +

+

+ modify functions accepts + a functor (or pointer to function) taking a reference to the data to be + changed, thus eliminating the need for spurious copies. Like replace functions, modify + functions does preserve the internal orderings of all the indices of the + bimap. However, the semantics + of modify functions are not entirely equivalent to replace functions. Consider + what happens if a collision occurs as a result of modifying the element, + i.e. the modified element clashes with another with respect to some unique + view. In the case of replace + functions, the original value is kept and the method returns without altering + the container, but modify + functions cannot afford such an approach, since the modifying functor leaves + no trace of the previous value of the element. Integrity constraints thus + lead to the following policy: when a collision happens in the process of + calling a modify functions, the element is erased and the method returns + false. This difference in behavior between replace + and modify functions has + to be considered by the programmer on a case-by-case basis. +

+

+ Boost.Bimap defines new placeholders named _key + and _data to allow a sounder + solution. You have to include <boost/bimap/support/lambda.hpp> + to use them. +

+

+ Go to source + code +

+

+

+

+ +

+
+typedef bimap< int, std::string > bm_type;
+bm_type bm;
+bm.insert( bm_type::value_type(1,"one") );
+
+// Modify (1,"one") to (1,"1") using the right map view
+{
+    bm_type::right_iterator it = bm.right.find("one");
+
+    bool successful_modify = bm.right.modify_key( it , _key = "1" );
+
+    assert( successful_modify );
+}
+
+bm.insert( bm_type::value_type(2,"two") );
+
+// Fail to modify (1,"1") to (1,"two") using the left map view
+{
+    assert( bm.size() == 2 );
+
+    bm_type::left_iterator it = bm.left.find(1);
+
+    bool successful_modify = bm.left.modify_data( it, _data = "two" );
+
+    1assert( ! successful_modify );
+    assert( bm.size() == 1 );
+}
+
+

+

+

+

+

+

+
+ + +
+1

it is not longer valid + and (1,"1") is removed from the bimap

+

+

+

+

+
+
+ +

+ Standard lower_bound and + upper_bound functions can + be used to lookup for all the elements in a given range. +

+

+ Suppose we want to retrieve the elements from a bimap<int,std::string> where the left value is in the range + [20,50] +

+

+

+

+ +

+
+typedef bimap<int,std::string> bm_type;
+bm_type bm;
+
+// ...
+
+bm_type::left_iterator iter_first  = bm.left.lower_bound(20);
+bm_type::left_iterator iter_second = bm.left.upper_bound(50);
+
+// range [iter_first,iter_second) contains the elements in [20,50]
+
+

+

+

+

+

+

+
+

+

+

+

+

+ Subtle changes to the code are required when strict inequalities are considered. + To retrieve the elements greater than 20 and less than 50, the code has + to be rewritten as +

+

+

+

+ +

+
+bm_type::left_iterator iter_first  = bm.left.upper_bound(20);
+bm_type::left_iterator iter_second = bm.left.lower_bound(50);
+
+// range [iter_first,iter_second) contains the elements in (20,50)
+
+

+

+

+

+

+

+
+

+

+

+

+

+ To add to this complexity, the careful programmer has to take into account + that the lower and upper bounds of the interval searched be compatible: + for instance, if the lower bound is 50 and the upper bound is 20, the iterators + iter_first and iter_second produced by the code above + will be in reverse order, with possibly catastrophic results if a traversal + from iter_first to iter_second is tried. All these details + make range searching a tedious and error prone task. +

+

+ The range member function, often in combination with lambda expressions, + can greatly help alleviate this situation: +

+

+

+

+ +

+
+typedef bimap<int,std::string> bm_type;
+bm_type bm;
+
+// ...
+
+1bm_type::left_range_type r;
+
+2r = bm.left.range( 20 <= _key, _key <= 50 ); // [20,50]
+
+r = bm.left.range( 20 <  _key, _key <  50 ); // (20,50)
+
+r = bm.left.range( 20 <= _key, _key <  50 ); // [20,50)
+
+

+

+

+

+

+

+
+ + + + + + + + +
+1

range_type is a handy + typedef equal to std::pair<iterator,iterator>. const_range_type + is provided too, and it is equal to std::pair<const_iterator,const_iterator>

+2

_key is a Boost.Lambda placeholder. + To use it you have to include <boost/bimap/support/lambda.hpp> +

+

+

+

+

+

+ range simply accepts predicates + specifying the lower and upper bounds of the interval searched. Please + consult the reference for a detailed explanation of the permissible predicates + passed to range. +

+

+ One or both bounds can be omitted with the special unbounded marker: +

+

+

+

+ +

+
+r = bm.left.range( 20 <= _key, unbounded ); // [20,inf)
+
+r = bm.left.range( unbounded , _key < 50 ); // (-inf,50)
+
+1r = bm.left.range( unbounded , unbounded ); // (-inf,inf)
+
+

+

+

+

+

+

+
+ + +
+1

This is equivalent to std::make_pair(s.begin(),s.end())

+

+

+

+

+

+ Go to source code +

+
+
+ + + +
Copyright © 2006 -2007 Matias Capeletto
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boostbook.css b/doc/html/boostbook.css new file mode 100755 index 0000000..e5d7bb5 --- /dev/null +++ b/doc/html/boostbook.css @@ -0,0 +1,582 @@ +/*============================================================================= + Copyright (c) 2004 Joel de Guzman + http://spirit.sourceforge.net/ + + Use, modification and distribution is subject to the Boost Software + License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ + +/*============================================================================= + Body defaults +=============================================================================*/ + + body + { + margin: 1em; + font-family: sans-serif; + } + +/*============================================================================= + Paragraphs +=============================================================================*/ + + p + { + text-align: left; + font-size: 10pt; + line-height: 1.15; + } + +/*============================================================================= + Program listings +=============================================================================*/ + + /* Code on paragraphs */ + p tt.computeroutput + { + font-size: 10pt; + } + + pre.synopsis + { + font-size: 10pt; + margin: 1pc 4% 0pc 4%; + padding: 0.5pc 0.5pc 0.5pc 0.5pc; + } + + .programlisting, + .screen + { + font-size: 10pt; + display: block; + margin: 1pc 4% 0pc 4%; + padding: 0.5pc 0.5pc 0.5pc 0.5pc; + } + + /* Program listings in tables don't get borders */ + td .programlisting, + td .screen + { + margin: 0pc 0pc 0pc 0pc; + padding: 0pc 0pc 0pc 0pc; + } + +/*============================================================================= + Headings +=============================================================================*/ + + h1, h2, h3, h4, h5, h6 + { + text-align: left; + margin: 1em 0em 0.5em 0em; + font-weight: bold; + } + + h1 { font: 140% } + h2 { font: bold 140% } + h3 { font: bold 130% } + h4 { font: bold 120% } + h5 { font: italic 110% } + h6 { font: italic 100% } + + /* Top page titles */ + title, + h1.title, + h2.title + h3.title, + h4.title, + h5.title, + h6.title, + .refentrytitle + { + font-weight: bold; + margin-bottom: 1pc; + } + + h1.title { font-size: 140% } + h2.title { font-size: 140% } + h3.title { font-size: 130% } + h4.title { font-size: 120% } + h5.title { font-size: 110% } + h6.title { font-size: 100% } + + .section h1 + { + margin: 0em 0em 0.5em 0em; + font-size: 140%; + } + + .section h2 { font-size: 140% } + .section h3 { font-size: 130% } + .section h4 { font-size: 120% } + .section h5 { font-size: 110% } + .section h6 { font-size: 100% } + + /* Code on titles */ + h1 tt.computeroutput { font-size: 140% } + h2 tt.computeroutput { font-size: 140% } + h3 tt.computeroutput { font-size: 130% } + h4 tt.computeroutput { font-size: 120% } + h5 tt.computeroutput { font-size: 110% } + h6 tt.computeroutput { font-size: 100% } + +/*============================================================================= + Author +=============================================================================*/ + + h3.author + { + font-size: 100% + } + +/*============================================================================= + Lists +=============================================================================*/ + + li + { + font-size: 10pt; + line-height: 1.3; + } + + /* Unordered lists */ + ul + { + text-align: left; + } + + /* Ordered lists */ + ol + { + text-align: left; + } + +/*============================================================================= + Links +=============================================================================*/ + + a + { + text-decoration: none; /* no underline */ + } + + a:hover + { + text-decoration: underline; + } + +/*============================================================================= + Spirit style navigation +=============================================================================*/ + + .spirit-nav + { + text-align: right; + } + + .spirit-nav a + { + color: white; + padding-left: 0.5em; + } + + .spirit-nav img + { + border-width: 0px; + } + +/*============================================================================= + Table of contents +=============================================================================*/ + + .toc + { + margin: 1pc 4% 0pc 4%; + padding: 0.1pc 1pc 0.1pc 1pc; + font-size: 10pt; + line-height: 1.15; + } + + .toc-main + { + text-align: center; + margin: 3pc 16% 3pc 16%; + padding: 3pc 1pc 3pc 1pc; + line-height: 0.1; + } + + .boost-toc + { + float: right; + padding: 0.5pc; + } + +/*============================================================================= + Tables +=============================================================================*/ + + .table-title, + div.table p.title + { + margin-left: 4%; + padding-right: 0.5em; + padding-left: 0.5em; + } + + .informaltable table, + .table table + { + width: 92%; + margin-left: 4%; + margin-right: 4%; + } + + div.informaltable table, + div.table table + { + padding: 4px; + } + + /* Table Cells */ + div.informaltable table tr td, + div.table table tr td + { + padding: 0.5em; + text-align: left; + } + + div.informaltable table tr th, + div.table table tr th + { + padding: 0.5em 0.5em 0.5em 0.5em; + border: 1pt solid white; + font-size: 120%; + } + +/*============================================================================= + Blurbs +=============================================================================*/ + + div.note, + div.tip, + div.important, + div.caution, + div.warning, + div.sidebar + { + font-size: 10pt; + line-height: 1.2; + display: block; + margin: 1pc 4% 0pc 4%; + padding: 0.5pc 0.5pc 0.5pc 0.5pc; + } + + div.sidebar img + { + padding: 1pt; + } + + + +/*============================================================================= + Callouts +=============================================================================*/ + .line_callout_bug img + { + float: left; + position:relative; + left: 4px; + top: -12px; + clear: left; + margin-left:-22px; + } + + .callout_bug img + { + } + + + +/*============================================================================= + Variable Lists +=============================================================================*/ + + /* Make the terms in definition lists bold */ + div.variablelist dl dt, + span.term + { + font-weight: bold; + font-size: 10pt; + } + + div.variablelist table tbody tr td + { + text-align: left; + vertical-align: top; + padding: 0em 2em 0em 0em; + font-size: 10pt; + margin: 0em 0em 0.5em 0em; + line-height: 1; + } + + /* Make the terms in definition lists bold */ + div.variablelist dl dt + { + margin-bottom: 0.2em; + } + + div.variablelist dl dd + { + margin: 0em 0em 0.5em 2em; + font-size: 10pt; + } + + div.variablelist table tbody tr td p + div.variablelist dl dd p + { + margin: 0em 0em 0.5em 0em; + line-height: 1; + } + +/*============================================================================= + Misc +=============================================================================*/ + + /* Title of books and articles in bibliographies */ + span.title + { + font-style: italic; + } + + span.underline + { + text-decoration: underline; + } + + span.strikethrough + { + text-decoration: line-through; + } + + /* Copyright, Legal Notice */ + div div.legalnotice p + { + text-align: left + } + +/*============================================================================= + Colors +=============================================================================*/ + + @media screen + { + /* Links */ + a + { + color: #0C7445; + } + + a:visited + { + color: #663974; + } + + h1 a, h2 a, h3 a, h4 a, h5 a, h6 a, + h1 a:hover, h2 a:hover, h3 a:hover, h4 a:hover, h5 a:hover, h6 a:hover, + h1 a:visited, h2 a:visited, h3 a:visited, h4 a:visited, h5 a:visited, h6 a:visited + { + text-decoration: none; /* no underline */ + color: #000000; + } + + /* Syntax Highlighting */ + .keyword { color: #0000AA; } + .identifier { color: #000000; } + .special { color: #707070; } + .preprocessor { color: #402080; } + .char { color: teal; } + .comment { color: #800000; } + .string { color: teal; } + .number { color: teal; } + .white_bkd { background-color: #E8FBE9; } + .dk_grey_bkd { background-color: #A0DAAC; } + + /* Copyright, Legal Notice */ + .copyright + { + color: #666666; + font-size: small; + } + + div div.legalnotice p + { + color: #666666; + } + + /* Program listing */ + pre.synopsis + { + border: 1px solid #DCDCDC; + border-bottom: 3px solid #9D9D9D; + border-right: 3px solid #9D9D9D; + background-color: #FAFFFB; + } + + .programlisting, + .screen + { + border: 1px solid #DCDCDC; + border-bottom: 3px solid #9D9D9D; + border-right: 3px solid #9D9D9D; + background-color: #FAFFFB; + } + + td .programlisting, + td .screen + { + border: 0px solid #DCDCDC; + } + + /* Blurbs */ + div.note, + div.tip, + div.important, + div.caution, + div.warning, + div.sidebar + { + border: 1px solid #DCDCDC; + border-bottom: 3px solid #9D9D9D; + border-right: 3px solid #9D9D9D; + background-color: #FAFFFB; + } + + /* Table of contents */ + .toc + { + border: 1px solid #DCDCDC; + border-bottom: 3px solid #9D9D9D; + border-right: 3px solid #9D9D9D; + background-color: #FAFFFB; + } + + /* Table of contents */ + .toc-main + { + border: 1px solid #DCDCDC; + border-bottom: 3px solid #9D9D9D; + border-right: 3px solid #9D9D9D; + background-color: #FAFFFB; + } + + + /* Tables */ + div.informaltable table tr td, + div.table table tr td + { + border: 1px solid #DCDCDC; + background-color: #FAFFFB; + } + + div.informaltable table tr th, + div.table table tr th + { + background-color: #E3F9E4; + border: 1px solid #DCDCDC; + } + + /* Misc */ + span.highlight + { + color: #00A000; + } + } + + @media print + { + /* Links */ + a + { + color: black; + } + + a:visited + { + color: black; + } + + .spirit-nav + { + display: none; + } + + /* Program listing */ + pre.synopsis + { + border: 1px solid gray; + background-color: #FAFFFB; + } + + .programlisting, + .screen + { + border: 1px solid gray; + background-color: #FAFFFB; + } + + td .programlisting, + td .screen + { + border: 0px solid #DCDCDC; + } + + /* Table of contents */ + .toc + { + border: 1px solid #DCDCDC; + border-bottom: 3px solid #9D9D9D; + border-right: 3px solid #9D9D9D; + background-color: #FAFFFB; + } + + /* Table of contents */ + .toc-main + { + border: 1px solid #DCDCDC; + border-bottom: 3px solid #9D9D9D; + border-right: 3px solid #9D9D9D; + background-color: #FAFFFB; + } + + .informaltable table, + .table table + { + border: 1px solid #DCDCDC; + border-bottom: 3px solid #9D9D9D; + border-right: 3px solid #9D9D9D; + border-collapse: collapse; + background-color: #FAFFFB; + } + + /* Tables */ + div.informaltable table tr td, + div.table table tr td + { + border: 1px solid #DCDCDC; + background-color: #FAFFFB; + } + + div.informaltable table tr th, + div.table table tr th + { + border: 1px solid #DCDCDC; + background-color: #FAFFFB; + } + + /* Misc */ + span.highlight + { + font-weight: bold; + } + } diff --git a/doc/html/images/bimap/bimap.structures.png b/doc/html/images/bimap/bimap.structures.png new file mode 100755 index 0000000000000000000000000000000000000000..c605aafe74946a0361483bea78caf3cc882ad23f GIT binary patch literal 78200 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 BryT$Q literal 0 HcmV?d00001 diff --git a/doc/html/images/bimap/boost.bimap.header.png b/doc/html/images/bimap/boost.bimap.header.png new file mode 100755 index 0000000000000000000000000000000000000000..c8684862d628376473bee01601ee0b8d59e8e5f1 GIT binary patch literal 10224 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 E0D|haPXGV_ literal 0 HcmV?d00001 diff --git a/doc/html/images/bimap/boost.bimap.logo.png b/doc/html/images/bimap/boost.bimap.logo.png new file mode 100755 index 0000000000000000000000000000000000000000..80bd8f38e142cbac1f66bce03c0e979e9e431fdc GIT binary patch literal 21616 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 Reg*~x22WQ%mvv4FO#t-lT%7;_ literal 0 HcmV?d00001 diff --git a/doc/html/images/bimap/collection.type.of.relation.png b/doc/html/images/bimap/collection.type.of.relation.png new file mode 100755 index 0000000000000000000000000000000000000000..d271f7608dddba943007add1262d2c0731d226b0 GIT binary patch literal 69430 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®a$}zd&S0r~vs07zl!{<>d+hbl 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 Ty$Tr^7#KWV{an^LB{Ts53dmuI literal 0 HcmV?d00001 diff --git a/doc/html/images/bimap/extended.mapping.framework.png b/doc/html/images/bimap/extended.mapping.framework.png new file mode 100644 index 0000000000000000000000000000000000000000..0115ad27f1f5654c1834af5ed015186eae196e7d GIT binary patch literal 82338 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 DahrdR literal 0 HcmV?d00001 diff --git a/doc/html/images/bimap/miBimapFramework.png b/doc/html/images/bimap/miBimapFramework.png new file mode 100755 index 0000000000000000000000000000000000000000..e9050ac305d8afb3d73d4811c7026b01de6c6f10 GIT binary patch literal 39373 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 Q5j5WK>FVdQ&MBb@0Fc=GEC2ui literal 0 HcmV?d00001 diff --git a/doc/html/images/bimap/more.bimap.structures.png b/doc/html/images/bimap/more.bimap.structures.png new file mode 100755 index 0000000000000000000000000000000000000000..f7d8fbc86c9e3693ca0c49b2006e176a3cd26aae GIT binary patch literal 69608 zcmeAS@N?(olHy`uVBq!ia0y~yV3uHDV4TLm#K6E%Vzp@#0|NtRfk$L90|U1Z2s2)~ zTla^7L4m>3#WAE}&YQcL1=7ze**|PO7x77D=C+Nm%d8&Xm>N^9mO1%WmWcdgtGUNE zCY#Hd+of3NJzD%x@p}1VQQb?3=9kmEDIm)Wd<>l zS`}Cs7#I`;nnV~F7#bWnf(|m!QnO~ywzjtZ{p**TyZhO+;yvZU3=9fJ0!tKhvbOG8yVh50YFbLln>#xvKTCgp zZmy)HWYEejYuEa&4LknZ8R}WZhEG;dKjlDb5 ze&y=btJkfY=AmL~X_=Xsd3}$Tsp-}=Yu4=Eefwd-k>7_I85mj^9J!np1ZZ@1b%~`f z`10jTR~OgLm~~;RZRPmSfB#rvleINUZ+du0$dcvD_3I8VTBOwKBzV=Ik%2)#lOsrA z&cTEgYuDc0nk|0P%G1-cwY9Zq=bfaDE>HgIigm~6>FenDczG$!zOgksJU934nKM2v z_v9HE6ubnMCVs?B}PI`KJTH3Pw?x2+-=7Ee2Zi^?L zerhyx&6X`D>gw%@5^ae^MMYlT-l;}2WAv_Pn0&nF{-e!lLetZiC06k*US3{W`uhD( zE4>z9oHBj-Z>f-=l_AS7AI*8qFhSu=T5)!Ewxc8CVP{82$LwtFdE9Lh&J&ulcgE<= z^m$gj$4_l?43X z^>~-x_xZNww+^bimS*dH%lKWj^>40o?9!(~@!47*wmrJ^y-D<$w8)YGK{kcyrzcOI zeDZOT*V3Z8I=g$-TY7%}tXvx8DJSRS=Qr*2Q;>I`7RscXNQpmJSsRvZAmO7n`DoI| zx%E0?-6vBnz5W`tw(O(5nN+XL@uR<;kF@)!B}+U@cy{pAv-PvwZae!1a;^2UG%ZNX zTCi^M!-O=o!v;n(&)naZbmw~%qd|{eb}PGPNQ>jybLXZ_pFY{I-$iNT?YAHAEmn9_ zw%bMNB z6g*(?y{xIJ>9y48-fm&0r9m?%O>(;YrIDFkOO4!U3Yl8bHguZ@8Bz{ho_!yTiyGqnCEaxdiw7?-G1Nu z-aQ6ATpOI4M6?b~2nh?D#L0K-_U*@e^#w27yXU9ozGBUqp6~lyc(e{3dH%7Y<~jT7 zt5SR2O`bh}UR!uJ!JuRNr;qI|vzr#Xrn}!#nzx88-HnYmygy7PSz_6$Ra$Aa`WFux zXx;GQ07c8^s=cbJs!x`!Sh#Ru#e2UaJiNRUqnCAccOR|uKUaCVI^AOOK0_^SxaC?aj&bGdQl%9VMx)hARUlys{C1iM<#rYYZFeln#i zwcvZzUbV@cIk(a_AI;evc=gt;QwBbTsgVsSldBhfINN_O((I;5jK%cmI0*~aSi`

VqUMq5-mjqSHtcFZ`NX2j;A{N~g1 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 X`8!kXxIaBx26m>WtDnm{r-UW|CQ9+1 literal 0 HcmV?d00001 diff --git a/doc/html/images/bimap/simple.bimap.png b/doc/html/images/bimap/simple.bimap.png new file mode 100644 index 0000000000000000000000000000000000000000..51506c8c696d3fef288519d972eb9d4c0535d37d GIT binary patch literal 80168 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 literal 0 HcmV?d00001 diff --git a/doc/html/images/bimap/standard.mapping.framework.png b/doc/html/images/bimap/standard.mapping.framework.png new file mode 100644 index 0000000000000000000000000000000000000000..9b5e641315cb137323c424811aaeae2d39bae1bc GIT binary patch literal 54971 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 literal 0 HcmV?d00001 diff --git a/doc/html/images/bimap/tagged.png b/doc/html/images/bimap/tagged.png new file mode 100755 index 0000000000000000000000000000000000000000..dd40a6f3074396abfd8481b551e0a0748b40cdf0 GIT binary patch literal 27281 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 literal 0 HcmV?d00001 diff --git a/doc/html/images/callouts/1.png b/doc/html/images/callouts/1.png new file mode 100644 index 0000000000000000000000000000000000000000..6003ad3af44ecde89a963d5af6a4180217319dfb GIT binary patch literal 391 zcmeAS@N?(olHy`uVBq!ia0y~yU=UznVBqFpV_;w?d&FzWz`*F|>EaktF{gKeVcsDJ z0oVU;*6~a;Smx2ZrsEQ?ZxM&ygvBnFE?nmtg94rky>!~x8m)3j$<^(USQPg)>&zq; zMi;kRX=V2=&tIr>`d!)XyUpL@9=UmHetuZ+!_#HmOU>-J$pS3-bN!ardIyAF-G1#? z>&)f7E`k#|4sWoP;JM|(l6I_WZ`%~1y>agujE%b%?TB9+mb}(fsxyPFgQGMy*=%;A z(aZyu>`GQPiY$*T-1gu1pAwY3_N%b5cB#xoiRPn8jf*q{Trb|_a%sui&dtzin6_r? zu}%d~p(mAmOGTO#c2u;xJ(}Y^?ex>t7XL(?7U+1p1hOa|ab;w%c)sCoo@_(^WX<=s zr#89B91nl^w~jx#=XQ?S<*?OXYm`>JmO9g8;`^U+STt2<{M7jt yFTo&UT%Db3I{*CoWB+`guig6oxB?on>HF_suX>mE-_|+p)}_VbyG%XWRxDs!Bbdb`rSkCf z_opQpQ)e&z9?Q3;X^2drllMU70&71c8CwuJm{abIp zeHPuYNTZJ3@x#oHxOW1*hRe1@t$mhYkYRMp!NudU$f{L`HtEbcpPpkT-Q%WwW82?% zC04fVjt$l>J1E5m&cv;Mo-ym249h`b!OT;yI|^kU z7g#)~+Iz@=rzNo?Z+rL2lqSFB&0ni{FPmfwyfr;gD5K)Z38R1FYejhuGSfQP|hTIvQJ?m5M8zE|_KJ2Ny0Fm1o>%kU%6J0MhalaBNL z`|XP~Ht29?&a!*3EqAew_mM&!z3HdD7hn7l!t9~x=u!|XzH8m#&o*bC7c(?GuT1E< zIxY74U)KBI?en(Zj`8vg@_IC9@{~!dRw-$!in=2h%i uo%h^T#Pz@K#3`Fjeg5EaktF{gFX#;)5A z0&V{%irr-ME}D3(<3UjG?A^;f=DTxNc8JvRJ?~omN$9208L_ft0gE{24F|>2&Q_(X zyZRk}S@Y!IJLwtuX$cuSW9kad-E9>}+B4ar@B8JKU&IA}ZdvzvdHazWz|5Z1g ze)`Eh`){a=Ty&?>q6`CxFY1#$=XWS5S;+8pJeF8|am8VmFNNE0pWSjTLp3m4UCF?B z)v7}^cJ1H)wSBfZUSXp*CCGT~*L1 z!O^woK;8cKATG~IcM5iAPD}l8PyF`VZ_(}ou7b0cInG+vv8ev~-ZX{}_a4{SRWsNx zp57$DG;5jTyyy8w3^D7&C6fPqtf+bOwJP3cC`GVy&NA$7e!FZ3*ZX_(gMKMn{jgqg*t>n5-mVwdc+LxmI|e9UlrZu5 zQ({_ROHtjRNV$1z%lk=bT+YJ`-QVnLY|jT_oBf)`qRPnx(gN%Xx|4tEMdaVwoi3 z8lgAcLau*<4)^ratatOor+TqI{wNVS?clathJwW!uZ)j$%&5q+Ew{P&-MZ_q|3(_ifRH$!b{%@XfPPgvO) wR!x~yId8sr_tEzopr0G&e8k^lez literal 0 HcmV?d00001 diff --git a/doc/html/images/callouts/13.png b/doc/html/images/callouts/13.png new file mode 100644 index 0000000000000000000000000000000000000000..5b41e02a670f020ae62b7854482c4ba1980d73cf GIT binary patch literal 509 zcmeAS@N?(olHy`uVBq!ia0y~yU=UznVBqFpV_;w?d&FzWz`%IK)5S5QVovKN`}4B` zMA$w&XL9s;aOlF(1%)YvneO4jm-o(&U;MKD#e?Mq8+>b)^R3G((>5$`ILflv=tsMT zqri^uWh?XJrteF)Ir(#L@uYSZ#}5m2PWL-;h`yh)YSr?%_21hCg6ylJ<~^TZ68k@M z*0PUs0U}2m4Zrz%{ru!$;?!{|$E-JRd$xd+!qOu@YuZ+=+K?-K{IOu7#Gy?(C029K zJuHwgKK8+3O1mEi<8zsP?~|?OE?SqZ;@R}Hh*OcJN#Q`=cIVYsi%fl`jgRf~&@_Gf zwzE(sdH3B%ReKL@(z)}#{LAm!8Ou74CNVNBn8MT`ef;AL!#4E;rLlAT)H7zW#a>U8 zU^AP|o3>d}=J>$`0|rHwDM43C-@g0)`~9hChd_}fnOvtgEzsbyc%HHSwnVR+$0Qaf z4hDzV>nAp?Vf*l#Q@}~VH~7Z3-c_p%=AWOKD!ECAd8tU(q6Mq8jughk>rJ2Tw)o@M zm#pV3mrVI!!@p|Pp+XrSHQ@j+Lm56tj!LO-Hu>!LzuT|B{(4Tap5^mRI^HKOr#o>( zhECmcH*b>$SLC#%J&RUEtqrq3WKa^{tg=+3a-Mjg$X|1pImHv7|6G6l?EhE#0)GDv Vq@B#jVqjok@O1TaS?83{1OO3{4iFg+V~@k_l_W_wBcH zWmp*BaqNHHW9Xsz@VDKv%bG0$2|bO5Z6>~kGkrGPetRKrdu;6W&)@+-S^-5e@qWpx=%~ppu-*HbtcU?B((KtQse2TO*ZEl8Jswt zRO&J4%x73CvPq};vBd=w-op^F6<=oH98=hD0fB5^~^0#Ht9-5wBo~e$L z1lS(@e{k6MP=#(Q)65P&Df1-{87Bltt+Mf&((ZAvc!Ef@>!Js&9H9b5iNOkrjBYL6 zJ*_!sB>iV?h@ACiit<@=<+J)R*K4P%cxw9w^X5-kmdSp5TRo@ZmA&eVHGWMv{dC`S zuce2g9b}I0mp%UT(3$h)E?kO6N0T-NtiR6f#9?6EcU;-Tw>eSb#{2IdZ1@=hR$sjr zzyA8Z#}+%3XYST(VGvBTnww-G;h@R7RHW^&qTY1wDM1E2%vZCnP73-ad;I5-GeP_8 zE`G0F6Q(`qeEN%Bd`m@QuDc4b82Acr%ROx3%dny5{(I}bX7&S{bY%G0Jv1kte!3xU z{l(W`FJx^snCW9M|9s%ekN~~u3#V){n|<~=yTas?3Ovp)cJVPNC~di&>!GEaktF{gFH!7eFB zfwuoy?SYP89?67Uc^u>7$ueKD;_TuU8yCKP?%y^nk6}6Q`Xb ztf|`>GH3mp6jYb?>^RdSfr%@^R!^go|6uIuQi$NDW>upBo%&=x}fma9VINW5Ly|Qkmm3JvHr(Hb1rr&)I%k zqW}1XsO0Up4@Uid#O=~jwU>`!u0>yZkk=jF7J(OKyBQi3I1HqEAMAR!+FC^5{Aa5( zf1b8B8nUgv%H`5>GKER;h_=JWcU60(815ha{H$oF%dBM*eC_{b&TZl;l$m|{>8A+2 z>GpSd7ik$I?GB%onzMHA^lP*F zk0)=tnX|7g@rLFCKI7=6AyTdvVl+z`(%Z>FVdQ I&MBb@0M`i8D*ylh literal 0 HcmV?d00001 diff --git a/doc/html/images/callouts/3.png b/doc/html/images/callouts/3.png new file mode 100644 index 0000000000000000000000000000000000000000..3ff0a93931515bb97a045dfa61a8530d87e458fd GIT binary patch literal 431 zcmeAS@N?(olHy`uVBq!ia0y~yU=UznVBqFpV_;w?d&FzWz`$7M>EaktF{gFH*{(+p zB5wOOu6l7m)8 z=-oKUH}V^&iJyB|uo8LF()AHB5)-MfO`N3nt zvX}OXM~sd8*9*0GtV!A!kzpdmy4F;zn{|?kqeR<^5G@5I1_ong&q>Sg=9!B)JHv7pU)=hauMINB3;oaL&ye>}mU!H{id4Bxig=9%^>^=*s?64R8I`k2o? pd-p8Ef~{sjr?y8+Fx+F*x_2OD_kw447#J8BJYD@<);T3K0RY@Tw*mkF literal 0 HcmV?d00001 diff --git a/doc/html/images/callouts/4.png b/doc/html/images/callouts/4.png new file mode 100644 index 0000000000000000000000000000000000000000..6aa29fc0b48c17aa6ce5540e1af5c00510c33ff7 GIT binary patch literal 441 zcmeAS@N?(olHy`uVBq!ia0y~yU=UznVBqFpV_;w?d&FzWz`)qx>EaktF{gFH#x5mC zfwup%GG$o)=ergqP)_hu?Cbmc-FuV6=PTSkE z?z;W`K`XyJWKnY38^_LI-}iXo6rn{K^Ugm{NGsVLTQQIQc;ScrMIF~}*~{?xZ|}UC z)%voeOU2Vbu7Bb(%{5!g=daxAHc3V5z+>?E76HlSc>&q{{ zJgU5>EY^K=``x_dYqp*_vnNK+lE-=9auZ+6u0=XLho7HKd(8afJ98Qv1B>H_g?h*I z^7xt(_!*jJt_^x6<$Ce%iJd)$VVYl~OqdVEFZF#=7-s1t%fP_E;OXk;vd$@?2>|9n B#bp2h literal 0 HcmV?d00001 diff --git a/doc/html/images/callouts/5.png b/doc/html/images/callouts/5.png new file mode 100644 index 0000000000000000000000000000000000000000..36e785867ad9b06bb5da296fee61b67cd8159ded GIT binary patch literal 423 zcmeAS@N?(olHy`uVBq!ia0y~yU=UznVBqFpV_;w?d&FzWz`&U2>EaktF{gFn*{nkj zBCY4o9LZ47@QCRUnZAf+N!}-g*k62kUh<2$=N}3cU-wJsu7~Tf`D?j51GwEfg_G2_ zuV#t97&qf=>*tSit#h_USr*FJFU!>WaGpbPU+ne2DLtw;&jomW^|@TLId}ILd4;Y; z`kGI<1$&J<4oW?f4p9*ch$x|rP+;KqSwET0Ksa~vKtM(>J91HOJ>EhB>xN^tsw+8di7uv`rMqUeL zJtlGLsS$%o&3$<<&56<(YY$o;PcU%UfB(F1o@3V5sOFBi;${Vo2fOrSjvstkva9-x zil;zZBGUt9^BXy4GknxI4hvj-p!#HTV6S6ePsEk3N^VkheYYwwc>v z!48gj&!5^CXy3`&YF5dr$YOKedHr?gg#ir$OfFx%f9Fdu@F;mr4Z2vhci-*k?73P? f@97_A_`n?SY~RWh)zCHu1_lOCS3j3^P6EaktF{gFH{#8D;%7vjax1W#KXIAnv(J`n z&5VyM+63~m6_r{NIT!+`rAn_gmE-I&+!3QUA?T1q^ClfZ7RG!2%96cqg2wgyaq?lS zMX$X!U8LbO@45W6mvfv$L-`J@Z+FmS&DLGD$|-VMfY)E~efQs=*mUM;<-bcWOZM5Z zTz)B%D3P@Lt`d*4kJ{wr1(Q_jEaktF{gLJ{wyX( zf%f{%yMM5|1Qs>DxO#n#YtRpleGYL4%{eMNMC?4cR!{jhN$+gat*(bhBwQW8eR)?F zba$a+^0L_vzt^7O@l~6=`|-z${Iyee1O}bTzyIC7L&Goql*H!=r=P}oFAaJ)O@ZgI z{@Sm`#{5B@N=kt`V%+OqiyeDxcc)!#?*L7k5+eADVIg?*L>hpfK3x*)1hCVBt; z;|%wV8@Gym{wcFIjN7SWb%BU0N0Y+6yzR|3cK@fSPF7(wKKyx4{o#4fYt#Iv1TDJ# z*2#-AZQqV>`4S8w#?i?>7PHU(+hgr1l-*Nl-OBiY{af+c^=0Sh`7EaktF{kyy#=ct) z0&EZJryZ5xyvdOv(510`p{HDvlxC~E$|>iVgULHQ3PYvrom?h2P4(>+k=FEToVfLb z-1}ul4-dV}J2m&O{aGGazV^u2>+);2+U^P78~6Tv*4AI1E_e2NCZAD1|9M}poAQ6# z2UUCjU5lzOJ!f0qp`v6c!}s@T(aY_*-6p<)(^RJf%{ZH;pv2Hn%$FKjXEE0=dabFI zOUbTczTJ2ED(5xNoT$P%L(+vssY!q-Q6kB1zW$Oa(QCh^Kc6#2_JRrTx8JslG@1mM zBBvdU`kln8=_3m^%&og1Cq^RrH#tzmz{IfafeFfcH9y85}Sb4q9e0BP^KrT_o{ literal 0 HcmV?d00001 diff --git a/doc/html/images/callouts/9.png b/doc/html/images/callouts/9.png new file mode 100644 index 0000000000000000000000000000000000000000..abe636072b61306fbcd6157b95dfdf7e86a77e5d GIT binary patch literal 420 zcmeAS@N?(olHy`uVBq!ia0y~yU=UznVBqFpV_;w?d&FzWz`&U8>EaktF{gEcf7T%f znb!OIl8YM`EC?0g)MK6LySsR*bBW@-#a{$sD|jaA?Rq5|BVw*<(2>_Fw2;L_Ls+eT z*=m-pP5G8*zMrjje*N{AqvqEc&v$lO8~PeQnNu$u7&XUG^XcT&$oGAZue{@YWbseb zX;0Q#doE68rNi6aM(w}9J~guKY8ESl1YdhX&(saqqyj~D?!KF+)#9L-_*{J2Y1Ks< zObjyp?mceG5^anO3Q8tYyaIvx98EzeZXaKe_`Z|7b6wRX+{3FhZAn{V<2dEM9+du_kptYsE+ z{WKfa2W_~S^T2{nZ8E1=H*3uG*3`)V4^%t_SRAV?Wb9U5edYbrW%=bs0jAGCWzMDv z&-uLjLxRB%P3bLBx;@8}pH%jFEoHiFvT*CZ6}7y~440#x2c4?eefQp-XqD5OV!VD< d@-ZKf|NC_Jf+y*vd<+Z>44$rjF6*2UngH>Mv>N~b literal 0 HcmV?d00001 diff --git a/doc/html/images/caution.png b/doc/html/images/caution.png new file mode 100755 index 0000000000000000000000000000000000000000..3c3b859c2276a628a5b5c7dc50ac720abec0b612 GIT binary patch literal 4286 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

gcjAdk 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 Y^Fzopr0NM(2ZvX%Q literal 0 HcmV?d00001 diff --git a/doc/html/images/extern/googlesoc.png b/doc/html/images/extern/googlesoc.png new file mode 100755 index 0000000000000000000000000000000000000000..5621b678a793c5ef39f5fb652bad429e563ba961 GIT binary patch literal 7535 zcmeAS@N?(olHy`uVBq!ia0y~yU|7Y#z!1v8#K6E1cHxC20|Ns~x}&cn1H<|g=B!;W z85kHOOI#yLg7ec#$`gxH85~pclTsBta}(23gHjVyDhp4h+AuK4GJ3i=hE&{o6U$i> z9J{tz#!|@x1lq-uJoHdHH#hW}DpANZ5Zrx9;W6 z+dIGifBW28UF3LSMoZmVm;OCXf;%E~U_vmw*}4T2A%HZPu@{O0S6JN#q0MC`~y1zFFR4*^y{p7av|Es4v)#crOWxGAt-{4s}74o`##y%%Lwdc zIm{pJtJM|xW=r>D3u^@*#bUv$Q<@Jwv-oC`%UXIOu%pPoWqzEx3(G`ve%Jcdw^#iO z{PFT!vAf?5olD<<)7A4{mlja$IYsXlG)vdh5TmB##cimm&tz zyXq|OzB;6IfNO>{Ur1UX_rC0FFFr5fZ_;x=rNR^O^RI_&vy-aQ>e)SS_MBv%^Lk&& zf%xCL>4)D&{Ca!tLwH@ot%`j4b)4bfgi1nkTnxQ`rN}xw`keLIEBf?elZB^`$Nl%% zIob1<_oq*ii!Zmmvkko0UgL27e`UC#hZ*C){m+lZ%@%ssv`f9OGO@lj#9x3(t>Rsu z=f0SQ-yc{T9lp&ND!<^=@gMFzPM6D+-&Pdz|E`s2YH#xu^jj|PuqxnARSs|Tf5wYU zUw-^|6PACQ_=;)W2ficMlJ^R1Wm8=@b-!!{TY{{c{i{_uzdUB0&ztx!d*9>k#NxmA z?uD9tKb*``-H>~K)s~~5lWJV}`dS`4`tR71zcQ!#&tu`{3x%@rHm2p(B07n75gb)1L)Ps87~M{0t@EdVVUC>&A1DiA)Alis}N{s zPH8R+_%|)B`rhOux|j+&wP&lyRRO3W^*X=R*NvF@R2(&Is}W-ihbuRO*@vQWFh=|p|`?o_JGFSdjGiV z{v8lCjbZ%Lb}&fsljl57X~(}w?(26?)UFo#TO*uxR{UFEywU^qN2h}tR^-0FDA8<0?)d#wUD$b^|KeodE4-Ce z7d7A2=Z3G8ShX~3YQi>sJ~_6d(%;3bD#hD`4a{Vo)a~n&{LJB1Bf#pnVC&_Z*KGQp zGS`YlERkLQO`_${u8FtKvCQ;j=wWu0K3t{|I9vYuIfXfY4xWwJ7g_N8S>vq)e)}V( zQx#`DJImZBv+|@gTiz$zzy_z{e-GBLcr9|(?!upszq&oUUDE=dnctXnwQ2gfPt*2& z3Re4RTJ^{F+p=T{eX;b<8gu7%zFgqk`{|T{NRHf(wvOBjo401AEM-y4(A_3qE8|qJ zV!-x{!Rn!?h|SgL^#@!P9&dI_jdVtOD8SW;-4&cSueSM%bBTLUtC_gLSaFa z?&KK{rdzafm7UdG_+u-l%h~|H2WOTSLv4lb9(n@wVRizKDJGL!*_eiO_kTcupA)nfj z->QC#jvx8SQh)BFSZ0%1=zIG&D-M4y$@_ie*HOoB6}$JGFMpo$bk59I(eFzR>W z;=jE>_Nfc|hkFbz^>@2Ed;fmvWnL4KwN|%YBz>7HUqad+-j$VQCi5J7?H5klJLhBe zkphvkQ@6wgXGMfv7ft5dr)7Svm)f75i2I&tvx z%&t6Mek)b8ZgOzIk*Pm8LN(@o)0@4QCB|kA16$i(XI_=-H~Umu<>- zo7+2Pzt&nRA*Q**>hzX=EwT4Gz53faXGS%D*Ez8%J2}?P(L4IouPcVtf%6_7Eq`+&7aO+n~I{!WtYxvaS9d{mVbM$ zT1>m1*V^HY>^+B|&3`>4JodjmA{}u-ROVmGgoW8x+8(jTf2aJYos!0X{$Ady9d3D{HGE3t{L0h6WwZZ#O6}Ue zGQ;?v;g7rFcP$+n_TSCT$cx~(u`~DOXN4~oi5q^qrg?S6*oa7fcv5}l2ft5$t=_ho z|5v%6o|yHif5k)fkVD5`NBmTF4LZCa)q`oxn+WaluvS}pJEaJ}{nN=lq-VTY{wHJ6l;c83uNXb4<~d8TI;} z@s8Y)?T(T&?$vd_sM(OR&MMwadsEHSFCRaMZtD?c`&4-`eGywdORHS2t4i~c!1-71 z`fgy~^*pP8aq)RQuPOg_Z@#xfd3BnD{;Qe1Pr6@Ci`*o3_o3|haxd?Q^8XKn|19Zv zUn69&?CX2?mgP}zvTM8lZ;GD##a%U3Q_9&zzV#Mc_?Oo2qBna)dAeWeetaF3-syI? z+m1b4p*Uv4mehLB&kk4iNpN+_ZB)rGA9YT=QJA?lhnK z!@Wv*P5tSP9+y9UDofI5VY|OL{OENC_6v#5pEw>c2RWLZJMrhnD~<2hjOVU+$lxb) zxhC$wTAhT%q9@Z%nSG4^@z1Z`nqgv}^N#d$U!T~`-v6(w#qWrHKx&M7^#&)NFRNe4 zR$f@VY+cu`bDzWJaMoz?M!$R!xNko9szaZqEw-4ydeIwS$C3bR*%X;o@7QinXtc~K z3+c~16Z-AWaYd#lhZ%pAT(g?>g=hZ*m!o?p%@9zJ`W5)CgLT&S{(Dniyp!*cV=WB- zUpFu9p>NzId!|2&OSD4Xf7!<;zI~qgkF~$+zUWE^H0o?Uk#=BniR1q5vTkKZRvhfJ z;_WTD&bG3NXG+zIJK|OsvYv;?N6U15*N7Wr4J)C@|7WQWSbBdq5@1r22htWOfHvy#)KBX+gD4UX?=Le}Flc?U5-IF`W3a$v^0oJhqLa=~f9AHc&rj=syc5Gw z;g9<|cH8{9Fgs-Jq>xYDTTFLXy_N0!%TU+6S!tqgW!H_}lh-Z@F}=T2vt--iF!_+C zmm*i|L?pX*OuO5_BAk~zQD|HHaeUDBJt?d1t{PCFh z&*X{uXT#_GSy8?INb!{oF|(6aJe)6F@aXP2&r2Eq>ek>Pf`T790k`glW7(apcVuGebVu`F?1_E5BAwz}wZAys2eKTF};oww|496gMt!dsyCYoLZ}1;k_|3aSYkKR3d!MeZJJ={c`$MrZk7rifs(`-ipa)I*T)rRdH(7p*)nsqDy!p}D z_kMD}1LssSox7l1udi_K0>j4V^YwZ>%U2yT%D-!z@u8WiLiO-fE#}*4bwL(OWEdK| z?l;}AvkwjCvzl{KZtqs>{pS{XEQ=Pjub-YRC6qoP_tL{ohA9HSj37=-Fn{y;~Hjz4XS+Z{n&~zWti|cn?bs^QHgB&wuIOaGMm?;&VRdLcMV~ z+mBb~tw~mPThnZ9=e?G62)vt^(&RIz_mHcl$nkj}?^h` zpSVy>nI_*F8`twN{fhtlyOLq&mWw++ zoqfR1w3mP4Zu13qPpXbiz5VCXzb5TX4^OU{^490Zf|)han?zY3o_^H3dFsDj z>mTlWl(l4C<2t?19(ul@B~&9%bk+u={g+S9)a8xoe7>0X(kcVS)8RWS7#=Wh)2+R? zskr)m<>5tp?mbkOVOZC-Tb;v-_sz{){oO@<+kf1Mm0!(%fSKc8!rUp$4aYw!Gk#cp zUGcD@$T#^Nc~*tivp(s1on8KHoAmdX!_OYOH(Xy>{nN6iW#_ivFNANHF8(P~(<&AH z`k+F!r%LKk(|;oQKQ!Amhu5EZcIUN8X^h@+bCGw&A9kdp<^ zEphdoePvx6t0V6ntQOM`T|LJ>ZoZYBhFZvDp-0Y3qC-+oX=VNT=+kX7lViCL=hyn@ z|5nD`*!=fo_|mI;UxmJ8{Qmdg(shiFVjp+wPb_qDKN$Se?Dodv0`~s?8eiIapUs$( z7L_e|;`KIB*CO7!Lni!gD?UB8xAc;BU%s#XGQUt$M&(Vp=M_B>zbyBEZLzmtMjmWk?h=WlQt)WI$G}%uL;_x^MbGGUuoRl z)2r_s{?9^-w62MK#ymXLjQKwf)puQ;r?Zr6>7@JRlF!(; z-{0H9cPGog@=I{9tLE={lkS#AJDfRlL36+VIi5=`JNB&T`~E-N>YnamSdruPz$DRef$%RwcKa#mxWe@BT|G7nQ6!lCk!;ki))Px3;OB4&S}&bN3ys z8yi=B_x8PTXU4;VvQ>7;-EyxQ?|eM@xiR3k>(MBY$G@j3Ki274s~}W*f$5vcC-2Hx z##3%&Z{t{_P_t#V)I5e3g?e zaC^n0SrT1GzHeFa_NQ>>5|3Kuqjz0d9(>l{SG7N+`c~iFt1hjn`_@@m9x^d|xydUJ@(0m?>hI7cH8-~>N#vY-TKl_;luA~8=imrSbB4c!Qtua zFN)1*5WZHh(CN*O-K}n7UMJK7Y&&Hc;zV2CAiI68J<8PN|Z)9p&H4epHEvY$|_2;~tv4CxZ;)Am2 z>*>$bJNnipKXW_Fw7`774Fsn(wq_*#Xnt72@yrcF&*U=3e%74oB3&zQ_-}#(Kefq9Tv$ z2v$${ZT@bOPMGLs3E$gIL7xLpIPF=pCFP(dN6+`QUd=ngbAB$pX7DC|;=YcJ><=Eg z`q!Pzyy)ljyvXA4_dR<)C9HN9c^Mse!{pkOevWm2j=3zoe5+7kKc}=t+24>1m11EVHb84^0fsNlsw3=O69$I+WL=7 zx~}l2s*|s0ocC2--*TtD)b3T-Beb6ZU{^#dq zGV2~^CoRzo)vzs=zN9Xk?{FZrae2yR!SIDIc9tCBS@|XSR^R~*pPXe1e_bA$%L=Wt zdDrLsYB}2v7R|+_i!K{5)ys3bth(Mf`4w+R+Qu*1hgV)XFY_{DHYf9Wjs=${hkuZ& zoODHIK|;(vci&j&)lL<)2hQI#u;Q8+9kIM=#j#)i!d1_9TZN(yb7rL!(5=EC&8{}U{QBBF=WH# zh~M*?Ud7d!9qBzX>%8jA#qJN}bF5CcGy90_dQ*J8v~<@iL4NgPrgg0sBrF)`FgKYz z>v?d}>Gu=&l?^UM2I*x7=1+SurS$$Ssa@u;)$dn_2VVCKa#*e3FZFG~|4GgB#cM0y zH11m6Y3%XZ_{bH3I#$Qag%8|om_k=5t4`X{w}PwX)zPO(jKQM!YR|d#HIpftCGO!Bxv7q<`bTyj=r)-v zG&@|sYkF1gQM0d`Y*VxC^*+V1PA=Z_v|PIHUGB>_rJd71dvz0^zWckqUFw23D<+w);O~M`EsZ)sm18X2iXsx(b7wa=XsC%ZeZN<;DV|P zn@c-a>9MV6pG|7x+xQ}};q>DE1Mg?PGOIou_a}9~A^)y-LB|t*vT@CNxr=+9*iJUn zJx$rYbA&DA?WSyU_#|!K;;`eR#Qxj;9FyV?6vm&*zVY&r{6}S$Z8y`tY->~6!Rl(h z=)mm4plfqC{XC?3Q`F+%#`8~m552j(NnB6I{Ee=S`!u)7ub3~eIC`-y`g0^B*DdNv z>(5(yqA%Z@N;=fdIv@Lm_5c60H^yvdC!9CwiEBPC+IaZMyP}^gb0c1SdwBHQtvXZt zhdIWHJCWzN;?Zso-1q9QspI^s^LxGi z2kC`%f}hVApYQlDaqHH(DbufBy{0K~%>F>8@ApH0YR=_df7QaV{O6sWn=W0tHZ5)G z{Gg>_-s=Nuer<7EtJW*FdFQ4@i$DmHm6w^i7i{U7IFWo3UcLnA4{4ZzW!} zzGr6|rziJFewArr;@$v?dOR|xX zk!I3yB1^YyDf#u~WpZ-z$!@(9_F=)z;xV0For>nxMJ^EyTbC>;xwog%N{(U2p@q)v zJ#NVr5fYh}6Xxc=iCngN=T6JiUnTzKj8>r~kDi zANEaGSO5Ofu=dTQ(_fcPDSzVO>dN|)&mgAy@7I0hFb738$ZXrcW(^PD-lS`5q{Vdt zG(?UbJ<9U3w)(r7iG^+_|LzA27Cd}y!4F)N%s=p?ZH_$kqhR@uA3yHjtFzvt|3Ya` z(#_ot+rQQPx3%e?A|4wR<8tcnsZGoO%$fW5eKY&qlIHyWm&w!btk=Klf5GsDT#3*w zF4=XD96xRJ-lTtX@5S%CcQ8L;so#CjK_Y(bMV413F59fEt-t)5kdnTyEw+F`#%)Q< zoD8$_W1pVvNU)w)%+k~LSj|?iDnC1O;(l-U_Wf?g)!UQ}it`IkJvbQ~`E82dX2}-K zfJJ9&YkcH)KdGyoxWGH0X3swc|Cj7L@4JdAw13eS5YnV89)J$v=X@8(IJot@uG{8Ca_c6dA}oMCN!vh!2tv=0Jtclq_2T#C zFInpfQhC{!V@_PVAt5PfXj(aId2zz@wYS;i*zXACbncG!SQW6p~ zCQZ7ue0PQ7P3_+v&6gPEHFb4$_4WC!I5`~KOAj7|rBf#vI*0Fj@|?I jPRbwp1^oZ(A7Jo&x7Nb=)B6Ml1_lOCS3j3^P6rMq>1 z7#LWXJzX3_D&~Ybz{S|QJTtnsltMyEt#Tl;v|NO;v9`l_))3dflS?I6H zS$jb(b8Yh49f>lyi&H+{FUwhqPozXyMAgO$PLw+`X@4OhhomGBmA=~_D1Q| z?(N^;kt-&UeO&ro!23z_CpvBXaP{id|0zp@PKp*eZJl6q)iCX`F;BBgsd=1hc4&a) zEyh_>uAVrSc;ahrP7&MLKNGHInTDUx&k)}w9vO34`!qEvb~Xy+uOKSNk6( zv>&s)yq>k+I;w5?&Zpg<%4gdDwqZYaQLJjmv+%jmwG|syM_%oVReo^o_PjjaM7Ish z%6k_b6+O8rr!cN%apG0A(wB=$YHNA-OxUBqxl-n{cURlZO&2dNS(0$Q<181K_wme! z!n{)kHWuM&S&UCb0aq0ZIGZW?u^!O<=L>-K(iWQ#!f&awIi~NtKn%sIO zysE`fPPtq4blT$3bj|?BBjQ%~?%&@&tBlv`vO)QZg=^(J6gAz#^&9)vzubFYGj(I{ z;}Tc-#3qy78U}A?EOcP#Q?apAnRvqG0f$UuEMI?tTUTx!%L4g}&z+lIz6|B7-m>kl z{@$C2P*-MY*kqgm~B%yI-s@dRDYk{?7W}Z?E5f|EK8s&W{ye*gx9diU zmOq8Ze{aYYzx3*^*y;8PBROw5)u6)m!yljToz+(LCcgfPjEu~jdGi)&tO}DlG?61f zZ+dF}*L%$?Zu8zQQ(T-`e_qx@ab<+kG!NC7_pvkDdvlNQojL3_|N8W^X@MeFn~tSu zvBuQxHhFhLMQQ74&b`&*29bNJ^)%*s9-q81#p>n93c2kQB5Z4agc-50<}GzhKbyAM zVQbXc`g6_Fw<;Ij$@`nI{ijW}qe`<%(8my~r=Ndorri2`P*7^B91lyN$XSIB$Mn-r zi|%i4dS;i`H0!41%9~HV{eEz!P;I84k|ayhf^~e)44$hl-W|W#tU>y=*Uqq|H?%~! z?7#ig{GS=TcFIjTcIC6 zg}t5zefbcecUez&&H3|QF5Z`Pn-4xMYkgo))FX0^>uAu&N1ql&t-W{W&L8ec{U2rK Uy!q45z`(%Z>FVdQ&MBb@04`<@YXATM literal 0 HcmV?d00001 diff --git a/doc/html/images/important.png b/doc/html/images/important.png new file mode 100755 index 0000000000000000000000000000000000000000..54b4846b49cb77d09578e03fddef8173e5b2cde6 GIT binary patch literal 4666 zcmeAS@N?(olHy`uVBq!ia0y~yV2}f04mJh`25Wk44otVv!`vx;GaF%2` zI|pPYCo?cq+iGS4^JFAuNVf4f%QU%gGJBl!RACQnlr-uwP+|2s@rY}U zg3=@rM;Au%nAoN@i)u_i-MQ;$eZ}u^fBR7X z_U)_cLwOtCR4A!yikdMfbWT6^y>w$bTYHPq#>EWW0S#PB8oXH4O>dq)e^Z`g^Cj+o zs_)$xw-oJJ{`>v;|HlP(dfMnQ2>6}&cxOdO--OF8GN*kXt-EqO+`?ElGNM_w)#o|4 ze!z)?+A=?Tg~KhLNx%Pd>+$>73Qvp}3YN@R?_;s+(8TzeRavc;8~>;RLJ@J^KWEz9Q-zk&No&OQ$yjCZ}fkDK9-N-?3 z1(WXr?w$t84J_LZaPDBvf57i_!0iCzMg`6fj%p_ucRSc=u&6#zSi!V)0i#J{SOHr} z)8_|9JJ|9XcPFseurV31#x+%b;L~vwXlXqmz&ojNibAOeyHV4P38qh2DxLNPaES07 zb+FNpJ=Iv|+!~-6!g|%w_k#Wf%NIr^%u-EqPQn*-zL1s<_R1!E%BRqtmtJ%vj*IjhsssQys*%fwIY_G6n z$$e$@bvwPd^nzH1d5M7)+uY7`?$Z}bUwr#w^$Wo-BEMwWniCTuB#e8s)mVi4PaYFV z6eM50-!MX5nP&PH_F8enhxTP>W-2 z%j%ZGL()nUS2&rd{}OoIVcjWurp`3r$_(TcprB@sj6n4|R{}9{is9CsH=C z-JB-l<){2!*?i*q3G*l2@4k5C%aJ=rb|hIJS#{LvNZZl4zz-s&U9zdls@*|;mfky^ zX9^$h&hD`8aPP<$UoU2_Zl|_S!Ev&|ln>K9CTUE{n6^XF(D`VP=?cFPJ=6ZGo~l+W zPv?wPChSt}+h$*L*zGlYQSu9&UDCGm;ynJ(wDXuheTkQpH=9@9#5L3QC}<`q@bI=t zD^CnOV{up_wPs4tgiVvXCf(A$s%5IPRYO-jS6fy!R^hIitlNC0{FAILw zspAzEea+o0_*=)D(3_T)yXGvFabM@~uIG+&Wkg)`y>Pqee>46x{Ap@h)YR>?$!X~! z(N;^>wnb}`_9V?r>VLFG$oFKFrr%1Rmy0fOFH^bPH}k}rgl~q=r#_t;JN5F^*HhT1 zP7jIDV$|BHm8<0+!nrEvYQ|Ngt8rH=O;t_xx5{i4+v@(RqI6r;nqP`v>%O}3PIH@Z zOs?0jS8|%k>E5YFvl4r=CzaFsU1li!Z z7IP0k_om$~}onwhgAcSQEyl$d=k?zmo3yt(`A+q2&r*ysN{c<74K*+)G`_yj1*38@zw6SZ$s?9TmT)%vGv z-+p1cmv@hS&-^vXYrP}C&*ndtKG%Qi`Qmuz`!e_I>}TCq+n=_-{NJ~KNB{LRn=oHu zu42|~Ol~`#PTcBwRlr?@s#4Sr#?BGZ-;G{y(PDEZ+ZKx zzCE(R*0E*t?zrBVy5V)%I>)@scen34?%w@b3=%!mVBW7 zvA-5O%D>(_wKtw?2dgDT3yWW4NER(x3VVpYg$ot1w=M59fEa^vrY zDaUW#p7zn;`-cyLx0Tm!<=Wc1Rlfh2Y;C~vpzDF_1LNy>igg~}_}q4&?cd`!k9~VL z^|toT_y6F>;rDCan{1=(tgLDIdU=h}m!i}BTj%cjz4`I^*tNUXmge?sJ9PO$$*-5< z`&<4SRULcm^FH$1&1>;j>(^#3-zr|>ARBG{%sSbcHC8d!`T3pmU(2G)w*O!D{dVW) zQ_olHd&FtHQ~dJet4{oxT{{Xie_p!tbjIn)duLb4$8+v0+JAm|{)bh^ufD!MXMOC; z?XUM&+Hh9}C-zu=y!Ipa{h?j0%imABr>iTr zXL@D*C+6SI|Bo-|zwAA8{)YKlcG

{yqAbT4R}68To`sNnBuO!wFUwJ%u91iQFAA z4(LLEUpNJL3u zX-P(Y5vU3F*;nVJk4{*DpN_{_PhHKE>He{kMlDyaCmsSIEHu}FAdKwmT?!g zEtmT}E$sc(!yD&F=&(m`6P9LT)S4<1T63EHAEW%w=$hp#9w}=s4^k0$qx9g$!D+(# zA4T|QFP-|$(%QJz@~*M=T4tZn_ut<6eBb;1PVxD-f}wwH8_X?hQl=Mm%-(UjW0s=N zrO?SHtS9wUEW`ZSl%y2>dR9$gd1&py4$MMs|kK4HvId)u+3dzd06JY z`5nGb_9<`L_O=KXy^pP^IK z$G5qfAz}|I8Qm84f8#HZT2|cl?s5XRM;Qm>;?G?%Pg3hX%1O*L=FM`u z?LT)4Ui~X!dnsbb@pFgl#;P>-j~C}(@MMdcyR*+gXIHJxm-P;7Go{b1nEoN|rYpB5 z$ES{+t0jaN-|sFgxifvm?UD`Re?p$Ub~yMs(?CGFzrgSKl2^HpfBaCEnYqg6?CleW zgIDODQF~e3|6U@KB|U^|PwbM7O3j}x=Eyxbc{%;Zr+2nBpMO}g1@b)SJ8L4Q_Tl#Z zJ&i{rXM5W_HzUA;W`3rhJ3+#&f-h2?;(PY>;tHR&*?WKZ1u zWgHXz)YV^S@lHM{8+Jm^a>|EFZzla_b7>*58XevB503Rp7rp$X>T@mqp{Vv9KLNw7 zaa9^mKiNvXeze6(sJNoDC zZ@Fc!O?jqESyY#aCT{HMu;XiE<5bl5;<;}Wb)5TI%jR>e-2ZZ(vXi=|yzjBKFK-m=k9EyZ zu=TC(|FU7{@I;VeDXLCP`@nzMVw<0M5t{h!#nx?H;C;#vU z@ZNspJ?E;is@RDMk0z{PiLIT?%X#SqYu{{rm5z3mkQyJon}32PmK-@H7}ObjIY?3Q zN!Q^r`9w?A%bkLaoEozi-fy2A^t@z_^?d&D`{xwjITc>C&DpxmBlgus{l7e7!jX0_ zBKnNlCZ{Z1Z)N{FdGk%T?RM+8`At@FJer>^SaK(#*@t)1M8&gH&Pi^|i|SQ(itXLi za_f+mM2b?r*JpEGPj6K_OFT7r-up};9>M)C~-pj+K zTH8)uE_~!+=JO~(l8?znFnEfTfAXu`i}EW@uiW@y)}7N1bIrHOoP3gX@YGWV_O~9d zzloWD_L5z<`B-lElfJYW(z4Hr(<5SUr|4U}`;_^~@&gkWqf?mIlU>p||IJpW+*L1N zGMZF8t%qar>+jVwX2_iI+0h#HV-iQvThA$LIArVc=PgxOsO=J}MW~NwwW-wP1^n~NzFeEDHtYDByN`O>o=W|-KIHQ= z;=2Bi9Tj0W+m+Q+%uV=q+n)UJdq$+Cl+KHtpS`7i)OiNI@7ZECIcP@3$u(-*rl$qm zzIH5rtzVb@ze?fxf3h{YKXb1z6?+*yHPyP+ae3$Z?cbi3%a>hP!GEIFWWB7g?X4nv?^4Sc-f+YJw^Bt`U4EyM zc;c1Ht3`r!t}pT({chMw`7rPAeVJG+zvJ^8n``%~gnM0`a`{cRX1Qul7B8uOu6O9A zdz4mosx7+i7b=%#$&*t!fH&zoht7We=<;H5(cdtx3Ep^)E#M3M1e&^lG zSzT9EE;x1O>Kz4%y}RO-SKIcVYd5mqts{LqeB;%c#;dK&oNqD@%~SEve0}#4%La?W z6PKU-UGvC9bhV3|OyP-dD(9bfJQQ3k>!t5k@cW<0yL~%U^OA!aNN$A zV>65MA6{&BE}4Jt2!D9r%JY%dqElmBW%oxG?i5jyz5MiHXGVmQrt*8fYmIh^IP!zw=8 z{`}M}qA&l4Reaj~)32QPS*2_1E|fRxlnPq6ZeBYfaMSLuzdLhm_zORGyVl%}nlAtU z$@GfvcgsKAnrWQ(|4)bZH{VC=7n^tPDc4@=`|bPpj~^cH|N8Oze~~ZmA3nNNYzC)wmA!f6#(`(${H8DMr%&2{`r5^9%Y`>S|B&eP&u!kDt;;1p zZ#t*H=G3iQ`~`)%zMd*pQL+cE|H)mgQ+@RR>!oSSR+j9Jee>SDwEFwfoZOFdYOY+0 zTd%FQHR*BY%8*GfZ(8c;o0e?cs8Ia*^NKJnuihW~-~0V%wBwUGdMNm~9|HpegQu&X J%Q~loCIHo{?ri`7 literal 0 HcmV?d00001 diff --git a/doc/html/images/next.png b/doc/html/images/next.png new file mode 100755 index 0000000000000000000000000000000000000000..f3a1221df31c3c2ba4e3a72edad38c13703767b9 GIT binary patch literal 768 zcmeAS@N?(olHy`uVBq!ia0y~yU=Rjj4kiW$hQCG&XEQJ`a29w(7Bet#3xP1>rMq>1 z7#Nr~dAc};RLp6eeB1w40K>80^1pI=K031Q+}6PA-o zut+zF-j;Gw?uf*D*{((14$Hcux3in6E_!$R{mVIjisa6HXWSoM6uZ0c{E^r9Ur$om zdhZ^4hON-~BYZ2GeK$N>`J?GiOJzY(!s6V|uRrr03%sLkr*1#v(teTeT^zk4U9DU7 zv%f8b6P+XKjO)LDUiZ<0p*o>#X6mOi#R1wP z8(l6)T21PWa1OIO8vZ)ea}qY-^=ZrWvbZQ6m)_kQvcrVw=bvte)59DYyUFcC9E$Tt4>&6 z+W%-jd;GDDoIH;dN(0uWOyTmnDE=b*gwcE+xwelYeE}Q`Hm&Y3XPNlB+x+oXzleq5 z0w#UgMVr)jUI2-(`lA6OUY& zu=Q|M1xs0v^{>u8Av+EoyuB{di7k}!tvm{Q)|ESyVT{*EHLXF20N@PNRO*vTc;nVG>kH2j-tEeVx#8P4@BjRN>Ropm;oHA%y^x5t(%-w` ajXhtHa_t{xfsG6d3=E#GelF{r5}E)mona0D literal 0 HcmV?d00001 diff --git a/doc/html/images/note.png b/doc/html/images/note.png new file mode 100755 index 0000000000000000000000000000000000000000..c3bebc7ea6aae0fd9b713ef8ab3cefc31751a03a GIT binary patch literal 4648 zcmeAS@N?(olHy`uVBq!ia0y~yV2}f04mJh`25Wk44otVv!`vx;GaF%2` zI|pPYCo?cq+iGS4^JFAuNVf4f%QU%gGJBl!RACQnlr-uwP+|2s@rY}U zg3=@rM;Au%nAoN@i)u_i-MQ;$eZ}u^fBR7X z_U)_cLwOtCR4A!yikdMfbWT6^y>w$bTYHPq#>EWW0S#PB8oXH4O>dq)e^Z`g^Cj+o zs_)$xw-oJJ{`>v;|HlP(dfMnQ2>6}&cxOdO--OF8GN*kXt-EqO+`?ElGNM_w)#o|4 ze!z)?+A=?Tg~KhLNx%Pd>+$>73Qvp}3YN@R?_;s+(8TzeRavc;8~>;RLJ@J^KWEz9Q-zk&No&OQ$yjCZ}fkDK9-N-?3 z1(WXr?w$t84J_LZaPDBvf57i_!0iCzMg`6fj%p_ucRSc=u&6#zSi!V)0i#J{SOHr} z)8_|9JJ|9XcPFseurV31#x+%b;L~vwXlXqmz&ojNibAOeyHV4P38qh2DxLNPaES07 zb+FNpJ=Iv|+!~-6!g|%w_k#Wf%NIr^%u-EqPQn*-zL1s<_R1!E%BRqtmtJ%vj*IjhsssQys*%fwIY_G6n z$$e$@bvwPd^nzH1d5M7)+uY7`?$Z}bUwr#w^$Wo-BEMwWniCTuB#e8s)mVi4PaYFV z6eM50-!MX5nP&PH_F8enhxTP>W-2 z%j%ZGL()nUS2&rd{}OoIVcjWurp`3r$_(TcprB@sj6n4|R{}9{is9CsH=C z-JB-l<){2!*?i*q3G*l2@4k5C%aJ=rb|hIJS#{LvNZZl4zz-s&U9zdls@*|;mfky^ zX9^$h&hD`8aPP<$UoU2_Zl|_S!Ev&|ln>K9CTUE{n6^XF(D`VP=?cFPJ=6ZGo~l+W zPv?wPChSt}+h$*L*zGlYQSu9&UDCGm;ynJ(wDXuheTkQpH=9@9#5L3QC}<`q@bI=t zD^CnOV{up_wPs4tgiVvXCf(A$s%5IPRYO-jS6fy!R^hIitlNC0{FAILw zspAzEea+o0_*=)D(3_T)yXGvFabM@~uIG+&Wkg)`y>Pqee>46x{Ap@h)YR>?$!X~! z(N;^>wnb}`_9V?r>VLFG$oFKFrr%1Rmy0fOFH^bPH}k}rgl~q=r#_t;JN5F^*HhT1 zP7jIDV$|BHm8<0+!nrEvYQ|Ngt8rH=O;t_xx5{i4+v@(RqI6r;nqP`v>%O}3PIH@Z zOs?0jS8|%k>E5YFvl4r=CzaFsU1li!Z z7IP0k_om$~}onwhgAcSQEyl$d=k?zmo3yt(`A+q2&r*ysN{c<74K*+)G`_yj1*38@zw6SZ$s?9TmT)%vGv z-+p1cmv@hS&-^vXYrP}C&*ndtKG%Qi`Qmuz`!e_I>}TCq+n=_-{NJ~KNB{LRn=oHu zu42|~Ol~`#PTcBwRlr?@s#4Sr#?BGZ-;G{y(PDEZ+ZKx zzCE(R*0E*t?zrBVy5V)%I>)@scen34?%w@b3=%!mVBW7 zvA-5O%D>(_wKtw?2dgDT3yWW4NER(x3VVpYg$ot1w=M59fEa^vrY zDaUW#p7zn;`-cyLx0Tm!<=Wc1Rlfh2Y;C~vpzDF_1LNy>igg~}_}q4&?cd`!k9~VL z^|toT_y6F>;rDCan{1=(tgLDIdU=h}m!i}BTj%cjz4`I^*tNUXmge?sJ9PO$$*-5< z`&<4SRULcm^FH$1&1>;j>(^#3-zr|>ARBG{%sSbcHC8d!`T3pmU(2G)w*O!D{dVW) zQ_olHd&FtHQ~dJet4{oxT{{Xie_p!tbjIn)duLb4$8+v0+JAm|{)bh^ufD!MXMOC; z?XUM&+Hh9}C-zu=y!Ipa{h?j0%imABr>iTr zXL@D*C+6SI|Bo-|zwAA8{)YKlcG

{yqAbT4R}68To`sNnBuO!wFUwJ%u91iQFAA z4(LLEUpNJL3u zX-P(Y5vU3F*;nVJk4{*DpN_{_PhHKE>He{kMlDyaF}_zIEHu}FAdMkmpLw2 zYkK_L8%MqA$3IQTi0XRsqCv%Z!<-|HB1bwN=C=tw@%|T5=VHgkF@eS7(Si9%tc5Jz z6Pb>0(LJ@urE9s%yMwmR-tBoeGj^>^%93Ya3aWOkx>p?bR_4iV)_xxiq$DKI?ns`b zc{A6&;#!}fh=a%1#LUF}dyN z%!Y@ii`5Ua{J+V+LHyQ?)!~I@r`VbeHyk;ke06nf-iyla0UIclG86^Uu%YE6ncQKmTLKol~*T z|6V!`>@NlTN_yd zl@gDbJmN@JP0#jPXQpsHP4W5iDN8E5KE|FZUHPU|xUyn`)Ls2+IhGPyk@qDpv`KN_ zlyt2&>iM|-t)0wy_q)P1pN$Sq4m%aIA;GYy+ko?Z=CSm@{zd0b*u5}$A+SZjB-ZNJ z+<=4USj3;@R_tqT-(9=M@O|=02R`PlmySNT`7q$^+?0seO;;37ZTP6%TDGqO0XHgH6P6o2B}4);WjzbySwLl^zoK^4L^<`}wDu zpN_k0{@W(`Y3|3)``XVk(q1H|CGDR3u;y@+FU!1gp)J*ht5T(&ZRTm)C{yaJdDXi^ z;%}inlP3FCB_6h2E~^f4o)?Q;GmY2iRzdSi;g*RlE6aQ`4{msoZpBde!bM54%9-8F zpDD~d^ShGH+0Y{wH+(tF;(q4-QcXRs;4Lpgtpk#irP2;>owqq8&GVDi_sb%lb0++@ zS!!}U^58~2J-f_T1^Kf->n(mM5Sx4X;;fG3rB#lrB8nw7`B|!tc4bb9(YV!d+Ge#( zQRp12TLCi56#}H9f*Fj9R&$l|Yi`%;%~bEu3DUcAx@U)vNX#9zBVAV&7gtP*;MOwM zH1SjSRl2O{eW|nK>#ZvpPSU0smow71ywWcD?!Nizc*kN3{kdM(v(8FCefRn00#ldF ztxVI`91Dz+*s8W*S;LmZL(y|Cux(R#vdrz~TO5h%RxMHCcEJvAS<4D9e*d|P zyZ!j%y6gtk^OLH2Zzeoi@O0Jl2R6pGQY<%Y-aP#6+doHSQKy@-9KYW>~>pJZbaq0#d>pAX|4<8H@}^=@Y#ys;J!tPM|nS0 z&$%x=X?=;t(L%4j2C4UPtr~vdzmI` zZxwy~V7IW%t(T9kEwwyz!TN2jh2Y5vD?c7B<3E2hGiUO4_cdgW_$DJ#uX1QdCgu~xuY_Zk$?NHAHRQb-P+wQjz-zVqxwMV(Z)I0;nQV*ts!Xxc`-k4Yf0xvF-hTHbm(7k3cUAhY zR5lY=oM60s*;8@zuqCU4e*U;uymG_(pHKP2Q`SE85;}gU<4nS>lY7th)%;s>)=R|e z$SKj*jRJx*SKs<{@$0fR8)bi9{u}#p8~dk=TPt^daEr})qqSzDE7#NYUp}c@EoTl} zyH~vS>&d^ef1aH)a}wLjzfM0nci}2IyVno?rLniGmnej9(3+*OLuc`4Q|a)q*RPK4 zWV6~UF#k_={I9!;dGYaK_VxLq+1jSpGIDQRY3>XDawsihop@Sp>E}<2>{345K411> zx3z!a&$Dg2N(<%8&t2Jgy?4WD=OwlszVD;8tt0ZL6z+Pbn8dl~_gBStwsyyOy1%Zk z+tBp=eq7jcvDF&C^?3Vs+x=bpYlg7!#+P$fM8w|u7WeJr)5+8RJUwXlZqv(4PfJ>5 z_HK-sd~~MKDb>Be ztk+A*m43F0Rtj4eWuwvhgDFjR{X{Aex82ms+k$zbJcbn|CXM(P3H;g*_}pu`y!7&{3yWw)}hZ& zX<0zhixnGwoVgYgIp^z5&tGp2)|xD{4dLi~{p@S4$-jJO`1tMO_}k&NpNnc#Nc uqerwuqg^+zYt_2{^P6@3mfoXZ;{*5dChuIwP|v`?z~JfX=d#Wzp$P!oJ@O|2 literal 0 HcmV?d00001 diff --git a/doc/html/images/people/hector.png b/doc/html/images/people/hector.png new file mode 100755 index 0000000000000000000000000000000000000000..40f52da6fd94304fc2d7f16998ac1706896d0224 GIT binary patch literal 28047 zcmeAS@N?(olHy`uVBq!ia0y~yV8~@)U})!HV_;yAQNO;4fkA=6)5S5QVou3k@BZA# zNzcD-{(7sw_|J~tdkgbZ++6Hdy<`%Nbq&9`NHdB_@yep5Vf<0AB;^+@Kl6i&M^fn{ zV*LwkQe1?K+N*oCWc~2s& z?&bYw`+u_j*ZhyK9*6%~|Nrv)c(KX>at@E_zbf{m0sF^=bG2AM-z1*Z-GqDBp3bF~uwQywIA5v*Z8F`TuSI&-Ieu>wP#F z3uTW<%n>`mJ%#z{---5rPU{y+9IWz}a64omRIE02=Bh43=6&}c9um8sfSF;aYPKQ8z*-T}CdN?zNCl4s#S2q!^(^k2>R!pZaH}U%UwOW zqr?w1Z0s=9Xj&Aq*27aG(4a|kse+QleMO}wQ)WJA&Dj09aR2eBc0;lEwoN;2F8sXe z$JfE3#CB!Pf6;)=dIql#*M8`J{k|bgAo*Ih)AqAERC$)eD~8uclnLC-)^|3w5dvR-n-^f2RRvRTl*Gy{XOR# zm-j5E^)v4!9t|atFU-lIjG~Tu{MyrJ^C<>oDIWFk<6J8md)H&_*PGAlcf2^paZT#Z z%@YpiX1>pvoZj~PDes4xiSy>25AgbZbKPr$OYgQ`anf9>yXfcB*4*os)lKQrZ#FT$ ze)>GgXUP-+%pS$>QnHt@Qu>oX4{8ic?Qv z?X#ktTc0lv-M{%@3`b+vrBd5_?0ozaC4^VCUY@k0zJ|dt;<@3gfYiIZMV-tZvH6d3 z3|uRtI)b#j99;u0s&C&Rbw;96%v<4kQC!f1qZ?w3RwVWQR&6$2Y$GX_DXld9&lZRK zg%fpEW}bdN=YIIr?uWPbiDcQ%*Jw5@`zs{CUDUVn`Rj&e5#K?sXlR>fzb9{kt|DX}$ciL)QPvoQ=oU&wh0CZ~gNr*P{Xi zd%jN3zV>y=-1z-g%l>Z4uKstfQn1%B=Kh@xdv`5-&9qc2>3mzzygA3)^Ztk5)ouuj zjm@duHgTTcb4!scSI^qjm#HV+o_*}m@5ZGm1$^0D_cR|r&``Q!P;jNoQB!r}m7W`2 zg3XJQLINVCJ{V{#88xxBd$O)%6TF_ZsBsqeEM?0GpGc3-ojPsjI8Rz=Ostrtd9q>i z6RxQ}7h)DB-o3iYVd*vDP_{Eax+Y6iO;?oFEL_I-u=z3@Z_JbsJ@p5V>{xp?Z!rkn zz;x}l)SI$Snb>wQ0J%md~B^rmCigEc`C_ zUN=nSBGb`?Ik_*kNC`Cf}dynS?6eZ14^U^)rnyUKzOifkj1XmanE^S@@C}Qg^Oi%kb8o^_hw8m0g{DJ7N~RuM)7B zt9IvxQivYw?xy~rQ@eI&6}z8*)R4t^`NG5wM#DAF6Kx-*8`~DI&;HY4SY#oya%)m= zE{E^z-z&BzT+cRf*sx57%Ufg3PyUR|TDxLm zclhRO0!|9cI(jF@7=_+8S|s{YG%ozQ?5%6(7Tvm#<8#X9e1}*F&$-|Hj_uRL{%>99 zw(9lu%ctk+C#+fc+B$3Hna@YMSIb@yE8KlIt|zU!KalZOQ`i>WIT}iQ6Rt9!es%in zta&d^$=K9y*j1-_dQ-rvq_ullGB{IRC;0z(`Nwkl`cmU9y+y~^TuGu=J zxcKG$&Pq%1RcR~4k{5oK%Z~1=swsc+urP7Y&z{P@l4eFtiRAj5SooSvHF4FKzBX4lnsJxFtoP?Qvt^ft`7IaTm;3B=o(+4x z;q%&iLJ5YwycbU|GBdBVQ-99>XM$s+UP+5yLT!%A9)5vbnrv=i1MGzZR4Hd(E`Rwi`v4iX0P=I8=7`N!eMQc@Aej z$DE(>EHP_sNEWk(#G0=bvo9p+-AUGL4YFUNFi-vajBhsL&yLLGldtl5ZrFU7?fB!r z^EPQL>T7Rj-<0;|g5Xt!vLi03!A8v%A?!u66S5ZAy{+hRUb9qcVVCMMrk#(pCKzpf zB6gr#U{C5iz9n-c&BJq!>CQguuyUg6+!b3Va8G$+u=Rn!9Emv*2LiemEY0q#e6v!h z!g1+o&fS;t)AJ`5?~^bKUdfhpRz-J(afkVeX~mBY&8+g?T2TF&OC&4z&l-zJ^JNJ~ z6e4)ov=a=LtkN+Ni7j%P&%F0_q1u9^lS!86+_@%3GTmee;aT)xF1t*U`3g=E z5%ugh8_zx3b2#GkCY`g-Z%=cHdTwxSYw+hBbHz5Tvw~5{CqBg%eRN8zIpHyf(OGxK ztdp8W_21{cv`HojhVlru0l;pNSBwe$EpP5cwr z?+%9#6B%X7XZ@Qj&1@2mRn63Zwx1zvM zDV=h@t!!7fT|UCKY1h7~bAB{zd@yshW&GxAP1k&;p82>zUC*0Y_41ib5x?$!eZ>}j zeSt&nzx$To8>J)vUoe|zI9=kvXZE^xhjMP8OmFzgQqkhHK*B%l=(DbjqgT%Sd&hfu zlH_)4pP347a__$Fsjg6X<|A%(tnkURXKcOv7SRFOnyE`KWjPifvbe0JoVx6o@-~^u zt=xa!z5ko`14>dJI2 zkT`NH>`_GV(jD z^O_}VH-4$DH_R};({6J0=7nn#ugc9X&AeN{*V5yB@o8WC`ubzr?SFHA`x5+2V(0$< zn!nrYkDB=Iss7yd_waA-#`?XxA8tNh=ioK-{rd%NvhTk&O>Vh5GpJ>bP^MjyiO`pp zC&K5#%;fJTJe{@hy@uw;qtEMm!@4)>PJ1qTVW;sK*Bw9piA-mE-@N#}`H`O+?EbXJ z-2LgYa?7tPGqZN>IFY{mEss>lSIHmRQ#K{6-I8LF&eJAf)swp}Wv2Ks+3cpM7gp7U z-OuNEN$qSmbh^*FrgZx6igU~C%lpM&y}4Pvs_WXJsrH8UcRpXe8~*2{{2%Xq|8C9~ zT+VLxZQkME*6;TJ<=*%2rMytn@+F8tpDi~PT);g`NHxyrR{r~CeA zDw?X(Bvxwm&W+eyWw`BOpjN1~meuF}vm4j2dJ9H1zOUIB|MybVg-I(^i)~~q=K2Lp z+2O+X`_Qvxs;ABxOk4N5z|Y?2+x&0r=^{VxEV!R~;`T}#ai`Zu8=k*9RATkv-)H-$ z56_10`Tr`u@O$_Egca_2ZD*F<-cUMkC&RJC6(zUj#B~<(zkWXBnc$k_7uF&>zM1PB z&;R+^{#R3s@pk=nH@`45ez4fHchRl`D<#&sAGY!B4KWbQmMW_IwnBHAWaiRoc0C;* zeMJ4dRs4*1-Cn!la?|G(8*i8{6w7E?9vR6M*drlwJBD9OHDKxDtekhN+Dv9$E;+D#9ek5`?aGUfO0^^)7obJlMw*{j;pRLm%D_M@)- zqji-qhtHg8C+cQtUQ@cI^~me!jjd@FD^o*{uGcVJJs~t&EIz#MjFpIUWZ~_U~`**B$)y zqpf{={HK3s^?&@ZD&D&@@iza0zFD>hEvMZ&F!TFAX7lLmMNe*M32ob`yfv)m{$_jK zJGM4OzaI(5)xS@kCL+0w`R=mAxAPKGBOSSs+^m+Z!zw-ZCvTbYcPxN(eKUV2<{UWb&?2CeH zjXE`df5uOG?DCw&*Ztf5x>kAH@Av;rnbmKR?0HmZx$x=7({1)uA3l6Le!=N^3Y~L> zoxZ(DF*ukQo1odnEw{Li&(C%<W`SS3?a`Mh=9@<0Bs@_HU?tTv(8Y3|Xe zcB$@Z$BHD`=$2G^m~4lK_kr8Iu6@V1+uXbR`FcP5y8E#o^Z(ycuTY<2 z^6}rhM*E*9nEq(lIg2v8Ar3b2S?7dNRRa<{uLS4=Il0A#hsQ2-IzcPj6+T-7iAzFGRQ!JE& zW}J57h-FrCy?$ipglVlo+_Bd;`l#Qtm*cqGCtveTxo6`Pq4O)H3fD!j$B9hs`rcM2 z;UHZrHhqU!J-7CoUk1yzY8hEP=dd%;*uSbFOE=B6+EAe_|PvyV; z&l#R-3ff8Y9*B1L<+hxs;I1N8CB4E_a5=M%<* zIq&i8^(!h9`IhJp_^ZmoLhu7^>#q%U;5A1MY)ao;c+qk>du~&WBW83BJ-(~jw zlRTcOw14;G#o>K<92~6{b2Y9B1ux;2o&C0LlCe@-)YQs(8riM2^VHWA)_l9!ew zw0F3#Ry@|SmD~CG#$!cd?zU6y?JY9XUmUk{$1%<> z!w$2@Q|1_M-S++ZrsmJOiM4Ip_3tR0pYhAsUi0cBrvoRN967HkdQMRK;+*h;d9H+2 z><7c-;*<~Xl(?LD#M(p8Zwcr5UQl!T?_cY>kIw`-*?%oo)co`1{J)m_zk2JN>z}{> zC!3ciThab@-Gy16%WZF!w$!PVNVjcx`0pJre|dhz=XbKVeKR=CyiV!zZVZ_g?7ZTx zL6Fz6j-+$e-l5zg_uRcN_|dy}eE+lB4d1P7 zI%@psLC%&{TUC#_NzE#Zb#~ACuyFAdpL3m2qNaU8XIk$r2DESuRA)Xrv400StQA2kvQ|D?acsfTMVDBtFWY>6 z^mO^3Z~K4CZ~ps3^i2NF-Tfk+d#e7f{}^5W-d!g!FgD^|-B*>CM(>TmB}!r4r?+3x zf4{PyU1;9xvj@`c>&{+vJ5l-U{Qp1vKMwZWKm7G=ao9KWu8sS4CM!f|YUrKsnVlV1 z`$v;Me}7`9U~u}J%@xnDf8wur?P(aab(4?qQMXT<5<)+QoGMyU7uY>{~N+Rcq9>q{`4cGpE>pF5)fV*lFTA&BM4a_UWCa zDI(<`H>c~$ulC;SvNe6{s!7pjJ$#d&MrJ3iN|?J`-t5nhtNlNZ|9>)n!|!{?|H%Kp z{l4)3*ZGTMAH>)Ht*!fOUe7GdRuoxb<0CHiWKPQUD9*1gffe76p8uJCT5h)d$8hO? z*Y4MxUH|__@}m;}wbA>2yppZ|^#2dz{@?Ha*YX8B`lQ{+anMOEn_%7MXd(M;NzBdM z{K8dx>VNYtf7$ppZBN4{?y1YB&N1%q@1OFgL?~9mQjT9_ZO;091Cb?aR>lFbP8LS~ zos*_!+HE+(nXkpq&wpggnnJgNZA*PpW24K@ZGAPXsQP{2TA6-#Ik|U*b6vCAi>;o&-?M@EARZ8Uz6g0f8ko+AF*FSYtO!y zmH)4vx4g4Ac~70M=A{-Bvj=ZG96h{KWY|m^Czfcgc@{NuS?3(%!v+R@%7$)9F?x>{ zNK9u_$tb*cscYueluI=#&slW^Us_#>;Bx9|-J>%lRZ&b)ulVx*HF?|DHQnXz-Kx|q zwmGD5ooe6mmq+gYwSBzpc=U#KQ!|g8U|-&`byn1MuJ=bXv<0KHb35O)9$gU1b41DQ z%o1O3zbwqTOWo_NhGd3eMe)_(XNUg%YkavyeR|rA z%P)^auD|r%*3fO*jtl(EwfBR)Q(shvOkMZ>MxOhwx{PC&I!gOog(p?dDUZ;OSn$2+ z_(qjPYrZ#sCrWs)UNK|YsdKCE#(d6W`%-i1&Z^3QpstLs9b3L1-SCcKsn@}bWD6J3 zi~NcIBG1(pDmtv(I(N}7t<60Tnv%arFDiZ#RG=s@M>+V#nuX6gJdV!j@=~q1&yjav z-J+Xi4Z@+e#VcEK&*y%h^mgh|%jWH}tJI4k3;5QpcmLLIK4nw7#5SMr>Pb;A+8efZ zv8WzzmFQnmv&8ENyT?oCt)C{Z*!oq5=dgocXQ9mOO=nAg2nZ}*tCB41cVNQBpo2%Q ztyE^ymc3SWq$)3O-OlR$>Uzt+O4xMvh#XbyJ#Q3caLG$~?MFocrvvQ%;#NiLIxIr2 z>GjPLSUPvntrCeVo3iB2FP*UYx5$FOJ*)%kKAI76*=S-$pTipX0Wc^EmD$w8^dP+~neRKWf6SeTQ4WYNzhnr+&Nj z@xKnG9TyfK6AV5S*1Wy%TzN#g0f(V`7t^I9JC3o=F?}-Sh12aECDFB8UNKJ9dV6H8 z>xE}oE;_L<4q65Y_T*lTeqYTcaOec5;?mAu-?v9*@_7m_4f@oxdF>njv$`A2x{gm+ zovFEP+vICH_XKY$K5Tnr6~iDebChM$>kqT1$Lz1^EtO0c-p1vrwDruDppKP6MLBJA z-_3Zp|Iz9Be_Ismy5EZVti4jSL~O?M*1A24CAQ|*x8Jdqo5|OIW_Dvj=FehIn{x_`)-HY24a?yOO^aIy*VAbh-U0@V&0OOmk7viM#}f^&89{%spJ$ZOXRW z$Z3*X^!=9iQkC<>y?iSiUbUEREltfln7z8?%sHdz%YISC`kTVm&zI71;^^2Ia&>E5 zn!Z)HmahHERVTFk48>ha^X5go)QXyTB_i_cA79lqYRP9>if8tk@0jzTV3GdB3HKKM zp7{8>?E7csJMvVXpZdGo{LS}%pXJI+T^`juD!4P5|NX?0L*9>8tzR-nVm;G2)@PNA zUR(V-+ZGl5{j@>Y5p#}vTG!Xc`)p<4RA${c_0g?w>$Gy#uRCG+xH)WCA9r-)?nU=+^>Ciw8oG1qvcGdz9_V~Id;f#g zUk-eFDxb(VfAjyJ*8g73w%=`{er?s0rwc>5R?OI%bNQ;1h3w1f`xQai8vvMFm+E*%2C2>S zvyto1>0Nxka@+3PVP%4|)+|!ySkj^=G?XA zcDeVqT1@oLlwEZ2v2%a%&WT5o!W@_GoU^R^#IwjpfB%$zJGwyRfYGh4v?J>xS@fO_@?YY7&P17AdFmB%TaUu7S zDSEqiX>OXeMd4|yfK8cb=d?vnCS}Mv^4&I{9--yauAC4SaMfht(y(c&rk(RI9ccT$ zHtAA7&+O=|vqvhHEbEc#u5gc?b?}at?6pO!*^CyMu4~J6(pvLr&%OIyI_a_2yPT>I zZ_?2*6cToseq!l?D4nZ+QeNzO^kZ|+f~VT)OQ$qWy_ugkaa(oH>IQAesXZdz2CT-m z3CWMtG_<)$3RO<(%Pq^6J**^c7zZ_XQj`HfPH|d?2dI-*WOK z#a+w3mEL2MkHJ^`E zBy>)!+nlMM@bBfpUTxLIH zQ80_I=WpBV)#5s*C&oNeTe*07lEqQmyPqzI9GtY#VwLD56_-b+T&33Z9ccQl+i?FL z+pmKYKR1;(7QT4-dtGRq;FSnJ&C5G|qO|WkinTs@?!k-=w~9P3vu5!=nR9Wg(8riB z%mFSOj}JWiC1p76vB_tP^G7NZjnBAf3&@;{SQ3?$xk|4`alU`T^A~M`hVwV=scaTM ze>;DFlC{;ld;1eN|LoXRc;lbg%e0goM=j4UYCWp6qBP?<=eubV>RvG)-f^XKUp6VM z|KB%9$WTva+NqUQU72f-yG75mz1rm|nN_!Hx$Sf_^ScTgvc9!$v)-qD(em*uE|0Y# z(HqnhvMvU#P+c$kTUb9n?s7k)pz3s1d7Zye9wL=Wb$g#G?X-J;=yR>*ZL6#~#SxFg zzF#kqEc{#h{En+ofS2M_wTQXPRvy)OEmgen)gS-m%7#+w)|FM{&n$Kdy_siLa$EZu zk5b<{X%35b@7`@(+I!Dpj@TUe6QM8LCSDc_ER47w7!b6^LU_lmn2q&&o>y2YDCKOw zUef&d;lp_$ytngMv@~7cBtHA`)^_Kd9|46w?#|d|XY<-AGF!iJUDoWn2Y)R$>iq~y ziB!yK{;?{-wtZU4fO6P3QO=B9!J4(< ziOnWSnY&+axMf{fvF$?X1M3NWbuT2hTh|qSm%E;OvM{Z@xI5`XZM((!v!|zbe7>@% z=F2Bjw&VJC|0f-O*toBFPu*9+*=G+t)Jtray=|~gaT#aYdy{%RGJKF{mvwp(&= z`};X2oArFwwnhaD=l^osykP32%aQXLzD{yf2${2y_vw`$k45jfW8)1bU3bXexbEZh z*cUH$3BJGmQhRCa_2~P@f;_lSgz<#U@;o=0wITFVx}L_iS;v003+R2?Wi0)8?(yFZ zN)h)1U+tV}7$n-3*qzaxz4xn*=Hp+2udR>psF*HEDvZ0ax8msPkR8?E+b;h*@ZIh& z<7cD9-Sghp{*qjN`OuEN2Y($9;*S4wQU3F{x6*ZQkJ~?(EMMm)E>oU=ztBRCD zb7i7TR~I>`OcOq*%Ts&w#uX`{C5>|gu5IMI^`!jp1t}FTza=K-hp(S{SrRije76(# z!e?Dl9fnM6d#;qm8mDAB{#~S3x6DCrr$E!v*VRtflh>qL$<6q-JXGa&p_S|m|A}=G z9J{sGnMbdS-=}u^!1Vijp1(f7Kdt^huYO*h#?GR@kCJ~qoE5~pUH+{>A6vqmL$Ceq z9+!0ec@zJ4%EIk`zTN-FYxnct@eJKPwZBD|A8t&1A=xIE%)3-2DQD``{QZ^3|5;p? z;+`F}?v&QUh`URFJD3~|7XLT%SMJ=uV%ff@FNGWJ_!@jQwB%}3rvK+No8G)+d(qDJ za;|aCu8qE`0UZ01CES8e$@H-&dBnuVZakx&u26wm-MAYrrE&>UfKS0 z_wMMO^Lf|FJGY)+dlcC<^NH}|XI=YV2e#~cf8omFlxeAHkwVG)v)_iD6ZBSHcIMsF zKL5X>w_gj-|F5&r{>{pzpB_D9m9PIZsXYJwMq@sCozT`i8AqAlkCp9zTjKxg~#ib<#9xO}Zc3>Y1tkn$~@;DcOB^hSPJ~bK4Dh zd=;K}%<4SezHP(Yhg;@+sP>doC%gy=kC3@%VQ8=MP`6ul)E}{?Mcy)iqE4 z{x0tb+a<8#=!dt5=LM++&9d-S?+bo*_pfq)@ItBk^G>fh`~BF1HOnL1b;@*`;!1w{ zZ?;WYYqXv3>=7gXBU7%;kG0kfUbNk-ck1DPw%enR=UsPb|K9gNRxx5)NW?S_r5_hw zl^VJ_aqt|zpdsCOH_!ckX~g|wUONP4EL*wL{h`st=WCAlXqtuVKD>0aicLAa&*bQh zteUM`Rl7I-Fjynn!?)Jyh14X=2A<4(=|yYJcz zD?Zgc=$>DH?)CNcg|Ai=s;MX1&9(4l|5kp#pvLggUEWadY&FLNRzWLMOuszt^E03G zNcQ(*+xs=rn%S3^#I0B-<~D~TOX^SYbF<6pq1QH_w9q(b^~q?h$7+RZfk&G{4Nlp- z_w-INK5)AKR!{HC5|_+X@#(y^_v8N*ay0IHZzjaE%`MJNw>V$+T8}%cCvp4j*k7wcXWxlh z9ptSvy=UV(Qxhp?-Oe3bz9>EE*^z#KwP-evU4>8Po}_b?zQHz;#;yl%En634dpU7m zK31ss-0Q>6()rI=4SVmsa_*mYX~}1$p2H2Bw=vEX5xjk5nHzWeq?f<@ z_PzhOaQXe1g-MZKsk4-)c208G%{$9IrP%cZ_w8u!74M^#zqHcUe(vPO+BtE~tOYNV z<{B5)ynC|!+SW^sm0a)6ZRc6L>%gRMcVxfu$XDj&m+{zb)Zy;fuvhBixy>)#L$tlK zOeTGwS2@peuHT(|_cq9ReCVug>D@=a=EHF7o^G_=48UW99{0 zcKIy~)i|fDckc4nJ^UT7X7N=7wWUTHxJew}=*j<$Jt&L2)N1aI^X%s~JFi<;)^bm{ zEqYyET*21e$0AQZ%ernd`&{$a8|R8kKR3OsSg@!1{EoYYzdwoQ?N(0iOwA1|nU>Q! z=ivk`_R=F4f)B}+$~ykKX7VW~>Ch&fD?%Ic^4eeV^v^H%+}19>EHi0ddfU3ilMj6P z(GhWaj?u@DjhBla-O|3MA}6=+V4fMzVTb#@J4#s=6gR3KEnPTkwU4G?@)H|FhpkBk zzQz?5DYMk>++wXPu5RAGHvOi@>Dw+_d70MUT2k@aghl?0>PEZ!yQMZ9T<`m1o#Cr2 zkLfFUr)`)safNzGV?pZ1ZHI67oqaY1}Xk(65|{JT_1@Sr36>AF0n1yl4^p0+uEW6HHj61hqJ z9ST)>5+*G7lXD*w*ff3&3EsH(c;32+iHFVahrPQO78et{m1Vo$+9wLr7T$lbTW*W# z3Gw8@Ym+ZIeVn%L_Jyy}UTudn8IxbsSYK7uJ@V5-S5o{}siMf7rLV0&ZCYSzzHGs^ zQ+a1PlVb`rw+9z)JzPF-)u}l_!dFtH4mT`*zddB@5sR&A0)lOYDof3r1RrxIHcRlU zO<3a2-flQ=2KUE`BQwmNetq_=?eV{s>GRHg31ISL+Pym5H*dv0$FhwUw--hvoqDq9 z3~P|!vYo2eQs-S1D!jL7`i2Q7GY_4<ZPz=IM7vRVZMOXv!2qvIgeIVXtm^ZuUqM$C#pO% z)oL3N5a*E+A8wu_^-{Okq( zCzD=Qa~!;e-WMB70PquzSsPHs(<4ZV|q+-(~1Sg zZC6B29W##0z3z8Gv~=!k-RXWOgQ9l#nm8`oJWYmMRm|@1lWFq*UZ~D~duoA7^K>?* zS*x=y)X2E|+%M+JRfvdW-Y$6lT~_~yBATFALn#t70MNf5!XBPKR~Re=5zid|DQJ zU-8;x!zEK@^d2l{UL=>yJNvC^Ud7Q*1xZ~qcb9+vac=Y7yBGSIj~?10Gjmz1YUq_M zw`O`w?tC5*@ytx@u;l62{dP(^PA6MMxHYGn&2J4$@6LQwVYBYVN1giB&$F_eJv3FP zq@9^FYhL|4HMabpPkvh;>y2D~-6Ct{9QS9xO78`0w&qFPniAJI$8U+r<}<>3+Y`4R zt~&nrZuGLuLr%fXH^aVNU(~_J%ficiuu5rlnJdrIlsWu6=6Dt+c5<(i7T{@Rz5g{P zw_K*5y=YyD!zs>{Tc2je%~&=wB6zhCf9|^Dn(0MrS48|ec*(Lc%Ho}Tpk~WC!ye^g zt(L;WWqY3edt3c(-;U&Lo$a%=g{JQQUCnpgJ*2fx;^ppnnX@cqzdx~jRM1n~|Lnx! zhX-b_-~Z4|=XJr(&2J6|njFepv|`hdD_sk6FZHeSe0S^eo^Nr_r)*es=ChM$XQq`A z%foNGo@c$`yl1R$tQYemeZuBzN7k2aX!tHV(MOm2ic?J5vda_mj34byztc10)-1C< zTUpdQzVqDHp7T9m$}FvIOSpf>XB}ksUm2VI?tH4KfN9#Er5f`RZxq?gi`$2LaYmb&Kt-a=0O+287Chi$L5vmKnAw8p^m=>yw^yBED)zvJFLrE{Bh z?_3t}a(T#OKe>t!bX3q?&rksCYMb&7WV>-j*G%>3R|);ePP+ zvqy5zpUtbPMEx#zN+>(FsGedytF`uP*(|AKrE5YQYj$^?nRc+e@$OgCzt3i!Yd8CF*4w6TM`kQ5wm84))4s0~{!1rJ zQ=Yro!u|9w-8b9hG@h(l+k34~L2~V_QwqnNG(B>8%QREp2)uAoD7Q6D-;?ik`{f6R zf@yjzdva&>&Jj{$S+()WqJV=^*VE#z`smFJd1V#5XQN`0&c4@z&o8)SuUN50_|pOQ ze*Jk8)7A7RF-G$IHBefX9G9eh^-7cG%ysWSm_5i{c>9Y2^YY#K2B~TbEFKH=c1X>U z@K|}0@7KHw`5ev4C2J2K>stDxb5{DNnnxf1@frGR?!CgAzT~P>w)DM~Wpmxqb;B47 zE$#=FJT&p`tX!YjDe>u%@uBW# zCaRjbmYm7mv?HqfZCmNVn(X+X%u8*PHs0H`QM&KA@^eMw8EtIsi3{YpmS0x>ef;~2 zE$V6RQA|gzw*3{m|FvS<6N!@>*YW&my6EGu@sgV84!wk!+(q)53j|Mg`SEAiZrSK% zxM@Z5wV5H>_n4P8qy?Q6iM+TfqK9kSmP{cDXWy@yJMH#|oPWEgP1W_8s^Q$0SH{2F zm6fKxO-tE*Q(@7U*y9&+1GY|CdG?U|tsPy5A3B_yId^wv=Ni#1+Z3;@2-+evCtc!p zyx)ZE*mSAp6Ok`21x-}b$o-p>Dl0O1>zZQ6=s?pS8_L#N#k}ZPDdfbz^6yc$+WX3v z((1SJUhuLxw=L|>y3JFJgkK-A(VsC%aO0VBv0sgaHLkodwJrFC|$#2EyaziTED-)zwyoY*YOF7*Me?d4zXEq()^sm z$DJmxE5F_<1EpKRv5 z%8DA5Wk=4Q7U#L`miqIx>?GqUF4tSHU0g3Z)$F!ccC?RRvw3#xdXb=0Q__77eylhm zmAJcUrtxNeK6mN8BFQ;ma6Iuy)ai#6hq@ocYQNDt?ZeR)zCQlri>ZI!#X4WM z+-!4a@o{ENO*0Fp4?K6-vZJ)~w7kLuo^#f^oA*VCcWmWV?>_C+2Vw>m{V z``^FLJbKgP6Pt9V_nF-}_>ke`i4H!`musfgz54#|e|^Tpb(7YtI;Sb&*u-$>FJIcS zVtbjbuM^V5Tojfxuso={>htx5W%c^rAis(|e>>%m1*TlmWD?EQRZEXLb)?ie@~lDC zp2^I&tzNQU+8O1=xm@L#gJ)n0yPJ%$sOr&xb9c4VpDbD{b^P$32WqQ=Hcaa~G&TQT zRQtwtvz2x4H5xADuh3rM#xa}6kiC00-yA!IU6ZG9ymsrG`1|X6joc4;Y4iMg9!oBk zUD2}n0h?srv|QEWK3DH9xTJMKcKJ<#;HMQ9g}03^znSs>PkPRtOV`4uoO8;*us?qK zcllSl-+tV^IamMZ>aZtVs^(s&V&e9F`e>NTrrPyN<*J%01?@We@r3aUcg zg`S?-T(B+E?u4N+BugZ`d+$m zPCR>O$pgcwFHIJ2wK-#{E&1O^`DR3v;9IZYf=Dx`rprG&pD9hhJy%A{G@UKiU>E0& zWy$7px0AB_cd!4O$0=`BbG3acZ^ZPeH!HSn_*C}u82@qkf@_c48&h{D_AGmPC*6T} zZQ`7?wnCA-l%6ZQ=P<70lequ8XX&M?BOb55T)yP6@b{jcW+L;cc1deJ-0C|KeFI`T7Q`Qsr10UOg8&P7oW&TvfWo_;p{&6tI^9X`uIx&W4pP5 z+oy^s8Rk6^;!I4wEp{y?;_#8O_`qX}rzFd`Tn$~@Y-aF-IZ`uemvHctqMJX;VmViS zcxbTLcbT4%s$k8Yh%(Vb>+YQYdVJB_3toHh!y^(h-#H(#$U zD_OAc?34`mGvoH8l>t*V0IIK2Z|7 zP0L)s>sX}s#n4L=f|jJb{Iq(K;o3_{30Cz7q;^^zkyFWzxquzXmQcF*k4rVV)$6GLojEeb8< z0`pj`7fnq(J9WD1$1ttT3qF^H>+R~^$aNej%Zz#Kw)s+xeyBlsTieB=_H|nW4d2K9 ztM9*Re5|BvmCZ*>ce^=#GW^EJr2ZHLWhF<7Y1UhZU8uhA{`>agxv9H$rp`p3);*8qs_p^K7wVe*qepVsUT5!%nT}(aMcBz)vI;9I| zKfPBqj}i`6ihb?0QY3q~kCNRgx2w8|Ta!1mFhuXa+)-ohKbdz6M3%B+ykX$d){y6fQlXv4}@5YdO+RD1}g_=v#?`k+0pEEus zvBt3HvBRD&-<4m?riE4?wz`}(&0N4BEP2h8^NZFA&D-~OA5(6R!>uV2-&u9DvxOl^HpQw|z}sD#d#*aqje{<2U@I?~C4Qi!iZt)-5tGi7T0*lxWh= z(D}Y!Go<~kiCk;g>bLgyE-&z3|Ciy^qAg3WI>a&mJFLLG>lVk(2g_#`&;PKiFlE*< z_NZ?qR)*(|*RNmS@>;ffhQYN?hG5O8(@&tOZmqbqmLR^-~2Z4#~7V>*3p1Suu?g%``hHHne%=}M$7rW%H=*HA$Pz3_3f;eR|?Ee z2+IZ6jcwzccosM)$up?Ls^1^ zZl2$bTfTj3Cq6z_W0AyneutvqU9SjX#k4tr6O2zkZE_3L?pbck>YK?Is=HGx$s@=? zR8X)tDlpqEvvp(A5}lpxQdh32zN}__IU_qY+B_&Y!}>yxIH%*)Emu4=FU)e&zP)t@ zThznT*$?jT)46l`K$y(Nro|JhHcYzuiLG~)hftXImRSozibTJ!D4#Y>N%!b?Cl{7U zzi(cXyY1S+IGah#vV79o4D(B?wxn;%O`elx`6hG49FA<)<0mG#wIwdHJpQxBP4npO z+tRniEM)j3Qg2RM%_0L(>r0ebFk8m^cJ1k)#;z2b zN7;=*8BvR?ttPz_i@omZzE-62_wHM3p6xZz`g`xDripgrgWt(x9f1?yR)h1 zU)_ED-QxMm!;Di>Wz>#kDzO<}w^To3o?LO_cHZ|^Pkx^EpN)}0zUQ_{gelHd-)a4p zal_7#DVj!JFP~2|n&h}(i^&e}cQ@?URvk=Qv6bV*+ADS2PQ4gTlliY&C+ccR?KJ5rJ|mlcTdwfnwBNoRH$T@1$W~7?vOjXd zq-vv`rT59MSxXPDDZT!-{E6_FM@txcX6Rg9bv3VF)WN*)&IR!^9RBV{Rs~kg4p=B zrbK9dw@%&tc#VMktPta*Q$CDA3gJ61OpmI+Z}4wl*OjQmxrvpxGj=_?d?!_ z!iNo#-o&w{t|>j!u6}BUdAk$QGEBFm*q(d1-U{Jr z-PTvSmvgp@_sVy3o*VGwoOpVjw`qpQZKpGw$!C+R&$x2QlvK0))tDl2C3OFq>3;-H zJe#7qle=}x!fy)-6NOG6ni{ks?SPcxX0x{&?j`?mS><(Z)4b`j+m1}Xzwgt}_4b?V zermsde*eev+f(a*=l|E2*jXdrUp!qetnJ{YeRYR5R~+jM+!qqWvm&=uD0A(e-A(r{ zr`6vVExh({?&C?ySG%l(xkPsc%k-P2jSLUbx+`0|{wOhj^r-e0kKFw6pF<*2o;;OHBYX7BE zcPH$SmP!#!;(0OWgr~D_f7g~W&z(G7?w-wBt#g#uiZJ&7l+2A~?>*&Y`eNzs3nE@C z_w3vEvH$-M`-;D}_fNWKm;88cm~ixOx1*af4s-M7n=XF8BR2QrVTSQxJwfU`yW*@J8h{MFawwk-Quw)69!k25o8HP)`!{&2bA z(gVLcGp#nX_HJVRGdVR8b?p&O>6{Yk7MPx5%dT%-<1npJS9=1*zKnnR2D!IvZHYoYEiq1kVee+2+sSUJenjK> z@3+zU=fa}&0z_T2qpDnYiyF&)Xcw07*5S=^TpStv^w+izZ?B8j{eE8m?6dv<@V>00 zW@is-_nkAo*1`DBEivoRl4G_KpFRqI{ov>!5P9Wtz{y=3+N_1WX0b|G>3qL?S$paY zyGP$G%olB5`ot@HR^_Y|X`h)>xb?($hG@HLcFys2cf8X6CwhBRao=+O^tOwI^WCn! z_3N4FdUu8(L+aU?xxy=!XZgPKY*wgT8Xn29clpd#Rb>L!p(Ki;p>QX~%IY zY+Z0a*7$yYZ~r=b*`L>=rZZ*yd2mqj%!3oQ7fPgBBEny4t^C(GJ8s32x93j34qs#H zbNR&ae)*f*X5N0vJ1ebsVYXVUeo&U9sfXt-ouwI00-2H8Mh8MxEx-AWm0hT7dhs;I zl*|m(t__JZSWaK>mU%7{q5MN_$^Dm6hiA+bVcw+?w9`2(V~G;W*$1*IJ3lRu)zr4^ zmfX4Y)a_*vw;3L@fBE8K%&eO4@;KwT{e)%wEo+mqT%U(?tlv_kI>kdvaIw%<)~q;< zhi??yL-#`RUdyR9kFVcKN2ps?SzF1SqCe&Os?5n8fzfc_gV05 z>J#~7k&l`0wVnuRx|&SBy=~H^jlZw-9obO0UtfuJM*6bCDPBRHf8Eo~9d5?=S|@MDLEk4gPOwh9^W&}V$0Gfls}I*MdoeLaSE{|p`0#Oi!}?#wdP`xK4Zf>DJs>%i4-}VG-9&<&?JaB?>!fH7$s^-YdafClPoo@b<04m0~?Y zJ@KKtQyem$YPt&cxb1p;v}wSIcgCL3*dssVRb!Me?}@)$8_gTO zXFK^#6wA{&?X`|KmA&WlkHke1ibg9E)xw=mEi(B1_V(QK`qJ0e3OF6we&*WV)TJq1 z!6{EQ4^Ld>w&|nB=gzWUExz^V3;ufT`RCR%(@=LsLA%bzQ?tA-7qQ-){c->9nD_Fl zf^5&ew4PD#H8aXl(wl?(p5(HFhWzuEEZwQeEmCl<&_d?Jz0+T;GV-=-n;bPcE5oPG zW?vXBmXs;e=N`17#nq(oTIDLaCEgd8RLdtT9CP7|E-yZ1rf1;Y`f8VV^3mw&!D5`d zw`ZgqZd=f?WX8_*(zmx=3VOr8QtkPd6&Ei3J@SH+IPp5wyj=hq#WU%w#Iy`yyk z*UGGI6L!YDi_w#It$aA?%lTl_52u2**lgIECNwe1C{R^vUg4jXtIW@;RBL~SN7cG6 zZRiuc%5_UK%lN~L^)J7h`_9_-H_6>!x1^{u=T=d)S9xWc{Sl8l9B(-sbYZi9IOllP@fWt1Yht!2PuyW=@T6;on(_+W-Fp* z9SEHgpy{n2qIouP%Z_(D^?Z}tCw?^GJ}0hPzA0BV?*0OfTTT0xE`FjnJ$X^tff-?4 z2P<#d&Qf(>sS(YT>*jP~$qf!e;YUnYC-iQapQCM}D4HVmme28RxOx%v~Sv#Sv(eN7puH1xH84%+JsFuCu_H?e>HFV z;ti9ZS)2{Y&8#}m?>=pUCY}EAblZooUylhXo4V!5o}4Ta>KERn^+e7h zZgtJEMZtpeHYx?rJuGvcg~y6r@_WX@uOV~RbbnjG)Avo@_WE!BWRb;_y;k$hn^ZidR~UruDx*WFdPY>hqsJJ@1T~k5??;zI)ZB9L0rOCOOEz=QNxUl-4aiCy>YQ zn8w-aBCjpe7M#3$MC#(w8MfV9>@$i!PTR6P_wAEy*ECEQpV3H_6 z?6$4iVw=>ncuQM0@AEdk;~_f|5B=gamb;Mlq$>JH&0PieHN`%kXR5N?(=*>!^Y_@+ zj#;O)nO83St&`h7S#RlrqGjJ04qp4>%z8bm+F?S=yWWPtUe@djrvhHZoi%UV|0msk z&*Y0uhDNjaHH+^Hd3(&UmwD2B%Pe4$xbb=8ec9e#n*9Ga2XUG6c?1CQH{==f^ylb6^|OKB;JEc00HopAB*2YnU9|qsm8<^>I!XkjXqrDzl7;nrO!0O(5~`Z3ueyZ=qtN8;pWkx zUD+X31_`-cmnME+na}jTPwcJDy%Q=`)48`qc_vP-j+wGy;rEl3iN4VAA1a++-sb8%#l2vgw^C^Q-?aPY`TjHmd5ks!Q1WSL^rBCzkWi%k;5dRPSR- z4Et&u5dAKRDNM4uxbpt5IiJsL=5cSoc=?ou&5_cDVu^OIcBT7&uZ|Gr4q3M-=u#}J z?K$DR4@*KjoL*NYpYHs8Tz+HiX_LGq3vN78a|vhFRC`n;esn{;qx7=E6stKIw) zakIWPIxV(y-@ZwYdDFQx+CTE;>WT)MTj$P9JHO26^;_xNVjq0J-+SLzf9daIF}sa1 zhAKBFga!I;b6qPc(O)$0)=ST|;$2?ZI(NH$Jfa3w{>&yqfe^zPnxfS-#(z88jj^SgEKq+ItqJ@6kX1R+3 zx+Hrio^$1?;9c36=eNt~)}pn~AIRvr`gr7M24C(noi>3f`rMXDnwkqj7wUYPw%qrK zbKy>=3GIzy;cxyl8%Rf|ewsH;+ARIc8q0ZpbLxKxfBPc5hV{(UIc9r4ZF#d|Rly84 zABzcJe0t5b7O7wC@ba1IvU1`o*8&BTMJ?+>Gx*LXp6MwR?(NA6Em?3jX!fCZpPgo& zTXlS9@I=qe#bVt{5=?k*Pn)sk@wZ>cs&*Tn6`rHLtI@Tp^00wTRK)HA)0PhjVMjIY z_TEyFaWC!sZZo%|aB+t2cfIKWWec`)ZGAAs?P`l=Qsz`P2Ystu)03>uRV*-be0^=v zk6&L|S07yArP(N9wrA?bvwjJ^hDG~N&;Fiso~JIMMDDdp;`fRfGyUq1e=JG+_e1%l z%*wY)oQHLTqYqo3uC!~G>Uen0l{4_CY{e~A=30C0rAd2T&0UW*Oj@_-=J~yLwV7K> zWxLPtfAZ-WlX(Fz|1m7i&|ULymhno5 zP&X^3s58IoBqFw-S-=0!p_djPYwQfqGruZ165VWE)YdgAyShLnTeyTR<`$zAV4KUu)xee~}A|-giYR!_=*mp^Z6i`w4ZcEXlvd$vyKE%{umq$u@g z&TNjtU0arldLG`eDsc9b8QWMks{A?l@#AInxcGfV@#0%1b%g|pxVmk~oo$j-{%`ul zCmR;bI{r;>;?}lHRq8I1N$c)hcgR!PKl#17pr%EcPxV5j`uPtY2ur$VGA0YJT%!~H zpvc$eC70IMBi(l=2N=42y&;mRX0mic{{6aCiDT|rhwJtmotrrO@pAe42W$Fd&ingZ zZrp8l|-y7Pb$x*i&+O>2)@;QtrlCon%6Wf zXluyQDxGP6%dBV~Hpbzg{k$HXjU&B!R>1yPz)FS)y|KP{RpoLukm-D6YKQbmEx zBPGwv>X+t)Pn%Iud$+=@E3@{g`sKH~`d94}m&s}m7SFl0?n%Y_+lwk?nkFq?_Vd9c z9vSZ^KYt4AANIde-9O(ZMXPN`=$yHcdF4eu?_&}l#O1$uZf_v#FVlOpV&-Yy%Li_6 zKR-o5Zo4i^kI|%+m$;f6H{8{%<$4$+zsX!zj`_9bv4lT9(n6+s66q@yOv02WS#WMT zJ*Vyu=Q{Rhj~kaCZU~*~sJ$)s@bRevN1Vm8-bO#wtF(BamU;MO-PFiSho+1B-jSMo zwPjYSa!Bj+?dN6s<)VdswL`Y`lqST+|9twXf6p=>zL{boD;bU!e&U<^uI0{&V~eLc zC!aJ-UR7}5$pyCFW5*=!Ex-CE@~Vx>$)z1kKTE6vS98R#JALf3#o`M+_ZDwGn&qqa z@?+WCnR=GozwM43d026zUuZ$X+@n_g*Vv1^G_*3m_`}od*pI>-Vn`I=93nsfhmRub3;=5np zXSugBA+3Iwj$YhmTQ;dp#bVd01t+f8+sNHKH1)?@Y3J1;=}W3NyH4sp)Mp}mwbA+v zPu-&xj^yBV(1=Cw@JS}^x`To_#i8s`D?EZDFdS=k+_UxbA^lT#g zH#08__t|-*{g?|=#h2#Z{w4wQoGmvJ45B6;^17ka{+KaaSktZNTF>Q)MkzQSuC8hp+2|0KQejaVMc2ijg>{a>z>ucTKXF|XTDgc zbIq-(>R4bI$5PX!nnhj}_nR4f#oSJ<$gI%Pwm!J~+O3rvW*z?MagIB>r{~&(<;+(m zrm^=Oo_MmtugpzaojL4jf$GG=UKip@rvCO`Qf=2iDetngllZmj{cBIJjLVMS@~+q{ zD!8c5r?0p*}iSk(MUn#MP|y|)VXJ^ z>)aC;_w#4^;RGqa^2XJZPWgQ;oBX-i=j~R}A}yibncm44_@28>>ANJYBYSC)==%F{ zJJ&E>wX?TP)Gwd1`bCQ5bK~XD?I)~0YVN&OGFN?yQN`lGb@~zYCvL_Xd&O;J*WDAA zbN0R7r|*8UzQTP+e5$}I-eZy_)68w3w`uH^e!WRxcZ=e3kF%Z6`XsCq zwkU3Q>XKaT8YcV5E4PjRy!sX~&cmB@0)Bm8m!*FwCEI?k=`K!YANUqj$Ef`k>H!e>?Xe@p+UJvv{dUt zi{?6iUF}r<_}%V>1wX&*2A?#$I7>`;cUxi2_c@`f17CISuq%vypL6@zLz`1O4!m2q zY}e=V{lbqUcIK~D^=#N~RFNAHa_^e7Vva__g+*&~RDUu23!rPtr_(cb#a zHMnWRJ%HS9Gq=<)G1cmsL?iF8~X#a2G_5J_+ z?_E2@KVR+GK_frmW7Ta3AFv!j~6h zB>K|(mTMKx^4NYTOHo$CtR{TP)3<&%-Z@1Z%$pJNJZf!)c;u(HwNlMa@;d3~c$yz? zS1mB_Ti7^{XIX07jElJnA-XcYcQsZe9AWKu3}`gD@R!jiaG8YaY39oTH!i=_XxXxF z(yI1*PZw$UvP`n%6g&8(<Q#l&!pL3_jeRRg`XC7^NR`c!7`^M?lwZo$CR8EL7)2;Y1L%7g;(aHBOj$GevKIPh(6%cHfygS~Et5_xeRQlb z?8vd`twMX&8Tzz0t7uL;WWlqEImC0yq$v)q@@`qVI|9`hx1JO$ix!KEi!V51Q(wV! zTjgkZY{u3iDRrq0I^8Z6lD+cmIn!@%Rg25_PAQV|alX97;icXF!#O`5-b`K<5Snb9 zz$RIg)w*h41lPh4Hty0bKJA>ZRaFA?ZZNb339robn#{OT^jh158*(2*V`onFp15jl zv9ZdhxH-DVKhONV`eAP5$K`y9Hht(*16D|*t$ zF9(M^bzWTj>`zAW)mt~F^@eGGwn*BwFG$O^`{JvI=K_5f_DFngv^yU>$4`CUeEWjR zO2s2buII0>Sa0d0e68|hYv$Qo>cY#q6Sn6jTXeCW$$Gd<=XyBHQ6=YFi2`Ew4rc|Q z%N{#B*zbSi$tii3b;kpaNSrKta{m8>pFf_r{JmcP zGrf#$@78YFFR$H7nsYS6->dQZ_3&-?N-X61KOOo0?vF*! zkIW}84IYN5uGud4CCalC&tc&_p}fCO~1@(utRJ2^wO^7{^?n(7K!~h z*OXTD%->)B=i&eV;*Xe44&MG<X6?B&b*+QdRF0}GuUMFstNvYLvDOfsaUiS6@66{jKT8fsv@R+OD;C}R?4?F` zAj|ZLzdbTOFweKEeX`vDenx!!N!B@2vnK|!^&Zn`^jxiWNTo;U!HTdaQ5m_1wffC= zYptFXz3|b+j4i+Pw6Ay+Oxjqme^27t;{CIk-%j6g>9+GNkMFUmyYjtqR_94r*xP=5 z`fKLxO@@-E7l^HC%M{rkx=uTBr{TGI4@=ah`b6YO*mrQG&yx6~@#6b2=7-yL8z;qe zUfYx>y`|02XwwC^m<7rF-QB(}R$kUwm-!iaqMrHhx@C9%@)oV|$p@?7ZJ(-|nf7!= ztd*};#G`Q*Rj6+Aa{F6qwZ3>9KZX!9kgXH2i#h`ckB5Uz3Jfr zU5^u|1bW7F?DUK??LEk;cinO!SIzHV++A&3dQ8?{9 zL$eWA&(uEe8!Nm_q*Pu1*nDZ>)m+rq-q|nTH|L!3&V#pa&rR)R+T@ma)$iu&rj;-3 zqb9%ImU&a}zW!M^f$y~)tG1@CV7hs2)uil+*Y2#ld%yn8|9$7Leya;#+iGihfp@XM z{_Cv=v(9~HFWR#?CVx$|N?VV-&S#Uy?8oPZ?#cZ;G11QGTvB38c;&4(&D^T>+vT5} zQ%~_lHM5R0h?`__}+I4M(X40(JYHSA;p3Qk0XQ^{%nuqI> zCzIuucnk6v>dZYH<6`3_e0aW4>D>$y`T2Z2ZX44Y^X=!S<#|6kecgQB_OFHx|IP=5 zRkOXQvtL%tRP42vsdd+P`RrPayK^?*NR-%D&2-QD&+f;r+oqMjt#kfbSf_lncM_AM zV`t|w6J60;wM%1+mODSFuzBF7ez!vP_T_mkH=-OhmGfOrzW2?RT4>%8>_7R_W0kjC zwPMS1O(ZgX%&)S}UlqPwfobNY1!^(PO-JUw3EddfcKGFyqTL^_@8A1j|KE@5J+Gz| z=E`5HFx=ODV2c@N@{Mb*s~&A~yt~14QE2iEwq=P2vI4``M!&j$-+IT>hkJ7W-mm_< z;eSNYmY=#yw^Pj1;KN~sS+%N0g{$u} z{|?VRwxxW6>fNoL`OBZGeb;#Hw(xQ2Q484}ap848|D3vf+1OINPbz2fv7HWVM^;99 zs|s#7Cm7~>uJiR%r#noKH7+J-=I;1-=KkL=6N9wv|9>^MZvOH6eWCe@?!x(cGpE+S zYhkX8i1Oc4pP$1J@zeSA`*|&Y^>5s_=xiUSMRl9IX4@40K3cy!dG6v_lkcd1|2N0z zirU2~*Y>bGbnw_Z$2)9Qmoz(>b=fy~?csv&Me)#`Ck5>+TU(G+Q*xpm)Jcz(~{NLFJH%$yCWuVPwb)hV%hgkzTw*f>he7wIReMkI0A*ZCZ@x?(0)m zci`tl$4(d9)W)Wx5x=%A=~%fa>+Rpm3ok!+*%h|+=#S2i98b54|9g7>pVvzJBCGiq zB98?uIxVbOmfO2UZ;8N#6Whvc9MeQ}JXQhv37KIhJzi@4kPxeEcu{ZPNVX zPIh%%rr-Xq$-eaVy3qftt3p0+o6>Xj(T^h>>^r`3%Xhv1mVEVl#fGrJ;MCsE#}=O- zUgke@Tv)+twd&!A@Bbb7|C9f}LzndR?ZNxMpIlmQ5H>?nbHmc|xFz@Ax81j$y3*8X z{?c5LATpKo-vp&(KfRq;ZM=IBUfDJEwFXF8t3UXCDb+8NF^b+Rafnr%#U9` zjd!N}`*Gaf@YmeuHw^9>zMLr``m;!UX~a1TdxIX~!xn;F%0>k<>=QmY`SrS`6ij>m zJlH+%4Ri2EwI%DOXRrPG&fQ;nTkPX_Bh`BI?P1&Y_j>7FKlO57#Mh5nr>}*|@Bg-- zFncHWRHailKL7NT+Od@5+d{FPpe?s5Dr-}v*yq{T3OH5l-_s_up*f~%s?q-LnP+x7 zthU(b%pIr1vaMA0sm}=~^$TGWU(daBWX-&n@w>0t21hTPyL6e4&&&zp0Tb^$u?n90 zc-Nj!zrK0JWg8zHz_3Wo`h-b!qPWI`y4^>zg$=a+fwsd)u zx%B32u5<4gIhI|n%zAI^)xY_hzTFWG|CM18??2SJ?Dh*eF)6+6;tH+m-K#$FrhU`g zGsoRfG)Yjn<{a;OqpEK`-)0Ih?f>(MyZ*O@@%iBE+g0?|-~aLJEqC(iD=R#fmb7l3 zG{y9F;Hl4_-X2;X9~ZgZ$z!T6+sd5i?+I@|8>*gLu(xza{Q9!npX);2a<81C^gMPU zkJtQ&7iRYiNTXyCGv5&KQFS}&+PT#J* zxIRga-SOzQx?F>4VXBT3{`G9xW}kS8)kD*(%0=wz^lfcDg5fLWFPsYud@?I=?ZVb2 z{XtzKDm}-y9LuntaM{93cuT@<_aAEu_uf6ZR519_)7#d{$OetNZuUxc%@6o3lQjPZSF9m-IOvx<6@2^cFeqNkxfoBbNP@{&X&JYq}I) zgn81MfFSO*&iiJ$7@S(H^LW{$8}GUwJdHK4-XZv$m6@N3Z|ic&9`>~svS~g$PFYGB zJ$@mvd}3kA6$?YTU3vHW`GZ#5pZW3gL}~OzKZW@la~8Zg+;HhtwL51;PJi|G%==oQ z(-p5=>SWugtm#w5vEj|bf&_CWE!Br>cOL(0=F!vOW$a&{e5z>5`0({~xD(Hx z3OmD!^EEbxXSOyAGcfQPf$j)6YkaNW$Y;;}h^!-cK??CcJ!9GU&r&m*Rx)C-=6qm@1|`J0!)IYOwHXYKc)6t zXw+f_4b|49STirapr)+jMf^{0YaOg;etg*G`^h4;HtSPSUOR${lIHX$m?)-hS$pF! z=agg1TKDW*n3X2gHzPAi!e7Gr(ySwamRwI-vSuEXSMl*R^^gwxV3(sYt2o2HOK7G? z@_`p^rb2~Ae!`DGDlag&9{%a8v10rO`Tq@eHHZBCHNN-kt3CQkJSKOE>V!XM3T8zF zr(Te?f2y$L$gi-9%G#&bGR`v++EkSdxfai;n&|Q9&fnQ`MPNxt2yu8 z$-11<`S;v4;(tl`YkRb_j2m-qN*ES&!Rk-?yOMQ=Ph`^EfJW zWjn4&`9^!C=k82&_&M`hNGY$MZf)qvnV;i+HGE^iRj>U^_Ui{^+nl@i zUflPaYt`)4Urz{q6y&g3aCl?++KS)ntk(rpyqDYMY$=lZwD)Sn;*7^9K9)TDblXcq z@UB+6Zug9!q;GPQeCBtXFWUHGM_1;okImC1!jspr`+{*Vk_mt1s>AOjKQCzT&;z+s6+(q|@?VYi*de!y&3O zb7`-z=*5y1wsHO44cSFp!E;{9e%Eo*4M_kpBL#eY2yrif+j+ z*neN{yZ5(yIXAc^mp)O{V12`H|HmV_y=`iFqCd|Q4d1(SJ}>^_V=45=sZ;R1`<(|D zIeW5n;_ojAePc6W&K|`b%#Uq4cN(zN^n7Ar(qzA+wMzTFuCxEuz4ygxCgeY<+g-4~ z=IA7gK0foG^L}VYdvG;AEpqK&u%~g-Z;7J|vJSt{3Vto}tD^JWn~is_OBdemnEl0P z`fcsUFFVU7)Mfa!-rmKzLhbIy#}ftKPg&(4nGw~c^!44^d-^}NMi;71%zV%NE_Bh4 zb+ca;@3+0t_v?e2$Kr=~E0=7oG2`7(|MO?M;%dw5$t_EZ?Y?H^Zohv_V)v5=2cF&v zXineOB_@98tJCR;8zYnWmI!co?(i$NE_e~TvTTz1W*zSM{d*I5ef%EIU7BSuw?;fT zZSVdCa~_w~Chv}y$W^}Gc(Zz@&~`7~*3#G;*FJf2$Sm)ru8es-wkaDRa+s zCV$?ttxDgY?ajI)9;kgVBxC8y-_qf`XIZ5do#mhJ;u-XpOWrj(`xeK>4R8AyPD}`t zK2}&2P~J09H*rqdvB!Z|++MxUxc2e${y)N+c{#7mojL^$O0{Yh{Cw+FbM{D-%Hg9X z7pr69A}_m1$lT+Pc$*=?R)5^uJ!=2QxA*Owg=3Y=j>-LNSjV2U;z`-^BKMUJUE=RD z7e`7stK10>`qgE|H+|iVs`PKnp`GoPYq_tVHotcNAM4hbj6!DnZ*D)lPT9U}YP&Sg ztme@yTgzMv>%{%m?J4oA`=`aP_2ptyjZS-ckhgy&r;u8pV9kaY<|~hTy|O1|?wjx^ zu-0o{ms(n9*2WTU?GG2;u7B+n$eJx{c+8#ujKpD+^K+YKv2ZLinP2yZ^QzWED?z*e zT&fE)Dwb!cZfrAW%-D78ZRq5=%f4PYXqq|cZb6=dc0{jYq%W8GwXa^ftoG+*o_8Kj zO!_t}K&f!|#+bMp)3{CDS9zUzd>~QEvWK}$qM~;9hi_lkx7_AlnmNy|=1}$NqWvF! zUO&HP`f8u$Q&T1QW&Hflv~Nye-#&Hw_V9gme-BB81+hoG5Bt8?n}6=gtH0N-U3t7g zSar$V<8uV$j{C2DS{Q!YK3-7!@Bh%bH}jOY3$@vctu{X?r+m=SZ^G<7|0k<@JdnJt z{PmEjxa+nY=3Pc9C-3@hTJ`U&vXFFr{Dkjwg!Nwjk zB)KDQ{z*fjCf~{+!2;%;YF=kf{GPk^&(U}HZfw75!koDM^0JiA9(e{q?ZH+0*@lU+ zZ8;8UE00}zw@IJ}USG`{cXF} zajoganH?HSBO00{EAm=)EV?)G^1%@IB@uRK_N}j}H(gj4@&1i{e$MXRm3<-?zw;l< z*RHyGv#BhGPtKuT*tIS-k5!aiqUk~pPjMx61==9aducPOU z>yGv$C-#*g%XR$q-|Q4}ekk_v$Iim&v#h2^59x~ZWyL8bi!NEUQ%xlJ(vxe>&nBI_ zdB4-;a#hkA)>oG{m0ghZT9nJJvux5v>FhNd*XjML`7`5eTj)Y9r@TiJ>mOIzUt!|j zr{&mq?DhNl6LtG_xL>t?eO_MF^=(V%hPUkQ9WlokMHfD@3_7N-uk%^h%0~G*>%~)7 zwSP2z_{Y5J@JrV9eUo&i+}?iS!w&fs5&n~n-?%T@bAN}tyob-3I)$fc;ntPw9#5^T zR6Bh@icA0gJPl1LpGmEzF7NK!dwfj`{ueSaXU@q&0WZ^XB|+2E9d&AntKCA^X5|)K z4L6xpJoRSjn?I-BxPD#9pV@KIV834PyNcBNXV)Bh@}$mh#X-dUE`}^|_e$c7Dlx)HATlRgHx2R8A-Q%3Q|gi**_h$6{x#?O>63z7t$|RetUaytL&j0N6VO_oK_Z# zygzq-LFnSSDbZf9k6W!=_0y(|vAd%3gWT@uZLMpkUY@gg_9C9QZByoW{BD!K^5(~@ z!+aCMwk(-4)6hi zZ6dWjd(V=n!mG0zdm_$@B&$6y*mdjc#5?JKn>r-4^n4w!7;SRZQBZp7E|+;m?8ajQ zuWCOtm2YbwoX~VUdd~WKSSV}JQj5p0ze``w`V$;@d;96nKPI)mi&~!f?~tWUdY`4F z!p#-T^Q(Ja-O0RL{!OdFYV*7^hJiuLmgKzLQDF8`{k50X>Tj1{FZpi9>0yWKL2nbaFFj7OIDg>0ef+xV^>b?fGrn`-oqFSW SjV=QN1B0ilpUXO@geCx)ZGP$i literal 0 HcmV?d00001 diff --git a/doc/html/images/people/joaquin.png b/doc/html/images/people/joaquin.png new file mode 100755 index 0000000000000000000000000000000000000000..f0b1a253b7c9e81dbf9a0fcb75d12eb0ddf382a9 GIT binary patch literal 22195 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⁢$;B)}3@!(Gniv9hFmxO! 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 Mr>mdKI;Vst08*gQ&j0`b literal 0 HcmV?d00001 diff --git a/doc/html/images/people/mafalda.png b/doc/html/images/people/mafalda.png new file mode 100755 index 0000000000000000000000000000000000000000..00781df3c73e989b7fdc5985173157cea81932b9 GIT binary patch literal 33491 zcmeAS@N?(olHy`uVBq!ia0y~yU}$AvU})!HV_;yg5SnGqz@Wh3>EaktF(+j2&&{eQ zOYeU_x%8D@{_EVds;V@D2zH4zEDky<90HR(noV3a5An4+E4o`8;`$#MmSLFcJuTzZ z5>K`kR|SU#21cP72N{|pcQ60`^lS9{pwO9>e-2wle)m(By8Qlb_3O0Mc~7hNJ)a%< zZu$NnQ@7+g-!EM24=3M2T>-!lj`q>K}%z5y!yHjJ(wmLBl1wV~%cG4P3a_-BfFfko%?AYhOfB%Gw_bnZ|Ze+-8 ze9|Kzpx)8p*B~7GAV{OCzoKw9C%2zCx2#8D>jN3T1r^6mUTeLQT72$dm%=@<_yZ3$ zN&~iisPb*MkX^vOx9`QH-5;NEE4ePeYZ+50@J2YzW?fxcHseXFcTIYe#B1{>u34?l zx3b$YR$y*KY{KzlUdL1&&Xl{b#2*MOSs1gmJaG9YSKS$foriZWD%Rg+@o3Mvs~I0s z_k7#Yaf9i$?ZZ+}TfT`s`bJV4HslKMsULloZt}A5A9t&UQiV+27l98A`m8k@ZkC9g z-1VVB+fO~rMY*AJ*5^3!Xs$Aq00_+sm-J6G!ctM{z_YW;ye4LVKbdrn)& z_NslYW}Q>H>BP5CR{g5pR}rNLk7sO5y>k1y`13Oh4m{R)b|7f(m3_M{dN(OOW_s9V zwS0%w^s3bNCa10%9*?bdm$fwT#V?dkoK7Ckys))r*7Lnz1K{u)o(G( zS#06Hg8Pk3T*;+lHc1n`k{kbCo2i)j?vSPXhlx#XM-{3zOD!_YzsM0T9(aafPvqR* zdzacPC*Iw>`TfO2Zr4v41xl~3`jwn1-S{=V+a$|u_R)21`ECuC7c&~l)@E(G$K$HJ zDo4q0>j5cCgT=S&Jat4D-hVo0`_2ok*I%SxpT5W~=z!-o({_)O8P~4LtX6dSkfeC8 zTXL3Olw-l8x2N~&?f5>;oArZ;!h(eX$;E(K*{W#d+sPlx#Y%?(nM3Y21PFrAzQ#G)Zk)2{=l&BJE=%2*yY;R*9J^wq z=eBoQqVDIqn6EK!{>dimY?$*tW^a9E_?k-&SuYRIG_*42{e4G5lw0|lx8LGrn>~Wm z7o1C*n4@`C$yT74)mccOO^V{9w=hii~w}{5KoFPdLtbGF(gGDokT zNPHc3s={8h=Guk5wZ6PHVu@XD4&lk(zOw7wCRFXMT0f2J$f3PwzkVyXGFEbAteMEG zA+tWiFPL|^o1N)}Udz+hejB*IXz$^!JCc7fvcq`#m42~>71BI)J^pdY9Z`QXR!(D* z5NrxlTM=%-zK`RPNJ6E^hFw7-JvXcO-j+DTVJ3L`xa9Musuc??4&+*PrCyF<+rw>D zD8^}USlf&-i^a4?>&NW}yt~`G+|PJq9o%@3^|5!=@wU?%E5vU<*{xf?dcLuDh)%#4 zFV|BMYa0y?H5fV>pWAvuO-tm4PR+$H5sew8QMKJo=_>^nUHP&&{*sCA(WiwrfzAt< zb_8*`?$J%ya3W>qUCj)c#>J}_6frBg%G}FjST}F)M=f8*C}ie@*DScd#cnZrS)IFA``wbQb= zwr#B3ZC*HQp3VkA@0(L9CvAS_xqRoWM;b{nE$q+#SSViMoR*|+vKJI_{_ zxQgt~&VLY)p7G_N;rzS%{)HaW{ZftEJqml4DeqzO``Bl}!>k%Tqikvk*MmKYT~fMVO))ZY@4n>K|1Kv^*G)EhlE?N;MLA3>@!{$IpD`!bWo4Vb zy|O|5oTOVp#cHb~nSP~aW%5j>udZA%_scTnI=1zqmZur_HW5izvf^0x@*GJry^&vyN%{9&VE@xHzeD{YWJqe>z?gTdb;#y!)Bpt zr(aCHYVY=Gm5|<*qZ7(|FE=XI9oxS&L*z3Pcadj<=&-6lFz-pbg!HHq#d=pXIa!6({$-h)8XR{-ps!~sa+4% zKN9}CXmM%oqp6iG+x0h=JX&M4V$CeGWmlxK8G{nLEzFm7^X4Z1FA`;sSao0~BiBN| zZOsy9z6SZ6p3zEOfk!@NIi9fW4?Px9E268r{kK)JYS6()Gxndh_$l4xIYq0Tx8nYy z1=*Q@*8P@F{@sysZ0Fqvi+oFtEQ;NhvG9iLi7S?yw%#z>_N#y6^}xmQIYAFQbY%kX z$8gv^+H+X6zx&>_c#)|}EYD3{EOk;MV~$B%gu0!PZYcb=%h@~nxh>;%&XZ;g>GM`6 zR!;7APhK-IaZj?TAAj4rTp^wnR?DZ^vn4FQdpqb#!rWkkU2(dR-{)SPovb7$%h)eL|?`02u znpAA+6cY2`%mkiri}fa}j2E4<%!+))6JpuE?Nx4XR>>;UnAkOflS3A7m^o=JXJG!t zrP9i)eQW%fUte9c>+g%5kCQ^eO1><6_0i~)$i2)Dx@<;n`wm#f1b&FUdESdD;@X{U zbJx0Vwmc{`v-?bJW%<^i#QSPns z-Y`?`&6%`@!@tGe%j&T>JyqW(c4MdS;gho+ue?xr>}&Pbvxhsx%yipiL5Gc76G|s} z?F~$yS)%>EJH@OxL_B2qk|#Mg0=r$vPEm}u(^H^3f4k#axn-YePg z37N;N!yMSIoNdmojA~qyw5FG_&yOv6O3}T{lR2-ArhR;|C;Z3m+=h>T&)0X{tT}dg zvGbvqf;(mjNwB}atG0wYBWt6y=A!l5>jSh~Ufq;#h-eI%yCG|{@&u7LrK`_p_p^S8 zUNp_O{KCdU_r0cuS$jl$bG!0ZyE}5sQ{?SPk#*M;__ORy*|&4M9G;b)dso>bu*iZZ zKQ=^AdUaq)8mDOdR4LJ=89&$U%oKjKUFN{A?ks_G50~`lzRh|e$2`q1v-p*X$6A}N zz25sPd`!+MhUS{N8E;SY*S&S*?%&uhk!!1$F6C_JcQkC+Eb~&^XiJKKme~cS0GnH< zwuuC;-8wDBROi~(n($W=)taW0X8iZK7n81XOzV5#{gCyM#k=kmtg!FScrEW>qbcfj zvp`=d_44kGhpL|#Z*Vp6ZN9>KU{Q0#@u^Ag4TZ(e+?Fl1+*Wa6qssSdaUr*=A3qN& zo_O2k*eTvzv5@=m+j#al70>n0P3kL7pLk2{(6uyXi~CnaL=|71wJd5BFiYHFq3H2- z)~Po;FYY=f{V^}t^u#moxqoGA@9a60>*gM6oBJo_@t>(m>-N}8JN&vdSJr&i;i}K? zKUq&c@bE;Cj;=+t%*{)Q32r+xpY*P+x%nu~ZLwy>YtsW|i&sg#PMc)T7vLQ*_x!2u zJ=To7eOHzAh)y$Gx6NbQ#VWJnG)15IwJ#S+{rj=fm*vixtslkB0uBn!EqBW~x#PpS zWz4IlGi=q43g6G$9h4>rRAdiIbyMq|3D} z=}fQu743ChwTF$t_^p*GQg*D3jHiStffgMtrGzEataX_}$pXrK%fQ zi==l|$GCS}Bt1UzY|g0~Dc6L%37Vqf9HrA%Gj{v!c^P1K@rGq?)z2>XH@l9WJa)pR zW0LSW_r;ri_1YIdap7Q`xM%6i3+J=i&+1&$T9dTXzI$q@>4WZ^7MW;;&BxXU?R9C9 zVA4$2*3ACCZ34Gi)Y}1+w41gtLJ{LI{MuHyY!wPkJK-2h}~jh z=A-DU9(G%0wt?=m($Z}qj(a=39#80YlijL(G}+^*-BceV<@<;DW~aP23tW83GDmBk zmdmn7V(VX~F{_y`-B+ZsRi!jdrcNe*@Bct;ovBan{E1n;pUc5jK~7Hok_qp*>RAGr z$wyd2Eld?}JPGl?W`8duEq~Fp5FwFv{=Cc81@oqud%ez@5ya)&G5fE~Hi=fJ4~;=G z2ep?^@K&6<=Dzy8AS1;#!&eq2MQ6&tSKj{}x8SR8{=Sdietmu?JYPPTXc}T-Ewx-@ zhhr8`!MRJ_Z<&nqznE2~vTSbSJZ2E%xa*NjtU>YGF1FR~)!na>&rI;G+VmlQg>++1 zq<3%9)q+>wrxn_o1U)s3?f9r7`lM-bjt=umw|oZYER}8Nk63?~7jpK_P|oe}xz%=Z z$m9S%* zlIF#DXJ6bubJNw_HCnHCEzRea-WfDA*LQbWe8(qlMn&nm%JT1*dX4I|))~y>I4ozn zBjia_V0}uZ_AritCGWPuQdL8;Gt>A z9sHM1aMMHn`&m(3`_45@?bcMDBtw)cgK zFV;SD;%ID8U(DhoEq!27Lvg?)-8R2-6SyL71xRZ=NnFr-c8BeH6#;RHqP96-tsA4} zRi!@?(iGL2ko&%+xG%9GsA^90%aT@_q+AjrBdy6=~D8^~jEPt_t(nP1|K|D>(|SmT(POysI~P zm2JY4C9{s)=uGW#HI)@jy6V}oOwnYbfYhGb6+4ZYRz*Z*EY90@ku~6gc&$QPL;pm9 z68-k?TrRgQHZq-lytl1-@4D;H!UdB)ScHGDQ#v=%%dqmnvXV2dizm9K?g>AC*5Y-# zNRgRt#)TEd`=Wxo4CeYZCgiM-|f)5DfIHxm4TOw45b;~ zoSkrF$uBv3qXk^Xr%vqc(R4UHbE5VN=`xWGi`tZK|Nf~JaV_rri;s29^SA9jW@U1I zn@->y<8z+JW39ytPe^hKihgiAFnOs!he@>NflB|^wwsqN%-qtVd+5g3)l*7(5_L`| zak#ucdG2CGzWE~6WvO9%x-INeJ!YcJu+nI%rTWH+OIgs!9B`Y&(o0bZXLSEUP>;<=Trk3P={%KfdQ7WQQ)}Pb9wJtU7q?nfN#n;)nJt21& zCHl**;_q^GDLA-kQe?@wlR=JclRECLGi>{H=w8jT$@7FcmMr)gv?RD~V@6cxLE*zK zi4q*W$r4r5PMdZZ%zby`hN04FNd@QahPxc(Y&Y)`mUh;R+BfZ#^b{9E*PCgVrXJFY z78l5Fc)D==Tb^IbS31n_z3lt{n#s0I_Ka6+ZpJh$kT_WVTI2Qhb}O#Oy{k6tdbE7i z%N2ev*WB79ed$F1XP;Y|7XG)l&1z2$*_(Rd%A<=XwKOlDkz#dSC$Ko^!9jPKK7pR~ zI+1%TJS?7P-e!Am!fNsUs>PmV3uD-tDt{WxD4g+1dy%ln9EH>X#tDt8{S&u6wyP>7ylt4WED8229jEt5I({=|o>y!uXqn%)WaUD+Z9%RU z^Aescoa(ZOZxPEPS2N9u^$YF=yLCFOds}hy&4PaG&z6%NYzvh zL$)G6l}3TRrf2tDd}MXfQr*wLe}-TAj4i^vlU+4b_I&1vJZ-~XwaQn|Lf&M)dird$ zrnudYINnR_;w!ur>|wdOJ$<2}RGcNhhh}b3GKYnli@e9*Sx-O7JXdg&77tVE`x!mE z_V&W761lu<{f=ES>wnMue9QE}KVeIimznF{3K2ON)aiEMYEkd!2QxM2H}{Bg<(Y76 zYlJ92+$*^`wExl8%ISi(ix2PGlE| z;b>kqW0vk*^%jSTF4s%12bbEDg)yu4;R`DBZtwEcsIC3`1s z%Pf%lmFIiC^vH#VscGxBZCkrZa-*y6*KJE$9xJV^mC!1@wpOPiFlNijYa33n|Jt|s zJ^Lkt3Et2C{OPe%|5jFRdE@r=9imKbTPNlwHs}7(Jo=+E>Xdb_pxq6bF1Ni(0%tB1 z2l)CJ7HBT|Jkk5&v3a>XLCsf$Rq&C#~7PcONxF7xgF(KUiLdt-nHjgs z)=W*GESW1jagL;l@yv5Og>DC441SpGjwi0vs_wEk5q37oU1IL& ztJrZlBh={cg^Q}JC0*Z)C!Z8qW5TVdRaVd^5VdTxhh}H!{D9F(0yF*8V|JBvnr&M$Cqn1k&br64ef@ow z@pFpH>bzdDm3{wS@#|ISI@{u@fA2ESTBhi7cX23x@#lrhGH1`wD+^?PEK9t(cI&22$CGB+b4vd*IPxk-b4nE4`ZM`Z)m`D)Q9E<0xRO2H<+S^F z>lr6)7K&3Xt}8pX_jmcvkN5w|n&;hl^5)H)uT{PsjeGyv##KCI)r;SC;OC<`huz)p z?Ec=6w>52R)aCElUYEFDJxG}Ud|vgmzk6-@^kN^}{BCo2v%mf68mr}*QOhoKDjpGh zvU+k(3fGR_$}7pNOGHdtCY?Ard6W8Y7mia--`TcJZ4Tse^t5!JbLN>y!XsVQ84vCr zcaRejY*&A@_|nPd6A{VNrwHCYBVBXAGVw+ACXS7rCAI$2%DwG#u06SOc^mKRkQ1uL z^UoY`o?i8pW%=HTH&dKWc`lw>Y;sN_aQQ@b@h$5gCSE^Z;-AX#rPlxI(RXK-rOlWp zp{$v{D>31g*0B?o8>943Xf{6Nc{;n~qO)yL;BqO=)T3) zJ_ne1hYMUY;kD#HB9ZMC9<`mLukr3nm&T3l0@8c#KfJb9`p(Ys{^jd!59gRYU%UN& zlGWT#55?`AO6E;r+qLiUj~^YIHw*jupO07{w&&9+{fd`M!z*ekJmzou#Hz&Oti)?D zx2j3l&;K09y}+Vn(Q99{-wWFOXu<=Vr7V4YeHuYC&X!5+>f8VSqkrY&ujV@oAM@_} z@iYGMO7-;_R1?N08InZbF!R2G0r?v6v zQ%7zH>{%|dbVK*$pyFF@Z6O)6*iO!z!hV!3GV{I~+bn^p+9#r_THQL=pIo9kZH409 z>Sbqn=5!@r3Eq1BB1^7@=G!?lO&C8snKE(C)XGxj(gm~YHB63eGMmh)DSbSVC!HhC zd&eTT_s$AS8;`fQ|9RkEf4KkOx8pMQcF%r(w>w`wuexvk-#5=~e&5;bqoynVjep12 zbEWsHUhBTQvvYZ%0l$o#-Ltu~%U}GOmniX~okzsFooUvx#GP@)4-YZs_RN_xzsccx z>61C44=S}eHJ`+BZdK}QO26ilk$n17&C&1wUa9|ib#?pCNBK2P{k30QzmD7YkAN-b14qO?Vbidq3>xQ;#w#@Ub2bFGB<>{WU zdOl&&gcxtv?1G;w)~2jy{&?@Ak9yd|D{lSC>C0F`&Yg6cJ2f|FR+{E_tAdsnQ)ivi zoXx{`tBlDZep74p!Y4TnAv*=$&)IgRagGV=Q31w859ZTPC0FO2JX@Yu_<8Pap3DRH zzvzf*pA&z6XLtGZ|9_7E=bx@8^Wnuk=4-F}j{ant=yY7I=p<|{fcY1jx*C`J-@nAN zSA2UOtm48Ed?_G8|NIu&I4b^JR6gr2722zgccsG+IwWK#f{sGbJZ+5 zOPtT&-QEA=+xGe+FJI2O|L0Kp&AIQRBv&U?T=L;KxGnubM7eit!uyZsB+{~%aJF5v zVF~vSxtH^^#35%E=RJn`pL_F!WjaMJD?jl$#raW6GAXAc>6Y)w3i*#41B<*A*levG z_bN>cQd`P6Ynqn);T?T*z8W9C5WK|Ti|oB>wcw+ohc7&yyF6FQSWP=sH)i^rlR-V+ z7wwJ~6}nAavs7Kc$+@TT@bTj{ulLu^e*gFD_d<&_Yipm`(-`K=o3k;lbjl>jUwrM) z56)%xxF|BM?aa%cns;|4o6Wsoas1%BIT2i|_bE)ayl(f!^WOi1{hwA(uRk_>{~yCz z`v>Zc4Z+PTd`%vkZ+Wd5wo3cQ(F1kHf&Y}2Ify-c*sQ$o^IQ4C|L+vze_ay)@u2#? z`(>X}Tc_lS>_Hb}3+$r0WJMp#sjOCh$kj z*ZeM@CGt^Dp4oZ3+VV4584oy_wuQ?xmz(6eupLxA zU$pnpbN&Bak0%S)z23g>gu2}?PBq`=pnHAR+uv>S%br*LOf%Uf)bmw}^0aT~1e2F! zs&C2d<}Z8_nw4y`Yf`8|qhFq2VBSJ+miI4Q1z#`8<+KxW-tt}Zq}HSZPyQ&iPMVY{ zvT5&m!};e;s0`XQrn_GEzL)Z4lbE1^>~%r)S^d!{_spZwAh`$^2Y-~-wSzOn@>DGtX!rZY{gV7x8vip*EW0V z#r2sNeq`bN;%uLnye2y5c*aSylS@}BEOoNy(V6aDHfM3BT8o9^vn4#mo_qd2<9&B; z-}y)L*ZjP*-2Q0ErL2z%eNTUGTI6qPw!UGroOt+>2ek?5*8-^Wha=PKj*Id*&YAsm45xnqut^^Z@9-l zxtYGc@axItCl+;WSheKqWJ?p_u-Br04FqPnEshGj^XbQn3Hf!uqxXFIbiVS#0|CuL z0ck8jJ#p0=X2@*9z_B zHwpAqQ!V1re$e6D?2#C>z~6KKf(&Jyr%uw$olg7TW$sD8S=ZSj#aZpiORd?*>OUX>gnkt5)pdSz0!`hZOiSn`|#pJfTv#Iw$H!5zW(#|d;N*W?fqwG zh}JAy6L-^$ck|CFmoFRJnxD3qxGnR9v%fvhHgCSyx+1eq>d9ArG}@kj-+fxP-qt?u z%aZKu(`Ur)JoME(Uis#~;8=;tiXmI`ua-wV`LONprfs^HCPeHOb#*Jez%eXVFum$&udYW?s#5^^0W86VALnEr=`jdZ1V0PMhaHezY8Q@?Te| z7OK7U!WLnff~u-6{=T_;Eo;p$thK)O`d_R=K-awNhY^hj_No=Fd{g}Jl1#{9SAQQT5`H6Ss2bK2kr`XQll)+h5h-9nsjyvVH$L(4WPW5jdD+vItNn|< zzPfy7w&tXS+Mk@~{Q7tPJjXn5-!GGXd7CGPo^p#dz6x_P=41Eca+Zovk4lnM_262>&AWWCEMc8*Son|*qNF5p3Yg+yYdxp^=8Rj9v)}+>zW?1Yp*Yv@^bgQ zy?bpRr5tK*=b!pnV_Bxo){~2s5~gx2I&%3!aZ%a2rP-&x{EZSnQn}=P=Rsq`Uo|h- zo_)5QyiIZWt;Hvg95dEhJx5vm;g2sw zP?k@%;`DguwlE;~>9uV;${7WZfBd+xb9-rcv?24Q+-5ZeO^#e)_q>C@S1{e0GnHji znvd7ab@88HW$%B&ZvThTJpWGG&IpZ(m(_pOCEQ)>896)Hi~swP3kLJg7usDo;_=1c z3v-zb-%(B5-A69+Gi$1bma+POnfSN4b`SrW-SgJHmb99BD>HOS6=SFj=cYJ8nKivJ zpAKwDwa5$*kW?2oZJ3nFw)S^(_Zzu4g3a>pwU;N_JhZ#9aO2?#nkO&raG7x~WQvT` zw9}$Z$uF+03FH3dSS|B-q2dCa4WGC1ZhEI|YNeIc8FBisP7=THi8pWGe3&R6|D-tn zht72UIF>6J_kZtuZdp@u;^RkWvFFFXsNOVVv&~_%S*p^k+?O3bKg>XmNpVZYgimG1 zrU{r=`sA8!(_MOLo7kyK1`3J+MbAE-RJ{N5-S(gV%Ky)rJel>P`H>qNqSDLCzu&O$ zkdc@D{ATm{jobGh_SWCeqx9zO8^f7fvKn@7cvl^*!n*NXb<&q-juUTe+2Wf#i(~7j zDQxHb{UX0MtNiu>C8n&-8(?C;mH%o50$eWJwZ@kwp}PdnrP+wA|$UpHHO zx?W#urDk8Z`1hN)??3$VglYS|o#&d{Wu2pxRF1g^K0KCUH2?eu$K#Vy4v6#bT=hc6 z@M&X**V|1Zzt*K+df{1FJHO+e@LJ)j*YAA)z5oA3zT&O;`px^xCyLwuk!zb|VQc$5 zd;ahD6`x)%|MAOw-??D_*r%t2r&qk)8ZWqa`Q4e>tef<%9o~>0z0$y;eA>dfcK1zo zr3M&TitgGvuh4YvxrnvXmfX2)CVVTcX}jz@)pX^}TQZ;SU7Q(xYnx)~*Gmh-i_R>Z zJ!6jVznoo%tLIho$NxB#|7rLB&!KuT77N~QQ4wj}_j*V9ce&bAYr1uL z%wl)`$hBcIvhz2^=vi7@Kfd@-u=^;drF!1|z24V#JtU7j-T3H(qiEp8ATGbz8Cze! z4EfrVuT;JJ_nr@jy8m3R|I}Xd(|iBHV1HZ7O-GWyHoemO_U+q`1MP7S4jp8DcX$8M zlQ*5;T7;iFlz#2CsN%bx*=whM{F3~th+`usZ{(&|DzYV^0nO7^Xs!;uUso{u|Bw0q zY}fDqq$dCG!ttMX@Bfx^j{LCx-}idfM-@LF=!MVUdFHD6`hu^oO#eM|uRpxky4>W< zwZkX3ZQIDY{zQ1Bzx#?`9+#t@%;7k9(Qo;icW*Yo3ggL4u$sGi#*+7iidtePSWh|J zSAWWSq+ynz+d1~6%M;oh7bj+L7#hqyQ}MA?{HOT;NAo{FU0>75&Hj5zlC7liman^> zC(GAQT$Yf6rH~ z+Wkwm-*aEF>%yuft6r+CSa7WRe2GzN`S%9@+Gm^peE$D({>Po?>)P(l-6^XZYA$%y zRx|2jR`7H0Ns8$rQ8a&GI%ErUW)U5>K(&a+LAi z@A}Wok>6$I+^uI`;P3Rz5hzJ?dGO&Q^S`_Df2HqLeD$^aKlA+O-}N7U&(Y_reA|2d z$7B0{#%&8P96Qn4&HiMLWYEIs^*$FD|LsuZOz&|2t^s zo8hsN-R5mc`y^rKb7yXewHwSl+iAEVN-sj^9Pg5EYp&0I#CW?~s;O(T`r9ep;`$qn zZ$CaNZhvb3pZNdjb{|iQb2@e|JM7+mXJ6&y4p-c4D3;MwzqWc_{GLxz^H7{mxBD-;bo<(cVf?<@&$bjwTsb^Tz~k_NpEot1KbmoV z*_O%ELiay=egBVD{@%j5{ri7#?)!9A|MQP0jP`$S%YXV_|KGSs=-OO82Xh{aEqCse z7=`{^T-BqM5FC0zp;Kvg?R=?2OqVkcr&uLk^0TnDRi1j}Tuyu5-Xo1+9FwR0y(?Sx z?c2*;rlF==-$^B%cyP{9##xTx#?1F0|5V>QuWtX7)9&+2|4(18uHN%uA%DT!nad-} zx$o7y*1cEr)+&E*ZFBYa_nYE$I}IN>9ZoTOdQy9O<)c%RWA>Fy1P!HZ&AvY4Y}%Rh z;@dWa!%P2I<7)qk{_C&*o+6xaR$;H@8q}(uZJyaC z&v_~~;=I}OB~G)`7VQ*Bz54p%nXjGI3wpH;b1rVvO;2C0a?=XqCmE#@exJ$^3dRBJQyJKG({PhOP#{Bn+e&7a4AZY{SvIep(3)p@n&P0Py5 zKb+ebq4VRV|NnXaKimIFkNf*{^_uJ2AELG$bu*7LU;8Z}?Xo62JG;%tBdPPMpIO@d zTChv+&!Oe>XVL#}XWxJ7|L^qt!q@kBz21e^J+R&U zQZIbH-QnN%KbZc%*uMYFal3zsWo2o}Q2{#>AN}|-<9d8`^Y!@p=GXcA&uXv#*QLkn zrGA9r=*I2a&)3*3ocp%m=_%ou-DOj?#q~DC=|<|Dd-1F9XN{fP3kfOT>zXtBf;)~c zS3k47IELfSuIhG$4_AWy9~RnJ)g9rl`%rt;?G4+%*XIAV)zz10O?2&5%rIK~x|%uv zXceE6=E(zd-BSXXj#e)|KKZRPLs#wsLq^}rCSRP_GxJQG#Qk}$WW;8U&NbopUfewN z^3j|iqq|kTPY$J+J?&JV_h4uG{O70RfBF9VAYb2`ectA9jh%A$g|*Y?%$xHe|Nqzj zN3ZYysGE0pucs!nQlEgWqDxu%_t2S7lwM!CxL$a5==r3bOI};w>YS8PU0rRWxZzdx zwA0Fb{eCy@-+uV&s``!F_t!^Bl$EFdS$zL5*ZIBArSAW^R=%U|vDH0xy|_JR)a}0( z+Wq?|zVq9c;OJuuI5s^wQnmHTySdhXu9p9s_5SZ!{>sm5%_G-}%~>xtCFn|pbBfvA zPd{D=?zY}-l6&~=Z1ak@)2;WsXMX?u)#T|BYp<=@ZK|%m{EPFVOq-2!C$zIz{F+m8 z&ij;2&7Y3M3kL6!4nKUTxKgC<>+1Lq58gRnny|C*uT|{*+4BNFNBXtqT*>(0n3|t? zfo%eJ%Zg~u(EAHLEF(^DGdXLKXsNDS>w7h{{#vo7(B_jDrndf`6aT;I{};FWJJY}T;~`d=4HmXfb9O#B*8BR;$@zaI|3CHr zKPfLlvU$eGdlOYJbX?%K-4|_?8GZVBl$l*!&6%W?6`AGb)3g2KlZ|G++Tr!=&zBkT ze;!Sb*;6o4|KG9noi#5f&0V7IvrO3TS114HgW~s&7j0bP@$k?=R<+BWCznbnbH6BS zwch^j)7|$q)8E&;-+gDtPd;~deoK4%^qXrv|2BLssETp3b>*1&Gw0a9dv?34ck76A z^YP1nyz}||r#r^}#&geZ?U>=SCad_1+KMcxyGBy155KJ~?@%X@vmB#GfPr4 zz0J|EA?%HloY3>TGjmmfwyn2&#@M*;_0~PSecLiEEq0s`xBvh8&q4V=a{Iq!&riwE zpI#SHTvl_c_x1Ii{~s{c|Gqr`{LWAP-ryH!hLuWwi|_e{oe;nQ#D zeZDNZJ@4+*ORd*;{(3U`OnKRi^JO#MpV{&2OR$KbpTBs_{<_)QW^UNO-(7Y?`MhPh zJ1u6uSlO6pqmlL6MqlyinUfbe@Be=H{pacY+HULe`wxG3e00A5{fp}4Uv(m{DweNW zwM|!N&B3eu%x_D&${S~2&sRu&@bmfn<#W$)$R#b_yJ#8bs@po(qW&+g|Gj>u-|}BE z#WK5hSNl9K{>JysGI~yNRo$UguYE2)`TD@Hb@Jm!f&A|@Si3GAXlXhi#a^YPI7sr49R`WICuZ(i=EDr%4UDdWZJO{F>PA$E#;{<3- z+5g|IF!CNz#R=q2e=U=i_X!Dapy|1tT{McW2$bA1_-*1}EqnFgwW;&|Yx^cja`F92WZ?JBD0w_R z<Cl)eJ9~39pN-o~2*&ZF9{t<9Y+~Rirla&U|2Bn+d z&MR{0V{AHg&FkEgxYHg>4!oNe_<7>dRga&B#~uBB;OEVz?|c9MjoDE!@ny=fC7GRT z4QEsqho##dSo6tHwCCE1=|zvO&fkA({{N@ffBrmQf9&@4`;VSHnQ=7hWY%3np3FNt zf+f?_XV3Ujn6>NSarML(Ob0EsLxnYUcUHbuvli!**d(VuH8@C-KkC#nBLV*YK1&;` zyC!}GK2dj>l`K?!ViZ_JtNql4mrb5Fcdo43=9yg)Y*X(XmFQfWVSXv&?gQJ^U%Q?@ z>e;+Gcs9$~`fBUyH}BpmTi)A7$%$Nx0?UHyBB;>IW)3ro9aYhPdAS^8OQ{oa34`~O_cwyCR05pw*x zCMd+|0|DS@r+^5e<4}X>I@f@B3=`>+5V! zpF1ZL-xM3o;rM)8nNsuWOI=1ue1Z?posIr;bN)Zp`j21jpWkb~y(Ub{M#?8eIY?t0 z_d2^=kM9-MwyRFQejnuZW#8p1J;}B_D*XL&HcOT?3M`2J{>4&|?fja#N(T&5Z09eE zdbK5&^Iq|`n2Xb0F0)Kqt?GQ~aZlQ1P1Cv0=UCcXr%GH}Vb5dNpm}hj)AqPoMlq^S zC$Y5|X~ZY8H;bL*i8YsNyL6k$(`$=w%HFukrOcau`W#M>vWVC7Y`(bN&-+HUzy0C$ z|9_?5ygl3ai>>qZ&kyd|-mCe{d#~cR6+b`!&eG?6$B!?!+PG9BaoX37yuUs$Eq|VE zar;z!&i_4sZFsVEqh)>6gKOqI_G}Wr*MFY7|Cg9~-oCR*TbHD~jeQdI=Dw8ScK^$lmrK5UwlpTIs{BHF zl1#|d`9iTLWn^V9m&?A@dF0x`k#aZpdGodxi$5_p3M?*r8X#ADqH_wj=4!3gxzenu zwTUmbnyl7Zxa$6u!xk5mr_WJlanEP(J-SFY>t##meaU8v0I_tg0v=%);{7k>-)ift8Fbp6Ti5+D{Gxxdb1 z%G0KpDN*zMzIWt0YaROd((>#VLw5FR89Cc$oy+GvdDQB?^_5${G>3ATsCEj*fY zDM%`DZy9@)l~cK4{slCzB(2XE(PE_`1iEOc(;=FNxe|5xun z{J!?>>NDxWZFa#$3tw09fpWrcz30!lbLYQe1%9MPJP+ z3u14(^UHnOJiYGR+uh}smUfb&53(4(DhNsLoGWFyVs+r+3B_e9+pf#LUdH&1 zs_4%@UPSEPV3GD&R#b%bcGpXVZ_ZMl!p}<=vRj8NmNQv&X+x5x;)A_;r@7B<-fq0u zd*;=mwa3{kHx^`SDKC${ob<)#cH7UKQ#n?tMl&x(OGT{>lhO;8DlgS!mG*Gb^*3(b+}&|5`y8v+wat4kHOR|Me%Zp#FaPnu!P;};&!244oV@y3`DMNB zR}#|GI+jkCy4k(Cz5e;4^9djQlzTmyg6CUA>qxZCyZds^KKYKxoJtR*^NaReyu|h7 z?84_uMJ7dVo?)bV#6WJxDlL`eb5E>UxFJ`%Xj4a$uh`kkRW6ryy)UfLi`#KX*gqy| ztHtuyR=d9bTycocPQ&7C)w#0!rElK74Q#ktv@q8HLG%0idH4VStv``tw)C~tEVok5 z*Li0@eiUr)m%H`vd~siYf25w6!ZQEu!O=%H_?vC===v*OptzzjqIA)5rJaS(!{bYo zH%PNpi_J`)@kJ;6`JKJx@h?BDd%pL5?L75)6-+M5M|Zt0>{yl|I7uW)?}*uhW@*u@ zp?lhA{5!mJV$7kJ%XBtwD%;(f_j~o$i_dI#F1V<_vPIF`aGu8&5pl;$4gIS+b(LJ+ z@0}a{*3I8pOVLP3U{w#-tv6arHMAvdj<)Re?a{H$owRa~_xz6+k9nM%xzFEJbkmz@ zHvjMW7e76f`tP55{qc8u-DT#_(`>w&Jy}ht$+-)`K#{rCUkuk(B-rQDo(uXyU} zjuU52otd<@dKvrXmU~CJ9?#Of8oxlYcmGtAOBrsrgcR5|Go-N_uU#JcGDPvtU#~ig z>&o0K^zX)o#!i)dSoq%ZedYPjn{K~98M*E7uZ7R=|9Lw9<3aZG9Cb=nH*II8arW%4 z`#o*C2BRUG*>P#Lg-&jVTY#-WYl0?c7z8s%Mj~U35#<=Dkty z-#JdaGI`DAJ9qAVxGTT!`Stz3tn2>WOy@Z~Yl@Mg$Hci#({}Gk*)xAfW%1#!SKk(% zbzo~h#A#f*wJ32WQ_-E`_2qvyCy1-AufJX?*8j? zo%7d8tLq&O!QnUhr;CLK*-g5kWwoMCQ8U%+V~~thbN{8w+?#e3t<|#d&307Ob@=f1 z9fRw~)AqkqKfl?zqvB-u_4Pj=b?XNly_TwU{A8AxRBIG$Er9D~3%>T|617{8);xPt za`@;`W*<}5ry8@LD^``2o5#fNfBN<+@9w|*;_M$Cyzq6^gIMnvU;P*#%X3^8{cnY4 z{&f-&^uFq!p_Djx>QT+uzf&ToElU!RcRjc1+>dX+roFv8ZQpy>+TNhanyeeIF@CoB z{ON4;vj?wd9FXHaTdnr&Qm&4h>fiHwWVnrrDto6lg=9PXEXvahJ0hUW<(e$rw(t1{ zdDTTb95gv^Tex4~nmWm1YVsPcN0*!mL+(B~yY^F=ZdTE>rP0~4{`aa6Jw2){XIJHO z+2Y%7+3nZExAN-vT=wBGo?rJzP<^%N^XKV*j{pC0U#RBE_5VMl_x<^mJ!O7oujABP zO3ROAZFQ19ef6s7@3-^ZpFg+RX`^0wUWQquw|`>hr#)4={71^R+pasvD&NQGaQwu} zUw?H!a!zS7d$z*q8JB2u#FWz;*M=_Ty#8qCzx5(VHkzIncD{e9oLM}b|Hqfh{e`~D z4x$Rn8BT3F5Z!z2&fVO~udhU1U3)Ga(V6BHd!5snL+9PQr6)p8d|kkhdZh5GnNsv} ztA;a{g3fmx)|*be#1$?7Xo9h8X3TA)h=&;&Yd7>}J2dOJUXxf9cINZmtu=!AV!F|a zWq+1srZ$FauPLqh^*R1idi}5TKd<-y@wWT*LfOyX|HHx0zrK2JD=(K|-Timo`~Cm> zHcuAiH_P6&EOB$>;;DyAb??{xHI1+RYHDtN-NwrD>CMgRCAo)ZU(c`j_iE__HmT!P zrU`40RTuVpTluGanRmC&{fpevmdS?agV#<}Dwf@L@?4IH`}CkE8ZXkH%V@3Mbu7OA zN_)o7D_nIe4h2mY-n#98TOY6rUpC-?%VnDiOp7PThA!s4nNhY| zS3iEw6tVfOQYo*P7knsQ_jbS9a+TKt{O2Nb&+XW~FR8lN_2lLPo1WCn`I|DXZ{nJ1 zto8gAduc{)f2rqfE3d|F?>}swuDQ}wEJn7E;ha>`q($ym)uS%8AN`Fcvy z|G(D%oWFDD&Zpmgu_c?Bo15>c{mivmaoNnj{}_yU{yLa%@%bF`KEm}|=iR&SB0Af% zw#?nTyh$lFBgCIQ+tg6&py<Qn-)bBh}nlVxrvl|374}tNFO-nn7Snj)-salV70*zD=n|tmNj* zf85rneqQe5my@dX|I7EM$?+!?mmald+;@GQ=CKopSg&&^EX$M%I=AJTkzd@mlC2$u zWqgM=#2t$0p7hvb|K=by*9|AG?@Z~O6~h*8Sorh79Q$8yjPF%{oAR~F_wp>Mw;L{K z-8bxg;&XY+nmcQK7&2{(DJ&_PD)OClj|HU6k3A{KBfpZ%gk3 z5oew!6E1FhB-edL(23(nq>t4(iJD1D;nB^jey{(ebn@`4H%2X|-F;P`hh%Go7W-Pv zN}ImBI+t-7-nB7)KYxX;o3dvL$JTWbTo+T*b6))3^(E({ zVq)*g?wh&+8#L9D=H>=)i!m$~T_w@AZt;gz(;Vl15%u?+c(_j8W1*F0u5|T(hZVos zA9+l4by2)q7Lo0F(OB}t?G7_0)s5FSNU^o;TRW-X!Oz#?0V_?zG@oT2iVO}EmyBIo zQ}@lqzFR_EoHO00!-}&2ys{UJ-y>qXv!J6u#)W)en2FDVn zUV9>R!tQGR4w-lk#kbihlCcw5gR(h(8L*#yx8ZU7`~8oX%hx};xq0~)XZQ8DekI(o z7x*51&Fe>)Yf06_4DkX_hbck6C7iAgKYg0B{Jh-fC+*zp?#C5wldSmmMrg_g-4LyY zg({kS%QIDeXw=u~ZHb!ftrGlD@#+chl`&q$_H%+)85xNGcx`=jo0+KD>`gz+roZP5 zoqGO|P4%vQhciy^u>Wv%dc4t>O%AfjhfTON-FuF8U0)yfdH(-j{~up{E#7mvu~2ID zMYjayl}~UEIz;^{553UT!**>puVs4U(WO3T zX70;eeN!Xp_BO^-h53q0LrxYi@_2RYv)<%Ai>`i@n|}1>nXg|>@7H|h^`B?A@U`_% z?smEC)rWT;V2T%7yXcDYc0b-+=2#)4*siZrn0B>YGv)C;efTtcjQy?y8fTB5Yzw`9 z<4x4=Wh40~=Ld&YnO@`A z;ybO*^jPFf;Y`LwItMPzY570Z=|Ovb{e#W%e0Ds^7GT@^FQCs zUcYni?!-^?EU(-#V{Pf0X%u3*^OcKc!!!;{>A-Y@g{3)z(?&3-X~8^+Oymx(k*Y!;zFU11yxmtw!vG>e} zFKnFuZBO0TX}jObwl}}fR8{Y~_9SG-``l@d?Kh{K>DM%NjjRldV*2KE_sR8DY1=~= z8r;8s>yyG3-NPFuEqxyK?1+HsTut?&z#B`yzM0K;Rg>>`Gtd50K{8L5R)`yT$!Z>&aJDrppq(g}OUCO7!9` zwtdY?$dLUqZSuC|3k}|uX*~A0dT(0OidM;;lW!jrs#Wl6_279aQEvLhiL=k{^oBJa zfw!#O9o9`=wzc%FV@gi)mI{kMA-yM~HeH*tWB=}L$y=ieH{JYjQhol1lj`!1V!Y4I z{8%8sa=>I`T(`pazq7a3{6G9X=Kh@m3mF#P1yc>IO3pfI9-3g_c73(OgCE|`0+SdD zwqBH2eZuv=_MEM0kxWJ6bD#csG)KK(Z{{@3n_tRy7=+C)3j1dTGn@DNM4y^olh@q?Ol4rC0c$_>2>3kGxxnuee8R3 z+Z@AfdSa(vUf!%M5**!l$Gn-2A{DZOGpC8Op*8_^48T4*#Zk{|@*r+vs|G&2S zAHVCLe7(KB=d;c)7t_aLOF1T&7~aarX zrK#*i<)1f_n&NXBXB5Y-pYr`~)W(EcE5if3t*3X+^5&YG@_a@1*MA-my3f!h zVSMX~P2l3l+^{1;lE;}pR~^mUzcf?UE7ZL>@{VuN;wM~Q-us+R^w@5aUAys#z>VDe ziqDtJWA^^&d~R=(UR~{+En26QviQQ<(?dCDm(Ky%$qK!z9#rQ3_;A_3;@g+bnp(?? zrG8uy*)x_mn0HPN4VRqrEMndyuZORGwO!46@a7HAduH?P<}Uhi3~RSeDdmcsvT@pB zlZks=?8;)Jb#t$HaQI%15MiC~tomK~(d6$-3?>IJcwJraF2hvYa`Wz;55L#{HvjYC z^7oj#=O#ROv}NfT;k}tN%Bz>%m3@3x*UTyF*5iP460WyRmY6JjKjz}sP38+7rsdlG zn85!0xkNI@SC(^InI~kXK3J{4??L(g|8oxS5U@D`w&3EK#6uaYKEJw=q!+YK zBdh(e$GO(cn}g@s)t);0mG`oVptDVt0N-Pe>--UKk4XGJ%)jUR8(YSi5);#FXK1?q z@aJ0iTub5I|~aJex6BgAy!fVsM8UO!s`~JtL z;qe>hx4f9{Rg-=$=7JGy#v zUt!l5=kqq4_mh)(HPvn{JQ&o!#C1~HwM$nNMC~hgUEX@*T6<%^Ty0BG*Xr%pdmgKt zI8=G8{lE_U4=*1t|KfbOd;UD`Q!7r`-uy1BP@%-AU&u18@3BT@bl`%N-Mgdr{rxk4 z$8O6HU;b#;|LnGJnsoEty+U&-zJFbrvpDPu%F9pREn~`_k!G2-)FJqV#EsBz*J3uG zIWWn|>3EA#+d^@jFRQ2LGy2|-{$o>IS9tDlySPN|%{g-l3hTUP*xt&>+g`q=&D8n+ z#F__h%iO&Lci%3mDr!6ccwl&B6_|vWb^Y#9pqUFDH=SI1`JQT5PL-&T` zAKSM~{Pf;wEK0>?>9?j z4^|uA)CqTgEE9YC;&A5G#hYFRy8DT)oukwntU*hhkG(?|UA8ormlE zduA5S%ZwI09%om7@cy5#@t+@mo}UsEZ>pg9He&^6%jssuZujJuvhV739u+K;InK_V z6e(MOzILJ}=fq2Kx4E=l&YBjKd}EF2lNlGi78!f7z1I5XUS`jezFgg=_LD@ej`Q|s ze?BpZ$Q)bQCTKm+rtZ{y+d7YPorQCb+!RsHUw^NtwDj=Jo05kO6pl@9;NQizBcv*} zYtnPmca}Np6+NPV{Q3R<$MN{TvhjZ(vYP)s(*Kb4^0x!&@-|0YkG^|0ZTt1>8L=;} zi!Ig3I3Dt`E%yF{Nzc!TKQk0qRTg-+ZOIJIl?g!$D{f}JuD*FzBPwyr;@8o?mOZ?9 zRMYqN*|LDUtiY=>=$-w z1%>{b!9VYu*`0T8e*R%M*5yh}&G_$o+khuq&aTGg+=mBm<{a;r-yGL%aGBqB_0_Jk zRfk``l#IQ7r6YUB-t>BjoqKmC-jNURy0}$#-7LS<;+4n3ru%p`3M~08@z~}1`U8=1 zd-f*Iv7LT*)_nWwQ|j`z$+@OSJmO7wH_YaH!(Y8gP{iq4(2re{Hr~24qv@i6a|4fG zXY!fIgHFFSxKFKHdt$+in`_KtV&)k4D!*QszF+>NYw@=SJTJvkAEd3hBKy}Mp(j!5 zsj&PrN&E9DBDK2@DOoh%|8v;>9fhiU@?wP zLyfHwx4D;kMAUi;ri)(AJO4)ce*Irt{rh(e&d#&{A3pyhXc*(Y$eDRJ&r9&CFIT^C z;4T04JvZMMsN432wXC_(Yjowd@4S=MC6g>&J&M*J(+P>sHC3N&+FN`lmw%3(#nV3r znP1+OK3=s~XhFN?lLv-hxpHrbtu<{w+?craQ1y9>KAEy;#XpNu+C#J-nSB2FJpRM{ z|M&Mld-iUfRIkx@?&I%$5+nQS7e3Q{B>aBGfz!?^z8$Mdk501ZI({Q()x0Iz-z>Y& zU0lz0&d-15-s8L4_6hEr8S2HL=G&~i%pSK9Qd_QA7v zv*hb4&gFfZ@Ze(F*_Tfp_=Gj1y|N-CuIZUr@aV7q*7COTp6Qm})K86fWjs_L1}mms zSo%wD%P~#o+uLUBIyXJ((UX*;PZxXNeAd^=zFgYub)&?jCGyXka;+K^(J2l=Ysw^!e)_uu5ndRxrBNop*-g&jkRj*r4SaSKyuU?@`w;hkO z+mmvYx1=`y_6f0EQ$yD^p>d!Cuez^FP#iUI#n~P`Mc%OID zQt(7gx$(tWGq(z_`Y$wjO7{mvZqD46$ydMgUH6zV>wDuAuI07tg=zQBm(*(We9BDY znYi`U%cz^Iym4kbZtpw1mDjLJ?0wqh?pK*xI^x#H?R#>){(Jn7SN!*didQIqt=VHG z{x{;Ks%dBP>y`Hy59`gZ`Z=-xy0@)%%B*M$zSGkT{~I=Kic$#dN`JrCU9YK2j{lH! zU=oW7U@yCe>3-6AX6v^j-yzA z!eZ{fKC&;_&76AK__^)&_3=f2|8oD@p;pdhD7`+fqh0W=&)tls6_7JZ{}5gGH@@!hi`A2&78Y{veO3{wk>ya!yKFjFqbkF@`6qb`rmPn~ zIlD?I#p0SMw|KDH;-3*q?5ckC)Co*l;Qw{X1-|)Ae&%QDmc6%nmYKxI`TNsTZV{=^ zA%#^{P92Tv{qq;hP2GQ2&hfSL^~>9M*KUr`oxvEpa%W25$7%N>zsaV$tP4>*)^urV z;(Q@XmC8xMPhPzRrKC!eH76vF-EGVe{%xLL`SI)anA+b`)h{CK_Z%^i%FEwT`?Jlw zy!`#1856j!?o(Uc?^S$f@s_B?T{X6rF263fEh{zYO}@Oo!RdqGbqh%cLBp_5Cwh&x zJXYEBUMGX;am$X|rfb)5PdRkgky!?F{`}@7>I}SNMV|EMwmYS-qk<}XgPB^=W z>(N=AnKI88zt##DOYw1>V+a`N|br`M^~uj8KT?A*5Gs+y9bEr0u#g`Cqb^_PFST z&oonOagBVX=e2IlQq|4ILh0vi&h`AB`9Qh;$1{GP&u6~AxOi)Ged*~R&)Up)zpva` zfB552CK#+qv1e(T<^{mdI*_mx-i=q=tQ zyW~H=OA`Gq|9_K4|7qog)A+a799_D{`E;=R)y-G#@7|yp^7pwlyZ77$r`UJAjk#)eoXA={* zE?aWMM6SbAX$#-u6Z!W4=d6~FO!At#G_YtLyHn|!y^G`ZxSko-ZkVUhE%@@qoTxPE zJ;q(>U%NEG0HlsG3#eP%|qcQWs0f0N!+8TGD9H~8!S z8GaV=V4P>OGo`rb(5igaEh~AwP1k5$3Hf(h_HVsnn%GU(K#iyg&W{YIWbJi1`D@;> z&c82q?%nlh`TPCs_LDB1@!xJ;_w{S}kqMPH61UbZoznKY;&iOX56eyb6D_+WmTp~9 zSeEFmq4-K=>67cl2d~|4p7?8dY2Uug>}pHH`;4*v&t)!~oxYWF-C@=5c~f6a?(8XM zTpKx`=ZVOTxA~dU3*SfP{`mOY{=@G3b?5T#EDS7d+t6_8o&V;VJznpwo=(2i6}3+4 z=%lx$^{cM9FzpptIV&jTXhGwColReZmUuPlYdt&Zb?5eFlcKUs$0WVaY*dqW@m#8R z$nUJioBChx{|PT&p3d`Ep|i3 zajR^R%LcAVvOz_Mq+C0Ub8idnS)Sec=ljp+@dcaj3)LR5{J2!__KH)o_P>G-Wj|Bmn8^sRPVyO4U=I;Ls6)VZUczv`USf9LW((Z?6R0!u&+qGxEIXoidVOSe;I&VGUUjL@eYPa? z#oEVK=Z~*o;wtHVyyku2(gzw}ZpwtqY>j&4!)2$n$xCADlGO}rf-H=VvU{>|U2>Z@ zqv@_>k&MAQMfaUnY|4GANdoPYv?6YYY+D}jc>mvT(sloT>!;3Qpn zd|4{wT#x6DM@rosI;zVZl3UHqj&{UOVwpSDK_FSA*HqbZ>N;xadLZF8+vEpJGAq~e zFNwJ56}2%lI?UHui*+vZ+RT^12h~r?7<*0Jq%`@Ymr2(PW-ryGEhWBRdyYAsc@Wg{ z;N)kQ%bw2{YCD*<`WStkGE4oM`s*$&hOPsT|G&uC{>WQJ>e@nZj zxbL)@7My%Bs85$UB=Sex%a~gi=NL}yoS3bxWuet<8pf2;WBG2C#?s8+)7<;z1#42a z7Wv$Jyhge0NS@7wQrX_si_2Ai<}BD4t1NiM^5h?cKFl zPQQiPvn;i@Y_zz|(6zViZ`tX$Z+R6tvJ>xd=^eP`v-(Wn8>uy^rBw%4@4jABvGLg! z(>XhqCDn4N$DaOq;iPG>kw~*==fNiaZyZXIrqetgJd%UF^<)@TH6d(^OUL|>X_@k zZ=uY|K(#*ClbMd|%JfTEXG+|ZJ*6a(vD9;la!0lm#}^*~jtP6!pL_Tj^eNAt%)V!D zan0|vcHPda4?b*NVRbtv5ZPUcX%0_C|S?%DFkI^1{Ks%o#lk6C~34 zHOd^f2rW15WqU9DPvC`F>!N0jrpSlQ$4%N6Mtav(U6<9ZdYt%Vwf_ERdE2d5ZClE> zJIL?-6)w|lk8UKLXjX`QcB%W%XDKJyc>A3~Q^nqe@+@N2j6KrNX`y~}>4egdT7#Uc z23bXlU77P4>mn;g}x^|VU+gkaq zNujltuF8dxf1NF6J<=4J>mb>^jWZhWvSuvBh{-#vspDo=3FXScW}Xu-o{0umZH~g zCT^0*og%c~)lG2biC29|y01SMPq~8SaA;ZIC< zq6v3C&Z>C6t75xTfV--9VacN_!Vg!(US-7Tc^{o<_IyQ6n4T%PH&WYQ#u;_B_`5v3E1%(q*ct#%C4*|lxC$u_nFq4Ty~ zI-b8MgI9CY2AP1V^XIx=GYi`xI;m1`cKop`vZps)5ue00CF@zGTi_Pe?49hg#@kem zX@o?)=22h%{EiR%x82%dzK56P?zEM;5xyoV?p@u2t6fu@)YR1!B%K%Ys^@mkPqi~@ zJyQ0iM}}d-@_y>i~vGe1hRH8(q2d;1wr*eEsY z)!IEfcP@Niy~Xg(8KI!>7atox+xhs_vjbP3NG312I*Z>-*8g19xiIZDnVIr)3d$;v zytV)m5%Fih|8->Id9C@~E>*0kSQNnxGk9S-P+7Wqu z!B%H!?c)XJ0>@`=%Z}7MTqPP%rM7G)kI%);x7q#7m-8H+_0qub*pXf3Yr>|_IXm%r zc=Ru(>AG{i&+PyIL-P6gd+9gUaM*qP`LA!;#*&j4zSy$8SR+!n*K~q#@+pa{O_wa# z=LS!yR9Vsy&3(Z1-Mfx;iWKBUeIumOpMFOby3%9ouMkWDpTgMg?uib=F-IvJ$FrU`803)`nb=x|Np9%v#&k1 z_;fed62|^R3vT4FExPV*DsHs?q$V4Y-iV$@R}Gd znbZ0wj>}L($~+;bJ7`&6w0h8#xf9pD&Ai=rx6J#x_p}bHUY@y&b!XLboKd`F;T$9& zxa6Tt-;HHYKW8^l`=WgNM1Vt?rXi*56-s&VT;? zmNkm3QA-0Y1vfpu<}SB&8XNDe3!w*>zt%aLvFv5TR=&$ziwym$A1yqn+;Mo)!`u1$ z9-qBxYIvNhX|2!NRbltM1COuz7*TQhZBXChFRm(K-AC5;r5+P}6x1b9GwawymRj}h z3m(gbotE7H;=a2+u?n9+nX_Wrt&pGn*DQOs9yi%Fr`0+3)S>C$o``6LJ64s=HoDdIH@0t)izCf+v0Cs^i0BL_ujp!wMB;xO4NNm%I!2m zLft=I#EO5$Im11B(&~*r-o370@$qbS(T9>==DQ1m)PA+-Jt$7e;az?0!IWb`8>Bb{ z=X1xt4p1ra3g9_%#O7UVu&8nQ?uqhsKN@G>*7eppe<@Sv_5bga&;6eG?NXJTb#GLM zyzGsy4_B(X-HkUiRq_r~aVcA`VEnu<){CR_@RLj{N2l)7t0xpa$*Vq{xBuy%kIwUI zzx32eXiN=wk}P86clpG<_S}t8YXlduYc*eDO*XpK*_0OhG$5s8;g!V~lDrieZf+I* zGIxf$KbLZ!Q?k_sw<`yQE?Qk&fBlQPw9_1kYs+Q6SwFJ5yk%zl^z;(v_EK}1KiQls zg9Cbe!t>X~7grazZWM~KKD&93gxkm8^WRl`{C41}`TC2J-?j_$@0xZmYmVqzH|F(905|qE{_kWGAijgj$WAVE-DR0LWCG+juBXXbUUyG7DwMKMV zropbHX~j;_y(ddMmp5$Wo8s|^P5tfkZ7T0QU9bJxGOck|>8dINA#r}WNi|R29PGRM zws*(6zUW@177LdG;6=&(R3( zW7qtP)ux>ZX%XIPt&+x-D{bj`*{p5Jky+(4(tmAJc9Z;eHq)Q4^LcoA0`Em}zPhwe zP8(zMII>pPT~S^ozvv44QiX8;NR7((e**UG{=c#1@2TwEw|k!pEh!V+wk-X{uE$TV zm_Fj4Dmn4bySx{cJ1w62|9f=)$BV!HDuF>Wy}o?SxyF1;qNc;d?Ef zJ0HK55#l40lvG`P{B@yP+Kiy2RRMCzCdpcR?wsEvYg>Ce;KZ6^4WV7fdKakX-_bw5 zKU3ub@7X%8BT_=aiH+-~&pBy$ z<(oH~Z}e;81htsko3f(y&RyH{aiWaSGSPi5UR=>ej*Xs8 z`fk}qT=L3m1HYWxxJ~N0jAmL|!t?T&ez~RE--Ax~q}!)2Q}DD%wO%+y?U?SdjH>h> z4=#4vWX$Hx%cxi)U3RHNn( zJ-p(^mY^zJ?3A5Yr2A~9YP9cSms@>;&!x_tJO8qcQN*V5TZ{ew$@Wh_{gIjE@yk+e zrKoi4YC)-04c|AfQPfb?VESl!>f5wc`cjcm$|0)9(r4~kD)1_HW#O`eCbB1gD}Ok% zGwjDbsjjXmQ(kqLE!wi|b@jE?yvvtAx7o2LW&hoxufIgsX200&@K{Q2UQWP)tGA;M z*-T#C^Q<(a#Ou$r?UU8TXL6n~UHqhK`*Abg>9O9{C3pHhxozp)Qns)u?3UEg2BGd- zOzGiVR;+6;ec?Li$0ldDbIIHACp>ozj3!6sUVEeFex)dp~#aGRl2x$zPI;kL<_i}mF9xqAlLzTaMc zX18o}u0)vZd;7glE*_Q4kK6mKV7Kzw#wA>anne@L6|ale=34W`86P|1f4QZst#?z5 zteaQh)nEF*ry8a=P4CP~J|grWWZ_1p-0Z1~wu%Ld^ajnz^~=~L8g9NlB6(-cj~VXU zjc@j)XjA;QT=`uT`A3qO&)Ueh){#w@y@nuuhQk%^p zU38a9gh`vJFXwPidi3;8h4_>eTf1qspb36GhRVpIKW5QCU7Kt1DIsARzr~7|C>Q{dJ+aI%c zpHZx}YlZI16K-Qtf7fpP_jlHAs&)hu8Fk30#t_yrlyz|uhV?Wub%#PW%-__niKK3+&zaV{gFsS`MFs z&J!N#FS@`w%j#38Q z(DTmI=1}+h7IJgfM&_RT@!)ZPMZrgoRGs;2{C3`co3TsOzPjM#&F1zw^Z&NR|37SB zR9qV@9Y1l|@3U=}Hw)kU{ek(A#mC?G|IXvL|Jzdk^>}^H*1o%Mad45C5_(Jy>FU`|Y&t`S*(ceJ)u2Tc?> zx@BQt$zivY_mxiWt%bVVs{TJ)sV1V&EIwJ2Zz*vV^_f%2 z>RQx_3(>wO7Olw2Js}}yb^M*dL~a`^`^Rrmj%vqR++6eX!{7EfbLJR)$-c&a?xnf* zu7$@@J6ipug1!?wzATXoy+ zzB}+Fy=|TKD}l=v$#aic96fy6Sn9P!k1&^SvTSduO8AD}AJN&bRVMm*f9hxIF@7R* zLUTb#@b11_QJTHm+Fqn5hDtXFg{gd&GF7NwRj@Yp_QU0#%O-M!rbh0Wsj((pddswf zcQ)81-pRlD_IuA`m+iMEr1h^4iQxL7BmMSZ^$8<+0Sk7Er53rmTI!wYn>I<#?>5lX z+vAcI7c*zGloZFruT=?KEf>mP`*OH#oAis>rt97oymbhhmSn6J)w6j~-K=TL{pCJ~ z|96w?`MjCi@7kx6Z|3HF)MgDgFPBi4zW><7@LX}}Cd~`qW7}fvi$Yo6cWRzGucfha z(d<=I?_YbG(ztJy)n2oV)E#^GJ=<`5JC!(TZ~rk#zRB*H zFQmF-=W#Zs&%EUrvb$_TndVWA-^;$PShdK`EqW5yk_VbAZ+(0?n^04RT>s_ z{EgM_;8?dl)OL#3mGIVUU)Qu5FU$0wq0aZX@o(L6n?9Lu>}{8OOLPoRrG?GtT%6Ed z@=&74-E(Td{1csAIny04ecEdh+iuvGxOd@3-oGbTy5#H<3-@PV%A3)=Rku&4YyDMI zi}MCwwC(=ANdEUo|6kMXyX)$dWUomwp6#1_M%SU}TF{dM3z_e>(|G!pF7Q`;bU9?V zfTEz+(n|jmXCzPRKD~D!dCk)JwGN$sKR$amZK142)aCNIE%%mqoS87y>G_eYy^G#j z{gL^gxFM3i$^4Y+!quD(*}h>>b8aYH31%=Kz>Wm0{bQDhjFoWs0RZtt~)8@JT@-~L`SKf5(6YD%WYF`4IK$8Ksh zX^OPXIhb+y!uOg_7u{=q|K(rAEaAFXYTdf^otl@-9{tXdQeR!=nz3t2s(6@OkC3q4 zF=f988d+0M=}td2FI6;Hy1h`>%`sp4*S4igdgRmJt;@5pu6DT3`+_O)+n@iwb3G@= zcn7uamv}!RQc9j9;=-GQ4XoT}e*J$R`Gu?J*uCmSrXedsLT8qD%xpb=)=Bzg%BGOi zw3hhqkJB9_6N}8x%c;h0nA&vh!^69>=d7GO?rw;EdHrb5wY}P5o2>j8-KX#S>hJ!| zBI()EsV8nli%ssI(=^5L`GN*{on@VjnV*BEW%*wdyqBna-R-cvw-Xz4@XU^6kyJm=UhVKWV2XLkan&62Q1feszUn-)md#$`B<+35`t`04zt`{o^zbqJ zoJ%6fHYx^im+b5r-)+~xB+*|Hxi-6hC1<&wd={=|l_Y|mBY zw4R?aIe%os#G+Rh);##8sqXpncKNo_)cbK&s;|m8-R^JN<2qgGq2ZSWVcD|Rd_`W| z-7C@hv+%%eN442`3*z!q_buoBR@)w-;I;cT`^|}K64NEvE>=xD_V_RVym#+^ewwcT zr{)*uiKP<`FR;vEzV&gJ*Q#cjNnW9g-mp8)Sb8e5Pa~_fqWozHht{Xx@8?VYIbr|r zvpr{gn#6{C6DP$y3+%S2x?6T``OFZhjUqLkHZ~Iz(x@K{AZ+d*#x7?#v-5XnL69P~!;@?5(WysJ7_yfB!pA1V^}^F`*SCG2^(PhHb?Io(-%`$_lN ziT?BdNj>JdzFhoU>1(as*JI3*dB4aQ)fR8LsPWaSBIrQktn~uBU&R<-jmWv5G<{CS zxdl;=t7;$q{{Ft^&r@YfR=N4}4DS`2`%ekl5fi>gTOg=z0B6n?d1 zk>;vP$7XKfcDxbgueUMyt`XZzsbwEkYMN?~XPh$9GoZypxH-noBP6*q(Nh zo;fe*PUr7q*H$mMV$)nYFUUo@==IhqPMOZSw(?6vqQqKEmmJx(HfMHBQ|iu7n_?{I zzSFq3aouhoHn%N1CV#bgeup>G_2{)#GiF6tbL{E8AlRSwxx&X|>D$P>wO<=-UNT3& zy>xJyhVKj3ORGiRy?_7n$6MvkHpS)7Gb}f~pOt&t!*X)d2aRbP9zSP%ex^`^$1Alj z-m+UIpwv9_vCUHRnqyX(PE#k@ha2+gtDgRRlYh>=J<4mib;XKqTW{0vmRKq?>DZbh zS{|MAj;x#~V$u=2`O>V5zDERJM!s91l_#+)&vD}7ngf?@Jd6CN3Fg_&jVxN2#@T4R zSfHJMN1Tfx-{Um`{#mwK<{^m|&u^Wu^nB1=d)GDRw%3VC>YLtAEal!~6JPP;-+^6g zrp!5MSa35;&^P+<=g0m|Ju!OXo~Bpa6Udt(s_bF5=qP|0kK&hBO|GN-Eb3 zTU+YXn_(lwnacaQX3~c}QzVyht~b41`f&UIpS?R=-@Ut6Q1^YB{hx>LU1QC>ivJfy zemH!hQYJW$0`OMez7S=}wH{ddtn z#WA|SnD6%CJ3i`7Q`Rwt&i$EceIX>vIkS1bj;WVbesJ$BV>f9>cJHN6m2O>*Jaet6 zD}%L8YK7+aXpQxnn~u2|^Sw_!xaGD&g@Y)sM`l-y=qk@$Njwwp_<96!#mv*s3EZ>r zTCVz$BirBe*Zll8^>vY>_Ss46mMHDJZs;N>U%%mfwfN^1av|zPK5ysNu(@9Oyifa9 z_I*>y}$xK8n?*RC?e{uu=~OOAkDs+JH!g-hPyRrEk0tnG{sV9Ye?hP zyC?pHNrdG_-+%f8nB*;AEtY!RuA6;#>L(?UyhTo%-4?&?4B9+nsfIUC z_nCLGKSRBb^$S0?5dOZle?#1!-PSLXr!e?QynHu1FhhCOFPY|ww95t&bGGf6bJDHH z)7d>ZK5kvj-u=&0cM3T_+Z0n-QS<2a_v&f2&MDJvU#--J+3@AbB@wwjf#^CEsWoB-0+>E@@(UZd0%eSnyoc@qQdrVt*O_!9Vs)S{kgi_yZs-3e3@MT|FQhf-H}!658m#ZaOiXCM7Pg7o~?S$^+bcuWNk`_ae|e= zRi344J)ah6ubp|%;H0mSY}M6U20g~lx67Z<6zWx6dgAh9X17SU&v8=A+5DuhSe(+# z|Fn6=Iqwy#HZSa*u``JKmR5}PuHEnTdh(;T8`vy7KW#(YlaI@JGaTcj@A94Ocrs6m z%QTf|VgJpo)50eO3JYXwCADU3eg5a0Z2q?sVO;#@@BetadMlSF0|Qf*r;B4q{r^LU z4=cakS2{6YxwR$ilKI-(ecKEoPVagmEjFbnO~(CLX4-B&r}?W7ojqZj@NUDzqI1H| z6GEOTEs`&tvGB{Xzdvk`DsYr&9+@#?Q;oP~>LSk{g(;EYa`N>7yTg8*o?adJ-OavwdxWE%}{K7HG(840sm-rDsu zr%gC3%OvX^i?!QA`UEls&I@H1VZ~m-~jBHVrBAKIm zQf`ZV+psBS{t?3;2LgW0Q+uvtnR-H3I3*}>g~qCsPSK4L1&3YUd3M~2+7oD^oRgm` zd$}fUjz7=g0~UNfyO*13PuVv|(^9D1F>YyR@A{CsCk$5VzVC}-^J=d3WuCfmMVang5LLU$hd}O;^@nU|?YIboFyt=akR{08{uy%K!iX literal 0 HcmV?d00001 diff --git a/doc/html/images/people/matias.png b/doc/html/images/people/matias.png new file mode 100755 index 0000000000000000000000000000000000000000..3fb32c7a0ac6f2913cd6171c6394bdbc647ac23d GIT binary patch literal 23853 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 literal 0 HcmV?d00001 diff --git a/doc/html/images/prev.png b/doc/html/images/prev.png new file mode 100755 index 0000000000000000000000000000000000000000..f7f036150f816cbbd5abb1adc8b0b3a23cb18884 GIT binary patch literal 741 zcmeAS@N?(olHy`uVBq!ia0y~yU=Rjj4kiW$hQCG&XEQJ`a29w(7Bet#3xP1>rMq>1 z7#NtQd%8G=RLtp}eB1w4fK0=0`CmCb9}jX&i{|bS;8JZU(rk@m$+@m&*6<)z@HwyJ zLBqu}Z%$LK7D(P>EYqc@HB&Dyz50OU9-qHYtF3<)O)B0e|K<5fMusbOSCWJ`ZtmV( z?SA2M)XNP=j_wrOvh>T^FG0c#0e7^lB950N-a2-pjIV5-IU~dL@adCpdRAZ9_a#*` z{!B7Y*d48=`p-K!8CJ{-`^oZt`k$BQGc!ZI>O5v;Tz+xp#l7o$FFkbJ8MH1$`?&h? z3$bs%KYO=q^?g$dQ;Uyh&b<`7lXvi~plwP^$w$2x-&VbjzrJ&- z%)R#hz0%$L``hog-LyIVEOOle*YHJ`HeK;h5pH~StMYA(2iLU;rjt4iGTY`Tzhs?t zcH{r%+0PXi4xBq^rYPVtMZw*JcWt9)#Ods_fyMc&rk@J>qV#vdg&2;gzgv=)ojH?z z%qU^v?~<GESXNgP1H(Vx*XJ);U?7_^S|hIc3Yfca{P?#O1blEjvK!&?6Z15 zm7&ag_qPdqXTLv|G{f&oChJ<&M8i(Ct^R9yGfElf&buW2yNB)62aj6y`~FQE7aUr? zfhU^BnN6p0>&;vLu7+#LPu0G9>f_6gkB`Rx-Q$%Syn%b0ip~#CYoGmB{M1&%dzJIVTo@P_7(8A5T-G@yGywp< C*k44otVv!`vx;GaF%2` zI|pPYCo?cq+iGS4^JFAuNVf4f%QU%gGJBl!RACQnlr-uwP+|2s@rY}U zg3=@rM;Au%nAoN@i)u_i-MQ;$eZ}u^fBR7X z_U)_cLwOtCR4A!yikdMfbWT6^y>w$bTYHPq#>EWW0S#PB8oXH4O>dq)e^Z`g^Cj+o zs_)$xw-oJJ{`>v;|HlP(dfMnQ2>6}&cxOdO--OF8GN*kXt-EqO+`?ElGNM_w)#o|4 ze!z)?+A=?Tg~KhLNx%Pd>+$>73Qvp}3YN@R?_;s+(8TzeRavc;8~>;RLJ@J^KWEz9Q-zk&No&OQ$yjCZ}fkDK9-N-?3 z1(WXr?w$t84J_LZaPDBvf57i_!0iCzMg`6fj%p_ucRSc=u&6#zSi!V)0i#J{SOHr} z)8_|9JJ|9XcPFseurV31#x+%b;L~vwXlXqmz&ojNibAOeyHV4P38qh2DxLNPaES07 zb+FNpJ=Iv|+!~-6!g|%w_k#Wf%NIr^%u-EqPQn*-zL1s<_R1!E%BRqtmtJ%vj*IjhsssQys*%fwIY_G6n z$$e$@bvwPd^nzH1d5M7)+uY7`?$Z}bUwr#w^$Wo-BEMwWniCTuB#e8s)mVi4PaYFV z6eM50-!MX5nP&PH_F8enhxTP>W-2 z%j%ZGL()nUS2&rd{}OoIVcjWurp`3r$_(TcprB@sj6n4|R{}9{is9CsH=C z-JB-l<){2!*?i*q3G*l2@4k5C%aJ=rb|hIJS#{LvNZZl4zz-s&U9zdls@*|;mfky^ zX9^$h&hD`8aPP<$UoU2_Zl|_S!Ev&|ln>K9CTUE{n6^XF(D`VP=?cFPJ=6ZGo~l+W zPv?wPChSt}+h$*L*zGlYQSu9&UDCGm;ynJ(wDXuheTkQpH=9@9#5L3QC}<`q@bI=t zD^CnOV{up_wPs4tgiVvXCf(A$s%5IPRYO-jS6fy!R^hIitlNC0{FAILw zspAzEea+o0_*=)D(3_T)yXGvFabM@~uIG+&Wkg)`y>Pqee>46x{Ap@h)YR>?$!X~! z(N;^>wnb}`_9V?r>VLFG$oFKFrr%1Rmy0fOFH^bPH}k}rgl~q=r#_t;JN5F^*HhT1 zP7jIDV$|BHm8<0+!nrEvYQ|Ngt8rH=O;t_xx5{i4+v@(RqI6r;nqP`v>%O}3PIH@Z zOs?0jS8|%k>E5YFvl4r=CzaFsU1li!Z z7IP0k_om$~}onwhgAcSQEyl$d=k?zmo3yt(`A+q2&r*ysN{c<74K*+)G`_yj1*38@zw6SZ$s?9TmT)%vGv z-+p1cmv@hS&-^vXYrP}C&*ndtKG%Qi`Qmuz`!e_I>}TCq+n=_-{NJ~KNB{LRn=oHu zu42|~Ol~`#PTcBwRlr?@s#4Sr#?BGZ-;G{y(PDEZ+ZKx zzCE(R*0E*t?zrBVy5V)%I>)@scen34?%w@b3=%!mVBW7 zvA-5O%D>(_wKtw?2dgDT3yWW4NER(x3VVpYg$ot1w=M59fEa^vrY zDaUW#p7zn;`-cyLx0Tm!<=Wc1Rlfh2Y;C~vpzDF_1LNy>igg~}_}q4&?cd`!k9~VL z^|toT_y6F>;rDCan{1=(tgLDIdU=h}m!i}BTj%cjz4`I^*tNUXmge?sJ9PO$$*-5< z`&<4SRULcm^FH$1&1>;j>(^#3-zr|>ARBG{%sSbcHC8d!`T3pmU(2G)w*O!D{dVW) zQ_olHd&FtHQ~dJet4{oxT{{Xie_p!tbjIn)duLb4$8+v0+JAm|{)bh^ufD!MXMOC; z?XUM&+Hh9}C-zu=y!Ipa{h?j0%imABr>iTr zXL@D*C+6SI|Bo-|zwAA8{)YKlcG

{yqAbT4R}68To`sNnBuO!wFUwJ%u91iQFAA z4(LLEUpNJL3u zX-P(Y5vU3F*;nVJk4{*DpN_{_PhHKE>He{kMlDyu=;qqIEHu}-x?O3FC8lI z@7bKMw>D1R!FRS*W!bCVdkle&uAzz{itqTRI!v8V@rd^yOGo{|{SQPr6<00dit609 zN-N{?GS8_k$1>*}>CNAL@3cYn#?76v$7>&`Y_8t3J3Z~(neS&Mvo?NKZZLP5!qFX2 z!(aFNV}60jiI2HCmZEtTVyPu;$t!JqrY3f=30ZA$_pfGo|Eevp)E+mJT(-%pVo3j$0unviQ}N zli%JP=w-<`WYE5Vd*8+^-*aikOQ!Y-UHR8%_27_Pfu^$CocRVf_Bl`dl-{P6VPeX3 zdfSY}0>`Zv2CUtioA~jY&Hs=U7bCWH%sj-?Kabs@N1shDS`hW&j#KLDrb`); z*_*MV@y&Z@9p6{`k%f#6h)a9e>9NfD2%e|NUFHal^ z2~pUppm|Rym;$X*ZmG6Y_gA*>mP`Vtnd2ybn1#} zY!8Dca)k#iRBaHxEG!`_=X%V4@x2v?%Ccf(xZL99zCTb|<;y6 zvhQ<^P52S^_3=lXcCt)8e{e!HZyvfeSxD`x#=gIQq|fXN5s_J8D}7J> z_&)VBTXOQGMHO0&FQ0fc*<8Q)Y~G{k)!_w?kCk?|rv1=6=G*)Dr;>l=;c}b?KB1mm`l{Oo-0<@#t3Vny_mRDop)6m(G&W zeUPAc{`$IqUPqmm7k>QfJ;%uSkfqcb!G!p8s^{;2G!|T0#(HYTVT;fj?-pxSyA><; zJ$P`(viH)h*od=SLC>B%SSYq{)AOHi4N7HOtcg;K>V49^U>kskX)! zB5jwS?>&DpUGBHDqCoSV3}xl5M>(Vy#+3y94Y=!gZNX99e|7~9(to=jebyHLx-Q1{ zS?qhI!z;@;rS>pSbZ!hS;GEqTyEbe6&vo}5=WLl`9yBEto(`(>tF_CQWW{D{`JPaYN|_K{dUgtfF0uEzhM}t6EQH psb#a8d#Lo`e!guT|C9f)E5E#+x?G@Khk=2C!PC{xWt~$(696HeggpQN literal 0 HcmV?d00001 diff --git a/doc/html/images/toc/acknowledgements.png b/doc/html/images/toc/acknowledgements.png new file mode 100755 index 0000000000000000000000000000000000000000..745297914f20ae12fe5c337fd9baee6f6c97f756 GIT binary patch literal 8644 zcmeAS@N?(olHy`uVBq!ia0y~yVED?wz@W#$#K6E%uXW-c0|NtRfk$L90|U1Z2s2)~ zTla^7L4m>3#WAE}&fD7R8j-6v|9_riY`lB+S+&`})fj~)6?ig*2|ii%RBL-sj$^={ zkm&bO*<1ImpC6a|_h!`UZCm$UyH?Y;)eS_?ZruqC)bkH*a!sb7f63Cfv<)cVS>q z%&6Xd;wC0n|$RbyUeoF_bD1a-V7wRE%yd1*eM!`;`= z;J~r4Maj{r!$tLPgTh5_HRIyKQ(kQod^D_UxD`V}?`}@_FE0LkVxsc#9!X_yAuh$F z>V-2Ey-&+dKR(Ig`Fz1CRfW!>H?J=dcR8>l`Ly?cBcTL?rNxEMJUZ5zGN0rYU}|w- zWZ@8SaA;}~I_P>NN73Oaz=+5h#L7LSH1<%|Jner4{`f?O|EY#Tq z!dy$&9ac|2<*a3+ru}h!36oWo5U)BzN5nJNANv-)Oxr#uGW+4|t=}wm9pc$`$X8j& z#bKel?aD>>El%;>XK;EPv+e1WC!z{T0n8!|QVnVj!fFx6Wm-PU+V$Ow4&vIl##z{S zP3digmIqd+zN!RoGYMVllGNj7^w_BQN7|h82C51B=6ZOg?dsp%FOsUW@c+!LGYihG zILz)M(&5o#!EjdA$n?VIqvkhMHO{!YvUza|G0h2HFR+v4(-M#5WeU;^XEZ0gS>`{- zVq@arUq3(Z4~dE4VL0PoWt4VOrk6t?hC^?MKofVKOp9|RBj*dTPIa+;M{5+fzP9XU zj*M+xscmxHX{BKEj4K}VC6_XU%~^2i!JStEhY~yQ^$7k^P+W2ReM^h;{0yBG*T~1S z3kyGmxL4mkdFtR*Rn=4uhY-b(M#Y8JRy_|SO4XHmj2lD}J^Qckuld<+x>fmjTmTD$ zqiL~o8pHHrJ%$~2xvD$r4jf`vnqxlZH^!6alB+L@h-RfeA}mDy}^~ozNkh`R_}~^OKDYX~kk% zn_Qd}oEoxJ(wtm^|A_F-3~E=^D=(b6{Lz7hhkKv*F*hujCTP~u(I!8qm~Bq+Ig88o zbBY@~n7(*M3cNg&zxdLJvuO!yFNY;9OUV-Vtf_1>5cKTR-K=_2z*;^%>!#KJ$d8OK zwJxp?_FCyOQ(#qq=EaY`8Vf@LyfiwG=v0Z!Y526}3n?t|AW12ug7lYVYpgXWEDH{!-qhFgEJH66!&J&T9!HI zCBIaN@7L9gp&1UGDpS>G{Zl_bu|V?izT{V3J5xdn-6VC->(1I>{tp-bEjxAa>OF^9>eg-%i<)N}ADel~ zv^R6rGPY*LdV>e)bz8hM*jZ-zm`^+9b7i{fx}cYAleKm9j&5R5Q91U~#xPs!go@cL zo`;?{y-#G`U7=b%P4>Le3%@59Vx~V(dcnP*tH(&oTWTr80Y{G}B}T6m4ihC-q;%)| zIXtx$cDlhJK9=SQQcppEU zDUevRTIzCD^0vA1ilwT5bRH_{V31wz3W#3;fx9k7K`*zk# zRz-0{>@E9ieBL%bD#|SL)}7h!cN`D3*>U{*<(^k8GY+g>x$4&a`|^`Qojlp@+5GEj zz3uZ{Z}XRD*Z%5GHTS=M|B|AbwMq0-ANCCHl}imZB^ho>Sr^_4dc(E!$o1#U)(tOb z+H*NQFusxR65@RD+O=x|7w%ua8yFqE_=M3!hZ7BEEUOvUsD@6P{_XqM>fP4&voq!F zl3KK{N7|R(x~S|cnyR{3%8kh(-95Ui>x-ta9?SEX$3Cf11_C?|9GbmTn^nCIcul=I z%hvmd`r4;DN4_lEb$(swKb<$J4UacJGI=zci6L@YZrN-p9!4e8H2zM77zV@hfoZ+@ z(=Qw5-Pti&J$m)3Rk423f=sH6Mom6O{o7Z!^Q>CCx;FjwvE}otKCN24UbEo&`+o)3 zmwHdD^5W)nWC+N(wCUIu&x&U*$x_L;98R?JNhQzJ6=BYNI)}?@S>8eSm$CQBNYmAHgH*Sivmw422 zgFDM@nsU(5)+ar)10_%|WwaZj<`gSWzEE|Wq|O>o)s-!jAR!ISxI&rIH^KD{t$Z-n2a4buab zPW_Vfw0G0lW#7JKizH1+y1|9KBqewd**kFzg$^K;{koEJH#!OeAnOoBVa z-n_Owdu4&k1feAg8cuEU%i6xZxmCI43diB zB>n95WZ%3%=f>?1&!XAC)k_7pcYc>hbau*C<5SlB$@)|0$czLZgXEC3sEZT6{^_(o zv3>7%$I};`OTWfv$k@6q5@BPxVR<9+)~16FALi!HmjC(FU#9H%PjR0=|N86WVhq>B zPyHRrD4?s?^5R{3Cu7$}g9|?n&rD!AutUw`(E+n#T*p*ZX3bn+|KV7dIo~_`4XJ-` zi|fx2K9`kp#boW~y}`j(4=r*^Ul+W8QKnQwqU(%Rf?k|T$vr_<1`l4pds8GX_T<^l zMKzokpTB)=clT}4&O5EFEdq)x={}Q|XjE@3-tLp^RIn^lfhVm+z}D9GUR-`$U0h;f za?jET|$}W0vsi!C5lO&nVpL?tlWJr zb1dxH*tf0BDKj%tQ)tosiBdtKp^xVTdxeI+&B#7~`gHNrok6=Nx=eKynyB#HCg&52 zU}DDthKYZF1T9OL?9ym`er3aLPm#{1SO>mkz5XV?)ju}6$H(t{^y~G$eLvs&nub2* zes*qywM?gFt3YGim&BT+3eW8ulf2@ym3YiW-hJ+jPy4pGePTXK!!qY~e>wY&88;`D zYG3!;lTlPxH*cPELx$CjFVCOqmu@M2kso(bhKZk=G2cj?E{@VIB+f5+F9 z{S2R`vq~n0lcBCY;kfl}X*bg;Q>HRCk@w!Gynbje2#hE!|>@|n{+hGdLxf0 zI&n<>cqMzoSN`XBDk2Y+oSu0=%I8^R=v7^5v+MnN5j&nt^8fbk_SbvoR&HMYI(qv9J5I|NnOG*|Udxc{~fltW|k8cl?}reEz;~&(=?$KE1rO z?B7d%{ki1_f12MZ3yyTXIc@v4Kd&0w|3BZUo)Q_i{Z+5%`aNZTbIq^uuFtl<`R~f( z{olXx*F3)Vx|VsLXnp0|Y5DiN8q}lx?)-0_f9L1j-Rbq2d`x*U+ZS$q>QY$PsTg|f z-zdrMGbpHLKiULgXbj8Nd_888oPf)a|k9WWcW>7&b8!@o&EP;JIop4_J8=b zvBK-(T|K#maYfS6@H2{d?<^c>K;+UE2Hp|CQf)m-VxF%p!|BO;(}nT)K|b zR@K%h9H>||b@fC^Cq{(}B1~>hmbIocH$KuX65=&bKBzb^@BN+4pAUDZ`RM9t&a^2# zb>BSq>sS64mH+;uI}z*ee&NY$KSEfyHw$F#U%IdEc5?A&TyO8 zd_K0)c)9nco`x>p$da3nj_I3-O&8Js@v7dEob^Y2&DwVH~o!wU#AD@4}&D>09&ll}o zGaZghOFka{KlkdQ(|WoZ8XRm*>te1S{j67){kF|6|NptS)_te*|ufP7jJIylG2iMv#fV-+O%og zy0TAGJmufqU~SOXuiv;}MZvE%k}(G7e!2$hmprq&zAkPt_x8e&!%L^@YksbfayPAe zc&GULyL;Z8k|r4eadq>K2ggN4X?Y7>Hi`d#pf!F^#;u;0X;)p22L;L|?I~KU)!I>S z%#c_0-Yom~+kgwf3YKpkHuX5_wb!&bDKA~S^ZV4N`|s|n{Ccdf}`*2b^jZs*7ED#^^uT)AjT*7V|aRVO`9bBZ(@eEYXJF?-tSegTGiQM(iG&+DIG z_r`Pg-Fr9hT`YO=;gR-qlX=Em40itt-p{@NyD#U55(`6lVq@I3_n&j4wtt-c|La;# zaX%v~!KBEY%aa0@-kamQ(Nd;wpIp9%z@w&qN$a*2*|QH6o7qG8f0o?;x0Cx>Xh_(e zzt5KGpPTdT-nR1hzwX`D|Nn65w8dxd#jRhq@_C=-bm_$cHkEs}{{HeZJpNyIl5x`g z0F5hEk6PC6|L=0T^H$>4burWJq8k_vxARKdq!=h|lgmF_zMGv_(&x}8$tdG3ix$mc z*tTs;S!wCoxSdshZ+%Vl-L&r9x^sPe4mvt|>(;Ef5cst0d3Z>en5gJ$r*oxG<+APC zI(FONxqR{7zXyNq`%mnA`(&kZyVuu;Z+?pREd6E1Kjqo3BI{e$O3Hyu9Sv8V+t1Cj zfBvuf{p{@t|E^xI>%B1JhuP1^sobZ}Sv+SFnR2!-X1!u|&1xz8YekFRro5i8u+;VF z(i5yL3{6ajwEqR1V^rbs$ox5>@7=#|+k)Bo<>r|cKfC+=&x1XN$#eYDJDfG1esVas z)BYi=smm31UX4Y~HC~C{{H8;kE$N6dUVY7_(oli%*v za(-t*&&f?XCoidb@B4M>v;H;{dFep=qF-wy-T7rJD}Q?Hh2Pu3DZbv% zgQn)^ig&x7zx(6S+LO8JmFD-FPaoBH`lYA*XY*3seRtW7CmSv+&naY?lKS(L_WBuy z*;OjDIDRny{Q0wLrA>I;lE7Mn-igI5E>l!qZp*JNKIJNI_v^%ZQ{UYWmr1YPk}A4f zMI-XEiBwrhVX%V+-m#_Wf>0e)(;GLpNii3f0_bQj)eRx6QN>2vMNkf4rGiz!VPI>5gqsE;zttf8h`PM?k zdl5T#t=jhM(|X<6rtcp`e%703`Tmh~-u}${_xfk^nJFHak}1A6@?(|1fB(IC4<0S% z|31&Aj)@_s?6!H{zIA7Uznz|Md+FAtERFLC+J{&e4qVtZ>(Qh~=GWJxN;x|)ZYcjg zuW#G8;^T9=8J^c9nxy}kD*pe^)ur94p1(dVYJLCr@7>yJ`&kyLlT=O%md6H%J8NcU zXKR11IAt?$(xgd;+4=|*jZf2h z^RriRajaUEcW=kf4+ot&EViVrIQ`V>Qpu7nYqp#T4vUH^`V(<_o9=C&ZG)RAvjA7C!+|56!t3{ctUBE8 zvb8mh@z`s_z>^aNuGoC!W=Q{3*X+AW+UmwsWq!FQnrFi`lq@WsDD7Bs&f$A<|DE~s z=Wj20Icc%`?CRR{YVSCY>omWL$CEs};vHX6^@Ws|!HVi%HpC$?%;#3G& zA|pAgAy3S!<^2y428K5lSO5Ln_BOocv6e|>m!mUV?|hrYqw)W~y{wd2R6_ILFk z7XFr-V^tjGx32j9yS?&z_P<{DzRq2I>Fxuyf7hDZeLfPr|JP6D`@h!bpYD<=+jr!F zD1$(**=CU0BxWNoSRG@a$qmc zni+=G%kmQzlts+VoYRn+n%b?u|I5kab@gvfYrQ_dOy#$y6kP4g$&Ea6)Qgciq5P06Tbgv!tr&Aq0WBuY+k;7S-LYO zWYV2?P1)=Af4kUTSGs6vs>|OKhuQgaZ*3^N*YtCeN}`0~Lu-Q%DGFvXlILdHm%o0t zmjBO_^vh{}{H;#X*Y=+< zcwmT;yiE0?l~O`~_xjlKsduO>3aEO&_j}ahGhM&f+4j`#JEgc))VXa}x0gjw=+ms| z_N?-@9LwG1?<>E}RDb{TU%#y7Iq_-s`zu~0@5;$qn{A!|^-HXdk-dgNIRCgplzelPhAfN4}JOw}@T$akBc2 z9J9{{QZr(G+Z20i%^}3a^Vcr}M=a~28>1gUo znpT-S_G!>quMwWJt?gnjUwdpj%kw>nAdg$=hsseD}L)Z~U&DldhNd zuXz8{MN?N(Th=~v((%U^cb`4c_G_2mVJ)rGr85Gwdacr@9DcZB)w)${SN|<|zAo0f zJkV=eZ0*w{nv+vpr=_giw{YQ}Lz^G({ceA2^Y!4sx}#UaLqfy*{~fY4o2_eZUjFEb z=O!I?rpCaE}b54miw%v_L2Va znU^iHrkqn`c=E(TT1rYJ($PU6ASx;-JUqSp#(8<`ZTr{%znlABCfm*|@zRmi>vu-Y zcX=Lj#oR39~)xwrp9mW5te_1(&~-Zwu#NyYJ<+*>CvV z-xL@n9a4_k9H7TgQd-v7v`IxXWa7${J<~l8F<)2{x52jb)s>CH%iBWuH{U!o`*#7~ z@9)l@CmW2Pzf_m6|F-hJ?f>KZ^KS3@`SHF@(fe9{on2oxozdE`#c=Gz~#cytW zeq1K_sHvIZ@5!adwk{CkTDkDwy}CSiskq6a=}R69`*MCfDBEyybE-J2laRM?cCpZ1 z52J5MmYs21GF0xJnJH9VRWDWbEo76 zcCn^IH}1@D+^b?4AZOLhKG&m^uDsCmtU$F{_weV_R<-5)np~(Z$d$nJo$B4PgwG^F!gX8-IAoO?lH8`h80lFN2`E&#Z{x=;Ad$Bf{O&_uY;)-?MJTiVmTyScSEr+ftOgzZsQC zO_P}={q^hbnmYNd!85&trfRf3lw~td>CYGGsr~h_eYy4RkWg(+t$-BH75n~4GbX&7 zW4TV|XmDIycy#L8Q#>7lQ#3cER13GLb8#v;DhX-@cixuZHxRp!vU`qH?SHO_=%wjr zvi|>kT+yeqOrq$`}*Tl>Vz9sVh;_7oaVEw?=TD2v}E3=|T@_6*N&*}?KELpd0 z*KUP;kI<>s;ma5nFx+5}sk&P7?@nao)tMeW3uA>ELvj?jR9XZaS1d4^IwRqZ+Lj5+ zemQkr7Mtc?C6oR_Px#fTLpICnc1_W(-sm1#@%hV}quXaMd7hF#@ABsKD_MyG!nDg_2;jRP8^D6p3_$92x{(fU+bA2`JR7aVN{5j$@(pR6Q`ExGd#c0o*C`8z@p1iJPPg(dQSId@~G;1UUr!-TNAa)hC?IZ#ce-st_BBz-bQ0p#`Wi) zl`yb6aRfC52G;Stu6K_(zG3=-mIqFceS%FxgROU4O^vbE&!-RE=k;+%}mDKmmP`R<1}Ey*_LO}^IAInDcQ+@01GiF0cX zru;pt6>YO%?J1_`P8^P$7cH*0s6Ewk2wXVHCpB`Cs*~ozU;AX@ER!mdE(>BE6^&?W0=Cy z%J6_;S?ubsd?LzSN4{$c&Gy-~HbE=R@a(htjcZlUrlgsD4etJt7ab7Q9oycK&(lp{z6b+ zX<9JGJkdF(zDn!XTcro5JLGH6PJK7Kgng<1Dg!OUb30Xbd`xCxJ2EM+aSmtd&YL-R z=B;~KR&U>sm<3)7P@lql|K!e7QujL|Vq$VO-~8g*-&EXDqqL^| zU`ZPLs#R=EjcdgCUMMYSV40{aoN09ppSHy8w%{qg`z;gx{rhKI{mp^J#L1!D+(IUyYI4y3y)1v*g}=;s zCbD;drRt=!5vE5Y6a-eRUw{5ol*==J&IupNPFy*#-E#iTnq;Bgc^{X~C_W+g;D6)v zbGvvRpDmx#d?L8_#r~2hviow)qW%2*iiy~rzbM)^W|Cm zQbYOn^t-;Z6(;3=E#G KelF{r5}E)=FTykc literal 0 HcmV?d00001 diff --git a/doc/html/images/toc/bimap_and_boost.png b/doc/html/images/toc/bimap_and_boost.png new file mode 100755 index 0000000000000000000000000000000000000000..652ebfca94fa85b0c3850cce4440631abdda1393 GIT binary patch literal 8389 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 literal 0 HcmV?d00001 diff --git a/doc/html/images/toc/compiler_specifics.png b/doc/html/images/toc/compiler_specifics.png new file mode 100755 index 0000000000000000000000000000000000000000..505f41c2ea154f08cf2e3aad62602a78134382db GIT binary patch literal 9429 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 HB{Ts5D&|Wm literal 0 HcmV?d00001 diff --git a/doc/html/images/toc/examples.png b/doc/html/images/toc/examples.png new file mode 100755 index 0000000000000000000000000000000000000000..eacba1367b0d591050810b31d643cd1f5b5becc2 GIT binary patch literal 7792 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 F69A^t$F%?e literal 0 HcmV?d00001 diff --git a/doc/html/images/toc/history.png b/doc/html/images/toc/history.png new file mode 100755 index 0000000000000000000000000000000000000000..27467888ab20e6a25dec6e93067f32ebc91ea2aa GIT binary patch literal 9114 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 literal 0 HcmV?d00001 diff --git a/doc/html/images/toc/introduction.png b/doc/html/images/toc/introduction.png new file mode 100755 index 0000000000000000000000000000000000000000..2594bd7d5eff68463cc8f7623445ad802605959b GIT binary patch literal 8244 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 R2?GNIgQu&X%Q~loCIDE{2|54( literal 0 HcmV?d00001 diff --git a/doc/html/images/toc/one_minute_tutorial.png b/doc/html/images/toc/one_minute_tutorial.png new file mode 100755 index 0000000000000000000000000000000000000000..669249cefc148eeb4573f0044eedee75812539a7 GIT binary patch literal 8902 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 literal 0 HcmV?d00001 diff --git a/doc/html/images/toc/performance.png b/doc/html/images/toc/performance.png new file mode 100755 index 0000000000000000000000000000000000000000..871fb5785513a172f3f216a3d58aa614d73655ed GIT binary patch literal 9305 zcmeAS@N?(olHy`uVBq!ia0y~yVED?wz@W#$#K6E%uXW-c0|NtRfk$L90|U1Z2s2)~ zTla^7L4m>3#WAE}&fD6`2{Fej?|=XL@!ss}v~>M5aW|Nc@OH4cdZ}?vob+arYUIQh zCnlzb3QZTXep(c%sX1xx4jt{4H^NRXSK9r^VwaHXHlUn3ipt|eSb2c_Bh8M=?^ zZP-0yZ~42|vUh(jPQQ2VV_KP5L&~kCY+28J=f~IoeZ7AFzhBk18cSPVb6<}??0?wa z!{NwlO}%W#E3C&0kCYuOl)1gl_i~BM@j{u?o4l7UQc{=dZBw4;p(4b=vOZ?toYSet zj~y$CeLg39mYb$(i$c=(DVtxvjQh&?@8g5$z%JeM@2bxH zHj3?1FFO7sY{Rs7_Agp`+L{yu1+qRfW;?9-|7vE*tcl36%FuXW&RW@wL;tRHm z@2I@Vo8-A>T2Xfi=iI7|v6Bx@%e}oVH+tIAd8fAqtPE)p=&&#`5$Qf^;;Y;`rxM960$;BmEuX&R9nbwBFY(JxT#--T^cC!z-1F9Z z3)iF9JZoRPba0-|@JeQz;IHeKoWfHt{GHIzz%hv-FoJ!jafi0U>}8P}B3(z5cE;#U z^_uE+bd%1xo$I6@KYqM1fAOu>R-Br&0o?ax$wpJ-@z-VoPWM}idK!V z(~>FXarT8r%S;66btebg3D$@IPKv@k$H;!5e==bri&ik2H-+r)L?wXgPV33!9lh@T5YtEWw zH0LvL>fPQZCpBrIwCA3s@635_`8B>i_fL9{=deF0ps;QdMGPbaV>+y>9wKCWj^gKBb~w*5-pD zTB1B`xwrRC{Iq*n%N50Ft3H7~fxdzkkyVrX9(!Ees+ih7A``oXdRHtH!)Gyf9Y#qgQP1iZxSh&VQWH=i+cq@~VVK!W5%Z8cRhq zoL4>Bap^*A$LU=PEf3~Q_j>BIZ$Y76i%5_~pYl=@-PJ)_;#{r0y}cPGMn*g(x+X^CFn6n9l(7q{GxFcA(-*_RfF3T2K9O=H>~ zX;}Po&rz8xngJ`-qF)E9{uBR0k6$4%PqI@R^AiY##m@9hY2ml?i;Z7=|7~t=-tyMqn8u|9gANX%1BES*IkpyuJQED4XXIq^ zU||Tnds?wU#Uo^~(2_NC9~YcU-WXvubyJq(T!Ed-ZRQ5PTRA_(eCM_To#SHLCZAd+ zBg?V0H)pTg&P`vJdavY(4tU8j{h8J__4AW2$?8kRPP%?4qS~R{Q*O)qU)$b%Q{iuT zJ;x|YZ;IA3PE&4fMV3Z^ovMdkf1l2fAmL`TGe&D_)4>HSk+<2oG?!$~+Lk-@bn3B4 z|2^%7YOB>mQxzFiJSK3sPw`T{Y~sB%Xkmno827fv0Zu%JJ6e)hJ9g~Yp+8OwCoG>L*_If&EOVCV<&gBhL0-px zUOno%|NQdTR>?k=ix?V;yaH#1Sa+B|+P!L~hvE`l8TT8@A`49%B^b*qY>xk_DtObW z^Py{xpvAYG4cs#KEk5lz`DxJ;w-wGW?q>YXWIJGC%;dH+f~`r+Y7ST9A}$5auX*ar zGR3-&#-wR3(Pf$LGC^Iq9ZvOe{r&CiaubAjc@Gvnv|8rD4{>;;&-{0OkukkY$zbw1thuFT=*Gf5q zxZExJ3Un@O%~ZXx-RmC1jxApMkDXatuu*sQ1nm_PZZq{CET2-=pZ3t=b@uC@Ie7{j zwI#Unoa17TNHd?kaArleW3hMe+!HJeS4!@#yK$%}XG`wG0H;8qHShi{5jeE*ZP3OI z+lmBFEzgs!tu@Y>bySoo*&{$8P)}TYnJ33aAMeX1v6lrLJ=hsIR2dXxHg4Ni_UVc7 zOrNxr6qU&*WA<3&-Y(M+;bLo^=)uC^we-@nXU{%;GFoaP*WcgM6SJ!%v$XW9ZhqzI z0|yuw1WLoW7A*N;_M>gpO_#8<_YQ58z0K4vaP3T|TG^i&z0#MT>(#x@-?!?el#1Z3mj-2)e%!gCrbuPus=(bLN>iOK37RRg z1Qhu?JN>b+f%%Gaw~OSHb8uYcNXH{X8#>H6o=-vdv*`+Gs(Ec|lX*NFJo=|OdG zw%gB>@Vau7VNW>!hXa?*o>aP2J;}NM^;u3F>o%eCzQ?kD#^!C=ciw-G_PeU09^j#r z_0P>H{>1d_@preUyFPdFGTAX%Pv5%FbA_YkR41`du3i$)XDQ1BNMD|{({`rMJc~l7 z>!zBiMl)@So}5_d+@7>?#-*dxRaHKhd0L(7_S*|}x+qPwt^TH?qqFDRt?Xr)-@blb zyJpRvKc7z9&G)}vx^&u(Q=Y4*ExL1Zbzj4}wnrX}45GJPdL6lw_RP5Qw&^wUpw&fNL3^E1oIEBkDPgN5537Rx;U z^d`nYz~c9(n-@QB^cGL&`uXT;>(PIWb?jLrnjeVUy$bgE%oo8%vVPw|tN4wabf7 zoKD*;e$MxN+@34K{qj~t0Y3}A9jU$+cAZmoYSGU#r_*&#+kAVLtem{~lu26TwO6N3 zWv9pc<}PDnWBVp|$9zY&04J*^_s>7ApT*Obr8gaXu#frov17+AlW%`m(YSlwpFHIm z+k({uCkh1_wg!JT5DE(8PiL@reA4Isflvu)c9sh}OSrVRg+4knLCD0HpG~#l%rm2d z2@?#TSv_Byzvlmom-2ybj0*G5?|&Wpe%7p6Mm)^|Ns-fjownSb8?AeNV?>X@rR&$l z`;Y6#?AWk#XXfp1r%s*X*54!0eRP|SO{w3*uL8^G|2&hPb-r{~=Z1rgHA@{V*FKie zTDO4v`K(Z3>6=UToL_ZFNczTmt7TV1yQ2SPMO+Vh`}xzGr#olfw0^(O`+Di^vUxur z_80B^V_o+zUH10R-RtZA?*9MXZo&-D<@FyQry`ak{pOM@jR6g<1~(p|1MmE)QoJwyy>IE86^{i?j7~M*=UubD`p~TvrhPrfA2j7!Z!6GP+7tBj zO;^Nc&q*72H)(LC`yf~^HcH`k;_Pc3RKKBp0U;gtBN<^J>i z^z_=C7e0OZw0!UDSav>{2Xl5aY|V{kG!fufQ8Cp;lb5Y|*ShCLJDnCDkcf_n>2X^; z(Zi+k;*R>+I*)j+I8Iy>9JoXz$ZDJK3hlRh!#|g4bx*Iz6Vth?KfU9_tC!*XKOFzx zYrJjSwrMdQ|Jv{W7IFP_YNoOJydMwM?f>4c=6~bfu$nvk{}=v$KbAg^pL55Ul_9uV zt^Q|xeT$(R!~b{n|KFOhdw2fd3x7TtD+@czy5ysqr~iAhmOIeNB5~bid!-eJJyauw zJ0Bi>Is2LTyxY6Oi`sZLO?|XXST?X#`Jut%o&?ba4G(S<)z;QNdvvtIW}c54zl_BM z4;7!wUw+oCD_gi^>+_YoO2;05oSnDJ^Q}d7Rh8ddtE;zfpOy&TR`5Mzv*i6!$EIxO zjjm@O?`=&#%X6=B)5EiIFHGbZUVQ(}R?h2EowWUK;q86S>}+i8f*&Wc%bC^e>wd0x zZqEF`or^D?c+6j4|0=oK#JBqOM{CJ+h65IhTQcSdtN7Rb?*xT#d%v8U3WI^2<;Qv7 z_kTb5Tdv}^^?Sya>bh@o=VmCSCS`rPcKiMrjcymE&W8*4{o8l<@oq*10iG{kjs(qK z>16l+)XeaIZ}a~|#n;<2863;o{kP22e~L`aZR>aU$`kCFjNJI;Z9jegepg@S95~1D{u%g3UDYkIwTZ)pRE@&@4o2_o|X#9y|XIt36m}Pv^xMQdax|L)dPy^nwYGD}?# zX>D70d)iZrbEiI?x-!qUCvT%Hr;!swL2YSiN=il9vq`gy9(-s#xsvlsf_JpZ_J=>p z8uEUuNw>dss7-479pS>JmY`FX@8x}T^xy3+seF6F(ffJXt_dYF?Fv&(uSYC36?C~R zc+;n>G*wlGZ|#~jGPYG)mM?EFj$0X`7q@4IkJ|EO%h=f2EuY6tX$m^7xpddM_xJWz z=jG|m^ig{B=+UDmPnO(rTzUA)vIX1vH3F3s!tSyNFlsDM;QGSwsQ+T(;cSUjUeBjB zMJgv1Wla+JG<*IJ-R*tc&(FX2;+Z*>OUb}3)cs19yMX3GXJ_Zlm#3cy)2;Y<=}tn@ z^iwA-!mBiyjGVS_V$8}5%3Z%Ob5@?j>61&D+4)xZgdN>uVqE;&rhHjp@b4#~t z96o$lTt6njPoy{J;OuX2cR!z-U;p0zH>>%lFDs3I^S}FEwBg3gSr;d*Jv_m*#!FM@ z_@$ZaBsffSJe;m@Ph1$VqW;CQ;^*i5`_xL+&c2yckaH^Xte_ktLyL%0$f>8jXM2-2 zE_gjFHL}yi>FS2+?|Jjje}A+2yxq4O$=mM~ot~)dKFejtV~g3dXB!(EGcz;qE`NV6 zZS&D2L#bZ1$(~LgR&&oi|12Am-YIS`AUIK}ORG1cd){JVERwP^8N2^*UzbZ z+V20yVDialML#d=&#ij0(EZ)trSV7F+@gOq_a0$jaL^E``fdIG=e7HF+0P#N=*{)(~kr zm{4C||JAkXm{8{t>w6#jK7RbzE?@U!-|u(3i=KKd4cd76Y0$z6K5Fvye?I2deV(0u zZcgC)D{f(aPp4FP!|g zpP2V;tA-f+;fF^8nuOYTQwwuy-W=ZlYhr%Q+x+?u8S@`^T%CHg{-d_M)O-p5V^U?f<>^eckK1`MT3jFHT-; zH-906WT%_ZVdr-tauP54kFC1Jrdu{a@F%$JPCO`ndeg#pso5BCcg^JYi{H^yI{k9~JTO z^2s>~2@hUfU481zAqj1vErL! zxkX++Q-(Fq&KkYxCwbpUt&lyPztp;Ka!kaW{YLy9i<1{SD<7T`bbQqH%7mG z*mX20E4jF!ARyO#>6Fvn-qX|dqotaO7`Fnd826&{d4$+$aTu*&+xT){_S+k@h zWHK)KmR0P#Jn{b7i2>VhF)&0d+dA`>%iLckhcA@$7P-wVN@V4Hb#AiP(jXnN%{Sl7 zoIa0lx}3D)D6bm>#^dG+sJU0vNWp~9x_{oe0whZ9R<9&F3M z{VjX_-fv6w>kLms@Gq@WD*SO{~+FdF&-w32?8op0*>u`XVIt2 zvHa~rra0%Od6u`8pG7^m6m*?WptxDaY?u4zb0@MFY_P4I=bbRUXjkhYwofw0HK%pC zET0n4G)3XytZD1-%?E|8+rMZ6ULY%SJx34&n_PzD+_L?7u^ZVUO4}bXm_v;IGhONKXglMgMv%Gh` zs>5Sfw$e7O?aUgSiXlQy69TftPMe&$@^7c=mct*vomMSza+$Gy~T(I&HQ?@qk@ zrmCPu_gJsAU)Eg*v$nkLk&gZu6|_xh_5bZk ztC@q-D_0y%UK^N^b!F+2d3)HZot&$AuQf+0CB=GWFP2+tI=d~ZBFOy{uUXz5jZdpe z5-w}bo3bfDW5y*R4a=uJK|$7mIVpxr4c+;^my4_Jr>vB&*>UWwlk4Yfk5@Uz-_38ESZw)R^rlSk(p$OmV6 zi`t*$DzoOZRLY*`-t#JB_Tg?J{i{1|TW`N`3ObdeHd$Z1aq+Po$1Ilj2zGg_TF-pF zI7(LM%90(463)uX#^UX1`s(cN-&b#!

mn^jh_L*LnF1ytZ>s^6>HK=Fb${zLlph1ub|xqqO<4Uf`vmH*Jq9erJ~HKFK}2 z_ua|QS@%uO*4V{wI_0u_ia~E-Z;{)K>fNEMIl_1C&_3$C@WO$04@>sxEJw7cx-=bt}+{;aU!W0+H{Jvq|8+H6mL{D%GeLvyaTdo3+`c}eyA zp{FZXYCfHR<6Tz4dQ}DiK@A}{$@G}yS?5fBpZg>)N||ody0-XVTk5A@)4WA5?rL+2 z)jiw0HU8}G5VKoBFFfU9`Zryiu*3P&Hb39>llMgVZU1}g_co=;e){Wm#OE3n9g;NP zv8=Gy_?*UKkK3m&Yo&=CDUFqvkWumQIyx!&X3z@DhL#11FCG?DXc+o%L`Fv&^E|$@ zv$(svds-^z?YP>Ht{1la`1kkgtBSq0(Q_ZnSY~N%Zfg9WK)*kWRQ~4w-c;fOo-$X9Wiiw{QCCj{U)fvY61>4t`Cl$TA^Lo8z z@x7J7%ll-luQ_L0&X(Qr*-uxZBzs+mR;!bu2$yERh@y+#e1Emc{)vjZu+!oCceAhZoB>K*Ds#K0jD~DzgG2qvbA*k+IOam z42?|AN>lWfp8GZRK0p5(1;&%nU^-_yl0WZ~_WU(x!n{F?UO{>9EC zyX%g_AJfLI&eQjLKY`gjI&so2}v%h}-r$1%-e_w{#XD*8N(hO`;(P&hdc-6Ku z=WE8xf9y$7lgp%D)eA3w`Moe|^16jp3>nSy=eFu;?lFtJV_R)IIV&{8_W_5gHfLD; z&X;M|c7D1o`tV>vL20QkSL2i*uT{3|_TA;)_3-uU_s%R6zFk(Yt9Z2X_;-05BRj*B z651kMFH3Hj_?C7AYfa^9byAzWG559s&sS%`hXp@=e0&@n9Q?2#;(Dp?<(Pu^4)&R^ z7(AXn_T%(w6v|5at^WIPgRH@Kf76%8rDF`PBm^#>Si+uXu2Hbt@8Pu6urpoDUNgK( z&vD>Lj9eC}mu4)z`gF1P=jXxNo2v@b(#&l4&zLi3m*zwd9)5mxq0WE*{uS-qvu|JC ztYwoHE)CM0>*uYhuBO%}W4S5){5-Xjch~;iZL7ShtdQl-t=_9wm#r)NF0(~?(iMyT zl;02E&-pT$=ek>BbL`V&pEj7DY|gk|u=O+R(XESEm>B1upYEepU9G({$83J=cCXj1 zZ-TN)x6O!SDZcCOEz&vnQPVfMU0eZRu zsgXBxzP-7*dAfeQ=JeCj(%EURF5Nr0bzXp~(1DBztfsp*sGL6|Eon4Q!hVj23eVvc zAzG(yme$tpjnL8ho_E;5X<>kk-21n0-@bnR`sK^O@_9S#zu!8mzwchd{qnDWs^)sm zHGgAn_EKH4ZqnahorTU@7e5JzJ0sDW!dVvD~dG2jiebwI$~9$W7nOu47c)ZH$MHVpm+cKS9VvJuhi~K z`(`Ry)7%DWpS5dM^^P{K zda1gkg`(*lD>9>&26^)ErU#qFVdQ&MBb@09Lq2F8}}l literal 0 HcmV?d00001 diff --git a/doc/html/images/toc/rationale.png b/doc/html/images/toc/rationale.png new file mode 100755 index 0000000000000000000000000000000000000000..276ea6ab3b5507d4d32913539bd75cd844e7a5ce GIT binary patch literal 7907 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 UvK?W*3=9kmp00i_>zopr0C#>~h5!Hn literal 0 HcmV?d00001 diff --git a/doc/html/images/toc/reference.png b/doc/html/images/toc/reference.png new file mode 100755 index 0000000000000000000000000000000000000000..4584e378d406479350008d20df6375660a516f5b GIT binary patch literal 8065 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 L^>bP0l+XkK2Mb6` literal 0 HcmV?d00001 diff --git a/doc/html/images/toc/test_suite.png b/doc/html/images/toc/test_suite.png new file mode 100755 index 0000000000000000000000000000000000000000..31432e9ec4ea5da91e30c22376add5fe80136961 GIT binary patch literal 9737 zcmeAS@N?(olHy`uVBq!ia0y~yVED?wz@W#$#K6E%uXW-c0|NtRfk$L90|U1Z2s2)~ zTla^7L4m>3#WAE}&fD6|2`a}+?^VwXy?XWeo$p(XH}5vCPAq5C*&v`GAkOc-#U+^Q z7SGK|s;!46$(98uYU>0G@!ndpRy!rIZ-cH^lZU6{$tlVj6O}wXR9aX)7`l(%`~K$4 zxviUxt&g9(dABsx?*EBZuU@@-HS^}t2FJ*n>XOpbuxG2M$M388d2e-=iqa18RqN{4 z>*jcN?07o!{l)wGK?;IS74x23_-%~1b3*)h{@K_)c7}GgpPBvbZ{5FoN;0{Jv0+M( zmt|%3L+$%EnKRm+@7x*l?Zmx*%+wO9gj0pt`G=6Pe z^x~h!wuA3~Rdz9Uzu)GksI+uytH89}`MZs*EVqAIC|^_MA3uFv=C)9a(to#-+rLX$ zg-@M+ZH=|}>i=Il-J@S`Udy}l-MMYX>H2G*ac_Gpu}wDX-GsLvc06)>Cw!l)$!^p3 zULK|(rciOWe(il>B5xT2->x^cQe;wHU9c;+t?>q1dB@+k+**ISZqJTxsZ-8!xX(Lf z`WJ&fR`%M6cQX-VwST(h}B>)j)epQkI$kLFEX^K4K0s@9$53qEGQDq}kE z>1TK9-Zu@?`i$h|_8a$vu2+r@`I^r3OXGfIhxTk1hAGd&T!PF}E*A?IOIK$-(PB(tJd+cxA)ND_V(aqoDK~ScH|x0=Gc|AafXMAMDi-fbC$_H z>?{lmUoLtf_u=j186KJ3Tovjc{@=Dc_Ab(JKeOwO$ImX;3NYoxFL%@5y?@`f+XhMk z3JT6HPEK4u_oz=fervMo7M34;CqM7`m6MfRTAP`<)^4(*nq+eG-n;TYA8cNJF8-=e zn%?ZplS{vUDOJ>1cAzx&_9lT7o7N<4W4)~4&C{5cj}(ERoh-~HNCp``9x=i0}_`@_cqNx z`$6`@x__RWL0WxFCp>u^tyLo&u$6bu%D@=r!*%<;))Y3~ezI#u)yAo2x&Q4na|()U z@>$(GT%VXp-(U3i#MXUJdwCdV+?u19++%#w;`7FH0)hgPt7eLQ5(qunwP*sDWsj9l z%anQQHs?!amPcqrOxwC?p1#;y7bQb8+xkaew=a7>jqTSidAnP;uieU0D>-+eH1*!5 z>F@M>k5JiKtq==;^0<__hgc2u|1YIj8gHUH0|T*sm+f z=I^s!x-9VF;#n*nl6U&lZ55ZQysVrzfr+tIV4grgb$6ucUvv2dzU$ZWzR`-^zINKZ z*sfc$g?ICGJF5+EByZan8m|@Q>~hZ1Xo`ze`Uwf=Wrphvdkv3CK7UcIKE+jTtH~9= zKv|6r=be-ND!rFX`PuaK*v-|Cw?DgdGR119hlED!p2}>y;Oho9Tb_TNoX+{+uzXE? zdUf}?045KmDM21WDoYhki*Ekhy?$?DR`S<(?DxN?WIOB4HJK$PeQD*CV+TJ!@m|00 z>#>uY<^MiRpY^JErjOc04~^m);~MRP_FGXC1cEA@b{rC(moBO+-l{DVUUk4QgeSCF zF!FM?hs>h|k-`f@&6vVMS6Zzy-4$AUbw$KUxnpyC9!tJ|I_>ez)knUoZ7vbsy*DN+ zuL_?Ro8}X{oz+9a|#cVz7OS zj!Nkk6V(#Auz7R$|312Y@4oB=h13_@UPtwX>O|f2N&A1{LZ`XkvNK26@BjA+ujWp= z@+7ofVab$9Hj39j9bNzL?CC=r>mD7Jx7e_pU4qHbsk7m7`Lw$4{Qv%ZT>M+kW`p(Y zv$K}1{5Cgh)6v`NEF!VZF%K&*eQtRkacBJdl$Z1T*2qve&}n<<6ExY z{t`|zWn>r{n18&R!m&^Gc%e-Cr)zIsFW1kUBQN*vd}?s_>DSlu&n{lp-*dmNqQ3sn zg(-dW=fxTY&wPBm@7i)6r3orF6XtQ}@2mCX__!~9-ivn`sXR-k*lF)O6nZX#Mdg^m zY(KlgKR3+de_p%4uWZ%!<+_uN1UVSHw;9`&TJH~ZNm;mbOY2|XeWt!Hmz2*>o~Io1 zu(NmTR^AN}O~p?b7!D|;F)Vg=ddmH|mZ@rX$4#}E1!_s}*w5ZhU%x7?MtiEy6}>w? zRTHiYrl@QWoLM~#>vfn^X{FmS_$V7!JWr=A51P6Ti4UG@BdBp zvhQCLIPXZ@iWK?7s-V#6l6#ido$qb+-zP7#lPB}b-8ei^S7+_ss#kwbZa-gp|Kh@b z=a!vVJ3Virqv_Atu0krU`I9?(d%r3b?_8;9#L#vi;H1E5lipv_Wk(n!4cK@lw))L} zuxL~FUww%!i~%>zrj$q2I;LDmie8ztzT}d9Z1dg|7i~9-#{^%?F4g9E>f<1)?)Wh6 zQg=bb**HmQ(;LY>OJ5szyog-)*s|~Wu0vm2J}mjr@*!sZ6XuPwy$drlcC(jdc3$bc ze7#FgmFMgxo#UFfw&mU|ySORVu{`{`?ZdU}#clj|Op^>i@Qte;#EyO*#DOkk{FWwf|R5 zjn}CTy?$hq_ zaN71YH-G+&jg>9k+2g{%GO0zP)06o}C39-CXPVK?+n0^)Y%8k^zxHlFcV9xb`o{qW z@8mw?Wv{DD-fJzf_}$XLq4M*=H=X4je8x<{)<;VB_{zvC9a?bkMA1w6fFpw2d>!8F z%sTyh?V}}4vp)&nb}8nO7qvO=soQt4nyKVZ&FZ_EsjHpjoY3rdwtz4?b)<- zclVgyxI4-FrBwQ<#6?bDBotR1*uH*`hiA=580gd`U>bA zdNKP^L{V~U8I!9@jenQHvPXQ1yT#U=w!ArIZv@}!o85_<**2AzJ<8qK!=P}uL@)Y| zh5(m%OhOCGyyv<)YvbhSTUNXfm^5MW<;?5V?=Sb8UwP`m;op(NcKPHK7SDONuV1t> zvSU=Zlcc!x@M8AzyEAqbKm7Excag2Zh4h_%+w@K|r05)Ap1nj%N+H_KmXm0eQir{Z1zRXO=%Vu=)2ynDak!JPg;=JVj zeABjE`T8dr#mUSZFPVf49cKDT9j-2$Z}aonb^keY=Fh%+`7+m&<)L4bksrJGWX+^|>`IRwrs_mA&o$PhDAQ?=J2P4Bb3u@1}oQ z=ePS_lsPPyq?8(T@zauo0}=~VZeEP}{$(+{U+kWJSrgv|rAHgP3n^GuGBr$0aVVX+ zX4%Z;`u)6LP1I(5uvy8V+&bNew>s08sc6|#bDbcC6}bxoQck8jXk5^}CF80!)1oHh zhqr#+WC^-Tbp@JJ;DPQulsjVy)WLP{Na()>;J5-|6RN@Mr@VVdyO^O zFJG>mKJo1#t0J{TwV2z5ODAX;7HqwmKKVCWbzIF`n*wHmMu~wpS4mApcm3Kz-pw~t^3&tBX4;hg zyEI$;SXudYxf{E^&3Vp$Hu2>St?;aG&l6U%&(ZW;mE+mQqvTeu5))~)LO{&*xvbX5 z)j20$l!QJOU-FWdM;MyPM@J-kp1MC%yiA{r^|>)$^qxgS4s z&W$fYZL)E9_T%kh(X*n@w1mY^pE+liW<=RFpOzV%oeUb2s^2f)#}Kj3+SdB|jSCY_ zrbvEb-d$}KEvfJ|3ZGIa^CBn6*-?Ze@@y3YLxQ0E#cPiP!{h&7sh%$>zxQYQ{NINzzpquB z)9|zR&y5qk7bjlyQQQ3g!oPFx^v;=1Dyn(&Y^rzouIgRiWpACgl$Vx`j*Q!BYPxmH zhAVe2$&>}^L_I%0XZP+cH4hq@ZEJ0RIwdCO?%ld}YB66!(5at0t!MhEP4#;F>i*P| zOWy0*l!}>T$|2UK{gzvyV>1 z;$vyA7Oc9grM$1p)+MDw>Vw9WJfCy1`?u~%f4^_$&fEEWYS*n^Y@7Vb!-;qM+g-}$ zc}g3;J$qIXG=Ijf+}%paQo*04^XEvvek(6?&p6>lRdn|4o!-;cm!*Gu|B`>PM+oPP zO@E?2i|Pt9vwnRuzF)4hRQi&tfAg=HZy($FUZ=fUt^dz=Uqb6l1I3Te=hxd^%2=?! z(MHquws4HmIf02k8yTj?h#j+>VRc@hNkwLVN8_p4?FT}e7x)>;zf6o!)CpBeRW-cM z6Y8KcY15`Xf4;7-dAs=kr{f`Sm$n|Y|1*F8|4-NVuay4v`d-=OFcVE7FC3VMmg`RrT|KF|p|Bj0P>rb}M z-~aR4#rD2=_O;*q<9}Rsm#ev|+`4|mS7>(qqvQPy9F2wv0hew_oY+>B*`x7c(w#$IOExg?TPkd^|FCX` z=6)fDQ{NX~{Cu^AN1`D~utng0#mD?<)8GC3w7hQX=H1?2l@H(iJYWB<|5w@9r{-o7 z$@c%f_dlqb7ph}sX8QNg@%oEeQU3ei-+XTOAKIgt{HB}Yv{GfTppx2P^K4aU?V}dp*{~XxP32QLNhCXTYGSXTr%JFZq zzTp4z9o1?9H@_@pmuR{fAbo9Wa$iG3-`hDqj%m-mdpG@_RqeMck_;bg&To9<{aoMn z=bP%B+y5Sk@B6V({%=5dxw+DdUFR%5$1fH%IcECyL$mw-KTG#Z-P!#6z(VGgY=)f2U6W|88M2|2u{?+H4E0w!I*5^?|f?eb4wT>U$i&$pO&dWMhWi4GSI1woERo2IK@ zA5G0Rzh_td@xZ=^F>0T~_3IXA+)PuN>8Cd7q)PIRU3)A(e26=IVX?le=1>1WZwyqH z6dYw?>nUuDOW|#G_{-*`H=Vuhhu++S1zd~z|9C7=H@U3b_~(+$!A&PO9Ien;=W*ic z)2BXq)qih&-H?)y;eX#DJ~;St{jc@&|J-@M|HH|6tKaYIJ|;W=ZaegqL%GATq5t3K z{#l(z((4{?@0YEAvb_FVx`dIbw4u>i$z;Vl&7$#ZpWQq4$w)AEZ;|PfwX0VbzrS$r zMC_Y0aT^}})1Ixjdatg-@o5~Itd+Z#86LAVVqxRV$Xul_!qxX$jd!oYjCGk-!n>`D zq+QGN>NF>xdeS{@W{%^eIiKhBIoGaz94vg6_v@VE>!sXB58e8;>-nzSw`))AinA}x zd-?9wMD}mr%eJKitEKY@s(K!u`m@QjHv8M7sS{@l2lLC>-MD)3+qa#cHG9ADmlq#v z5m=|Ld%X6%GW+dlDd*EElb>I%sh+uT)5b>S^jDh8I%d>@PI~-=BV#rEl<4kkKSoT0*AcS?&4S2lD@wLl1x6v+?4_d;8+f{amQb zU-Rhl`TBpG=l_0e|L0Eq&tCuOxuQzGuiHK@mj8QV-{0SLe}ngb`w@J9zR#>fpIatq zE#+a^**DuqEp)%mjT8+#p2HdMU%a?|_4j1^&%s_cE+$2PtHQ&@R~M}g%YM2ldT;z% zp1>`~y!f}t?ESFf%RAN-A7_QwS(7?SVy~OjRi~xBeD~?Yx@8aFE!*?9_V=3`JRA01 zTeI+WP(_a+(~Y~g%W^-RTdIA%<@wrm>x@Ls_C{X+`b=EBt*yOZ&eF)L>hrPb@maa6 zq~E+=x&HJl&b=AY-lu=gy#2ZS*}Er2FCQQ8d-Lx7?wYT=l12Mu-}t`JNmTJMp6D@y z(|DqnnlPvH_1eF(yeZQjS~nOdDY-vWELyr(V9IafDUuf@Ofz0ZB0Bkr{4=Uemrzm~4A`D6dz zOEG@O?k!iY-o3kfb$L#SPEw*vwDZHxixZ`N&-&`-u3Z^&O7qsR?&z4P_Hm$A?H#HMzF#dMf{?o$yf3B>z{qthuzeYx;T?NnXaL=!O_|xBh{@G`b z97MQZdpO=S-8k*!-__4`!}-sD<do|FR$=q8JQ#Dm_R+#-+qt>jr&l}wjeT%) zndf`kedmkzgftnmB>24LpIx-FosTDOpW)rRQU5<&m^Y%c+?n%=n8lQ6xf3 zD@{^LfkpMYg;LuqTZ_o(%PKs@*B$mtC7=6g{Jy#@vF=}a-QVrj)w`~RUk{%)z5ZSD z|7Cj@KaN(9`#o9Q?*84owzigEC)@wNJnLBOIcqEH%{ODN+?;tnzvip{{-WpSWL%n z)6YF`cedpf9J72p$1p`>ri;tDonALrpH6LJuj090${Ty0V`JjY?a#w6opdo<>8+@H zTx{Lu`VH&X+a7nlxGk4aXo=01-M`sw|0C;7avneCf4 zNiDsH!y%|P_T9C&nd@G1#v1z?&-7{gVaDTpQ(aWECH4IB*7JwGHDfhn&KKrf7o9il z%Asie%r}!BXt^~iDRKD+F0uH*Tz7^2&@G8&TiOrZKcmdY(3k7)>+@FfmhiOQea2=+ zR@K#JiL-XMmu=s=opFIk(UV(Wt&59u-{v0v{asPXbC+$g_4LzEUlj!|ShIFr{NAFY zrFRzA9zLskHf!!|iTQJOSo%5C?*7GA#;DEwO4D$&Yk;8)Y$1% z=WOB2lP7oFu(!By_ww3v_xJDJ=(|=XSoxgHt$FWVEABn|G^yQas*hUfAL zBW z;_Zu9JG(#dXtCJ8p{Ba*o|cG>;x4PGwsv-*wsVrk67eySzi$iQ|2J{DT*jHDK`TS7 z=7#;?o4=FiYx&D*i+<=G)%WDmjCp7^@AVBnV~fWNCoib@Ay;`N!G+8f>*_Qpm-G>_XnRXuyX+{V4ReX})A-*4Rz=Hejz`gQhE-n0)} zCK{DqzEILz%+_=2{&iuyjnC|_2W#l8&zrN??BhayJ9A6h>Supc`KFwDR`+1%`}y-` zT9-d83J;Fj(I*ue{it*EV_92fUEQ-%OvyQWC)ig%i>Zyu&R(@Wr~K2mL;IT9e^>4D znVZeiy{-Du?d5&E<#KoKPW4d}-N$=4V47zRSK`!qfvep2r*NLLoa}a}K$qRe<=mnf z>zpd5o?%L1_nOi4aJ9*rzg7}a?;b>JUcJ#P+ke*Lpwx~I*W$>N*SLRKm*ri#Cvxpo zN%zmN+?|0qRQkTupU$<^;wr1?(nB<46&QDm_WTCWb`jVeJgM+vfr=+edWGM>2 z{^=|4SGkRyH<#8{ORekmU9;xtbzS!WH>S@mKI*==#ro7Gl{n5P_bic-pMPrBn~lu1 zGp973*fndj`ud)XnAa~eSbc*vON>8z^UFzis0dX#T)lm2!m01m8%6s%cq9xjH3&~g zdvR%U!-6a|rkKEn+wtIE!Md`&SQceuJ~X1 zGn@ieY8J-+`P*E2=4ZL+H36@b*H@hzt1EL`ORnrl%V;}T>RY*QUS*zq`!?5K;@@c&#s?b@SAWirv#9;n^t@8zNbvD*^7ckc zdh)(b`~Au`bxPL0{az~z92oiz1bD41JX;!@(z8+_aLyU+rBVxoIyoXW75Gm%eZ08l zkfr0Nsqw8z4Xy#E|2F326r1YXui825c%xyRWaammQbpzOi8)u2lyBJ!MzXFB&=Hxl zDD73pj0-%mmrK@V_pGk)5J=NdX3e|)by>Rj=C5bpSJq@Kez51$uak@2`Rz(FSd#ojdX4MQ?AC-rS0JJHKDKzI3Xw z%h#!X%j;jvboYyuSa~{CUgF*PB|b~{EVh3bpgHM89U2fhh*v72>bl%_^)ziDd#zdlet0$9jUxwya8v@UlycqH9E5L zrmk4;45{y1GL95B6{=@{7w)dmJXsohe534n-3ZstNz${YT!nZieI`PPw&y)btmWd`X@Or*shyQ zk6C7X&cyk0>AKgm*8P5v#uJ%yL!QAY!SKktYibX>%=P+mEUw(UGr@D#i}Y85ih>M^ zt52sbbyr?&y!-a#UB@h+?^^b9*F3M6XL(CcEeU&Ytu(fD;eoXq7G97!D{$wNdc~uU zvUw(qBBuhGijGN6R8dKAP-y(4^GT~?YJfz|?bms$FJ0Seww2+1=PB!C2Cc$L5~>CZzic_Tb<(Y4 z40o2YT$*)6a@&>VyJi{Rx3a%?WrDDal!9^yLwFstB=ZYQL|Y;=JJC zVdncRT8Xh+-JVWXe8Z~5>!$3mLA5A5!K@@c@2-<*XiTX0{@nc&e@8mMOWo#}GUJe{ z^Gds|Ud6{G9!ouz`Fowu$ffP${(CKgTzAD?kMB0!f9c}AU7I#-+OzFmOgy^=l*@x_@-IDF z#(FiR_mRc3_kycu8w=T|uKMs++5C?6CIOoh7MpahmWkYX{qvFZbN5ZYbN}{!4PW28 zr}WpOV1F6!j5&e}R5)`?^JDkh-Mew&5QmlZt#$o9%!>|fxn;EKaRy)c6<6U$)?BZ3 zLw{V`f4|}B`dt3`>bIBOT(QFEX4veP0SlKm>o3)Qf0XBEyGvbCf#-px>!Zb7XMMOB zRAt0nyE-MCjcNA6jNPv**BfT9S^r%4j}wB!B2A+iFs_MB`s#NA7LU#1!|xDcKt%Vj`pC zqvE!%UG%tO{k**sGc&x?H(y_W|3rSyn^!MyneVB7bZsrquHRL&jb@fu%{}+DNR(40 z`qt&|Ue@1!9}SdNtJ+g3=u-c%)#-0wq{~x#7U%ELU*;~6O|%R8rYE*{ay8Fe;ll<+ zGq)Twn15aO_*Ij>S=%P+t6aEge8qJ84x{SyiHz}4kzQ}#`!2uiRjgg0oqw{gS^D0| z_u}CJQ#Nzy?dR^^H~C9!(P?Wv-m6WUR1cl#{uIjmn8U)-@Tt``WB#}AvR2N|KR0)u znIp^Y-BOnw?|pl=GSJ%Td(Qlt{(bI&Tx&nPIRF3Vw%Y8x!knzI>o?}zD`Rm=DZl=y sVa?v1cC$U(&#NA>o3f$#%YTNoD>_Y*-nDFGU|?YIboFyt=akR{0KH;RegFUf literal 0 HcmV?d00001 diff --git a/doc/html/images/toc/the_tutorial.png b/doc/html/images/toc/the_tutorial.png new file mode 100755 index 0000000000000000000000000000000000000000..590265507e3a19332bdc3d6ca80309e69266b1b1 GIT binary patch literal 8816 zcmeAS@N?(olHy`uVBq!ia0y~yVED?wz@W#$#K6E%uXW-c0|NtRfk$L90|U1Z2s2)~ zTla^7L4m>3#WAE}&fD6`2`QeH_opAdFB%mzIV^Q?@#sj|9Lw7=O@K;mT%Mzj#)gPQ+zDKTf~V& z@yWkOeYZA0iMzB%u5JTU@|kV9r#I=GUUfC=YL;pIjk;Gyz1Ob^k=yb526KCRsu$1Y zeLE-BralYHEB=~stNi?t2M$JZ94sQPfg-NcQk^&yS(1G?9D6S;X2{t8L+pWAeAMZz zhTDs0UElcISxiPbBXU~ithU4{r=P~y)jvD5_44N1(zXLZqu-kd5|3{@8`fP z_`c${<(4BRzOmP{x8CyG_~VQB^#5rKD@w9n%{!?$^OD(L1&0O;bDeFo?pFSMb+)MP zZ-&)}0}B_rn5@d2wQAKQm6MxvJcTk@7+&O^;6LR5D&E1N#yl1j7=;Be{dmqo;R@(Df_-}3rH~Y2Sq4ym-jE~7gEqYzGHA+`xTl}u7&ri1AIr8Jk z#fx?OS1Dv%*1R>fhw(}G)M)M5+}fw>vY-DbsIj^%-|I5Ptzhz}cWpKDKi1uTb8P=H zfA$;p6+hmk-L!oy_3&Hnm+zAIc?}dl`uogDkpFCU{=o&IV>8yhZcDt9wY6s9hetHO}&?c!h8wfDUaX<>dW(_s8yj^Vqkg>k1}vbdW^ybJKRwY}D_j1pqGL7Au<=?IEnJzu|ejP(OSI$hm($kO6 z-I;aa^xrGloqgMOC+xlWhi`}AF^TJQclkQp4==bZl(=(ydD*$McdQC4P4C(lWt3c4 zuc>!uYxB*I`?sFp?DE8r#pAL)@JY3(yO^A2mYM*@!!M7x`Ux2t_!DdnI~}{+57Qrld15DZIa17H}9nN z-0UfQ&|^6J<~fjJ@J zGZdTzj!6jnu)L5~{(DbA{KU50+a|v4(`w#d`a0Qo_Qoq89$sXOTqLpe;Y~?*fd=j; z9HxH@+?80C9lch3`}%Y7FMn>?IxkdyeE4LR!m5)pjx`@sQ>7IETCW-e0bKs8)StvTu9z`r0Yo-+V6WZmHn4F0tnKPnhez?k`Hh!d>4C~H!pE#_t8g3Ul%V=yQb8+ z@Z&-e)s~NKwvMIQ8abPPIB+N)S(sSapxk5e<`owsdyfUfBZeuHQcP4lC%?Y=;^@_% zPyd|xc=1YXaPlIi^v27A>qYOEMjf(veCL_Zfm@q&FK?50K6P%<)pdrFIeEo~H5D88 zEX!WIMr7;Jl3g#l@|yEjdw%lZdC*&N{U{$p!Cx`?J-QR8tGpGx{{P*z6SEiD20jkt zYG|Kjt9<+YmdOj6LKOOPk7>1bEnB(GMJLC*$7@OuBM(ahqaw?l<|jKcJ2Pi}bv@sS<>Hu!Yv2)B!vdX=;F#j@)@I$&v@ zqvlznFq4Cwd3AQS`g$F=rhgCrnH-A{C_HxK9aF$*58WA^59Frh&OT$5dwP>k>~-&} zn>=$D>}dAQW>>5*TR6LZYup!)n=6kV?4A8=$L-_3t1W)Fl&bH1x1wTRQe|1@`Dukq zQ+j5aHb?V#Pw@&-OLB}^G(*6L<5QWz_8&W2SO1>6db9tW_zBG`KQ3f!ns|0bqT%VJ zo?-`%LWdpaRwm?vFGkDfu6f{iB-`&|YDeaEPxX&c+PS-KNS?LrxE{9BJH?6PWA?JVS*C~6 z%ueiic#Vansb{;EheZB&rPP%%`|S3Ax&B<-v6uDF!J3V?1lScBddg$_d8aRFE-~=g zeS+6Dt;s@;`m_q!;ONI!x)2G1deeq7cd-7>M3-RI5y)^Y`!W( z2VXmbRB@7mL|{|b(n($?pFBw@RJY&1tu!a=%(mR)8;@J&A2ToDn^SzuV)KmDsI-+4 zTDL}U%Du&w4ernOUf5&*(I$V>UT#^JJ$*vkJTEPtd(Yd(t7DC(+tm#nsR}*@ zX)_WOVk`_S3eK^r7jBy#Ge6#{Fma*V;g1Oit!O{*_?9`8^abU9u0Qa z3;mupZ#VCBS?|oozJ;&P&#%e*_RIJ7CPqfZl%%SnlB7S{|6l9>`uXP1Dc}CN?B~`ux0dP4Y{)&WHif~tp|SA0mEY2! zop$^GyxqLr%VvV#GO6G82O?z-@&4m2y~lHQ!#jqO#3i#o_U?$hds8o0Z}sQve9t#+ zUCht7|K-Ar3;D%ySI=@^&%3*;C{d~9_IBZ*j2|p>71X9LOAOfGWFvC-cEi1^e$DQu zOHEsPFX>!f6}C#>=6};7jqiIO)}7wsb@bBD>F0M#Rm30WP;l6MJ^xB%Qu@c7+xyB= z(^MvB3JRIl?=bH3_xp3>u>Gs?m^|zmEv~zN{ zG%d@$c_nR*@i9Sz2M1>4MovqVxSCa3R`~Se=FO@c%Y->kE>zu7X?AmgD#!arqSY6K zwohC)IY*~Pr;Jzp`i)~>&pzEc>73G(7c=--mlOnSwhZBU{p!!D&*$fHZJygOOCZm2 zJDY}yS>VQ9(Hs1dvfBDY@32|AM?QZrL)b8WBAmy?ncYPvNomwElP)7swJ z?R@gPUjK;Qq{N+A5<7qP+|^gVtX%0i|9<+5wnbVT42%jb-z6?DF!qX8vVOc{=axJ- zub2=KSN&H$Nj-*b5=<;IGtTOqUiI?VpHsIcKTq#|@ZMiVMeD87R^@%tE=OmVRX>~^ zy<>~t^SBA-`oBDS*^gg~>{(U&>F>-3H&{F-<=x!uovl8<(rm%=Uy~n3n7oRcBfjw9 z{zh(fp2ugN@f4;MOTVpR**||n-a7HE+j~=^;{RR>pZD)vaF~$|6&abgn zTr%PQzeDnM@20-rJLi>u`u0uV@6><)ZU3QPc;yo1hu5B6OaJ$K`M+QP|HPktzM1Fq z@_V1(_1FFQ{{L-zowD&X!KeRErvE=7&++HS?t4EM)_<0d`+3h>fA5E+wNbV2?f?9Y zG5dbgzwXzco1a&f6eZU_{>Ls~@nrtrA{)W~$HL{U|K537wA04Y)Y8!OK&~Ib|&dju57T zjqIEf1r9PSmXR@cf1JB{Q}^<8zon^Krp{suk6qc2cu6+z?hdZ6XJdHX`UKx>l4@Zn z?#@|1sa1UG)y;}$`Fc|`EcWd?wOQI=swAhpwV%oS#KVVfJ)69Ip6kt@4?|R@`uO?y zSomkX`!xBNpO&~|;+&h?w(hRwo;Bf4?v6KIY3ILv$eH!-?Zb0j3<3+B^y**#dh`C@ z_I{T|7njTZf0rEp^VVMed*VE-|9@Pbzdm&J{GapZbGJGzO?p{8|JR%8`+tc4{}OJ$ z;%ALhhl|n2h4+8z9{c&^%M<-SmwuOR+s?hSDfeby*{P>SP8t(??0?zY{fqy9+Wp?Q zzV`Y*vF~-nPuKtG^iS-u|9{Gkhyn{M1GJ^yk3zn$}URz6nCyOH-~;jM7S zX=-O?KgY$lGq7++&<)Y`r^nM(j-^j|BmDCaQLx3hHiN&wAg9Kk2yEs{bN) zZuxp!n60izcb#RuSZp18t$>YL>hI*&rm2a(nhO_b{_d0Y_euL@IzO#&)22v^!dI5b zZ;wUT2z0wGU$*Sh%Pr@h7ted~a$Eg|i~IIUJ!6he{gB1K-bS~K^-dZ;Bi9$!He=;S z+ZSofDNNhwv~9!AeP7qEuMZ9tojB1@?N{z*>6LuRA@_wZik!DpFsyoa&*D^Wn({>t z6`?W*QwtjxP0c5tIRdQaPE*O;9^+8Fxwu@`-cL2^{k(>ER&_C#uej|k?@IfUGBtMM zytPl)@fkieICj92VO74jSBrE0NtWl_&%T|z7PECypZcL%My0?z=a$_5v3>R~lV1#n z!=~olU9kH3mbW(pJif_FZLYbvvuoG9t63InjtMg=9aVm~^5GH{!N~`YxxG92+%Ny$ z9s|km>W@C2JbALQk#YX{=QigaPssmp$ed~8`3<3G@25xX_9}c6XS-49^o^NXCPqJN zZY@-9ulv0HfAar?{T`8PLsmV_QV}cU?v2@+=#=7WSaNvf_OP{I`FTv1GJRnGv(@XU ziSF`Em;6p{%h`XQpJ9@YuuEC^L4hNWHZDD?x}C}V+I8K_MQ2rRef(A1yj8f_VtX#P zVAGL1Yc`rWaY%NsrJk7Gaz=dh>g?04N%tL$Za)8>7-T*>ZuLjG@Pe%l+tzu%p3by& zX+l8YGGkFyv*fZd~s5;P%ElN+!$J^!D$PU}0u{c=cezhj$5&rd^uJub`gVeO+jG@fNjgt+gwe z4saNhEx0p{hha|DYtERHE;(sAAy>Dg&$m-ent68L-?RDkk5~84YXQQdIMfdfS$^NRBPgdC6D-mvB z5McZA;kJC;&!f}z=ImBjC;sW@@qgd1cQ2i^c#qlJ#OMCqOy!eJS1;8x`SNDz-ep^E ztag|_Y2(=(1_usir#<^ti&{LFSlr<6%d+HfpwY$S3%1oJ7bfOrd*{@>QWetaKvi2c@G-KFBm(RluS_4n$!U)=M5{#h%%`C`SFo$2#t&ziOCedBMJ{GiaO zL7a?U%O?H*bG`0qvV7&2OFz3Ox2vVEJF`Y-?Vn%ye^w`GsCaK$bb={ml8dP?b4#DB z{kMPa_x|tR|Mg*e-Iuc$BiU3dZp0r{~mR3=(+dZqyeHYdpkh6U>&u}gq z?>R{mD;~BMgGXk}4PV#Z@mo4eQYvZN+Ba`9Cdqxj*=>F7(y63%6Xr|FzWtop*Ue}C zqU^3ifwXj}X1Vh``?aChm6$no?LyPO{Mj}sRq#>2I~#j#qg_vDZuHezdfp{j7Av(T zovqloXue(b&qv(n`&ys6nAjK@8JU@>o!e0~!?XJ%n}GJZIi2nobB^VtNl#lDy(?~Q zsKauj-2I=Anfpg<-^%!D*9)&ZaV6&dN(}6EpKtkUUA*`)kYz*cjd?q3zPjK0qc+iL z{Z+mAJvOx&Ru{w>T8eJoDVMk3xO3mccmDg|%JRD>O)UGkE@qd|3vQnN9tDPTKi_`5>z}V(wTPi1H8Na3-gnvLlOaJ1l($c{{dlCack9>2g$K9qef-cv zg@=LrGxyf0+@dP3+9=m>t9(OHn{g=nYpi@|2+HZe+#$U zZP~VM-rYO9e&5?|oppZcfxicCZSL_q@cmiu&zOTQ(^NdALNyk4D4*U^viDoM|D1WT z_bOg|xDjxse`l=LRIRCAJ7Z41dr_>a(J;$z>95Hj3ltnSWG|f?y=0H)X7j0QwQIL7 zbx?8>cCPe}zIQNMN2&Gq;*Ti`5=&Zc^+Yd=T>VnW@$uh{4e?tg^sn~>-?#pK>1BFb zNVdUL30YZLY3XhgKNmr7v2)4O^EwtE%M(h=qt4~W^yMFD(hE-l& zUa4Lhj}m51TPQs}?@aCMo71;<{W=ox>)ytY2<53YcGWMF-o5e(QSzj#0p!!@!*-xv8^t zO~d{C8DgQcd@A~D4zGT?Yn%J@{c#z2+N&4e{Ji4o>iwl+`TB;|9yba0nbe=mq z`qcC0)|waZeizHEJAd!Y)9roBnkUYc&iauBV(qnbL6dWqMjj~ONBm8dB)9= z#mI4FTXd|s#rETDlN{$CVl275tETwj%jNTW7I|4oNl8h~nlXc;{qWl@OJwgncy@oC zB%4}?fKP*hfyHte!8^;=%11@KSA58Cvc`2qm{waV!^3sO#RkVXI22nvCW*ZJ?ElsM zcSc#>!%uH!UUg=a@l^Rz{oZ-juC{D_s^5{acg5^=a;n- z>2wJR72UGLddIlwTq5yR;^+=HCOhm?a}Pj zU(R)3pY>u};hnnA^I}dItxZ~)k~mvPD^bg@M?pf_VNS7A$Fj`i``%yGuqyn9+hS`d#k2%%ZZRl97{VM9IFdec=S+DjH}hn-QCo8v$*)m z``aVe#+rS7bmvm3?B1sV{}-$`dvQK{R*2rh+0w_B^42a~l~*{UFQYTz%JcV=U$e`+ zpA{Qx?sIudZncGIANyaK37MN(x1QZ!^+_e?EU&ur%aE+9DyxYeJ1on8X9~Ps$a(*( zsAG$Ul1%YTgO46UhB~X01g0i=-Rl0mu&FfKYkl|E8MQZGhO=M0aM5pjhkD<-Csysi2SqDX-Iupm6@u#Y42RivNtsg4U8tOIrZ$+r8DN?`Meohx6AnU zFHE zeSRIS?q?euv%_dA&(cXJU%q^qV)XKY(08lU-)na|8}Dm%mrP_>;9xQFh^w%oL&EEA zffu*h&HwDeU$OOsW83NG2R{@P_C0>|_OkPH&1Z6t-YyiLexiETbH7)HzQ(i97V-En z^=$M>?F^dfaix~QP@%{0c}&iC?Yvx3aj`F6sfGe8mIgIHer)!9;@n4<-0~{f<>oKt zKXp;SFo-!wLBN6IW!uBaC%iV=*jMk}5Nu;&XEetzp~?5MkmZx=Vg^ih=-8`?QM_Mj1mX}98Vp;!Jy?35hW7CIo$}9~A8#i?JPCC~R z7`aG@^$uUpvjcMot zIz4h9nVzf3o87am^SZ^m2vgMwd4SPyYLNP-XL)q>Ua0C)FQrIXJESTAbbP&4wlgC0QX# zM@-g+s7&BuH*i~awtMQW^7DK46n(8xQ&La9xN@cD#=T2YS@($-FjvgAe^GJd=rNDk zhLa|mNZ@d?M za^8$LK?V6wzg$_6d(xVxK1scES(bwUyPM(E4wZ?&md^<0ddAz^%Xuy{^xWakSF=K| zm$nEjy|V4C*V0WJHf-3nYuDbrd-sIS&@YnexNB}%Vl$cNXU5hbO|kB)QD?VBZp+aX zo9Vjs;J+^uSDsn;Q03r_O_BRTEWhq8etvGwtUj-k6*V#72 zL4mG|Qt#IMd)h4?Z)5wWJwj#D$&|MC_M_RJQ5l~758C{mXLpIt-*s8w`tS7?uZ~u7 z%r9hH*Bmjo`A+;&@wOez>*rtWxWn{jeao@wVRaXx3!YnXT)EZqe(%9NdyB;aMcbw) zIJ&%A=Wxkl+Y(vNM_m;kdy_BTWf$aPuQZV0VQW5p`t+w8~^?^Gd(z@zy0t`AGOIRcWj@&W4_hx z<7dl`x8Inhbm7c`!ex6u+ZcUGS!)}we(6(j{lQ)x{}pmP+sbXe=sj$F@b=om03DG4!i!Am8&m&fVuL4WIoHi9d2t(4nMXje&tl473*D(U*>>wbM>Noi-f= zKDWO8dg$CLz2m}v-HrdYw=b4D`m`uBz4&s)%crNcLw~B*n@#1hFaNaC;=Y{6F?Zvc z%ID-1K91 zvD39T6ze^y>3T53W261G%ES&8&)VABg#j6vnJ3@h=6bU2dU1F9w$HDBKHTj-nR(-a zmXCfqQgil}J-hSNPM-gk^-GtMf`o*cnmZfsY-i59A$f?_tk6mOT8)$eQeYFP^V!F*M&*aiVrnJ?C-{cd#ob4+<96KG`y4=+w`r5T?&z?Oq zGdJH}-le_sQWdMZj@;I)%?^(YjVAS|2z4eO?>qXqFf{b&mP?UKj_lpLc8Beo-2HbC ze*PCd<>|klw|aiv=2<^6y6)?ihixs!na}2MFMDkE{AEehavwfkb;{i5y-_BH$E;`poC+80>w<1rMq>1 z7#Nr~c)B=-RLp6;bl3k@f(YA(e{|{j<+dCaBWI8i{UJGmx+J6bk>#`QET?BKe36&H*(nnSBa;ApSy0(ER7Nl zYjK~DdPMD3MyK4#Cy_?w)4JauzrJMaoGHfVq|e*WcV=C=Vc&MWXGed2*wbhhAslAX z7UinF)0wTSaiWO7tC8C-rFCD@tmMPc4`y z%U|lDdFu7GtxYm~?Q8wGlMTW1?_|wC`1<}Q_HE2> z^iIDmzSz7XK*VES&i%h3)A;-OuW+R<)KS~csg`gxduo+mZiGRCh}r2gmkfVB{P?~2 br+99$L2LK4shb%X7#KWV{an^LB{Ts5mN;Xz literal 0 HcmV?d00001 diff --git a/doc/html/images/warning.png b/doc/html/images/warning.png new file mode 100755 index 0000000000000000000000000000000000000000..51a30f751179811a3367891c0e54b1dea7afd3ac GIT binary patch literal 3927 zcmeAS@N?(olHy`uVBq!ia0y~yV2}f04mJh`25Wk44otVv!`vx;GaF%2` zI|pPYCo?cq+iGS4^JFAuNVf4f%QU%gGJBl!RACQnlr-uwP+|2s@rY}U zg3=@rM;Au%nAoN@i)u_i-MQ;$eZ}u^fBR7X z_U)_cLwOtCR4A!yikdMfbWT6^y>w$bTYHPq#>EWW0S#PB8oXH4O>dq)e^Z`g^Cj+o zs_)$xw-oJJ{`>v;|HlP(dfMnQ2>6}&cxOdO--OF8GN*kXt-EqO+`?ElGNM_w)#o|4 ze!z)?+A=?Tg~KhLNx%Pd>+$>73Qvp}3YN@R?_;s+(8TzeRavc;8~>;RLJ@J^KWEz9Q-zk&No&OQ$yjCZ}fkDK9-N-?3 z1(WXr?w$t84J_LZaPDBvf57i_!0iCzMg`6fj%p_ucRSc=u&6#zSi!V)0i#J{SOHr} z)8_|9JJ|9XcPFseurV31#x+%b;L~vwXlXqmz&ojNibAOeyHV4P38qh2DxLNPaES07 zb+FNpJ=Iv|+!~-6!g|%w_k#Wf%NIr^%u-EqPQn*-zL1s<_R1!E%BRqtmtJ%vj*IjhsssQys*%fwIY_G6n z$$e$@bvwPd^nzH1d5M7)+uY7`?$Z}bUwr#w^$Wo-BEMwWniCTuB#e8s)mVi4PaYFV z6eM50-!MX5nP&PH_F8enhxTP>W-2 z%j%ZGL()nUS2&rd{}OoIVcjWurp`3r$_(TcprB@sj6n4|R{}9{is9CsH=C z-JB-l<){2!*?i*q3G*l2@4k5C%aJ=rb|hIJS#{LvNZZl4zz-s&U9zdls@*|;mfky^ zX9^$h&hD`8aPP<$UoU2_Zl|_S!Ev&|ln>K9CTUE{n6^XF(D`VP=?cFPJ=6ZGo~l+W zPv?wPChSt}+h$*L*zGlYQSu9&UDCGm;ynJ(wDXuheTkQpH=9@9#5L3QC}<`q@bI=t zD^CnOV{up_wPs4tgiVvXCf(A$s%5IPRYO-jS6fy!R^hIitlNC0{FAILw zspAzEea+o0_*=)D(3_T)yXGvFabM@~uIG+&Wkg)`y>Pqee>46x{Ap@h)YR>?$!X~! z(N;^>wnb}`_9V?r>VLFG$oFKFrr%1Rmy0fOFH^bPH}k}rgl~q=r#_t;JN5F^*HhT1 zP7jIDV$|BHm8<0+!nrEvYQ|Ngt8rH=O;t_xx5{i4+v@(RqI6r;nqP`v>%O}3PIH@Z zOs?0jS8|%k>E5YFvl4r=CzaFsU1li!Z z7IP0k_om$~}onwhgAcSQEyl$d=k?zmo3yt(`A+q2&r*ysN{c<74K*+)G`_yj1*38@zw6SZ$s?9TmT)%vGv z-+p1cmv@hS&-^vXYrP}C&*ndtKG%Qi`Qmuz`!e_I>}TCq+n=_-{NJ~KNB{LRn=oHu zu42|~Ol~`#PTcBwRlr?@s#4Sr#?BGZ-;G{y(PDEZ+ZKx zzCE(R*0E*t?zrBVy5V)%I>)@scen34?%w@b3=%!mVBW7 zvA-5O%D>(_wKtw?2dgDT3yWW4NER(x3VVpYg$ot1w=M59fEa^vrY zDaUW#p7zn;`-cyLx0Tm!<=Wc1Rlfh2Y;C~vpzDF_1LNy>igg~}_}q4&?cd`!k9~VL z^|toT_y6F>;rDCan{1=(tgLDIdU=h}m!i}BTj%cjz4`I^*tNUXmge?sJ9PO$$*-5< z`&<4SRULcm^FH$1&1>;j>(^#3-zr|>ARBG{%sSbcHC8d!`T3pmU(2G)w*O!D{dVW) zQ_olHd&FtHQ~dJet4{oxT{{Xie_p!tbjIn)duLb4$8+v0+JAm|{)bh^ufD!MXMOC; z?XUM&+Hh9}C-zu=y!Ipa{h?j0%imABr>iTr zXL@D*C+6SI|Bo-|zwAA8{)YKlcG

{yqAbT4R}68To`sNnBuO!wFUwJ%u91iQFAA z4(LLEUpNJL3u zX-P(Y5vU3F*;nVJk4{*DpN_{_PhHKE>He{kMlDyu%>#tIEHu}-y0sCFYPMw z@7%jv(zkb?JNjkOl2@v}mnUsuU3iF@Kg7f1ODlU^g_F~xUi-uG4e|&0HH3n^SBYKf zT43he;I=TcxL^4A$zR*pI802`JK7IY&rz3~7 zdGfgB86VtL>SbQJ*d&f+4u8X+P_HE!(N>pIZM|D>O%}R(?%8Kg)9@Y6-xc>>7cmlF z@T%Uh&|KncWk;>kR?aPJ?H-3N3N73#npwqg;=+W9tp(TKKT*G58fGQo_FS`XK~}x; zy7P{f?#2TgP@zQBToLwwn9SmAkvz_MiQ(q+;G>apO{vS8Kalt;UWo z_u527^Y6EME}kS5vP#v*=gjJzJB|G2y*V~jo4H`qUxUxnx6YX;-L{1Lzif=IgQ;Ln zk8&5U#Jk8(r)JF7e)RCL>6&$6hL$^fT7N2Sou06(xkHKh;WOL4?@|NhCuOy+*vB!y zjrY6K;@k9nn8~W2h+KQE`cs}PSI0d3o5^TReJK5i@){XV~v_=ku0~3Ikx?4 zh~2?+c-2Pj)+G{t=PofU3S4H^@;GAG8kbj7qTP2H^enJBy45(!fAQI z>HnUI9QtLn>z_YPj zt9G}{px4$SF`iL}ezEOomG&r~-#6`Y&AC)6Ms%Xs?o-wbg!Kt6${PGj? zAc>2OEm|8cxh}bzSMk|Cv$jy?z4y=V2SF3BnAeGmhN?tc9NT0f1C?=i za$@h<&7U4~ZOX-maxc$CPEp)3Z{m@K245$=-1;+aQq)KDcL6)j_kB&;@_L1C@4=Vy zO`Z-5cOJ;_T(#};XC2YxCo$%3ZPkUDOZc~WatNgSc0cfSbwS^kgV8$=UWs=)C3)lJ ztYgIqF9l7ne0wybY2lQ&H@uoMRnJORJ>Ixrv8)ltnum_zwZA@cmVT`1HwxYJzS?P0 zz?+qN+fP=l(#n5n_VxFzGy4ySE)JaMTKX}4hdYB^XH z)80}%XMe9sQeyclx9=;nBj)|%+q7X}Z&{V^+aHT&NKCikQocSRN#4J2t-NRW;|+sTQSQJ0kN;+$zDxJQ84oit1_lNO MPgg&ebxsLQ0L+(v)Bpeg literal 0 HcmV?d00001 diff --git a/doc/html/index.html b/doc/html/index.html new file mode 100644 index 0000000..41449f8 --- /dev/null +++ b/doc/html/index.html @@ -0,0 +1,160 @@ + + + +Chapter 1. Boost.Bimap + + + + + + + + + + + + + +
+Boost C++ LibrariesChapter Logo +HomeLibrariesPeopleFAQMore
+


+
Next
+
+
+

+Chapter 1. Boost.Bimap

+

+Matias Capeletto +

+
+
+

+ Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +

+
+
+ +
+ +

+ + Description +

+

+ boost.bimap.logo +

+

+ Boost.Bimap is a bidirectional maps library for C++. With Boost.Bimap you can + create associative containers in which both types can be used as key. A bimap<X,Y> can be thought of as a combination of a + std::map<X,Y> + and a std::map<Y,X>. + The learning curve of bimap is almost flat if you know how to use standard + containers. A great deal of effort has been put into mapping the naming scheme + of the STL in Boost.Bimap. The library is designed to match the common STL + containers. +

+

+ + Influences and Related + Work +

+

+ The design of Boost.Bimap interface follows the standard template library. + It has been strongly influenced by Joaquin Lopez Muñoz's Boost.MultiIndex + library (the heart of bimaps) and codeproject::bimap library. +

+
+
+ + + +

Last revised: June 04, 2007 at 19:49:38 GMT

+
+
Next
+ + diff --git a/doc/introduction.qbk b/doc/introduction.qbk new file mode 100755 index 0000000..25c1fa3 --- /dev/null +++ b/doc/introduction.qbk @@ -0,0 +1,99 @@ +[/license + +Boost.Bimap + +Copyright (c) 2006-2007 Matias Capeletto + +Distributed under the Boost Software License, Version 1.0. +(See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt) + +] + + +[/ QuickBook Document version 1.4 ] + +[section Introduction] + +[heading How to use this document] + +This documentation contains a large amount of information. Whereas it +may be worth reading it all, this documentation is intended for +programmers with various motives: + +[variablelist +[[I have to finished this today, I just want a bidirectional map!][ +If your boss will kill you if the project is not finished by the end of +the day, just read the [link boost_bimap.one_minute_tutorial One-minute tutorial]. +If you have a background in STL, you can be testing a bimap within ten minutes. +]] +[[I am a serious programmer and want to learn Boost.Bimap][ +Boost.Bimap has a lot to offer if you are prepared to spend some time +reading this documentation. You will need to read [link boost_bimap.the_tutorial The tutorial] +and skim through some of the [link boost_bimap.examples Examples]. +The best way to read this documentation is in the order given here. +Just click on the arrow at the right bottom corner as you finish each page. +You may skip the reference section, and return to it later to look up a function +signature or to find a specific metafunction. +]] +[[I just love C++, I want to see the inner workings of Boost.Bimap.][ +If you are a library developer, this documentation is the best place to +learn how Boost.Bimap is implemented. It is strongly recommended that +you first learn to use the library as if you were the second type of +programmer above. This library was developed in the Google SoC 2006, and +the mentor and student generated a great deal of documentation in the +building process. The rationale section is very large and contains a lot +of information. There is a history section for those who might find it +useful. Finally, in the reference section, each entity of the library is +documented and its source code is presented. +]] +] + +[note +If anything in the documentation is unclear, please email me at ['matias +{dot} capeletto {at} gmail {dot} com], telling me which of the three +types of programmer above you are and which section needs improvement. +Please use the following notation for the subject: ['\[boost\]\[bimap\] Your +problem] as this will help me to identify it more easily. If appropriate, +I will act on your advice to improve the documentation. Thanks and enjoy! +] + +[important +If you should find a bug or would like to see an additional feature in +the library, please use the standard Boost methods of dealing with this +kind of issue rather than emailing me directly. Boost has a very good +system to [@http://www.boost.org/more/bugs.htm track bugs] and +[@http://www.boost.org/more/requesting_new_features.htm features requests], +and using it is the best way of dealing with them as soon as possible. +] + +[heading Navigation] + +Used in combination with the configured browser key (usually Alt), the +following keys act as handy shortcuts for common navigation tasks. + +* [*General] + + * [^[*p]] - Previous page + * [^[*n]] - Next page + * [^[*h]] - home + * [^[*u]] - Up + +* [*Main TOC] + + * [^[*i]] - Introduction + * [^[*o]] - One minute tutorial + * [^[*t]] - The tutorial + * [^[*b]] - Bimap and Boost + * [^[*r]] - Reference + * [^[*c]] - Compiler specifics + * [^[*v]] - Performance + * [^[*e]] - Examples + * [^[*s]] - Test Suite + * [^[*f]] - Future work + * [^[*m]] - Release notes + * [^[*w]] - Rationale + * [^[*y]] - History + * [^[*a]] - Acknowledgements + +[endsect] \ No newline at end of file diff --git a/doc/jamfile.v2 b/doc/jamfile.v2 new file mode 100755 index 0000000..b597ddd --- /dev/null +++ b/doc/jamfile.v2 @@ -0,0 +1,37 @@ +# Boost.Bimap +# +# Copyright (c) 2006-2007 Matias Capeletto +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + + +# Quickbook +# ----------------------------------------------------------------------------- + +import quickbook ; + +xml bimap + : + bimap.qbk + ; + +boostbook standalone + : + bimap + : + toc.max.depth=2 + toc.section.depth=4 + chunk.section.depth=2 + logo.image.src="'images/bimap/boost.bimap.header.png'" + ; + + +# Doxygen +# ----------------------------------------------------------------------------- +# This generate the doxydocs and write "bimap.hdt". +# Delete this file if you want to regenerate the doxydocs again +# import directdoxygen ; +# html-doxydocs bimap.hdt : bimap.hdf ; + diff --git a/doc/performance.qbk b/doc/performance.qbk new file mode 100755 index 0000000..3433579 --- /dev/null +++ b/doc/performance.qbk @@ -0,0 +1,19 @@ +[/license + +Boost.Bimap + +Copyright (c) 2006-2007 Matias Capeletto + +Distributed under the Boost Software License, Version 1.0. +(See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt) + +] + +[/ QuickBook Document version 1.4 ] + +[section Performance] + +Section under construction. + +[endsect] \ No newline at end of file diff --git a/doc/quick_tutorial.qbk b/doc/quick_tutorial.qbk new file mode 100755 index 0000000..bc14fcd --- /dev/null +++ b/doc/quick_tutorial.qbk @@ -0,0 +1,182 @@ +[/license + +Boost.Bimap + +Copyright (c) 2006-2007 Matias Capeletto + +Distributed under the Boost Software License, Version 1.0. +(See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt) + +] + +[/ QuickBook Document version 1.4 ] + +[section One minute tutorial] + +[heading What is a bimap?] + +A Bimap is a data structure that represents bidirectional relations between +elements of two collections. The container is designed to work as two opposed STL maps. A bimap between a collection `X` and a collection `Y` can be viewed as a map from `X` to `Y` (this view will be called the ['left map view]) or as a map from `Y` to `X` (known as the ['right map view]). Additionally, the bimap can also be viewed as a set of relations between `X` and `Y` (named the ['collection of relations view]). + +The following code creates an empty bimap container: + + typedef bimap bm_type; + bm_type bm; + +Given this code, the following is the complete description of the resulting bimap. +[footnote A type is ['signature-compatible] with other type if it has the same +signature for functions and metadata. Preconditions, postconditions and the order +of operations need not be the same. +] + +* `bm.left` is signature-compatible with `std::map` +* `bm.right` is signature-compatible with `std::map` +* `bm` is signature-compatible with `std::set< relation >` + +__SIMPLE_BIMAP__ + +You can see how a bimap container offers three views over the same collection of bidirectional relations. + +If we have any generic function that work with maps + + template< class MapType > + void print_map(const MapType & m) + { + typedef typename MapType::const_iterator const_iterator; + for( const_iterator iter = m.begin(), iend = m.end(); iter != iend; ++iter ) + { + std::cout << iter->first << "-->" << iter->second << std::endl; + } + } + +We can use the ['left map view] and the ['right map view] with it + + bimap< int, std::string > bm; + ... + print_map( bm.left ); + print_map( bm.right ); + +And the output will be + +[pre +[^1 --> one] +[^2 --> two] +... +[^one --> 1] +[^two --> 2] +... +] + +[heading Layout of the relation and the pairs of a bimap] + +The `relation` class represents two related elements. The two values are +named left and right to express the symmetry of this type. +The bimap pair classes are signature-compatible with `std::pairs`. + +__RELATION_AND_PAIR__ + +[heading Step by step] + +[import ../example/step_by_step.cpp] + +A convinience header is avaiable in the boost directory: + + #include + +Lets define a bidirectional map between integers and strings: + +[code_step_by_step_definition] + +[heading The collection of relations view] + +Remember that `bm` alone can be used as a set of relations. +We can insert elements or iterate over them using this view. + +[code_step_by_step_set_of_relations_view] + +[heading The left map view] + +`bm.left` works like a `std::map< int, std::string >`. We use it +in the same way we will use a standard map. + +[code_step_by_step_left_map_view] + +[heading The right map view] + +`bm.right` works like a `std::map< std::string, int >`. It is +important to note that the key is the first type and the data +is the second one, exactly as with standard maps. + +[code_step_by_step_right_map_view] + +[heading Differences with std::map] + +The main difference between bimap views and their standard containers counterparts +is that, because of the bidirectional nature of a bimap, the values stored in +it can not be modified directly using iterators. +For example, when a `std::map` iterator is dereferenced the return type is +`std::pair`, so the following code is valid: +`m.begin()->second = new_value;`. +However dereferencing a `bimap::left_iterator` returns a type that is +['signature-compatible] with a `std::pair` + + bm.left.find(1)->second = "1"; // Compilation error + +If you insert `(1,"one")` and `(1,"1")` in a `std::map` the second insertion will have no effect. In a `bimap` both keys have to remain unique. The insertion may fail in other situtions too. Lets see an example + + bm.clear(); + + bm.insert( bm_type::value_type( 1, "one" ) ); + + bm.insert( bm_type::value_type( 1, "1" ) ); // No effect! + bm.insert( bm_type::value_type( 2, "one" ) ); // No effect! + + assert( bm.size() == 1 ); + +[heading A simple example] + +Look how you can reuse code that is intend to be used with std::maps, like the +print_map function in this example. + +[@../../example/simple_bimap.cpp Go to source code] + +[code_simple_bimap] + +The output of this program will be the following: +[pre +[^The number of countries is 4] + +[^The winner is Argentina] + +[^Countries names ordered by their final position:] +[^1) Argentina] +[^2) Spain] +[^3) Germany] +[^4) France] + +[^Countries names ordered alphabetically along with their final position:] +[^Argentina ends in position 1] +[^France ends in position 4] +[^Germany ends in position 3] +[^Spain ends in position 2] +] + + +[heading Continuing the journey] + +For information on function signatures, see any standard library +documentation or read the [link boost_bimap.reference reference] section of +this documentation. + +[caution +Be aware that a bidirectional map is only signature-compatible with standard +containers. Some functions may give different results, such as in the case of +inserting a pair into the left map where the second value conflicts with a +stored relation in the container. The functions may be slower in a bimap +because of the duplicated constraints. It is strongly recommended that +you read [link boost_bimap.the_tutorial The full tutorial] if you intend to +use a bimap in a serious project. +] + +[endsect] diff --git a/doc/rationale.qbk b/doc/rationale.qbk new file mode 100755 index 0000000..4a5028c --- /dev/null +++ b/doc/rationale.qbk @@ -0,0 +1,914 @@ +[/license + +Boost.Bimap + +Copyright (c) 2006-2007 Matias Capeletto + +Distributed under the Boost Software License, Version 1.0. +(See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt) + +] + +[/ QuickBook Document version 1.4 ] + +[section Rationale] + +This section assumes that you have read all other sections, the most of +important of which being ['tutorial], ['std::set theory] and the ['reference], +and that you have tested the library. A lot of effort was invested in +making the interface as intuitive and clean as possible. If you +understand, and hopefully like, the interface of this library, it will +be a lot easier to read this rationale. The following section is little +more than a rationale. This library was coded in the context of the +Google SoC 2006 and the student and mentor were in different continents. +A great deal of email flowed between Joaquin and Matias. The juiciest +parts of the conversations where extracted and rearranged here. + +[note To browse the code, you can use the [@doxydoc/index.html ['Bimap Complete Reference]], a +doxygen-powered document targeted at developers. +] + +[section General Design] + +The initial explanation includes few features. This section aims to +describe the general design of the library and excludes details of those +features that are of lesser importance; these features will be +introduced later. + +The design of the library is divided into two parts. The first is the +construction of a [^relation] class. This will be the object stored and +managed by the [^multi_index_container] core. The idea is to make this +class as easy as possible to use, while making it efficient in terms of +memory and access time. This is a cornerstone in the design of +[*Boost.Bimap] and, as you will see in this rationale, the rest of the +design follows easily. + +The following interface is necessary for the [^relation] class: + + typedef -unspecified- TA; typedef -unspecified- TB; + + TA a, ai; TB b, bi; + + typedef relation< TA, TB > rel; + STATIC_ASSERT( is_same< rel::left_type , TA >::value ); + STATIC_ASSERT( is_same< rel::right_type, TB >::value ); + + rel r(ai,bi); + assert( r.left == ai && r.right == bi ); + + r.left = a; r.right = b; + assert( r.left == a && r.right == b ); + + typedef pair_type_by< member_at::left , rel >::type pba_type; + STATIC_ASSERT( is_same< pba_type::first_type , TA >::value ); + STATIC_ASSERT( is_same< pba_type::second_type, TB >::value ); + + typedef pair_type_by< member_at::right, rel >::type pbb_type; + STATIC_ASSERT( is_same< pbb_type::first_type , TB >::value ); + STATIC_ASSERT( is_same< pbb_type::second_type, TA >::value ); + + pba_type pba = pair_by< member_at::left >(r); + assert( pba.first == r.left && pba.second == r.right ); + + pbb_type pbb = pair_by< member_at::right >(r); + assert( pbb.first == r.right && pbb.second == r.left ); + + +__RELATION__ + +Although this seems straightforward, as will be seen later, it is the +most difficult code hack of the library. It is indeed very easy if we +relax some of the efficiency constraints. For example, it is trivial if +we allow a relation to have greater size than the the sum of those of +its components. It is equally simple if access speed is not important. +One of the first decisions made about [*Boost.Bimap] was, however, that, in +order to be useful, it had to achieve zero overhead over the wrapped +[*Boost.MultiIndex] container. Finally, there is another constraint that +can be relaxed: conformance to C++ standards, but this is quite +unacceptable. Let us now suppose that we have coded this class, and it +conforms to what was required. + +The second part is based on this [^relation] class. We can now view the +data in any of three ways: `pair`, `relation` and `pair`. +Suppose that our bimap supports only one-to-one relations. (Other +relation types are considered additional features in this design.) +The proposed interface is very simple, and it is based heavily on the +concepts of the STL. Given a `bimap bm`: + +# `bm.left` is signature-compatible with a `std::map` +# `bm.right` is signature-compatible with a `std::map` +# `bm` is signature-compatible with a `std::set >` + +__SIMPLE_BIMAP__ + +This interface is easily learned by users who have a STL background, as +well as being simple and powerful. This is the general design. + +[heading Relation Implementation] + +This section explains the details of the actual [^relation] class implementation. + +The first thing that we can imagine is the use of an [^union]. Regrettably, +the current C++ standard only allows unions of POD types. For the views, +we can try a wrapper around a `relation` that has two references +named first and second that bind to `A` and `B`, or to `B` and `A`. + + relation r; + + const_reference_pair pba(r); + const_reference_pair pbb(r); + +It is not difficult to code the relation class using this, but two +references are initialized at every access and using of `pba.first` will +be slower in most compilers than using `r.left` directly . There is +another hidden drawback of using this scheme: it is not +iterator-friendly, since the map views iterators must be degraded to +['Read Write] instead of ['LValue]. This will be explained later. + +At first, this seems to be the best we can do with the current C++ +standard. However there is a solution to this problem that does not +conform very well to C++ standards but does achieve zero overhead in +terms of access time and memory, and additionally allows the view +iterators to be upgraded to ['LValue] again. + +In order to use this, the compiler must conform to a +layout-compatibility clause that is not currently in the standard but is +very natural. The additional clause imposes that if we have two classes: + + struct class_a_b + { + Type1 name_a; + Type2 name_b; + }; + + struct class_b_a + { + Type1 name_b; + Type2 name_a; + }; + +then the storage layout of [^class_a_b] is equal to the storage layout of +[^class_b_a]. If you are surprised to learn that this does not hold in a +standards-compliant C++ compiler, welcome to the club. It is the natural +way to implement it from the point of view of the compiler's vendor and +is very useful for the developer. Maybe it will be included in the +standard some day. Every current compiler conforms to this. + +If we are able to count on this, then we can implement an idiom called +[^mutant]. The idea is to provide a secure wrapper around [^reinterpret_cast]. +A class can declare that it can be viewed using different view classes +that are storage-compatible with it. Then we use the free function +[^mutate(mutant)] to get the view. The `mutate` function checks at +compile time that the requested view is declared in the mutant views list. +We implement a class name `structured_pair` that is signature-compatible +with a `std::pair`, while the storage layout is configured with a third +template parameter. Two instances of this template class will provide +the views of the relation. + +The thing is that if we want to be standards-compliant, we cannot use +this approach. It is very annoying not to be able to use something that +we know will work with every compiler and that is far better than +alternatives. So -- and this is an important decision -- we have to find +a way to use it and still make the library standards-compliant. + +The idea is very simple. We code both approaches: the +const_reference_pair-based and the mutant-based, and use the mutant +approach if the compiler is compliant with our new layout-compatible +clause. If the compiler really messes things up, we degrade the +performance of the bimap a little. The only drawback here is that, while +the mutant approach allows to make ['LValue] iterators, we have to degrade +them to ['Read Write] in both cases, because we require that the same code +be compilable by any standards-compliant compiler. + +[note +Testing this approach in all the supported compilers indicated that the +mutant idiom was always supported. The strictly compliant version was +removed from the code because it was never used. +] + + +[heading Bimap Implementation] + +The core of bimap will be obviously a `multi_index_container`. The basic +idea to tackle the implementation of the bimap class is to use +[^iterator_adaptor] to convert the iterators from Boost.MultiIndex to the +`std::map` and `std::set` behaviour. The `map_view` and the `set_view` can be +implemented directly using this new transformed iterators and a wrapper +around each index of the core container. However, there is a hidden +idiom here, that, once coded, will be very useful for other parts of +this library and for Boost.MRU library. Following the ideas from +`iterator_adaptor`, Boost.Bimap views are implemented using a +[^container_adaptor]. There are several template classes (for example +`map_adaptor` and `set_adaptor`) that take a `std::map` signature-conformant +class and new iterators, and adapt the container so it now uses this +iterators instead of the originals. For example, if you have a +`std::set`, you can build other container that behaves exactly as a +`std::set` using `set_adaptor` and [^iterator_adaptor]. The combined use +of this two tools is very powerful. A [^container_adaptor] can take classes +that do not fulfil all the requirements of the adapted container. The +new container must define these missing functions. + +[endsect] + +[section Additional Features] + +[heading N-1, N-N, hashed maps] + +This is a very interesting point of the design. The framework introduced +in ['std::set theory] permits the management of the different constraints +with a very simple and conceptual approach. It is easy both to remember +and to learn. The idea here is to allow the user to specify the collection type +of each key directly. In order to implement this feature, we have to +solve two problems: + +* The index types of the `multi_index_container` core now depends on +the collection type used for each key. +* The map views now change their semantics according to the collection type +chosen. + +Boost.Bimap relies heavily on Boost.MPL to implement all of the +metaprogramming necessary to make this framework work. By default, if +the user does not specify the kind of the set, a `std::set` type is used. + +__BIMAP_STRUCTURES__ + +[heading Collection type of relation constraints] + +The constraints of the bimap set view are another very important +feature. In general, Boost.Bimap users will base the set view type on +one of the two collection types of their keys. It may be useful however to give +this set other constraints or simply to order it differently. By +default, Boost.Bimap bases the collection type of relations on the left collection +type, but the user may choose between: + +* left_based +* right_based +* set_of_relation<> +* multiset_of_relation<> +* unordered_set_of_relation<> +* unordered_multiset_of_relation<> +* list_of +* vector_of + +In the first two cases, there are only two indices in the +`multi_index_core`, and for this reason, these are the preferred options. +The implementation uses further metaprogramming to define a new index if +necessary. + +[/ +[heading Hooking Data] + +This is one of the things that makes Boost.Bimap very appealing in +tackling a problem. In general, programmers use maps to access +information quickly. Boost.Bimap allows the user to hook data inside the +bimap so that it is not necessary to maintain another map. The +implementation is based heavily on metaprogramming. +] + +[heading Tagged] + +The idea of using tags instead of the [^member_at::side] idiom is very +appealing since code that uses it is more readable. The only cost is +compile time. ['boost/bimap/tagged] is the implementation of a non-invasive +tagged idiom. The [^relation] class is built in such a way that even when +the user uses tags, the [^member_at::side] idiom continues to work. This is +good since an user can start tagging even before completing the coding +of the algorithm, and the untagged code continues to work. The +development becomes a little more complicated when user-defined tags are +included, but there are many handy metafunctions defined in the [^tagged] +idiom that help to keep things simple enough. + +__TAGGED__ + +[endsect] + +[section Code] + +You can browse the code using the [@doxydoc/index.html [*Boost.Bimap doxygen docs]]. + +The code follows the [@http://www.boost.org/more/lib_guide.htm Boost Library Requirement and Guidelines] as +closely as possible. + +[table folders in boost/bimap +[[name][what is inside?]] +[[/ ][user level header files ]] +[[tagged/ ][tagged idiom ]] +[[relation/ ][the bimap data ]] +[[container_adaptor/ ][easy way of adapting containers ]] +[[views/ ][bimap views ]] +[[property_map/ ][support for property map concept ]] +] + +[table folders in each folder +[[name][what is inside?]] +[[ ][class definitions]] +[[support/ ][optional metafunctions and free functions]] +[[detail/ ][things not intended for the user's eyes]] +] + +[endsect] + +[section The student and the mentor] + +[tip It is a good idea to read the original +[@http://h1.ripway.com/mcape/boost/libs/misc/ Boost.Misc SoC proposal] first.] + +[:[^- The discussion starts with Joaquin trying to strip out the "misc" name out of the library -]] + +__JOAQUIN_PHOTO__ + +[*Joaquin] +[:[' +Thinking about it, the unifying principle of MISC containers is perhaps +misleading: certainly all miscs use multi-indexing internally, but this does +not reflect much in the external interface (as it should be, OTOH). So, from +the user's point of view, miscs are entirely heterogeneous beasts. Moreover, +there isn't in your proposal any kind of global facility common to all miscs. +What about dropping the misc principle and working on each container as a +separate library, then? You'd have boost::bimap, boost::mru, etc, and no common +intro to them. This also opens up the possibility to add other containers to +the suite which aren't based on B.MI. What's your stance on this? Do you see a +value in keeping miscs conceptually together? +]] + +__MATIAS_PHOTO__ + +[*Matias] +[:[' +As the original proposal states only two containers (bimap and mru set) both +based in B.MI, it was straight forward to group them together. When I was +writing the SoC proposal I experienced a similar feeling when the two families +begin to grow. As you say, the only common denominator is their internal +implementation. I thought a bit about a more general framework to join this two +families (and other internally related ones) and finally came up with an idea: +Boost.MultiIndex! So I think that it is not a good idea to try to unify the two +families and I voted in favor of get rid of the misc part of boost::misc::bimap +and boost::misc::mru. Anyway, for my SoC application it seems OK to put the +two families in the same project because although from the outside they are +completely unrelated, the work I will have to do in order to build the libraries +will be consistent and what I will learn coding the bimap family will be used +when I start to code the mru family. When the mru family is in place, I will +surely have learnt other things to improve the bimap group. +]] +[:[' +On the other hand, I think it will be useful for the general user to +have at least some document linked in the B.MI documentation that +enumerates the most common cases of uses (a bimap and an mru set for +example) and points where to find clean implementation for this useful +containers. For now, a link to boost::bimap and other one to boost::mru +will suffice. If you think about the title of such a document, +you will probably come up with something like: Common Multi Index +Specialized Containers, and we are back to our misc proposal. +So, to order some ideas: +]] +[:['- A new family of containers that can be accessed by both key will +be created. (boost::bimap)]] +[:['- A new family of time aware containers will see the light. +(boost::mru)]] +[:['- A page can be added to B.MI documentation, titled misc that links +this new libraries.]] +[:[' +This is a clearer framework for the user. They can use a mru container +without hearing about Boost.MultiIndex at all. +And B.MI users will get some of their common containers already +implemented with an STL friendly interface in other libraries. +And as you stated this is more extensible because opens the door to use +other libraries in bimap and mru families than just Boost.MultiIndex +without compromising the more general boost framework. +The word "misc" it is going to disappear from the code and +the documentation of bimap and mru. From now on the only use for it will be to +identify our SoC project. I am thinking in a name for the bimap library. +What about Boost.BidirectionalMap? Ideas? +]] + +[*Joaquin] +[:[' +Yes, Boost.Bimap. In my opinion, bimap is a well known name +in the Boost and even in the C++ community. It sounds and is short. Why not to +vindicate yourself as the owner of this name? +]] + +[^- Then after a week of work -] + +[*Matias] +[:[' +Now that Boost.Bimap is getting some shape, I see that as +you have told me, we must offer a "one_to_many_map" and a "multi_bimap" +as part of the library. The framework I am actually working allowed to +construct this kind of bidirectional maps and it is easy to understand from +the user side. +]] + +[*Joaquin] +[:[' +OK, I am glad we agree on this point. +]] + +[*Matias] +[:[' +With respect to the symmetry of the key access names, I have to +agree that there is not much a difference between the following ones: +]] +[:['- to - from]] +[:['- to - b]] +[:['- 0 - 1]] +[:['- left - right]] +[:[' +In my opinion it is a matter of taste, but left/right sounds more symmetrical than +the others. +]] + +[*Joaquin] +[:[' +I like very much the left/right notation, it is very simple to +remember and it is a lot more symmetrical than to/from. +]] + +[*Matias] +[:[' +At first my idea was to obtain ease of use hiding the B.MI +core, making it more STL-intuitive. Nevertheless I have realized +that B.MI is a lot more coherent and easy to use that I had imagined. This +makes me think again in the problem. In the design that I am coding now, bimap +*is-a* multi_index_container specializes with a data type very comfortable +called bipair, that can be seen like any of the two maps that integrates it +using map views. This scheme has great benefits for users: +]] +[:[' +- If the user already knows B.MI, he can take advantage of the tools that +it provides and that are not present in the STL containers. In addition, in some +cases the use to indices to see the data can be very useful. +]] +[:[' +- If the user does not know anything about B.MI but have an STL framework, +the learning curve is reduced to understand the bimap instantiation and how a +is obtained the desired map view. +]] +[:[' +Another very important benefit holds: All the algorithms done for +B.MI continues to work with Boost.Bimap and if B.MI continues growing, bimap +grow automatically. +]] + +[*Joaquin] +[:[' +Umm... This is an interesting design decision, but +controversial in my opinion. Basically you decide to expose the +implementation of bimap; that has advantages, as you stated, but also +a nonsmall disadvantage: once *you have documented* the implementation, +it is not possible to change it anymore. It is a marriage with B.MI without +the chance of divorce. The other possibility, to hide the implementation and +to duplicate and document the provided functionality, explicitly or +implicitly due to the same characteristics of the implementation, is +of course heavier to maintain, but it gives a degree of freedom to change +the guts of your software if you need to. Do not take this like a frontal +objection, but I think that it is quite important design decision, not only +in the context of bimap but in general. +]] + +[*Matias] +[:[' +You are quite right here. I think we have to choose the hardest +path and hide the B.MI core from the user. I am sending you the first draft of +bimap along with some documentation. +]] + +[^- This completes the second week, the documentation was basically the first +section of this rationale -] + +[*Joaquin] +[:[' +I must confess that I am beginning to like what I see. +I am mathematical by vocation, and when I see symmetry in a formulation +I believe that it is in the right track. +]] + +[*Matias] +[:[' +We are two mathematicians by vocation then. +]] + +[*Joaquin] +[:[' +I think that the part of std::set theory is very clear. +To me, it turns out to me somewhat strange to consider the rank of a map +(values X) like a std::set, but of course the formulation is consistent. +]] + +[*Matias] +[:[' +I like it very much, it can be a little odd at first, but +now that I have get used to it, it is very easy to express in the code my +contrains on the data, and I believe that if somebody reads the code and +sees the bimap instantiation he is not going to have problems understanding +it. Perhaps it is easier to understand it if we use your notation: +ordered_nonunique, unordered_unique, but this goes against our STL facade. +In my opinion the user that comes from STL must have to learn as less as possible. +]] + +[*Joaquin] +[:[' +Considering a relation like a `struct {left, right}` +is clean and clear. If I understand it well, one relation has views of type +`pair{first, second}`, is this correct? +]] + +[*Matias] +[:[' +Yes, I believe that the left/right notation to express symmetry +is great. I believe that to people is going to love it. +]] + +[*Joaquin] +[:[' +OK, perfect. I likes this very much: +]] +[:['- bm.left is compatible with std::map]] +[:['- bm.right is compatible with std::map]] +[:['- bm is compatible with std::set>]] +[:[' +It is elegant and symmetric. I feel good vibrations here. +]] + +[*Matias] +[:[' +Great! +]] + +[*Joaquin] +[:[' +Moving on, the support for N-1, N-N, and hashed index is very easy +to grasp, and it fits well in framework. +However I do not finish to understand very well the "set constraints" section. +Will you came up with some examples of which is the meaning of the different +cases that you enumerate? +]] + +[*Matias - ] +[:[' +Yes, I mean: +]] +[:['- based on the left]] +[:['- based on the right]] +[:[' +The bimap core must be based on some index of multi index. If the index +of the left is of the type hash, then in fact the main view is going +to be an unordered_set< relation >. Perhaps this is not what the user +prefers and he wants to base its main view on the right index. +]] +[:['- set_of_relation ]] +[:['- multiset_of_relation ]] +[:['- unordered_set_of_relation ]] +[:['- unordered_multiset_of_relation ]] +[:[' +However, if both of them are hash indexes, the user may want the main view +to be ordered. As we have a B.MI core this is very easy to support, we just have +to add another index to it. +]] + +[*Joaquin] +[:[' +I understand it now. OK, I do not know if we have to include this +in the first version, is going to be a functionality avalanche! +]] + +[*Matias] +[:[' +The user is not affected by the addition of this functionality, +because by default it will be based on the left index that is a very natural +behaviour. I do not think that this is functionality bloat, but I agree with +you that it is a functionality avalanche. +]] + +[*Joaquin] +[:[' +There are restrictions between the left and right set types +and the possible main view set types. For example if some of the index is +of unique type, then the main view cannot be of type multiset_of_relation. +To the inverse one, if the main view is of type set_of_relation the left and +the right index cannot be of type multi_set. All this subject of the unicity +constrictions and the resulting interactions between indexes is one of the subtle +subjects of B.MI. +]] + +[*Matias] +[:[' +This can be checked at compile time and informed as an error +in compile time. +]] + +[*Joaquin] +[:[' +It can be interesting. +]] + +[^- And right when everything seems to be perfect... - ] + +[*Joaquin] +[:[' +I have some worse news with respect to mutant, it is very a +well designed and manageable class, unfortunately, C++ does not guarantee +layout-compatibility almost in any case. For example, the C++ standard does +not guarantee that the classes `struct{T1 a; T2 b;}` and `struct{T1 b; T2 a;}` +are layout-compatible, and therefore the trick of reinterpret_cast is an +undefined behavior. I am with you in which that in the 100% of the cases +this scheme will really work, but the standard is the standard. If you can +look the layout-compatibility subject in it (http://www.kuzbass.ru/docs/isocpp/). +As you see, sometimes the standard is cruel. Although mutant seems a lost case, +please do not hurry to eliminate it. We will see what can be done for it. +]] + +[*Matias] +[:[' +I read the standard, and you were right about it. Mutant was an implementation +detail. It is a pity because I am sure that it will work perfect in any compiler. +Perhaps the standard becomes more strict some day and mutant returns to life... +We can then try a wrapper around a relation that have two references named +first and second that bind to A and B, or B and A. +]] +`` +relation r; +const_reference_pair pba(r); +const_reference_pair pbb(r); +`` +[:[' +It is not difficult to code the relation class in this way but two references +are initialized with every access and the use of `pba.first` will be slower +than `r.left` in most compilers. It is very difficult to optimize this kind of +references. +]] + +[*Joaquin] +[:[' +This workaround is not possible, due to technical problems with +the expected behavior of the iterators. If the iterators of bm.left are of +bidirectional type, then standard stated that it have to return an object of type +const value_type& when dereferenced. You will have to return a const_reference_pair +created in the flight, making it impossible to return a reference. +]] + +[*Matias] +[:[' +I understand... I have workaround for that also but surely +the standard will attack me again! We must manage to create the class relation +that responds as we want, the rest of the code will flow from this point. +This clear separation between the relation class and the rest of the library, +is going to help to us to separate the problems and to attack them better. +]] + +[*Joaquin] +[:[' +What workaround? It already pricks my curiosity,I have dedicated +a long time to the subject and I do not find any solution except that we +allow the relation class to occupy more memory. +]] + +[*Matias] +[:[' +We must achieve that the relation size equals the pair size +if we want this library to be really useful. I was going to write my workaround and +I realized that It does not work. Look at this: +http://www.boost.org/libs/iterator/doc/new-iter-concepts.html +Basically the problem that we are dealing is solved if we based our iterators on +this proposal. The present standard forces that the bidirectional iterators also +are of the type input and output. Using the new concepts there is no inconvenient +in making our iterators "Readable Writable Swappable Bidirectional Traversal". +Therefore the const_reference_pair returns to be valid. +]] + +[*Joaquin] +[:[' +It is correct in the sense that you simply say that +your iterators are less powerful than those of the std::map. It is +not that it is wrong, simply that instead of fixing the problem, you +confess it. +]] + +[*Matias] +[:[' +OK, but in our particular case; What are the benefits +of offering a LValue iterator against a Read Write iterator? +It does not seem to me that it is less powerful in this case. +]] + +[*Joaquin] +[:[' +The main problem with a ReadWrite is that the following thing: +`value_type * p=&(*it);` +fails or stores a transitory direction in p. Is this important in the real life? +I do not know. How frequently you store the direction of the elements of a map? +Perhaps it is not very frequent, since the logical thing is to store the +iterators instead of the directions of the elements. +Let us review our options: +]] +[:[' +1. We used mutant knowing that is not standard, but of course it is +supported in the 100% of the cases. +]] +[:[' +2. We used const_reference_pair and we declared the iterators not LValue. +]] +[:[' +3. We found some trick that still we do not know. I have thus been playing +with unions and things, without much luck. +]] +[:[' +4. We leverage the restriction that views have to support the first, second +notation. If we made this decision, there are several possibilities: +]] +[:[' +''' '''a. The left map has standard semantics first/second while the right map +has the inverse semantics. +]] +[:[' +''' '''b. Instead of first and second we provide first() and second(), with +which the problem is trivial. +]] +[:[' +''' '''c. The map view do not support first/second but left/right as the +father relation +]] +[:[' +5. We solve the problem using more memory than sizeof(pair). +]] +[:[' +In any case, I would say that the only really unacceptable option is the last one. +]] + +[*Matias] +[:[' +Lets see. +]] +[:[' +1. I want the "standard compliant" label in the library. +]] +[:[' +2. This is the natural choice, but knowing that there is another option +that always works and it is more efficient is awful. +]] +[:[' +3. I have also tried to play with unions, the problem is that the union members +must be POD types. +]] +[:[' +4. This option implies a big lost to the library. +]] +[:[' +5. Totally agree. +]] +[:[' +I want to add another option to this list. Using metaprogramming, +the relation class checks if the compiler supports the mutant idiom. +If it supports it then it uses it and obtains zero overhead +plus LValue iterators, but if it do not supports it then uses +const_reference_pair and obtains minimum overhead with ReadWrite iterators. +This might be controversial but the advantages that mutant offers are very big +and the truth is that I do not believe that in any actual compiler this idiom is +not supported. This scheme would adjust perfectly to the present standard +since we are not supposing anything. The only drawback here is that although +the mutant approach allows to make LValue iterators we have to degrade they +to Read Write in both cases, because we want that the same code can be +compiled in any standard compliant compiler. +]] + + +[^- Hopefully we find our way out of the problem -] + +[*Joaquin] +[:[' +Changing the subject, I believe that the general concept of hooking data +is good, but I do not like the way you implement it. It has to be easy +to migrate to B.MI to anticipate the case in that Boost.Bimap becomes insufficient. +It is more natural for a B.MI user that the data is accessed without the indirection +of `.data`. I do not know how this can be articulated in your framework. +]] + +[*Matias] +[:[' +I have a technical problem to implement the data_hook in this way. +If the standard would let us use the mutant idiom directly, I can implement it +using multiple inheritance. But as we must use const_reference_pair too, It becomes +impossible for me to support it. We have three options here: +]] +[:[' +1) relation { left, right, data } and pair_view { first, second, data } +]] +[:[' +- This is more intuitive within the bimap framework, since it does not +mix the data with the index, as a table in a data base does, but gives more importance to +the index. +]] +[:[' +- It is not necessary that the user puts the mutable keyword in each member of +the data class. +]] +[:[' +- This moves away just a little bit from B.MI because the model +of it is similar to a table, but it continues to exist a clear path of migration. +]] +[:[' +2) relation { left,right, d1,d2... dn } and pair_view { first, second, data } +]] +[:[' +- The path to B.MI is the one you have proposed. +]] +[:[' +- It is very asymmetric. It is necessary to explain that the views are +handled different that the relation. +]] +[:[' +- The user must place the mutable keyboards in the data class. +]] +[:[' +3) Only relation { left,right, d1,d2... dn } +]] +[:[' +- Simple migration path to B.MI. +]] +[:[' +- You are not able to access the hooked data from the views. +]] +[:[' +My vote goes to the first proposal. +]] + + +[*Joaquin] +[:[' +Yes, the first option is the one that less surprises hold to the user. +I also vote for 1. +]] + +[^- The third week was over -] + +[*Matias] +[:[' +There is still one problem that I have to solve. I need to +know if it is necessary to create a map_view associated to nothing. If +it is necessary there are two options: that it behaves as an empty container or +that it throws an exception or assert when trying to use it. If it is not necessary, +the map_view is going to keep a reference instead of a pointer. +To me, the map_view always must be viewing something. In the case of the iterators +being able to create them empty, makes them easy to use in contexts that require +constructors by default, like being the value_type of a container, but I do not +believe that this is the case of map_view. +]] + +[*Joaquin] +[:[' +How would an empty map_view be useful? My intuition is like yours, +map_view would have to be always associate to something. If we wished to obtain +the semantics "is associated or not" we can use a pointer to a map_view. +]] + +[*Matias] +[:[' +OK, then you agree to that map_views stores a reference instead +of a pointer? +]] + +[*Joaquin] +[:[' +It depends on the semantics you want to give to map_views, and in +concrete to the copy of map_views. +]] +`` +map_view x=...; +map_view y=...; +x=y; +`` +[:[' +What is supposed to do this last line? +]] +[:[' +1. Rebinding of x, that is to say, x points at the same container that y. +]] +[:[' +2. Copy of the underlying container. +]] +[:[' +If you want to implement 1, you cannot use references internally. +If you want to implement 2, it is almost the same to use a reference or a pointer. +]] + +[*Matias] +[:[' +If I want that they behave exactly as std::maps then I must go for 2. +But if I think they as "views" of something, I like 1. The question is complicated. +I add another option: +]] +[:[' +3. Error: operator= is declare as private in boost::bimap::map_view std_container +]] +[:[' +Also What happens with `std_container = view;`? and with `view = std_container;`? +]] + +[endsect] + +[endsect] + + + + diff --git a/doc/reference.qbk b/doc/reference.qbk new file mode 100755 index 0000000..63803be --- /dev/null +++ b/doc/reference.qbk @@ -0,0 +1,64 @@ +[/license + +Boost.Bimap + +Copyright (c) 2006-2007 Matias Capeletto + +Distributed under the Boost Software License, Version 1.0. +(See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt) + +] + +[/ QuickBook Document version 1.4 ] + +[section Reference] + +[section Headers] + +The following are the interface headers of Boost.Bimap: + +[*Convenience] + +* "boost/bimap.hpp" ['(includes "boost/bimap/bimap.hpp" and imports the bimap class to boost namespace)] + +[*Container] + +* "boost/bimap/bimap.hpp" ['(includes "boost/bimap/set_of.hpp" and "boost/bimap/unconstrained_set_of.hpp")] + +[*Set Types] + +* "boost/bimap/set_of.hpp" +* "boost/bimap/multiset_of.hpp" +* "boost/bimap/unordered_set_of.hpp" +* "boost/bimap/unordered_multiset_of.hpp" +* "boost/bimap/list_of.hpp" +* "boost/bimap/vector_of.hpp" +* "boost/bimap/unconstrained_set_of.hpp" + +[*Boost Integration] + +* "boost/bimap/support/lambda.hpp" +* "boost/bimap/property_map/set_support.hpp" +* "boost/bimap/property_map/unordered_set_support.hpp" + +A program using Boost.Bimap must therefore include +"boost/bimap/bimap.hpp" and the headers defining the collection types to be used. + +Additional headers allow the integration of Boost.Bimap with other boost libraries, +like Boost.Lambda and Boost.Property_map. + +In order to use the serialization capabilities of Boost.Bimap, the appropriate +Boost.Serialization library module must be linked. Other than that, Boost.Bimap +is a header-only library, requiring no additional object modules. + +[endsect] + +[include reference/bimap.qbk] +[include reference/set_of.qbk] +[include reference/unordered_set_of.qbk] +[include reference/list_of.qbk] +[include reference/vector_of.qbk] +[include reference/unconstrained_set_of.qbk] + +[endsect] \ No newline at end of file diff --git a/doc/reference/bimap.qbk b/doc/reference/bimap.qbk new file mode 100755 index 0000000..737a110 --- /dev/null +++ b/doc/reference/bimap.qbk @@ -0,0 +1,523 @@ +[/license + +Boost.Bimap + +Copyright (c) 2006-2007 Matias Capeletto + +Distributed under the Boost Software License, Version 1.0. +(See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt) + +] + +[/ QuickBook Document version 1.4 ] + +[section Bimap Reference] + +[section View concepts] + +`bimap` instantiations comprise two side views and an view of the relation +specified at compile time. Each view allows read-write access to the elements contained +in a definite manner, mathing an STL container signature. + +Views are not isolated objects and so cannot be constructed on their +own; rather they are an integral part of a `bimap`. The name of the view +class implementation proper is never directly exposed to the user, who +has access only to the associated view type specifier. + +Insertion and deletion of elements are always performed through the +appropriate interface of any of the three views of the `bimap`; these +operations do, however, have an impact on all other views as well: for +instance, insertion through a given view may fail because there exists +another view that forbids the operation in order to preserve its +invariant (such as uniqueness of elements). The global operations +performed jointly in the any view can be reduced to six primitives: + +* copying +* insertion of an element +* hinted insertion, where a pre-existing element is suggested in order to improve +the efficiency of the operation +* deletion of an element +* replacement of the value of an element, which may trigger the +rearrangement of this element in one or more views, or may forbid the +replacement +* modification of an element, and its subsequent +rearrangement/banning by the various views + +The last two primitives deserve some further explanation: in order to +guarantee the invariants associated to each view (e.g. some definite +ordering) elements of a `bimap` are not mutable. To overcome this +restriction, the views expose member functions for updating and +modifying, which allows for the mutation of elements in a controlled +fashion. + +[endsect] + +[#complexity_signature_explanation] + +[section Complexity signature] + +Some member functions of a view interface are implemented by global +primitives from the above list. The complexity of these operations thus +depends on all views of a given `bimap`, not just the currently used view. + +In order to establish complexity estimates, a view is characterised by +its complexity signature, consisting of the following associated +functions on the number of elements: + +* `c(n)`: copying +* `i(n)`: insertion +* `h(n)`: hinted insertion +* `d(n)`: deletion +* `r(n)`: replacement +* `m(n)`: modifying + +If the collection type of the relation is `left_based` or `right_based`, and we use +an `l` subscript to denote the left view and an `r` for the right view, then +the insertion of an element in such a container is of complexity +`O(i_l(n)+i_r(n))`, where n is the number of elements. If the collection type of +relation is not side-based, then there is an additional term to add that +is contributed by the collection type of relation view. Using `a` to denote the +above view, the complexity of insertion will now be +`O(i_l(n)+i_r(n)+i_a(n))`. To abbreviate the notation, we adopt the +following definitions: + +* `C(n) = c_l(n) + c_r(n) [ + c_a(n) ]` +* `I(n) = i_l(n) + i_r(n) [ + i_a(n) ]` +* `H(n) = h_l(n) + h_r(n) [ + h_a(n) ]` +* `D(n) = d_l(n) + d_r(n) [ + d_a(n) ]` +* `R(n) = r_l(n) + r_r(n) [ + r_a(n) ]` +* `M(n) = m_l(n) + m_r(n) [ + m_a(n) ]` + +[endsect] + +[section Set type specification] + +Set type specifiers are passed as instantiation arguments to `bimap` and +provide the information needed to incorporate the corresponding views. +Currently, Boost.Bimap provides the collection type specifiers. The ['side collection type] +specifiers define the constraints of the two map views of the +bimap. The ['collection type of relation] specifier defines the main set view +constraints. If `left_based` (the default parameter) or `right_based` is +used, then the collection type of relation will be based on the left or right +collection type correspondingly. + +[table +[[Side collection type ][Collection type of relation ][Include ]] +[[`set_of` ][`set_of_relation` ][`boost/bimap/set_of.hpp` ]] +[[`multiset_of` ][`multiset_of_relation` ][`boost/bimap/multiset_of.hpp` ]] +[[`unordered_set_of` ][`unordered_set_of_relation` ][`boost/bimap/unordered_set_of.hpp` ]] +[[`unordered_multiset_of` ][`unordered_multiset_of_relation`][`boost/bimap/unordered_multiset_of.hpp` ]] +[[`list_of` ][`list_of_relation` ][`boost/bimap/list_of.hpp` ]] +[[`vector_of` ][`vector_of_relation` ][`boost/bimap/vector_of.hpp` ]] +[[`unconstrained_set_of` ][`unconstrained_set_of_relation` ][`boost/bimap/unconstrained_set_of.hpp` ]] +[[ ][`left_based` ][`boost/bimap/bimap.hpp` ]] +[[ ][`right_based` ][`boost/bimap/bimap.hpp` ]] +] + +[endsect] + +[section Tags] + +Tags are just conventional types used as mnemonics for the types stored +in a `bimap`. Boost.Bimap uses the tagged idiom to let the user specify +this tags. + +[endsect] + +[section Header "boost/bimap/bimap.hpp" synopsis] + + namespace boost { + namespace bimaps { + + template< class Type, typename Tag > + struct tagged; + + // bimap template class + + template + < + class LeftCollectionType, class RightCollectionType, + + class AdditionalParameter_1 = detail::not_specified, + class AdditionalParameter_2 = detail::not_specified + > + class bimap ``['- implementation defined { : public SetView } -]`` + { + public: + + // Metadata + + typedef ``['-unspecified-]`` left_tag; + typedef ``['-unspecified-]`` left_map; + + typedef ``['-unspecified-]`` right_tag; + typedef ``['-unspecified-]`` right_map; + + // Shortcuts + // typedef -side-_map::-type- -side-_-type-; + + typedef ``['-unspecified-]`` info_type; + + // Map views + + left_map left; + right_map right; + + // Constructors + + bimap(); + + template< class InputIterator > + bimap(InputIterator first,InputIterator last); + + bimap(const bimap &); + + bimap& operator=(const bimap& b); + + // Projection of iterators + + template< class IteratorType > + left_iterator project_left(IteratorType iter); + + template< class IteratorType > + left_const_iterator project_left(IteratorType iter) const; + + template< class IteratorType > + right_iterator project_right(IteratorType iter); + + template< class IteratorType > + right_const_iterator project_right(IteratorType iter) const; + + template< class IteratorType > + iterator project_up(IteratorType iter); + + template< class IteratorType > + const_iterator project_up(IteratorType iter) const; + + // Support for tags + + template< class Tag > + struct map_by; + + template< class Tag > + map_by::type by(); + + template< class Tag > + const map_by::type & by() const; + + template< class Tag, class IteratorType > + map_by::iterator project(IteratorType iter); + + template< class Tag, class IteratorType > + map_by::const_iterator project(IteratorType iter) const + + }; + + + } // namespace bimap + } // namespace boost + + +[/ + // Metafunctions for a bimap + + template< class Tag, class Bimap > struct value_type_by; + template< class Tag, class Bimap > struct key_type_by; + template< class Tag, class Bimap > struct data_type_by; + template< class Tag, class Bimap > struct iterator_type_by; + template< class Tag, class Bimap > struct const_iterator_type_by; + template< class Tag, class Bimap > struct reverse_iterator_type_by; + template< class Tag, class Bimap > struct const_reverse_iterator_type_by; + template< class Tag, class Bimap > struct local_iterator_type_by; + template< class Tag, class Bimap > struct const_local_iterator_type_by; + + // Functions for a bimap + + template + result_of::map_by< Tag, Bimap>::type map_by(Bimap &); + + // Metafunctions for a relation + + template< class Tag, class Relation > struct value_type_of; + template< class Tag, class Relation > struct pair_type_by; + + // Functions for a relation + + template + result_of::get< Tag, Relation>::type get(Relation &r); + + template + result_of::pair_by< Tag, Relation>::type pair_by(Relation &); + +] + +[endsect] + +[section Class template bimap] + +This is the main component of Boost.Bimap. + +[section Complexity] + +In the descriptions of the operations of `bimap`, we adopt the scheme +outlined in the complexity signature section. + +[endsect] + +[section Instantiation types] + +`bimap` is instantiated with the following types: + +# LeftCollectionType and RightCollectionType are collection type specifications +optionally tagged, or any type optionally tagged, in which case that +side acts as a set. +# AdditionalParameter_{1/2} can be any ordered subset of: + * CollectionTypeOfRelation specification + * Allocator + +[endsect] + +[section Nested types] + + left_tag, right_tag + +[: Tags for each side of the bimap. If the user has not specified any tag the + tags default to `member_at::left` and `member_at::right`. +] + + left_key_type, right_key_type + +[: Key type of each side. In a `bimap ` `left_key_type` is `A` and + `right_key_type` is `B`. + If there are tags, it is better to use: `Bimap::map_by::key_type`. +] + + left_data_type, right_data_type + +[: Data type of each side. In a bimap left_key_type is B and + right_key_type is A. + If there are tags, it is better to use: `Bimap::map_by::data_type`. +] + + left_value_type, right_value_type + +[: Value type used for the views. + If there are tags, it is better to use: `Bimap::map_by::value_type`. +] + + + left_iterator, right_iterator + left_const_iterator, right_const_iterator + +[: Iterators of the views. + If there are tags, it is better to use: + `Bimap::map_by::iterator` and + `Bimap::map_by::const_iterator` +] + + + left_map, right_map + +[: Map view type of each side. + If there are tags, it is better to use: + `Bimap::map_by::type`. +] + +[endsect] + +[section Constructors, copy and assignment] + + bimap(); + +* [*Effects:] Constructs an empty `bimap`. +* [*Complexity:] Constant. + + template + bimap(InputIterator first,InputIterator last); + +* [*Requires: ] `InputIterator` is a model of Input Iterator over elements of +type `relation` or a type convertible to `relation`. last is reachable from `first`. +* [*Effects:] Constructs an empty `bimap` and fills it with the elements in the range +`[first,last)`. Insertion of each element may or may not succeed depending on +acceptance by the collection types of the `bimap`. +* [link complexity_signature_explanation +[*Complexity:]] O(m*H(m)), where m is the number of elements in `[first,last)`. + + + bimap(const bimap & x); + +* [*Effects:] Constructs a copy of x, copying its elements as well as its +internal objects (key extractors, comparison objects, allocator.) +* [*Postconditions:] `*this == x`. The order of the views of the `bimap` +is preserved as well. +* [*Complexity:] O(x.size()*log(x.size()) + C(x.size())) + + + ~bimap() + +* [*Effects:] Destroys the `bimap` and all the elements contained. +The order in which the elements are destroyed is not specified. +* [*Complexity:] O(n). + + + bimap& operator=(const bimap& x); + +* [*Effects:] Replaces the elements and internal objects of the `bimap` +with copies from x. +* [*Postconditions:] `*this==x`. The order on the views of the `bimap` +is preserved as well. +* [*Returns: ] `*this`. +* [*Complexity:] O(n + x.size()*log(x.size()) + C(x.size())). +* [*Exception safety:] Strong, provided the copy and assignment operations +of the types of `ctor_args_list` do not throw. + +[/ + allocator_type get_allocator() const; + +* [*Effects:] Returns a copy of the `allocator_type` object used to construct +the `bimap`. +* [*Complexity:] Constant. +] + +[endsect] + +[#reference_projection_operations] + +[section Projection operations] + +Given a `bimap` with views v1 and v2, we say than an v1-iterator +it1 and an v2-iterator it2 are equivalent if: + +* `it1 == i1.end()` AND `it2 == i2.end()`, +* OR `it1` and `it2` point to the same element. + + + template< class IteratorType > + left_iterator project_left(IteratorType iter); + + template< class IteratorType > + left_const_iterator project_left(IteratorType iter) const; + +* [*Requires:] `IteratorType` is a bimap view iterator. it is a +valid iterator of some view of `*this` (i.e. does not refer to some other +`bimap`.) +* [*Effects:] Returns a left map view iterator equivalent to `it`. +* [*Complexity:] Constant. +* [*Exception safety:] nothrow. + + + template< class IteratorType > + right_iterator project_right(IteratorType iter); + + template< class IteratorType > + right_const_iterator project_right(IteratorType iter) const; + +* [*Requires:] `IteratorType` is a bimap view iterator. it is a +valid iterator of some view of `*this` (i.e. does not refer to some other +`bimap`.) +* [*Effects:] Returns a right map view iterator equivalent to `it`. +* [*Complexity:] Constant. +* [*Exception safety:] nothrow. + + + template< class IteratorType > + iterator project_up(IteratorType iter); + + template< class IteratorType > + const_iterator project_up(IteratorType iter) const; + +* [*Requires:] `IteratorType` is a bimap view iterator. it is a +valid iterator of some view of `*this` (i.e. does not refer to some other +`bimap`.) +* [*Effects:] Returns a collection of relations view iterator equivalent to `it`. +* [*Complexity:] Constant. +* [*Exception safety:] nothrow. + +[endsect] + +[#reference_support_for_used_defined_names] + +[section Support for user defined names] + + template< class Tag > + struct map_by; + +* `map_by::type` yields the type of the map view tagged with `Tag`. +`map_by::`['-type name-] is the same as `map_by::type::`['-type name-]. +* [*Requires: ] `Tag` is a valid user defined name of the bimap. + + + template< class Tag > + map_by::type by(); + + template< class Tag > + const map_by::type & by() const; + + +* [*Requires: ] `Tag` is a valid user defined name of the bimap. +* [*Effects:] Returns a reference to the map view tagged with `Tag` held by +`*this`. +* [*Complexity:] Constant. +* [*Exception safety:] nothrow. + + + template< class Tag, class IteratorType > + map_by::iterator project(IteratorType iter); + + template< class Tag, class IteratorType > + map_by::const_iterator project(IteratorType iter) const + +* [*Requires: ] `Tag` is a valid user defined name of the bimap. `IteratorType` +is a bimap view iterator. it is a valid iterator of some view of `*this` +(i.e. does not refer to some other `bimap`.) +* [*Effects:] Returns a reference to the map view tagged with `Tag` held by +`*this`. +* [*Complexity:] Constant. +* [*Exception safety:] nothrow. + + +[endsect] + +[section Serialization] + +A `bimap` can be archived and retrieved by means of __BOOST_SERIALIZATION__. +Boost.Bimap does not expose a public serialisation interface, as this is +provided by Boost.Serialization itself. Both regular and XML archives +are supported. + +Each of the set specifications comprising a given `bimap` contributes its +own preconditions as well as guarantees on the retrieved containers. In describing +these, the following concepts are used. A type `T` is ['serializable] +(resp. XML-serializable) if any object of type `T` can be saved to an output +archive (XML archive) and later retrieved from an input archive (XML archive) +associated to the same storage. If `x`' of type `T` is loaded from the serialization +information saved from another object x, we say that x' is a ['restored copy] of x. +Given a __SGI_BINARY_PREDICATE__ `Pred` over `(T, T)`, and objects `p` and `q` of +type `Pred`, we say that `q` is ['serialization-compatible] with `p` if + +* `p(x,y) == q(x`'`,y`'`)` + +for every `x` and `y` of type `T` and `x`' and `y`' being restored copies of `x` +and `y`, respectively. + +[blurb [*Operation:] saving of a `bimap b` to an output archive +(XML archive) ar.] + +* [*Requires:] Value is serializable (XML-serializable). Additionally, each +of the views of b can impose other requirements. +* [*Exception safety:] Strong with respect to `b`. If an exception is thrown, ar +may be left in an inconsistent state. + +[blurb [*Operation:] loading of a `bimap` m' from an input archive +(XML archive) ar.] + +* [*Requires:] Value is serializable (XML-serializable). Additionally, each of +the views of `b`' can impose other requirements. +* [*Exception safety:] Basic. If an exception is thrown, ar may be left in an +inconsistent state. + +[endsect] +[endsect] + +[endsect] \ No newline at end of file diff --git a/doc/reference/list_of.qbk b/doc/reference/list_of.qbk new file mode 100755 index 0000000..b8f495e --- /dev/null +++ b/doc/reference/list_of.qbk @@ -0,0 +1,798 @@ +[/license + +Boost.Bimap + +Copyright (c) 2006-2007 Matias Capeletto + +Distributed under the Boost Software License, Version 1.0. +(See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt) + +] + +[/ QuickBook Document version 1.4 ] + +[section list_of Reference] + +[section Header "boost/bimap/list_of.hpp" synopsis] + + namespace boost { + namespace bimaps { + + + template< class KeyType > + struct list_of; + + struct list_of_relation; + + + } // namespace bimap + } // namespace boost + +[endsect] + +[section list_of Views] + +A list_of set view is a std::list signature compatible +interface to the underlying heap of elements contained in a `bimap`. + +If you look the bimap by a side, you will use a map view and if you looked +it as a whole you will be using a set view. + +Elements in a list_of view are by default sorted according to +their order of insertion: this means that new elements inserted through a +different view of the `bimap` are appended to the end of the +list_of view. Additionally, the view allows for free reordering of elements +in the same vein as `std::list` does. Validity of iterators and references to +elements is preserved in all operations. + +There are a number of differences with respect to `std::lists`: + +* list_of views are not +__SGI_ASSIGNABLE__ (like any other view.) +* Unlike as in `std::list`, insertions into a list_of view may fail due to +clashings with other views. This alters the semantics of the operations +provided with respect to their analogues in `std::list`. +* Elements in a list_of view are not mutable, and can only be changed +by means of `replace` and `modify` member functions. + +Having these restrictions into account, list_of views are models of +__SGI_REVERSIBLE_CONTAINER__, __SGI_FRONT_INSERTION_SEQUENCE__ and +__SGI_BACK_INSERTION_SEQUENCE__. +We only provide descriptions of those types and operations that are either +not present in the concepts modeled or do not exactly conform to the +requirements for these types of containers. + + namespace boost { + namespace bimaps { + namespace views { + + template< ``['-implementation defined parameter list-]`` > + class ``['-implementation defined view name-]`` + { + public: + + // types + + typedef ``['-unspecified-]`` value_type; + typedef ``['-unspecified-]`` allocator_type; + typedef ``['-unspecified-]`` reference; + typedef ``['-unspecified-]`` const_reference; + typedef ``['-unspecified-]`` iterator; + typedef ``['-unspecified-]`` const_iterator; + typedef ``['-unspecified-]`` size_type; + typedef ``['-unspecified-]`` difference_type; + typedef ``['-unspecified-]`` pointer; + typedef ``['-unspecified-]`` const_pointer; + typedef ``['-unspecified-]`` reverse_iterator; + typedef ``['-unspecified-]`` const_reverse_iterator; + + typedef ``['-unspecified-]`` info_type; + + // construct/copy/destroy + + this_type & operator=(const this_type & x); + + template< class InputIterator > + void ``[link reference_list_of_assign_iterator_iterator assign]``(InputIterator first, InputIterator last); + + void ``[link reference_list_of_assign_size_value assign]``(size_type n, const value_type & value); + + allocator_type get_allocator() const; + + // iterators + + iterator begin(); + const_iterator begin() const; + + iterator end(); + const_iterator end() const; + + reverse_iterator rbegin(); + const_reverse_iterator rbegin() const; + + reverse_iterator rend(); + const_reverse_iterator rend() const; + + // capacity + + bool empty() const; + + size_type size() const; + + size_type max_size() const; + + void ``[link reference_list_of_resize_size_value resize]``(size_type n, const value_type & x = value_type()); + + // access + + const_reference front() const; + const_reference back() const; + + // modifiers + + std::pair ``[link reference_list_of_push_front_value push_front]``(const value_type & x); + void pop_front(); + + std::pair ``[link reference_list_of_push_back_value push_back]``(const value_type & x); + void pop_back(); + + std::pair ``[link reference_list_of_insert_iterator_value insert]``(iterator position, const value_type & x); + + void ``[link reference_list_of_insert_iterator_size_value insert]``(iterator position, size_type n, const value_type & x); + + template< class InputIterator > + void ``[link reference_list_of_insert_iterator_iterator_iterator insert]``(iterator position, InputIterator first, InputIterator last); + + iterator ``[link reference_list_of_erase_iterator erase]``(iterator position); + iterator ``[link reference_list_of_erase_iterator_iterator erase]``(iterator first, iterator last); + + bool ``[link reference_list_of_replace_iterator_value replace]``(iterator position, const value_type & x); + + // Only in map views + // { + + template< class CompatibleKey > + bool ``[link reference_list_of_replace_key_iterator_key replace_key]``(iterator position, const CompatibleKey & x); + + template< class CompatibleData > + bool ``[link reference_list_of_replace_data_iterator_data replace_data]``(iterator position, const CompatibleData & x); + + template< class KeyModifier > + bool ``[link reference_list_of_modify_key_iterator_modifier modify_key]``(iterator position, KeyModifier mod); + + template< class DataModifier > + bool ``[link reference_list_of_modify_data_iterator_modifier modify_data]``(iterator position, DataModifier mod); + + // } + + + void clear(); + + // list operations + + void ``[link reference_list_of_splice_iterator_this splice]``(iterator position, this_type & x); + void ``[link reference_list_of_splice_iterator_this_iterator splice]``(iterator position, this_type & x, iterator i); + void splice( + iterator position, this_type & x, iterator first, iterator last); + + void ``[link reference_list_of_remove_value remove]``(const value_type & value); + + template< class Predicate > + void ``[link reference_list_of_remove_if_predicate remove_if]``(Predicate pred); + + void ``[link reference_list_of_unique unique]``(); + + template< class BinaryPredicate > + void ``[link reference_list_of_unique_predicate unique]``(BinaryPredicate binary_pred); + + void ``[link reference_list_of_merge_this merge]``(this_type & x); + + template< class Compare > + void ``[link reference_list_of_merge_this_compare merge]``(this_type & x,Compare comp); + + void ``[link reference_list_of_sort sort]``(); + + template< class Compare > + void ``[link reference_list_of_sort_compare sort]``(Compare comp); + + void ``[link reference_list_of_reverse reverse]``(); + + // rearrange operations + + void relocate(iterator position, iterator i); + void relocate(iterator position, iterator first, iterator last); + + } + + // view comparison + + bool operator==(const this_type & v1, const this_type & v2 ); + bool operator< (const this_type & v1, const this_type & v2 ); + bool operator!=(const this_type & v1, const this_type & v2 ); + bool operator> (const this_type & v1, const this_type & v2 ); + bool operator>=(const this_type & v1, const this_type & v2 ); + bool operator<=(const this_type & v1, const this_type & v2 ); + + } // namespace views + } // namespace bimap + } // namespace boost + +In the case of a `bimap< list_of, ... >` + +In the set view: + + typedef signature-compatible with relation< Left, ... > key_type; + typedef signature-compatible with relation< Left, ... > value_type; + +In the left map view: + + typedef Left key_type; + typedef ... data_type; + + typedef signature-compatible with std::pair< Left, ... > value_type; + +In the right map view: + + typedef ... key_type; + typedef Left data_type; + + typedef signature-compatible with std::pair< ... , Left > value_type; + + +[#list_of_complexity_signature] + +[section Complexity signature] + +Here and in the descriptions of operations of `list_of` views, we adopt the +scheme outlined in the +[link complexity_signature_explanation complexity signature section]. +The complexity signature of a `list_of` view is: + +* copying: `c(n) = n * log(n)`, +* insertion: `i(n) = 1` (constant), +* hinted insertion: `h(n) = 1` (constant), +* deletion: `d(n) = 1` (constant), +* replacement: `r(n) = 1` (constant), +* modifying: `m(n) = 1` (constant). + +[endsect] + +[section Instantiation types] + +`list_of` views are instantiated internally to `bimap` and specified +by means of the collection type specifiers and the bimap itself. +Instantiations are dependent on the following types: + +* `Value` from `list_of`, +* `Allocator` from `bimap`, + +[endsect] + +[section Constructors, copy and assignment] + +As explained in the view concepts section, views do not have public +constructors or destructors. Assignment, on the other hand, is provided. + + this_type & operator=(const this_type & x); + +* [*Effects: ] `a = b;` +where a and b are the `bimap` objects to which `*this` and `x` belong, +respectively. +* [*Returns: ] `*this`. + + +[#reference_list_of_assign_iterator_iterator] + + template< class InputIterator > + void assign(InputIterator first, InputIterator last); + +* [*Requires: ] `InputIterator` is a model of __SGI_INPUT_ITERATOR__ over elements of type +`value_type` or a type convertible to `value_type`. first and last are not +iterators into any views of the `bimap` to which this view belongs. +`last` is reachable from `first`. +* [*Effects: ] `clear(); insert(end(),first,last);` + + +[#reference_list_of_assign_size_value] + + void assign(size_type n, const value_type & value); + +* [*Effects: ] `clear(); for(size_type i = 0; i < n ; ++n) push_back(v);` + + +[endsect] + +[section Capacity operations] + +[#reference_list_of_resize_size_value] + + void resize(size_type n,const value_type& x=value_type()); + +* [*Effects: ] +`if( n > size() ) insert(end(), n - size(), x);` +`else if( n < size() ) {` +` iterator it = begin();` +` std::advance(it, n);` +` erase(it, end());` +`}` +* [*Note:] If an expansion is requested, the size of the view is not +guaranteed to be n after this operation (other views may ban insertions.) + +[endsect] + +[section Modifiers] + +[#reference_list_of_push_front_value] + + std::pair push_front(const value_type& x); + +* [*Effects:] Inserts `x` at the beginning of the sequence if no other views +of the `bimap` bans the insertion. +* [*Returns:] The return value is a pair `p`. `p.second` is `true` if and only +if insertion took place. On successful insertion, `p.first` points to the element +inserted; otherwise, `p.first` points to an element that caused the insertion to be +banned. Note that more than one element can be causing insertion not to be allowed. +* [link list_of_complexity_signature [*Complexity:]] O(I(n)). +* [*Exception safety:] Strong. + + +[#reference_list_of_push_back_value] + + std::pair push_back(const value_type & x); + +* [*Effects:] Inserts `x` at the end of the sequence if no other views of the +`bimap` bans the insertion. +* [*Returns:] The return value is a pair `p`. `p.second` is `true` if and only if +insertion took place. On successful insertion, `p.first` points to the element +inserted; otherwise, `p.first` points to an element that caused the insertion +to be banned. Note that more than one element can be causing insertion not +to be allowed. +* [link list_of_complexity_signature [*Complexity:]] O(I(n)). +* [*Exception safety:] Strong. + + +[#reference_list_of_insert_iterator_value] + + std::pair insert(iterator position, const value_type & x); + +* [*Requires: ] `position` is a valid `iterator` of the view. +* [*Effects:] Inserts `x` before position if insertion is allowed by all other +views of the `bimap`. +* [*Returns:] The return value is a pair `p`. `p.second` is `true` if and only if +insertion took place. On successful insertion, `p.first` points to the element +inserted; otherwise, `p.first` points to an element that caused the insertion +to be banned. Note that more than one element can be causing insertion not +to be allowed. +* [link list_of_complexity_signature +[*Complexity:]] O(I(n)). +* [*Exception safety:] Strong. + + +[#reference_list_of_insert_iterator_size_value] + + void insert(iterator position, size_type n, const value_type & x); + +* [*Requires: ] `position` is a valid `iterator` of the view. +* [*Effects: ] `for(size_type i = 0; i < n; ++i) insert(position, x);` + + +[#reference_list_of_insert_iterator_iterator_iterator] + + template< class InputIterator> + void insert(iterator position,InputIterator first,InputIterator last); + +* [*Requires: ] `position` is a valid `iterator` of the view. `InputIterator` is +a model of __SGI_INPUT_ITERATOR__ over elements of type `value_type`. +`first` and `last` are not iterators into any view of the +`bimap` to which this view belongs. `last` is reachable from `first`. +* [*Effects: ] `while(first != last) insert(position, *first++);` +* [link list_of_complexity_signature +[*Complexity:]] O(m*I(n+m)), where m is the number of elements in `[first,last)`. +* [*Exception safety:] Basic. + + +[#reference_list_of_erase_iterator] + + iterator erase(iterator position); + +* [*Requires: ] `position` is a valid dereferenceable `iterator` of the view. +* [*Effects:] Deletes the element pointed to by `position`. +* [*Returns:] An iterator pointing to the element immediately following the +one that was deleted, or `end()` if no such element exists. +* [link list_of_complexity_signature +[*Complexity:]] O(D(n)). +* [*Exception safety:] nothrow. + + +[#reference_list_of_erase_iterator_iterator] + + iterator erase(iterator first, iterator last); + +* [*Requires: ] `[first,last)` is a valid range of the view. +* [*Effects:] Deletes the elements in `[first,last)`. +* [*Returns: ] `last`. +* [link list_of_complexity_signature +[*Complexity:]] O(m*D(n)), where m is the number of elements in `[first,last)`. +* [*Exception safety:] nothrow. + + +[#reference_list_of_replace_iterator_value] + + bool replace(iterator position,const value_type& x); + +* [*Requires: ] `position` is a valid dereferenceable iterator of the view. +* [*Effects:] Assigns the value `x` to the element pointed to by `position` into +the `bimap` to which the view belongs if replacing is allowed by +all other views of the `bimap`. +* [*Postconditions:] Validity of `position` is preserved in all cases. +* [*Returns: ] `true` if the replacement took place, `false` otherwise. +* [link list_of_complexity_signature +[*Complexity:]] O(R(n)). +* [*Exception safety:] Strong. If an exception is thrown by some user-provided +operation the `bimap` to which the view belongs remains in its +original state. + + +[#reference_list_of_replace_key_iterator_key] + + template< class CompatibleKey > + bool replace_key(iterator position, const CompatibleKey & x); + +* [*Requires: ] `position` is a valid dereferenceable iterator of the set view. +`CompatibleKey` can be assigned to `key_type`. +* [*Effects:] Assigns the value `x` to `e.first`, where `e` is the element pointed +to by `position` into the `bimap` to which the set view belongs if replacing is allowed by +all other views of the `bimap`. +* [*Postconditions:] Validity of position is preserved in all cases. +* [*Returns: ] `true` if the replacement took place, `false` otherwise. +* [link list_of_complexity_signature +[*Complexity:]] O(R(n)). +* [*Exception safety:] Strong. If an exception is thrown by some user-provided +operation, the `bimap` to which the set view belongs remains in +its original state. + + +[#reference_list_of_replace_data_iterator_data] + + template< class CompatibleData > + bool replace_data(iterator position, const CompatibleData & x); + +* [*Requires: ] `position` is a valid dereferenceable iterator of the set view. +`CompatibleKey` can be assigned to `data_type`. +* [*Effects:] Assigns the value `x` to `e.second`, where `e` is the element pointed +to by `position` into the `bimap` to which the set view belongs if replacing is allowed by +all other views of the `bimap`. +* [*Postconditions:] Validity of position is preserved in all cases. +* [*Returns: ] `true` if the replacement took place, `false` otherwise. +* [link list_of_complexity_signature +[*Complexity:]] O(R(n)). +* [*Exception safety:] Strong. If an exception is thrown by some user-provided +operation, the `bimap` to which the set view belongs remains in +its original state. + + +[#reference_list_of_modify_key_iterator_modifier] + + template< class KeyModifier > + bool modify_key(iterator position, KeyModifier mod); + +* [*Requires: ] `KeyModifier` is a model of __SGI_UNARY_FUNCTION__ accepting arguments of +type: `key_type&`; `position` is a valid dereferenceable iterator of the view. +* [*Effects:] Calls `mod(e.first)` where e is the element pointed to by position and +rearranges `*position` into all the views of the `bimap`. +If the rearrangement fails, the element is erased. +It is successful if the rearrangement is allowed by all other views of the `bimap`. +* [*Postconditions:] Validity of `position` is preserved if the operation succeeds. +* [*Returns: ] `true` if the operation succeeded, `false` otherwise. +* [link list_of_complexity_signature +[*Complexity:]] O(M(n)). +* [*Exception safety:] Basic. If an exception is thrown by some user-provided +operation (except possibly mod), then the element pointed to by position is erased. +* [*Note:] Only provided for map views. + + +[#reference_list_of_modify_data_iterator_modifier] + + template< class DataModifier > + bool modify_data(iterator position, DataModifier mod); + +* [*Requires: ] `DataModifier` is a model of __SGI_UNARY_FUNCTION__ accepting arguments of +type: `data_type&`; `position` is a valid dereferenceable iterator of the view. +* [*Effects:] Calls `mod(e.second)` where e is the element pointed to by position and +rearranges `*position` into all the views of the `bimap`. +If the rearrangement fails, the element is erased. +It is successful if the rearrangement is allowed by all other views of the `bimap`. +* [*Postconditions:] Validity of `position` is preserved if the operation succeeds. +* [*Returns: ] `true` if the operation succeeded, `false` otherwise. +* [link list_of_complexity_signature +[*Complexity:]] O(M(n)). +* [*Exception safety:] Basic. If an exception is thrown by some user-provided +operation (except possibly mod), then the element pointed to by position is erased. +* [*Note:] Only provided for map views. + +[/ +[#reference_list_of_modify_iterator_modifier] + + template< class Modifier > + bool modify(iterator position,Modifier mod); + +* [*Requires: ] `Modifier` is a model of __SGI_BINARY_FUNCTION__ accepting arguments of +type: `first_type&` and `second_type&` for ['Map View] and `left_type&` and `right_type&` +for ['Set View]. `position` is a valid dereferenceable iterator of the view. +* [*Effects:] Calls `mod(e.first,e.second)` for ['Map View] or calls `mod(e.left,e.right)` +for ['Set View] where `e` is the element pointed to by `position` and +rearranges `*position` into all the views of the `bimap`. +Rearrangement on `list_of` views does not change the position of the element +with respect to the view; rearrangement on other views may or might not suceed. +If the rearrangement fails, the element is erased. +* [*Postconditions:] Validity of `position` is preserved if the operation succeeds. +* [*Returns: ] `true` if the operation succeeded, `false` otherwise. +* [link list_of_complexity_signature +[*Complexity:]] O(M(n)). +* [*Exception safety:] Basic. If an exception is thrown by some user-provided +operation (except possibly `mod`), then the element pointed to by position is erased. +] + +[endsect] + +[section List operations] + +`list_of` views provide the full set of list operations found in `std::list`; +the semantics of these member functions, however, differ from that of `std::list` +in some cases as insertions might not succeed due to banning by other views. +Similarly, the complexity of the operations may depend on the other views +belonging to the same `bimap`. + + +[#reference_list_of_splice_iterator_this] + + void splice(iterator position, this_type & x); + +* [*Requires: ] `position` is a valid iterator of the view. `&x!=this`. +* [*Effects:] Inserts the contents of `x` before position, in the same order as +they were in `x`. Those elements successfully inserted are erased from `x`. +* [link list_of_complexity_signature +[*Complexity:]] O(`x.size()`*I(n+`x.size()`) + `x.size()`*D(`x.size()`)). +* [*Exception safety:] Basic. + + +[#reference_list_of_splice_iterator_this_iterator] + + void splice(iterator position, this_type & x,iterator i); + +* [*Requires: ] `position` is a valid iterator of the view. `i` is a valid +dereferenceable iterator `x`. +* [*Effects:] Inserts the element pointed to by `i` before position: if insertion +is successful, the element is erased from `x`. In the special case `&x==this`, +no copy or deletion is performed, and the operation is always successful. If +`position==i`, no operation is performed. +* [*Postconditions:] If `&x==this`, no iterator or reference is invalidated. +* [link list_of_complexity_signature +[*Complexity:]] If `&x==this`, constant; otherwise O(I(n) + D(n)). +* [*Exception safety:] If `&x==this`, nothrow; otherwise, strong. + + +[#reference_list_of_splice_iterator_this_iterator_iterator] + + void splice(iterator position, this_type & x, iterator first, iterator last); + +* [*Requires: ] `position` is a valid iterator of the view. `first` and `last` are +valid iterators of `x`. last is reachable from `first`. position is not in the +range `[first,last)`. +* [*Effects:] For each element in the range `[first,last)`, insertion is tried +before position; if the operation is successful, the element is erased from x. +In the special case `&x==this`, no copy or deletion is performed, and insertions +are always successful. +* [*Postconditions:] If `&x==this`, no iterator or reference is invalidated. +* [link list_of_complexity_signature +[*Complexity:]] If `&x==this`, constant; otherwise O(m*I(n+m) + m*D(x.size())) +where m is the number of elements in `[first,last)`. +* [*Exception safety:] If `&x==this`, nothrow; otherwise, basic. + + +[#reference_list_of_remove_value] + + void remove(const value_type & value); + +* [*Effects:] Erases all elements of the view which compare equal to `value`. +* [link list_of_complexity_signature +[*Complexity:]] O(n + m*D(n)), where m is the number of elements erased. +* [*Exception safety:] Basic. + + +[#reference_list_of_remove_if_predicate] + + template< class Predicate > + void remove_if(Predicate pred); + +* [*Effects:] Erases all elements `x` of the view for which `pred(x)` holds. +* [link list_of_complexity_signature +[*Complexity:]] O(n + m*D(n)), where m is the number of elements erased. +* [*Exception safety:] Basic. + + +[#reference_list_of_unique] + + void unique(); + +* [*Effects:] Eliminates all but the first element from every consecutive +group of equal elements referred to by the iterator `i` in the range +`[first+1,last)` for which `*i==*(i-1)`. +* [link list_of_complexity_signature +[*Complexity:]] O(n + m*D(n)), where m is the number of elements erased. +* [*Exception safety:] Basic. + + +[#reference_list_of_unique_predicate] + + template< class BinaryPredicate > + void unique(BinaryPredicate binary_pred); + +* [*Effects:] Eliminates all but the first element from every consecutive +group of elements referred to by the iterator i in the range \[first+1,last) +for which `binary_pred(*i,*(i-1))` holds. +* [link list_of_complexity_signature +[*Complexity:]] O(n + m*D(n)), where m is the number of elements erased. +* [*Exception safety:] Basic. + + +[#reference_list_of_merge_this] + + void merge(this_type & x); + +* [*Requires: ] `std::less` is a __SGI_STRICT_WEAK_ORDERING__ over `value_type`. +Both the view and `x` are sorted according to `std::less`. +* [*Effects:] Attempts to insert every element of `x` into the corresponding +position of the view (according to the order). Elements successfully inserted +are erased from `x`. The resulting sequence is stable, i.e. equivalent elements +of either container preserve their relative position. In the special case +`&x==this`, no operation is performed. +* [*Postconditions:] Elements in the view and remaining elements in `x` are sorted. +Validity of iterators to the view and of non-erased elements of `x` references +is preserved. +* [link list_of_complexity_signature +[*Complexity:]] If `&x==this`, constant; otherwise +O(n + `x.size()`*I(n+`x.size()`) + `x.size()`*D(`x.size()`)). +* [*Exception safety:] If `&x==this`, nothrow; otherwise, basic. + + +[#reference_list_of_merge_this_compare] + + template< class Compare > + void merge(this_type & x, Compare comp); + +* [*Requires:] Compare is a __SGI_STRICT_WEAK_ORDERING__ over `value_type`. Both the view +and `x` are sorted according to `comp`. +* [*Effects:] Attempts to insert every element of `x` into the corresponding position +of the view (according to `comp`). Elements successfully inserted are erased from `x`. +The resulting sequence is stable, i.e. equivalent elements of either container preserve +their relative position. In the special case `&x==this`, no operation is performed. +* [*Postconditions:] Elements in the view and remaining elements in `x` are sorted +according to `comp`. Validity of iterators to the view and of non-erased elements +of `x` references is preserved. +* [link list_of_complexity_signature +[*Complexity:]] If `&x==this`, constant; +otherwise O(n + `x.size()`*I(n+`x.size()`) + `x.size()`*D(`x.size()`)). +* [*Exception safety:] If `&x==this`, nothrow; otherwise, basic. + + +[#reference_list_of_sort] + + void sort(); + +* [*Requires: ] `std::less` is a __SGI_STRICT_WEAK_ORDERING__ over value_type. +* [*Effects:] Sorts the view according to `std::less`. The sorting is stable, +i.e. equivalent elements preserve their relative position. +* [*Postconditions:] Validity of iterators and references is preserved. +* [*Complexity:] O(n*log(n)). +* [*Exception safety:] nothrow if `std::less` does not throw; otherwise, basic. + + +[#reference_list_of_sort_compare] + + template< typename Compare > + void sort(Compare comp); + +* [*Requires:] Compare is a __SGI_STRICT_WEAK_ORDERING__ over value_type. +* [*Effects:] Sorts the view according to comp. The sorting is stable, i.e. equivalent +elements preserve their relative position. +* [*Postconditions:] Validity of iterators and references is preserved. +* [*Complexity:] O(n*log(n)). +* [*Exception safety:] nothrow if comp does not throw; otherwise, basic. + + +[#reference_list_of_reverse] + + void reverse(); + +* [*Effects:] Reverses the order of the elements in the view. +* [*Postconditions:] Validity of iterators and references is preserved. +* [*Complexity:] O(n). +* [*Exception safety:] nothrow. + + +[endsect] + +[section Rearrange operations] + +These operations, without counterpart in `std::list` (although splice provides +partially overlapping functionality), perform individual and global repositioning +of elements inside the index. + + +[#reference_list_of_relocate_iterator_iterator] + + void relocate(iterator position, iterator i); + +* [*Requires: ] `position` is a valid iterator of the view. `i` is a valid +dereferenceable iterator of the view. +* [*Effects:] Inserts the element pointed to by `i` before `position`. +If `position==i`, no operation is performed. +* [*Postconditions:] No iterator or reference is invalidated. +* [*Complexity:] Constant. +* [*Exception safety:] nothrow. + + +[#reference_list_of_relocate_iterator_iterator_iterator] + + void relocate(iterator position, iterator first, iterator last); + +* [*Requires: ] `position` is a valid iterator of the view. `first` and `last` are +valid iterators of the view. `last` is reachable from `first`. `position` is not +in the range `[first,last)`. +* [*Effects:] The range of elements `[first,last)` is repositioned just before +`position`. +* [*Postconditions:] No iterator or reference is invalidated. +* [*Complexity:] Constant. +* [*Exception safety:] nothrow. + + +[endsect] + +[section Serialization] + +Views cannot be serialized on their own, but only as part of the +`bimap` into which they are embedded. In describing the additional +preconditions and guarantees associated to `list_of` views with respect to +serialization of their embedding containers, we use the concepts defined in the +`bimap` serialization section. + +[blurb [*Operation:] saving of a `bimap` b to an output archive +(XML archive) ar.] + +* [*Requires:] No additional requirements to those imposed by the container. + + +[blurb [*Operation:] loading of a `bimap` b' from an input archive +(XML archive) ar.] + +* [*Requires:] No additional requirements to those imposed by the container. +[*Postconditions:] On successful loading, each of the elements of +`[begin(), end())` +is a restored copy of the corresponding element in +`[m.get().begin(), m.get().end())`, +where `i` is the position of the `list_of` view in the container. + + +[blurb [*Operation:] saving of an `iterator` or `const_iterator` it to an output +archive (XML archive) ar.] + +* [*Requires: ] `it` is a valid iterator of the view. The associated +`bimap` has been previously saved. + + +[blurb [*Operation:] loading of an `iterator` or `const_iterator it`' from an input +archive (XML archive) ar.] + +* [*Postconditions:] On successful loading, if it was dereferenceable then `*it`' is the +restored copy of `*it`, otherwise `it`'` == end()`. +* [*Note:] It is allowed that `it` be a `const_iterator` and the restored `it`' an iterator, +or viceversa. + + +[endsect] +[endsect] + + +[endsect] diff --git a/doc/reference/set_of.qbk b/doc/reference/set_of.qbk new file mode 100755 index 0000000..543a6af --- /dev/null +++ b/doc/reference/set_of.qbk @@ -0,0 +1,935 @@ +[/license + +Boost.Bimap + +Copyright (c) 2006-2007 Matias Capeletto + +Distributed under the Boost Software License, Version 1.0. +(See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt) + +] + +[/ QuickBook Document version 1.4 ] + +[section set_of Reference] + +[section Header "boost/bimap/set_of.hpp" synopsis] + + namespace boost { + namespace bimaps { + + + template + < + class KeyType, + class KeyCompare = std::less< KeyType > + > + struct set_of; + + + template + < + class KeyCompare = std::less< _relation > + > + struct set_of_relation; + + + } // namespace bimap + } // namespace boost + + +[endsect] + +[section Header "boost/bimap/multiset_of.hpp" synopsis] + + + namespace boost { + namespace bimaps { + + + template + < + class KeyType, + class KeyCompare = std::less< KeyType > + > + struct multiset_of; + + + template + < + class KeyCompare = std::less< _relation > + > + struct multiset_of_relation; + + + } // namespace bimap + } // namespace boost + + +[endsect] + + +[section Collection type specifiers set_of and multiset_of] + +These collection type specifiers allow for insertion of sets disallowing or +allowing duplicate elements, respectively. The syntaxes of `set_of` and +`multiset_of` coincide, so they are described together. + +[endsect] + + +[section \[multi\]set_of Views] + +A \[multi\]set_of set view is a std::\[multi\]set signature-compatible +interface to the underlying heap of elements contained in a `bimap`. + +There are two variants: set_of, which does not allow duplicate elements +(with respect to its associated comparison predicate) and multiset_of, +which does accept those duplicates. The interface of these two variants +is largely the same, so they are documented together with their +differences explicitly noted where they exist. + +If you look the bimap from a side, you will use a map view, and if you +look at it as a whole, you will be using a set view. + + + + namespace boost { + namespace bimaps { + namespace views { + + template< ``['-implementation defined parameter list-]`` > + class ``['-implementation defined view name-]`` + { + public: + + typedef ``['-unspecified-]`` key_type; + typedef ``['-unspecified-]`` value_type; + typedef ``['-unspecified-]`` key_compare; + typedef ``['-unspecified-]`` value_compare; + typedef ``['-unspecified-]`` allocator_type; + typedef ``['-unspecified-]`` reference; + typedef ``['-unspecified-]`` const_reference; + typedef ``['-unspecified-]`` iterator; + typedef ``['-unspecified-]`` const_iterator; + typedef ``['-unspecified-]`` size_type; + typedef ``['-unspecified-]`` difference_type; + typedef ``['-unspecified-]`` pointer; + typedef ``['-unspecified-]`` const_pointer; + typedef ``['-unspecified-]`` reverse_iterator; + typedef ``['-unspecified-]`` const_reverse_iterator; + + typedef ``['-unspecified-]`` info_type; + + this_type & operator=(const this_type & x); + + allocator_type get_allocator() const; + + // iterators + + iterator begin(); + const_iterator begin() const; + + iterator end(); + const_iterator end() const; + + reverse_iterator rbegin(); + const_reverse_iterator rbegin() const; + + reverse_iterator rend(); + const_reverse_iterator rend() const; + + // capacity + + bool empty() const; + + size_type size() const; + + size_type max_size() const; + + // modifiers + + std::pair ``[link reference_set_of_insert_value insert]``(const value_type & x); + + iterator ``[link reference_set_of_insert_iterator_value insert]``(iterator position, const value_type & x); + + template< class InputIterator> + void ``[link reference_set_of_insert_iterator_iterator insert]``(InputIterator first, InputIterator last); + + iterator ``[link reference_set_of_erase_iterator erase]``(iterator position); + + template< class CompatibleKey > + size_type ``[link reference_set_of_erase_key erase]``(const CompatibleKey & x); + + iterator ``[link reference_set_of_erase_iterator_iterator erase]``(iterator first, iterator last); + + bool ``[link reference_set_of_replace_iterator_value replace]``(iterator position, const value_type& x); + + // Only in map views + // { + + template< class CompatibleKey > + bool ``[link reference_set_of_replace_key_iterator_key replace_key]``(iterator position, const CompatibleKey & x); + + template< class CompatibleData > + bool ``[link reference_set_of_replace_data_iterator_data replace_data]``(iterator position, const CompatibleData & x); + + template< class KeyModifier > + bool ``[link reference_set_of_modify_key_iterator_modifier modify_key]``(iterator position, KeyModifier mod); + + template< class DataModifier > + bool ``[link reference_set_of_modify_data_iterator_modifier modify_data]``(iterator position, DataModifier mod); + + // } + + void swap(this_type & x); + + void clear(); + + // observers + + key_compare key_comp() const; + + value_compare value_comp() const; + + // set operations + + template< class CompatibleKey > + iterator ``[link reference_set_of_find_key find]``(const CompatibleKey & x); + + template< class CompatibleKey > + const_iterator ``[link reference_set_of_find_key find]``(const CompatibleKey & x) const; + + + template< class CompatibleKey > + size_type ``[link reference_set_of_count_key count]``(const CompatibleKey & x) const; + + + template< class CompatibleKey > + iterator ``[link reference_set_of_lower_bound_key lower_bound]``(const CompatibleKey & x); + + template< class CompatibleKey > + const_iterator ``[link reference_set_of_lower_bound_key lower_bound]``(const CompatibleKey & x) const; + + + template< class CompatibleKey > + iterator ``[link reference_set_of_upper_bound_key upper_bound]``(const CompatibleKey & x); + + template< class CompatibleKey > + const_iterator ``[link reference_set_of_upper_bound_key upper_bound]``(const CompatibleKey & x) const; + + + template< class CompatibleKey > + std::pair + ``[link reference_set_of_equal_range_key equal_range]``(const CompatibleKey & x); + + template< class CompatibleKey > + std::pair + ``[link reference_set_of_equal_range_key equal_range]``(const CompatibleKey & x) const; + + // Only in maps views + // { + + template< class LowerBounder, class UpperBounder> + std::pair ``[link reference_set_of_range_lower_upper range]``( + LowerBounder lower, UpperBounder upper); + + template< class LowerBounder, class UpperBounder> + std::pair ``[link reference_set_of_range_lower_upper range]``( + LowerBounder lower, UpperBounder upper) const; + + typedef ``['-unspecified-]`` data_type; + + // Only in for `set_of` collection type + // { + + template< class CompatibleKey > + const data_type & ``[link reference_set_of_at_key_const at]``(const CompatibleKey & k) const; + + // Only if the other collection type is mutable + // { + + template< class CompatibleKey > + data_type & ``[link reference_set_of_operator_bracket_key operator\[\]]``(const CompatibleKey & k); + + template< class CompatibleKey > + data_type & ``[link reference_set_of_at_key at]``(const CompatibleKey & k); + + // } + + // Only if info_hook is used + // { + + template< class CompatibleKey > + info_type & ``[link reference_set_of_info_at_key info_at]``(const CompatibleKey & k); + + template< class CompatibleKey > + const info_type & ``[link reference_set_of_info_at_key info_at]``(const CompatibleKey & k) const; + + // } + + // } + + // } + }; + + // view comparison + + bool operator==(const this_type & v1, const this_type & v2 ); + bool operator< (const this_type & v1, const this_type & v2 ); + bool operator!=(const this_type & v1, const this_type & v2 ); + bool operator> (const this_type & v1, const this_type & v2 ); + bool operator>=(const this_type & v1, const this_type & v2 ); + bool operator<=(const this_type & v1, const this_type & v2 ); + + } // namespace views + } // namespace bimap + } // namespace boost + + + +[/ Functions that may be implemented some day + + template< class Modifier> + bool ``[link reference_set_of_modify_iterator_modifier modify]``(iterator position, Modifier mod); + + template< class CompatibleKey, class CompatibleCompare > + iterator find(const CompatibleKey & x, + const CompatibleCompare & comp); + + template< class CompatibleKey, class CompatibleCompare > + const_iterator find(const CompatibleKey & x, + const CompatibleCompare & comp) const; + + template< class CompatibleKey, class CompatibleCompare > + size_type count(const CompatibleKey & x, + const CompatibleCompare & comp) const; + + template< class CompatibleKey, class CompatibleCompare > + iterator lower_bound(const CompatibleKey & x, + const CompatibleCompare & comp); + + template< class CompatibleKey, class CompatibleCompare > + const_iterator lower_bound(const CompatibleKey & x, + const CompatibleCompare & comp) const; + + template< class CompatibleKey, class CompatibleCompare > + iterator upper_bound(const CompatibleKey & x, + const CompatibleCompare & comp); + + template< class CompatibleKey, class CompatibleCompare > + const_iterator upper_bound(const CompatibleKey & x, + const CompatibleCompare & comp) const; + + template< class CompatibleKey, class CompatibleCompare > + std::pair equal_range( + const CompatibleKey & x, const CompatibleCompare & comp); + + template< class CompatibleKey, class CompatibleCompare > + std::pair equal_range( + const CompatibleKey & x, const CompatibleCompare & comp) const; + +] + + +In the case of a `bimap< {multi}set_of, ... >` + +In the set view: + + typedef signature-compatible with relation< Left, ... > key_type; + typedef signature-compatible with relation< const Left, ... > value_type; + +In the left map view: + + typedef Left key_type; + typedef ... data_type; + + typedef signature-compatible with std::pair< const Left, ... > value_type; + +In the right map view: + + typedef ... key_type; + typedef Left data_type; + + typedef signature-compatible with std::pair< ... ,const Left > value_type; + + +[#set_of_complexity_signature] + +[section Complexity signature] + +Here and in the descriptions of operations of this view, we adopt the +scheme outlined in the [link complexity_signature_explanation complexity signature section]. +The complexity signature of \[multi\]set_of view is: + +* copying: `c(n) = n * log(n)`, +* insertion: `i(n) = log(n)`, +* hinted insertion: `h(n) = 1` (constant) if the hint element precedes the point of +insertion, `h(n) = log(n)` otherwise, +* deletion: `d(n) = 1` (amortized constant), +* replacement: `r(n) = 1` (constant) if the element position does not change, +`r(n) = log(n)` otherwise, +* modifying: `m(n) = 1` (constant) if the element position does not change, +`m(n) = log(n)` otherwise. + +[endsect] + +[section Instantiation types] + +Set views are instantiated internally to a `bimap`. +Instantiations are dependent on the following types: + +* `Value` from the set specifier, +* `Allocator` from `bimap`, +* `Compare` from the set specifier. + +`Compare` is a __SGI_STRICT_WEAK_ORDERING__ on elements of `Value`. + +[endsect] + +[section Constructors, copy and assignment] + +Set views do not have public constructors or destructors. +Assignment, on the other hand, is provided. + + this_type & operator=(const this_type & x); + +* [*Effects: ] `a = b;` +where a and b are the `bimap` objects to which `*this` and x +belong, respectively. +* [*Returns: ] `*this`. + + + +[endsect] + +[section Modifiers] + +[#reference_set_of_insert_value] + + std::pair insert(const value_type & x); + +* [*Effects:] Inserts `x` into the `bimap` to which the set view belongs if + * the set view is non-unique OR no other element with equivalent key exists, + * AND insertion is allowed by the other set specifications the `bimap`. +* [*Returns:] The return value is a pair `p`. `p.second` is `true` if and only if insertion +took place. On successful insertion, `p.first` points to the element inserted; +otherwise, `p.first` points to an element that caused the insertion to be banned. +Note that more than one element can be causing insertion not to be allowed. +* [link set_of_complexity_signature +[*Complexity:]] O(I(n)). +* [*Exception safety:] Strong. + + +[#reference_set_of_insert_iterator_value] + + iterator insert(iterator position, const value_type & x); + +* [*Requires: ] `position` is a valid iterator of the view. +* [*Effects: ] `position` is used as a hint to improve the efficiency of the operation. Inserts `x` into the `bimap` to which the view belongs if + * the set view is non-unique OR no other element with equivalent key exists, + * AND insertion is allowed by all other views of the `bimap`. +* [*Returns:] On successful insertion, an iterator to the newly inserted +element. Otherwise, an iterator to an element that caused the insertion to be +banned. Note that more than one element can be causing insertion not to be allowed. +* [link set_of_complexity_signature +[*Complexity:]] O(H(n)). +* [*Exception safety:] Strong. + + +[#reference_set_of_insert_iterator_iterator] + + template< class InputIterator > + void insert(InputIterator first, InputIterator last); + +* [*Requires: ] `InputIterator` is a model of __SGI_INPUT_ITERATOR__ over elements of +type `value_type` or a type convertible to value_type. `first` and `last` are not +iterators into any view of the `bimap` to which this index +belongs. `last` is reachable from `first`. +* [*Effects: ] +`iterator hint = end()`; +`while( first != last ) hint = insert( hint, *first++ );` +* [link set_of_complexity_signature +[*Complexity:]] O(m*H(n+m)), where m is the number of elements in +`[first, last)`. +* [*Exception safety:] Basic. + + +[#reference_set_of_erase_iterator] + + iterator erase(iterator position); + +* [*Requires: ] `position` is a valid dereferenceable iterator if the set view. +* [*Effects:] Deletes the element pointed to by `position`. +* [*Returns:] An iterator pointing to the element immediately following +the one that was deleted, or `end()` if no such element exists. +* [link set_of_complexity_signature +[*Complexity:]] O(D(n)). +* [*Exception safety:] nothrow. + + +[#reference_set_of_erase_key] + + template< class CompatibleKey > + size_type erase(const CompatibleKey & x); + +* [*Requires: ] `CompatibleKey` is a compatible key of `key_compare`. +* [*Effects:] Deletes the elements with key equivalent to `x`. +* [*Returns:] Number of elements deleted. +* [link set_of_complexity_signature +[*Complexity:]] O(log(n) + m*D(n)), where m is the number of elements deleted. +* [*Exception safety:] Basic. + + +[#reference_set_of_erase_iterator_iterator] + + iterator erase(iterator first, iterator last); + +* [*Requires: ] `[first,last)` is a valid range of the view. +* [*Effects:] Deletes the elements in `[first,last)`. +* [*Returns:] last. +* [link set_of_complexity_signature +[*Complexity:]] O(log(n) + m*D(n)), where m is the number of elements +in `[first,last)`. +* [*Exception safety:] nothrow. + + +[#reference_set_of_replace_iterator_value] + + bool replace(iterator position, const value_type& x); + +* [*Requires: ] `position` is a valid dereferenceable iterator of the set view. +* [*Effects:] Assigns the value `x` to the element pointed to by `position` into +the `bimap` to which the set view belongs if, for the value `x` + * the set view is non-unique OR no other element with equivalent key exists +(except possibly `*position`), + * AND replacing is allowed by all other views of the `bimap`. +* [*Postconditions:] Validity of position is preserved in all cases. +* [*Returns: ] `true` if the replacement took place, `false` otherwise. +* [link set_of_complexity_signature +[*Complexity:]] O(R(n)). +* [*Exception safety:] Strong. If an exception is thrown by some user-provided +operation, the `bimap` to which the set view belongs remains in +its original state. + + +[#reference_set_of_replace_key_iterator_key] + + template< class CompatibleKey > + bool replace_key(iterator position, const CompatibleKey & x); + +* [*Requires: ] `position` is a valid dereferenceable iterator of the set view. +`CompatibleKey` can be assigned to `key_type`. +* [*Effects:] Assigns the value `x` to `e.first`, where `e` is the element pointed +to by `position` into the `bimap` to which the set view belongs if, + * the map view is non-unique OR no other element with equivalent key exists +(except possibly `*position`), + * AND replacing is allowed by all other views of the `bimap`. +* [*Postconditions:] Validity of position is preserved in all cases. +* [*Returns: ] `true` if the replacement took place, `false` otherwise. +* [link set_of_complexity_signature +[*Complexity:]] O(R(n)). +* [*Exception safety:] Strong. If an exception is thrown by some user-provided +operation, the `bimap` to which the set view belongs remains in +its original state. + + +[#reference_set_of_replace_data_iterator_data] + + template< class CompatibleData > + bool replace_data(iterator position, const CompatibleData & x); + +* [*Requires: ] `position` is a valid dereferenceable iterator of the set view. +`CompatibleKey` can be assigned to `data_type`. +* [*Effects:] Assigns the value `x` to `e.second`, where `e` is the element pointed +to by `position` into the `bimap` to which the set view belongs if, + * the map view is non-unique OR no other element with equivalent key exists +(except possibly `*position`), + * AND replacing is allowed by all other views of the `bimap`. +* [*Postconditions:] Validity of position is preserved in all cases. +* [*Returns: ] `true` if the replacement took place, `false` otherwise. +* [link set_of_complexity_signature +[*Complexity:]] O(R(n)). +* [*Exception safety:] Strong. If an exception is thrown by some user-provided +operation, the `bimap` to which the set view belongs remains in +its original state. + + +[#reference_set_of_modify_key_iterator_modifier] + + template< class KeyModifier > + bool modify_key(iterator position, KeyModifier mod); + +* [*Requires: ] `KeyModifier` is a model of __SGI_UNARY_FUNCTION__ accepting arguments of +type: `key_type&`; `position` is a valid dereferenceable iterator of the view. +* [*Effects:] Calls `mod(e.first)` where e is the element pointed to by position and +rearranges `*position` into all the views of the `bimap`. +If the rearrangement fails, the element is erased. +Rearrangement is successful if + * the map view is non-unique OR no other element with equivalent key exists, + * AND rearrangement is allowed by all other views of the `bimap`. +* [*Postconditions:] Validity of `position` is preserved if the operation succeeds. +* [*Returns: ] `true` if the operation succeeded, `false` otherwise. +* [link set_of_complexity_signature +[*Complexity:]] O(M(n)). +* [*Exception safety:] Basic. If an exception is thrown by some user-provided +operation (except possibly mod), then the element pointed to by position is erased. +* [*Note:] Only provided for map views. + + +[#reference_set_of_modify_data_iterator_modifier] + + template< class DataModifier > + bool modify_data(iterator position, DataModifier mod); + +* [*Requires: ] `DataModifier` is a model of __SGI_UNARY_FUNCTION__ accepting arguments of +type: `data_type&`; `position` is a valid dereferenceable iterator of the view. +* [*Effects:] Calls `mod(e.second)` where e is the element pointed to by position and +rearranges `*position` into all the views of the `bimap`. +If the rearrangement fails, the element is erased. +Rearrangement is successful if + * the oppositte map view is non-unique OR no other element with equivalent key in that +view exists, + * AND rearrangement is allowed by all other views of the `bimap`. +* [*Postconditions:] Validity of `position` is preserved if the operation succeeds. +* [*Returns: ] `true` if the operation succeeded, `false` otherwise. +* [link set_of_complexity_signature +[*Complexity:]] O(M(n)). +* [*Exception safety:] Basic. If an exception is thrown by some user-provided +operation (except possibly mod), then the element pointed to by position is erased. +* [*Note:] Only provided for map views. + +[/ + +[#reference_set_of_modify_iterator_modifier] + + template< class Modifier > + bool modify(iterator position, Modifier mod); + +* [*Requires: ] `Modifier` is a model of __SGI_BINARY_FUNCTION__ accepting arguments of +type: `first_type&` and `second_type&` for ['Map View] or `left_type&` and `right_type&` +['Set View]; `position` is a valid dereferenceable iterator of the view. +* [*Effects:] Calls `mod(e.first,e.second)` for ['Map View] or Calls `mod(e.left,e.right)` +for ['Set View] where e is the element pointed to by position and rearranges `*position` +into all the views of the `bimap`. +If the rearrangement fails, the element is erased. +Rearrangement is successful if + * the view is non-unique OR no other element with equivalent key exists, + * AND rearrangement is allowed by all other views of the `bimap`. +* [*Postconditions:] Validity of `position` is preserved if the operation succeeds. +* [*Returns: ] `true` if the operation succeeded, `false` otherwise. +* [link set_of_complexity_signature +[*Complexity:]] O(M(n)). +* [*Exception safety:] Basic. If an exception is thrown by some user-provided +operation (except possibly mod), then the element pointed to by position is erased. + +] + +[endsect] + +[section Set operations] + +`[multi]set_of` views provide the full lookup functionality required by +__SGI_SORTED_ASSOCIATIVE_CONTAINER__ and __SGI_UNIQUE_ASSOCIATIVE_CONTAINER__, +namely `find`, `count`, `lower_bound`, `upper_bound` and `equal_range`. +Additionally, these member functions are templatized to allow for non-standard +arguments, so extending the types of search operations allowed. + +[/ +The kinds of arguments permissible when invoking the lookup member functions +are defined by the following concept. + +Consider a __SGI_STRICT_WEAK_ORDERING__ `Compare` over values of type `Key`. A pair of +types `(CompatibleKey, CompatibleCompare)` is said to be a ['compatible extension] +of Compare if + +* `CompatibleCompare` is a __SGI_BINARY_PREDICATE__ over `(Key, CompatibleKey)`, +* `CompatibleCompare` is a __SGI_BINARY_PREDICATE__ over `(CompatibleKey, Key)`, +* if `c_comp(ck,k1)` then `!c_comp(k1,ck)`, +* if `!c_comp(ck,k1)` and `!comp(k1,k2)` then `!c_comp(ck,k2)`, +* if `!c_comp(k1,ck)` and `!comp(k2,k1)` then `!c_comp(k2,ck)`, + +for every `c_comp` of type `CompatibleCompare`, `comp` of type `Compare`, `ck` of type +`CompatibleKey` and `k1`, `k2` of type `Key`. +] +A type `CompatibleKey` is said to be a ['compatible key] of `Compare` +if `(CompatibleKey, Compare)` is a compatible extension of `Compare`. This implies +that `Compare`, as well as being a strict weak ordering, accepts arguments of type +`CompatibleKey`, which usually means it has several overloads of `operator()`. + +[/ +In the context of a compatible extension or a compatible key, the expressions +"equivalent", "less than" and "greater than" take on their obvious interpretations. +] + +[#reference_set_of_find_key] + + template< class CompatibleKey > + iterator find(const CompatibleKey & x); + + template< class CompatibleKey > + const_iterator find(const CompatibleKey & x) const; + +* [*Requires: ] `CompatibleKey` is a compatible key of `key_compare`. +* [*Effects:] Returns a pointer to an element whose key is equivalent to `x`, or +`end()` if such an element does not exist. +* [*Complexity:] O(log(n)). + +[/ + template< class CompatibleKey, class CompatibleCompare > + iterator find(const CompatibleKey & x, + const CompatibleCompare & comp); + + template< class CompatibleKey, class CompatibleCompare > + const_iterator find(const CompatibleKey & x, + const CompatibleCompare & comp) const; + +* [*Requires: ] `(CompatibleKey, CompatibleCompare)` is a compatible extension of +`key_compare.` +* [*Effects:] Returns a pointer to an element whose key is +equivalent to `x`, or `end()` if such an element does not exist. +* [*Complexity:] O(log(n)). +] + +[#reference_set_of_count_key] + + template< class CompatibleKey > + size_type count(const key_type & x) const; + +* [*Requires: ] `CompatibleKey` is a compatible key of `key_compare`. +* [*Effects:] Returns the number of elements with key equivalent to `x`. +* [*Complexity:] O(log(n) + count(x)). + +[/ + template< class CompatibleKey, class CompatibleCompare > + size_type count(const CompatibleKey & x, + const CompatibleCompare & comp) const; + +* [*Requires: ] `(CompatibleKey, CompatibleCompare)` is a compatible extension of +`key_compare.` +* [*Effects:] Returns the number of elements with key equivalent to `x`. +* [*Complexity:] O(log(n) + count(x)). +] + +[#reference_set_of_lower_bound_key] + + template< class CompatibleKey > + iterator lower_bound(const key_type & x); + + template< class CompatibleKey > + const_iterator lower_bound(const key_type & x) const; + +* [*Requires: ] `CompatibleKey` is a compatible key of `key_compare`. +* [*Effects:] Returns an iterator pointing to the first element with key not +less than `x`, or `end()` if such an element does not exist. +* [*Complexity:] O(log(n)). + + +[#reference_set_of_upper_bound_key] + + template< class CompatibleKey > + iterator upper_bound(const key_type & x); + + template< class CompatibleKey > + const_iterator upper_bound(const key_type & x) const; + +* [*Requires: ] `CompatibleKey` is a compatible key of `key_compare`. +* [*Effects:] Returns an iterator pointing to the first element with key greater +than `x`, or `end()` if such an element does not exist. +* [*Complexity:] O(log(n)). + + +[#reference_set_of_equal_range_key] + + template< class CompatibleKey > + std::pair + equal_range(const key_type & x); + + template< class CompatibleKey > + std::pair + equal_range(const key_type & x) const; + +* [*Requires: ] `CompatibleKey` is a compatible key of `key_compare`. +* [*Effects:] Equivalent to `make_pair(lower_bound(x),upper_bound(x))`. +* [*Complexity:] O(log(n)). + + + +[endsect] + +[section Range operations] + +The member function range is not defined for sorted associative +containers, but `[multi]set_of` map views provide it as a convenient utility. +A range or interval is defined by two conditions for the lower and upper +bounds, which are modelled after the following concepts. + +Consider a __SGI_STRICT_WEAK_ORDERING__ `Compare` over values of type Key. +A type `LowerBounder` is said to be a lower bounder of `Compare` if + +* `LowerBounder` is a `Predicate` over `Key`, +* if `lower(k1)` and `!comp(k2,k1)` then `lower(k2)`, + +for every `lower` of type `LowerBounder`, `comp` of type `Compare`, and `k1`, `k2` +of type `Key`. +Similarly, an upper bounder is a type `UpperBounder` such that + +* `UpperBounder` is a `Predicate` over `Key`, +* if `upper(k1)` and `!comp(k1,k2)` then `upper(k2)`, + +for every `upper` of type `UpperBounder`, `comp` of type `Compare`, and `k1`, `k2` +of type `Key`. + +[#reference_set_of_range_lower_upper] + + template< class LowerBounder, class UpperBounder> + std::pair range( + LowerBounder lower, UpperBounder upper) const; + +* [*Requires: ] `LowerBounder` and `UpperBounder` are a lower and upper bounder of +`key_compare`, respectively. +* [*Effects:] Returns a pair of iterators pointing to +the beginning and one past the end of the subsequence of elements satisfying +lower and upper simultaneously. If no such elements exist, the iterators both +point to the first element satisfying lower, or else are equal to `end()` if this +latter element does not exist. +* [*Complexity:] O(log(n)). +* [*Variants:] In place of lower or upper (or both), the singular value +`boost::bimap::unbounded` can be provided. This acts as a predicate which +all values of type `key_type` satisfy. +* [*Note:] Only provided for map views. + +[endsect] + +[section at(), info_at() and operator\[\] - set_of only] + +[#reference_set_of_at_key_const] + + template< class CompatibleKey > + const data_type & at(const CompatibleKey & k) const; + +* [*Requires: ] `CompatibleKey` is a compatible key of `key_compare`. +* [*Effects:] Returns the `data_type` reference that is associated with `k`, or +throws `std::out_of_range` if such key does not exist. +* [*Complexity:] O(log(n)). +* [*Note:] Only provided when `set_of` is used. + +The symmetry of bimap imposes some constraints on `operator[]` and the +non constant version of at() that are not found in `std::maps`. +Tey are only provided if the other collection type is mutable +(`list_of`, `vector_of` and `unconstrained_set_of`). + +[#reference_set_of_operator_bracket_key] + + template< class CompatibleKey > + data_type & operator[](const CompatibleKey & k); + +* [*Requires: ] `CompatibleKey` is a compatible key of `key_compare`. +* [*Effects: ] `return insert(value_type(k,data_type()))->second;` +* [*Complexity:] O(log(n)). +* [*Note:] Only provided when `set_of` is used and the other collection +type is mutable. + +[#reference_set_of_at_key] + + template< class CompatibleKey > + data_type & at(const CompatibleKey & k); + +* [*Requires: ] `CompatibleKey` is a compatible key of `key_compare`. +* [*Effects: ] Returns the `data_type` reference that is associated with `k`, or +throws `std::out_of_range` if such key does not exist. +* [*Complexity:] O(log(n)). +* [*Note:] Only provided when `set_of` is used and the other collection +type is mutable. + +[/ +The symmetry of bimap imposes some constraints on `operator[]` that are +not found in `std::maps`. If other views are unique, +`bimap::duplicate_value` is thrown whenever an assignment is attempted to +a value that is already a key in these views. As for +`bimap::value_not_found`, this exception is thrown while trying to access +a non-existent key: this behaviour differs from that of `std::map`, which +automatically assigns a default value to non-existent keys referred to +by `operator[]`. + + const data_type & operator[](const typename key_type & k) const; + +* [*Effects:] Returns the `data_type` reference that is associated with `k`, or +throws `bimap::value_not_found` if such an element does not exist. +* [*Complexity:] O(log(n)). + + + ``['-unspecified data_type proxy-]`` operator[](const typename key_type & k); + +* [*Effects:] Returns a proxy to a `data_type` associated with `k` and the +bimap. The proxy behaves as a reference to the `data_type` object. If this +proxy is read and `k` was not in the bimap, the bimap::value_not_found is +thrown. If it is written then `bimap::duplicate_value` is thrown if the +assignment is not allowed by one of the other views of the `bimap`. +* [link set_of_complexity_signature +[*Complexity:]] If the assignment operator of the proxy is not used, then +the order is O(log(n)). If it is used, the order is O(I(n)) if `k` was not +in the bimap and O(R(n)) if it existed in the bimap. +] + + +[#reference_set_of_info_at_key] + + template< class CompatibleKey > + info_type & info_at(const CompatibleKey & k); + + template< class CompatibleKey > + const info_type & info_at(const CompatibleKey & k) const; + +* [*Requires: ] `CompatibleKey` is a compatible key of `key_compare`. +* [*Effects:] Returns the `info_type` reference that is associated with `k`, or +throws `std::out_of_range` if such key does not exist. +* [*Complexity:] O(log(n)). +* [*Note:] Only provided when `set_of` and `info_hook` are used + + +[endsect] + +[section Serialization] + +Views cannot be serialized on their own, but only as part of the `bimap` +into which they are embedded. In describing the additional preconditions and guarantees +associated to `[multi]set_of` views with respect to serialization of their embedding containers, +we use the concepts defined in the `bimap` serialization section. + +[blurb [*Operation:] saving of a `bimap` m to an output archive (XML archive) ar.] + +* [*Requires:] No additional requirements to those imposed by the container. + + +[blurb [*Operation:] loading of a `bimap` m' from an input archive (XML archive) ar.] + +* [*Requires:] In addition to the general requirements, `value_comp()` must be +serialization-compatible with `m.get().value_comp()`, where i is the position +of the ordered view in the container. +* [*Postconditions:] On successful loading, each of the elements of `[begin(), end())` +is a restored copy of the corresponding element in `[m.get().begin(), m.get().end())`. + + + +[blurb [*Operation:] saving of an iterator or `const_iterator` it to an output archive +(XML archive) ar.] + +* [*Requires: ] `it` is a valid iterator of the view. The associated `bimap` +has been previously saved. + + +[blurb [*Operation:] loading of an `iterator` or `const_iterator` `it`' from an input archive ( +XML archive) ar.] + +* [*Postconditions:] On successful loading, if it was dereferenceable then `*it`' is the +restored copy of `*it`, otherwise `it`'` == end()`. +* [*Note:] It is allowed that it be a `const_iterator` and the restored `it`' an iterator, +or viceversa. + + +[endsect] +[endsect] + +[endsect] \ No newline at end of file diff --git a/doc/reference/unconstrained_set_of.qbk b/doc/reference/unconstrained_set_of.qbk new file mode 100755 index 0000000..9b487dd --- /dev/null +++ b/doc/reference/unconstrained_set_of.qbk @@ -0,0 +1,123 @@ +[/license + +Boost.Bimap + +Copyright (c) 2006-2007 Matias Capeletto + +Distributed under the Boost Software License, Version 1.0. +(See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt) + +] + +[/ QuickBook Document version 1.4 ] + +[section unconstrained_set_of Reference] + +[section Header "boost/bimap/unconstrained_set_of.hpp" synopsis] + + namespace boost { + namespace bimaps { + + + template< class KeyType > + struct unconstrained_set_of; + + struct unconstrained_set_of_relation; + + + } // namespace bimap + } // namespace boost + +[endsect] + +[section unconstrained_set_of Views] + +An unconstrained_set_of set view is a view with no constraints. The use +of these kind of view boost the bimap performance but the view can not +be accessed. An unconstrained view is an empty class. + + namespace boost { + namespace bimaps { + namespace views { + + template< ``['-implementation defined parameter list-]`` > + class ``['-implementation defined view name-]`` + { + // Empty view + }; + + } // namespace views + } // namespace bimap + } // namespace boost + + + +In the case of a `bimap< unconstrained_set_of, ... >` + +In the set view: + + typedef signature-compatible with relation< Left, ... > key_type; + typedef signature-compatible with relation< Left, ... > value_type; + +In the left map view: + + typedef Left key_type; + typedef ... data_type; + + typedef signature-compatible with std::pair< Left, ... > value_type; + +In the right map view: + + typedef ... key_type; + typedef Left data_type; + + typedef signature-compatible with std::pair< ... , Left > value_type; + + + +[#unconstrained_set_of_complexity_signature] + +[section Complexity signature] + +We adopt the scheme outlined in the +[link complexity_signature_explanation complexity signature section]. +An unconstrained view can not be accessed by the user, but the +formulas to find the order of an operation for a bimap hold with +the following definitions. +The complexity signature of a `unconstrained_set_of` view is: + +* copying: `c(n) = 0` +* insertion: `i(n) = 0` +* hinted insertion: `h(n) = 0` +* deletion: `d(n) = 0` +* replacement: `r(n) = 0` +* modifying: `m(n) = 0` + +[endsect] + +[section Serialization] + +Views cannot be serialized on their own, but only as part of the +`bimap` into which they are embedded. In describing the additional +preconditions and guarantees associated to `list_of` views with respect to +serialization of their embedding containers, we use the concepts defined in the +`bimap` serialization section. + +[blurb [*Operation:] saving of a `bimap` b to an output archive +(XML archive) ar.] + +* [*Requires:] No additional requirements to those imposed by the container. + +[blurb [*Operation:] loading of a `bimap` b' from an input archive +(XML archive) ar.] + +* [*Requires:] No additional requirements to those imposed by the container. + + +[endsect] +[endsect] + +[endsect] + + diff --git a/doc/reference/unordered_set_of.qbk b/doc/reference/unordered_set_of.qbk new file mode 100755 index 0000000..d386b87 --- /dev/null +++ b/doc/reference/unordered_set_of.qbk @@ -0,0 +1,853 @@ +[/license + +Boost.Bimap + +Copyright (c) 2006-2007 Matias Capeletto + +Distributed under the Boost Software License, Version 1.0. +(See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt) + +] + +[/ QuickBook Document version 1.4 ] + +[section unordered_set_of Reference] + +[section Header "boost/bimap/unordered_set_of.hpp" synopsis] + + namespace boost { + namespace bimaps { + + + template + < + class KeyType, + class HashFunctor = hash< KeyType >, + class EqualKey = std::equal_to< KeyType > + > + struct unordered_set_of; + + + template + < + class HashFunctor = hash< _relation >, + class EqualKey = std::equal_to< _relation > + > + struct unordered_set_of_relation; + + + } // namespace bimap + } // namespace boost + + +[endsect] + +[section Header "boost/bimap/unordered_multiset_of.hpp" synopsis] + + namespace boost { + namespace bimaps { + + + template + < + class KeyType, + class HashFunctor = hash< KeyType >, + class EqualKey = std::equal_to< KeyType > + > + struct unordered_multiset_of; + + + template + < + class HashFunctor = hash< _relation >, + class EqualKey = std::equal_to< _relation > + > + struct unordered_multiset_of_relation; + + + } // namespace bimap + } // namespace boost + + +[endsect] + +[section Collection type specifiers unordered_set_of and unordered_multiset_of] + +These collection types specifiers allow for set views without and +with allowance of duplicate elements, respectively. The syntax of +`set_of` and `multiset_of` coincide, thus we describe them +in a grouped manner. + +[endsect] + +[section unordered_\[multi\]set_of Views] + +An unordered_\[multi\]set_of set view is a tr1::unordered\[multi\]set signature compatible +interface to the underlying heap of elements contained in a `bimap`. + +The interface and semantics of `unordered_[multi]set_of` views are +modeled according to the proposal for unordered associative containers given +in the __CPP_STANDARD_LIBRARY_TECHNICAL_REPORT__, also known as TR1. +An `unordered_[multi]set_of` view is particularized according to a given +`Hash` function object which returns hash values for the keys and a +binary predicate `Pred` acting as an equivalence relation on values of Key. + +There are two variants: unordered_set_of, which do not allow duplicate elements +(with respect to its associated comparison predicate) and unordered_multiset_of, +which accept those duplicates. The interface of these two variants is the same +to a great extent, so they are documented together with their differences +explicitly noted when they exist. + +If you look the bimap by a side, you will use a map view and if you looked +it as a whole you will be using a set view. + +Except where noted, `unordered_[multi]set_of` views (both unique and non-unique) are models +of [^Unordered Associative Container]. +Validity of iterators and references to elements is preserved in all cases. +Occasionally, the exception safety guarantees provided are actually stronger +than required by the extension draft. We only provide descriptions of those +types and operations that are either not present in the concepts modeled or +do not exactly conform to the requirements for unordered associative containers. + + + namespace boost { + namespace bimap { + namespace views { + + template< ``['-implementation defined parameter list-]`` > + class ``['-implementation defined view name-]`` + { + public: + + // types + + typedef ``['-unspecified-]`` key_type; + typedef ``['-unspecified-]`` value_type; + typedef ``['-unspecified-]`` key_compare; + typedef ``['-unspecified-]`` value_compare; + typedef ``['-unspecified-]`` hasher; + typedef ``['-unspecified-]`` key_equal; + typedef ``['-unspecified-]`` allocator_type; + typedef ``['-unspecified-]`` reference; + typedef ``['-unspecified-]`` const_reference; + typedef ``['-unspecified-]`` iterator; + typedef ``['-unspecified-]`` const_iterator; + typedef ``['-unspecified-]`` size_type; + typedef ``['-unspecified-]`` difference_type; + typedef ``['-unspecified-]`` pointer; + typedef ``['-unspecified-]`` const_pointer; + typedef ``['-unspecified-]`` local_iterator; + typedef ``['-unspecified-]`` const_local_iterator; + + typedef ``['-unspecified-]`` info_type; + + // construct/destroy/copy: + + this_type & operator=(const this_type & x); + + allocator_type get_allocator() const; + + // size and capacity + + bool empty() const; + size_type size() const; + size_type max_size() const; + + // iterators + + iterator begin(); + const_iterator begin() const; + iterator end(); + const_iterator end() const; + + // modifiers + + std::pair< iterator, bool > ``[link reference_unordered_set_of_insert_value insert]``(const value_type & x); + + iterator ``[link reference_unordered_set_of_insert_iterator_value insert]``(iterator position, const value_type & x); + + template< class InputIterator > + void ``[link reference_unordered_set_of_insert_iterator_iterator insert]``(InputIterator first, InputIterator last); + + iterator ``[link reference_unordered_set_of_erase_iterator erase]``(iterator position); + + template< class CompatibleKey > + size_type ``[link reference_unordered_set_of_erase_key erase]``(const CompatibleKey & x); + + iterator ``[link reference_unordered_set_of_erase_iterator_iterator erase]``(iterator first, iterator last); + + bool ``[link reference_unordered_set_of_replace_iterator_value replace]``(iterator position, const value_type & x); + + // Only in map views + // { + + template< class CompatibleKey > + bool ``[link reference_unordered_set_of_replace_key_iterator_key replace_key]``(iterator position, const CompatibleKey & x); + + template< class CompatibleData > + bool ``[link reference_unordered_set_of_replace_data_iterator_data replace_data]``(iterator position, const CompatibleData & x); + + template< class KeyModifier > + bool ``[link reference_unordered_set_of_modify_key_iterator_modifier modify_key]``(iterator position, KeyModifier mod); + + template< class DataModifier > + bool ``[link reference_unordered_set_of_modify_data_iterator_modifier modify_data]``(iterator position, DataModifier mod); + + // } + + + void clear(); + + // observers + + key_from_value key_extractor() const; + hasher hash_function() const; + key_equal key_eq() const; + + // lookup + + template< class CompatibleKey > + iterator ``[link reference_unordered_set_of_find_key find]``(const CompatibleKey & x); + + template< class CompatibleKey > + const_iterator ``[link reference_unordered_set_of_find_key find]``(const CompatibleKey & x) const; + + template< class CompatibleKey > + size_type ``[link reference_unordered_set_of_count_key count]``(const CompatibleKey & x) const; + + template< class CompatibleKey > + std::pair + ``[link reference_unordered_set_of_equal_range_key equal_range]``(const CompatibleKey & x); + + template< class CompatibleKey > + std::pair + ``[link reference_unordered_set_of_equal_range_key equal_range]``(const CompatibleKey & x) const; + + // bucket interface + + size_type bucket_count() const; + size_type max_bucket_count() const; + size_type bucket_size(size_type n) const; + size_type bucket(const key_type & k) const; + + local_iterator begin(size_type n); + const_local_iterator begin(size_type n) const; + local_iterator end(size_type n); + const_local_iterator end(size_type n) const; + + // hash policy + + float load_factor() const; + float max_load_factor() const; + void max_load_factor(float z); + void ``[link reference_unordered_set_of_rehash_size rehash]``(size_type n); + + // Only in maps views + // { + + typedef ``['-unspecified-]`` data_type; + + // Only in for `unordered_set_of` collection type + // { + + template + const data_type & ``[link reference_unordered_set_of_at_key_const at]``(const CompatibleKey & k) const; + + // Only if the other collection type is mutable + // { + + template + data_type & ``[link reference_unordered_set_of_operator_bracket_key operator\[\]]``(const CompatibleKey & k); + + template + data_type & ``[link reference_unordered_set_of_at_key at]``(const CompatibleKey & k); + + // } + + // Only if info_hook is used + // { + + template< class CompatibleKey > + info_type & ``[link reference_unordered_set_of_info_at_key info_at]``(const CompatibleKey & k); + + template< class CompatibleKey > + const info_type & ``[link reference_unordered_set_of_info_at_key info_at]``(const CompatibleKey & k) const; + + // } + + // } + + }; + + } // namespace views + } // namespace bimap + } // namespace boost + + + +In the case of a `bimap< unordered_{multi}set_of, ... >` + +In the set view: + + typedef signature-compatible with relation< Left, ... > key_type; + typedef signature-compatible with relation< const Left, ... > value_type; + +In the left map view: + + typedef Left key_type; + typedef ... data_type; + + typedef signature-compatible with std::pair< const Left, ... > value_type; + +In the right map view: + + typedef ... key_type; + typedef Left data_type; + + typedef signature-compatible with std::pair< ... ,const Left > value_type; + + + +[#unordered_set_of_complexity_signature] + +[section Complexity signature] + +Here and in the descriptions of operations of `unordered_[multi]set_of` views, +we adopt the scheme outlined in the +[link complexity_signature_explanation complexity signature section]. +The complexity signature of `unordered_[multi]set_of` view is: + +* copying: `c(n) = n * log(n)`, +* insertion: average case `i(n) = 1` (constant), worst case `i(n) = n`, +* hinted insertion: average case `h(n) = 1` (constant), worst case `h(n) = n`, +* deletion: average case `d(n) = 1` (constant), worst case `d(n) = n`, +* replacement: + * if the new element key is equivalent to the original, `r(n) = 1` (constant), + * otherwise, average case `r(n) = 1` (constant), worst case `r(n) = n`, +* modifying: average case `m(n) = 1` (constant), worst case `m(n) = n`. + +[endsect] + + +[section Instantiation types] + +`unordered_[multi]set_of` views are instantiated internally to `bimap` +specified by means of the collection type specifiers and the `bimap` itself. +Instantiations are dependent on the following types: + +* `Value` from `bimap`, +* `Allocator` from `bimap`, +* `Hash` from the collection type specifier, +* `Pred` from the collection type specifier. + +`Hash` is a __SGI_UNARY_FUNCTION__ taking a single argument of type +`key_type` and returning a value of type `std::size_t` in the range +`[0, std::numeric_limits::max())`. +Pred is a __SGI_BINARY_PREDICATE__ inducing an equivalence relation on elements of +`key_type`. It is required that the `Hash` object return the same value for +keys equivalent under `Pred`. + +[endsect] + +[section Nested types] + + iterator + const_iterator + local_iterator + const_local_iterator + +[: These types are models of __SGI_FORWARD_ITERATOR__. +] + + +[endsect] + +[section Constructors, copy and assignment] + +As explained in the concepts section, +views do not have public constructors or destructors. Assignment, on the other +hand, is provided. +Upon construction, `max_load_factor()` is 1.0. + + this_type & operator=(const this_type & x); + +* [*Effects: ] `a = b`; +where a and b are the `bimap` objects to which `*this` +and x belong, respectively. +* [*Returns: ] `*this.` + + + +[endsect] + +[section Modifiers] + +[#reference_unordered_set_of_insert_value] + + std::pair insert(const value_type & x); + +* [*Effects:] Inserts `x` into the `bimap` to which the view belongs if + * the view is non-unique OR no other element with equivalent key exists, + * AND insertion is allowed by all other views of the `bimap`. +* [*Returns:] The return value is a pair `p`. `p.second` is `true` if and only if +insertion took place. On successful insertion, `p.first` points to the element +inserted; otherwise, `p.first` points to an element that caused the insertion to +be banned. Note that more than one element can be causing insertion not to be +allowed. +* [link unordered_set_of_complexity_signature +[*Complexity:]] O(I(n)). +* [*Exception safety:] Strong. + +[#reference_unordered_set_of_insert_iterator_value] + + iterator insert(iterator position, const value_type & x); + +* [*Requires: ] `position` is a valid iterator of the view. +* [*Effects: ] `position` is used as a hint to improve the efficiency of the operation. +Inserts `x` into the `bimap` to which the view belongs if + * the view is non-unique OR no other element with equivalent key exists, + * AND insertion is allowed by all other views of the `bimap`. +* [*Returns:] On successful insertion, an iterator to the newly inserted element. +Otherwise, an iterator to an element that caused the insertion to be banned. +Note that more than one element can be causing insertion not to be allowed. +* [link unordered_set_of_complexity_signature [*Complexity:]] O(H(n)). +* [*Exception safety:] Strong. + +[#reference_unordered_set_of_insert_iterator_iterator] + + template< class InputIterator> + void insert(InputIterator first, InputIterator last); + +* [*Requires: ] `InputIterator` is a model of __SGI_INPUT_ITERATOR__ over elements of type +`value_type`. `first` and `last` are not iterators into any views of the +`bimap` to which this view belongs. `last` is reachable from first. +* [*Effects: ] +`iterator hint = end();` +`while(first != last) hint = insert(hint, *first++);` +* [link unordered_set_of_complexity_signature +[*Complexity:]] O(m*H(n+m)), where m is the number of elements in `[first, last)`. +* [*Exception safety:] Basic. + +[#reference_unordered_set_of_erase_iterator] + + iterator erase(iterator position); + +* [*Requires: ] `position` is a valid dereferenceable `iterator` of the view. +* [*Effects:] Deletes the element pointed to by `position`. +* [*Returns:] An `iterator` pointing to the element immediately following the one +that was deleted, or `end()` if no such element exists. +* [link unordered_set_of_complexity_signature +[*Complexity:]] O(D(n)). +* [*Exception safety:] nothrow. + + +[#reference_unordered_set_of_erase_key] + + template< class CompatibleKey > + size_type erase(const CompatibleKey & x); + +* [*Effects:] Deletes the elements with key equivalent to `x`. +* [*Returns:] Number of elements deleted. +* [link unordered_set_of_complexity_signature +[*Complexity:]] Average case, O(1 + m*D(n)), worst case O(n + m*D(n)), +where m is the number of elements deleted. +* [*Exception safety:] Basic. + + +[#reference_unordered_set_of_erase_iterator_iterator] + + iterator erase(iterator first, iterator last); + +* [*Requires: ] `[first,last)` is a valid range of the view. +* [*Effects:] Deletes the elements in `[first,last)`. +* [*Returns: ] `last`. +* [link unordered_set_of_complexity_signature +[*Complexity:]] O(m*D(n)), where m is the number of elements in `[first,last)`. +* [*Exception safety:] nothrow. + + +[#reference_unordered_set_of_replace_iterator_value] + + bool replace(iterator position, const value_type & x); + +* [*Requires: ] `position` is a valid dereferenceable `iterator` of the view. +* [*Effects:] Assigns the value `x` to the element pointed to by `position` into +the `bimap` to which the view belongs if, for the value `x` + * the view is non-unique OR no other element with equivalent key exists +(except possibly `*position`), + * AND replacing is allowed by all other views of the `bimap`. +* [*Postconditions:] Validity of position is preserved in all cases. +* [*Returns: ] `true` if the replacement took place, `false` otherwise. +* [link unordered_set_of_complexity_signature +[*Complexity:]] O(R(n)). +* [*Exception safety:] Strong. If an exception is thrown by some user-provided +operation the `bimap` to which the view belongs remains in its original state. + + +[#reference_unordered_set_of_replace_key_iterator_key] + + template< class CompatibleKey > + bool replace_key(iterator position, const CompatibleKey & x); + +* [*Requires: ] `position` is a valid dereferenceable iterator of the set view. +`CompatibleKey` can be assigned to `key_type`. +* [*Effects:] Assigns the value `x` to `e.first`, where `e` is the element pointed +to by `position` into the `bimap` to which the set view belongs if, + * the map view is non-unique OR no other element with equivalent key exists +(except possibly `*position`), + * AND replacing is allowed by all other views of the `bimap`. +* [*Postconditions:] Validity of position is preserved in all cases. +* [*Returns: ] `true` if the replacement took place, `false` otherwise. +* [link unordered_set_of_complexity_signature +[*Complexity:]] O(R(n)). +* [*Exception safety:] Strong. If an exception is thrown by some user-provided +operation, the `bimap` to which the set view belongs remains in +its original state. + + +[#reference_unordered_set_of_replace_data_iterator_data] + + template< class CompatibleData > + bool replace_data(iterator position, const CompatibleData & x); + +* [*Requires: ] `position` is a valid dereferenceable iterator of the set view. +`CompatibleKey` can be assigned to `data_type`. +* [*Effects:] Assigns the value `x` to `e.second`, where `e` is the element pointed +to by `position` into the `bimap` to which the set view belongs if, + * the map view is non-unique OR no other element with equivalent key exists +(except possibly `*position`), + * AND replacing is allowed by all other views of the `bimap`. +* [*Postconditions:] Validity of position is preserved in all cases. +* [*Returns: ] `true` if the replacement took place, `false` otherwise. +* [link unordered_set_of_complexity_signature +[*Complexity:]] O(R(n)). +* [*Exception safety:] Strong. If an exception is thrown by some user-provided +operation, the `bimap` to which the set view belongs remains in +its original state. + + +[#reference_unordered_set_of_modify_key_iterator_modifier] + + template< class KeyModifier > + bool modify_key(iterator position, KeyModifier mod); + +* [*Requires: ] `KeyModifier` is a model of __SGI_UNARY_FUNCTION__ accepting arguments of +type: `key_type&`; `position` is a valid dereferenceable iterator of the view. +* [*Effects:] Calls `mod(e.first)` where e is the element pointed to by position and +rearranges `*position` into all the views of the `bimap`. +If the rearrangement fails, the element is erased. +Rearrangement is successful if + * the map view is non-unique OR no other element with equivalent key exists, + * AND rearrangement is allowed by all other views of the `bimap`. +* [*Postconditions:] Validity of `position` is preserved if the operation succeeds. +* [*Returns: ] `true` if the operation succeeded, `false` otherwise. +* [link unordered_set_of_complexity_signature +[*Complexity:]] O(M(n)). +* [*Exception safety:] Basic. If an exception is thrown by some user-provided +operation (except possibly mod), then the element pointed to by position is erased. +* [*Note:] Only provided for map views. + + +[#reference_unordered_set_of_modify_data_iterator_modifier] + + template< class DataModifier > + bool modify_data(iterator position, DataModifier mod); + +* [*Requires: ] `DataModifier` is a model of __SGI_UNARY_FUNCTION__ accepting arguments of +type: `data_type&`; `position` is a valid dereferenceable iterator of the view. +* [*Effects:] Calls `mod(e.second)` where e is the element pointed to by position and +rearranges `*position` into all the views of the `bimap`. +If the rearrangement fails, the element is erased. +Rearrangement is successful if + * the oppositte map view is non-unique OR no other element with equivalent key in that +view exists, + * AND rearrangement is allowed by all other views of the `bimap`. +* [*Postconditions:] Validity of `position` is preserved if the operation succeeds. +* [*Returns: ] `true` if the operation succeeded, `false` otherwise. +* [link unordered_set_of_complexity_signature +[*Complexity:]] O(M(n)). +* [*Exception safety:] Basic. If an exception is thrown by some user-provided +operation (except possibly mod), then the element pointed to by position is erased. +* [*Note:] Only provided for map views. + +[/ +[#reference_unordered_set_of_modify_iterator_modifier] + + template< class Modifier> + bool modify(iterator position, Modifier mod); + +* [*Requires: ] `Modifier` is a model of __SGI_BINARY_FUNCTION__ accepting arguments of +type: `first_type&` and `second_type&` for ['Map View] or `left_type&` and `right_type&` +for ['Set View]; `position` is a valid dereferenceable iterator of the view. +* [*Effects:] Calls `mod(e.first,e.second)` for ['Map View:] or calls `mod(e.left,e.right)` +for ['Set View] where `e` is the element pointed to by `position` and +rearranges `*position` into all the views of the `bimap`. +If the rearrangement fails, the element is erased. +Rearrangement is successful if + * the view is non-unique OR no other element with equivalent key exists, + * AND rearrangement is allowed by all other views of the `bimap`. +* [*Postconditions:] Validity of position is preserved if the operation succeeds. +* [*Returns: ] `true` if the operation succeeded, `false` otherwise. +* [link unordered_set_of_complexity_signature +[*Complexity:]] O(M(n)). +* [*Exception safety:] Basic. If an exception is thrown by some user-provided +operation (except possibly `mod`), then the element pointed to by `position` is erased. +/] + +[endsect] + +[section Lookup] + +`unordered_[multi]set_of` views provide the full lookup functionality required by unordered +associative containers, namely `find`, `count`, and `equal_range`. Additionally, +these member functions are templatized to allow for non-standard arguments, +so extending the types of search operations allowed. The kind of arguments +permissible when invoking the lookup member functions is defined by the +following concept. + +[/ +Consider a pair `(Hash, Pred)` where `Hash` is a hash functor over values of type +`Key` and `Pred` is a __SGI_BINARY_PREDICATE__ inducing an equivalence relation on `Key`, +with the additional constraint that equivalent keys have the same hash value. +A triplet of types `(CompatibleKey, CompatibleHash, CompatiblePred)` is said to +be a ['compatible extension] of `(Hash, Pred)` if + +* `CompatibleHash` is a hash functor on values of type `CompatibleKey`, +* `CompatiblePred` is a __SGI_BINARY_PREDICATE__ over `(Key, CompatibleKey)`, +* `CompatiblePred` is a __SGI_BINARY_PREDICATE__ over `(CompatibleKey, Key)`, +* if `c_eq(ck,k1)` then `c_eq(k1,ck)`, +* if `c_eq(ck,k1)` and `eq(k1,k2)` then `c_eq(ck,k2)`, +* if `c_eq(ck,k1)` and `c_eq(ck,k2)` then `eq(k1,k2)`, +* if `c_eq(ck,k1)` then `c_hash(ck)==hash(k1)`, + +for every `c_hash` of type `CompatibleHash`, `c_eq` of type `CompatiblePred`, hash of +type `Hash`, `eq` of type `Pred`, `ck` of type `CompatibleKey` and `k1`, `k2` of type `Key`. +] + +A type `CompatibleKey` is said to be a ['compatible key] of `(Hash, Pred)` +if `(CompatibleKey, Hash, Pred)` is a compatible extension of `(Hash, Pred)`. This +implies that `Hash` and `Pred` accept arguments of type `CompatibleKey`, which usually +means they have several overloads of their corresponding `operator()` member +functions. + +[/ +In the context of a compatible extension or a compatible key, the expression +"equivalent key" takes on its obvious interpretation. +] + +[#reference_unordered_set_of_find_key] + + template< class CompatibleKey > + iterator find(const CompatibleKey & x); + + template< class CompatibleKey > + const_iterator find(const CompatibleKey & x) const; + +* [*Effects:] Returns a pointer to an element whose key is equivalent to `x`, +or `end()` if such an element does not exist. +* [*Complexity:] Average case O(1) (constant), worst case O(n). + + +[#reference_unordered_set_of_count_key] + + template< class CompatibleKey > + size_type count(const CompatibleKey & x) const; + +* [*Effects:] Returns the number of elements with key equivalent to `x`. +* [*Complexity:] Average case O(count(x)), worst case O(n). + + +[#reference_unordered_set_of_equal_range_key] + + template< class CompatibleKey > + std::pair + equal_range(const CompatibleKey & x); + + template< class CompatibleKey > + std::pair + equal_range(const CompatibleKey & x) const; + +* [*Effects:] Returns a range containing all elements with keys equivalent +to `x` (and only those). +* [*Complexity:] Average case O(count(x)), worst case O(n). + + + +[endsect] + +[section at(), info_at() and operator\[\] - set_of only] + + +[#reference_unordered_set_of_at_key_const] + + template< class CompatibleKey > + const data_type & at(const CompatibleKey & k) const; + +* [*Requires: ] `CompatibleKey` is a compatible key of `key_compare`. +* [*Effects:] Returns the `data_type` reference that is associated with `k`, or +throws `std::out_of_range` if such key does not exist. +* [*Complexity:] Average case O(1) (constant), worst case O(n). +* [*Note:] Only provided when `unordered_set_of` is used. + +The symmetry of bimap imposes some constraints on `operator[]` and the +non constant version of at() that are not found in `std::maps`. +Tey are only provided if the other collection type is mutable +(`list_of`, `vector_of` and `unconstrained_set_of`). + + +[#reference_unordered_set_of_operator_bracket_key] + + template< class CompatibleKey > + data_type & operator[](const CompatibleKey & k); + +* [*Requires: ] `CompatibleKey` is a compatible key of `key_compare`. +* [*Effects: ] `return insert(value_type(k,data_type()))->second;` +* [*Complexity:] If the insertion is performed O(I(n)), else: Average case +O(1) (constant), worst case O(n). +* [*Note:] Only provided when `unordered_set_of` is used and the other collection +type is mutable. + + +[#reference_unordered_set_of_at_key] + + template< class CompatibleKey > + data_type & at(const CompatibleKey & k); + +* [*Requires: ] `CompatibleKey` is a compatible key of `key_compare`. +* [*Effects: ] Returns the `data_type` reference that is associated with `k`, or +throws `std::out_of_range` if such key does not exist. +* [*Complexity:] Average case O(1) (constant), worst case O(n). +* [*Note:] Only provided when `unordered_set_of` is used and the other collection +type is mutable. + +[/ + +The symmetry of bimap imposes some constraints to the `operator[]` that are not +found in `std::maps`. +If other views are unique, `bimap::duplicate_value` is thrown whenever an assignment is +attempted to a value that is already a key in this views. +As for bimap::value_not_found, this exception is thrown while trying to access +a non-existent key: this behavior differs from that of std::map, which automatically +assigns a default value to non-existent keys referred to by `operator[]`. + + const data_type & operator[](const typename key_type & k) const; + +* [*Effects:] Returns the `data_type` reference that is associated with `k`, or +throws `bimap::value_not_found` if such an element does not exist. +* [*Complexity:] O(log(n)). + + + ``['-unspecified data_type proxy-]`` operator[](const typename key_type & k); + +* [*Effects:] Returns a proxy to a `data_type` associated with `k` and the +bimap. The proxy behaves as a reference to the `data_type` object. If this +proxy is read and `k` was not in the bimap, the bimap::value_not_found is +thrown. If it is written then `bimap::duplicate_value` is thrown if the +assignment is not allowed by one of the other views of the `bimap`. +* [link unordered_set_of_complexity_signature +[*Complexity:]] If the assignment operator of the proxy is not used, then +the order is O(log(n)). If it is used, the order is O(I(n)) if `k` was not +in the bimap and O(R(n)) if it existed in the bimap. + +] + +[#reference_unordered_set_of_info_at_key] + + template< class CompatibleKey > + info_type & info_at(const CompatibleKey & k); + + template< class CompatibleKey > + const info_type & info_at(const CompatibleKey & k) const; + +* [*Requires: ] `CompatibleKey` is a compatible key of `key_compare`. +* [*Effects:] Returns the `info_type` reference that is associated with `k`, or +throws `std::out_of_range` if such key does not exist. +* [*Complexity:] Average case O(1) (constant), worst case O(n). +* [*Note:] Only provided when `unordered_set_of` and `info_hook` are used + + +[endsect] + +[section Hash policy] + + +[#reference_unordered_set_of_rehash_size] + + void rehash(size_type n); + +* [*Effects:] Increases if necessary the number of internal buckets so that +`size()/bucket_count()` does not exceed the maximum load factor, and +`bucket_count()>=n`. +* [*Postconditions:] Validity of iterators and references to the elements +contained is preserved. +* [*Complexity:] Average case O(size()), worst case O(size(n)2). +* [*Exception safety:] Strong. + + +[endsect] + +[section Serialization] + +Views cannot be serialized on their own, but only as part of the +`bimap` into which they are embedded. In describing the +additional preconditions and guarantees associated to `unordered_[multi]set_of` views +with respect to serialization of their embedding containers, we use +the concepts defined in the `bimap` serialization section. + +[blurb [*Operation:] saving of a `bimap` b to an output archive +(XML archive) ar.] + +* [*Requires:] No additional requirements to those imposed by the container. + + +[blurb [*Operation:] loading of a `bimap` b' from an input +archive (XML archive) ar.] + +* [*Requires:] Additionally to the general requirements, `key_eq()` must +be serialization-compatible with `m.get().key_eq()`, where i is the +position of the `unordered_[multi]set_of` view in the container. +* [*Postconditions:] On successful loading, the range `[begin(), end())` +contains restored copies of every element in +`[m.get().begin(), m.get().end())`, though not necessarily in +the same order. + + +[blurb [*Operation:] saving of an `iterator` or `const_iterator` `it` to an output +archive (XML archive) ar.] + +* [*Requires: ] `it` is a valid `iterator` of the view. The associated +`bimap` has been previously saved. + + +[blurb [*Operation:] loading of an iterator or `const_iterator it`' from an +input archive (XML archive) ar.] + +* [*Postconditions:] On successful loading, if `it` was dereferenceable then +`*it`' is the restored copy of `*it`, otherwise `it`'` == end()`. +* [*Note:] It is allowed that `it` be a `const_iterator` and the restored +`it`' an `iterator`, or viceversa. + + +[blurb [*Operation:] saving of a local_iterator or const_local_iterator it +to an output archive (XML archive) ar.] + +* [*Requires: ] `it` is a valid local iterator of the view. The associated +`bimap` has been previously saved. + + +[blurb [*Operation:] loading of a `local_iterator` or `const_local_iterator` +`it`' from an input archive (XML archive) ar.] + +* [*Postconditions:] On successful loading, if `it` was dereferenceable then +`*it`' is the restored copy of `*it`; if `it` was `m.get().end(n)` for some n, +then `it`'` == m`'`.get().end(n)` (where `b` is the original `bimap`, +`b`' its restored copy and `i` is the ordinal of the index.) +* [*Note:] It is allowed that `it` be a `const_local_iterator` and the restored +`it`' a `local_iterator`, or viceversa. + + +[endsect] +[endsect] + +[endsect] \ No newline at end of file diff --git a/doc/reference/vector_of.qbk b/doc/reference/vector_of.qbk new file mode 100755 index 0000000..882302e --- /dev/null +++ b/doc/reference/vector_of.qbk @@ -0,0 +1,843 @@ +[/license + +Boost.Bimap + +Copyright (c) 2006-2007 Matias Capeletto + +Distributed under the Boost Software License, Version 1.0. +(See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt) + +] + +[/ QuickBook Document version 1.4 ] + +[section vector_of Reference] + +[section Header "boost/bimap/vector_of.hpp" synopsis] + + namespace boost { + namespace bimaps { + + + template< class KeyType > + struct vector_of; + + struct vector_of_relation; + + + } // namespace bimap + } // namespace boost + + +[endsect] + +[section vector_of views] + +vector_of views are free-order sequences with constant time positional +access and random access iterators. Elements in a vector_of view are by +default sorted according to their order of insertion: this means that new elements +inserted through a different view of the `bimap` are appended to +the end of the vector_of view; additionally, facilities are provided for +further rearrangement of the elements. The public interface of vector_of views +includes that of list_of views, with differences in the complexity +of the operations, plus extra operations for positional access +(`operator[]` and `at()`) and for capacity handling. Validity of iterators and +references to elements is preserved in all operations, regardless of the +capacity status. + +As is the case with list_of views, vector_of views have the following +limitations with respect to STL sequence containers: + +* vector_of views +are not __SGI_ASSIGNABLE__ (like any other view.) +* Insertions into a vector_of view may fail due to clashings with other views. +This alters the semantics of the operations provided with respect to their analogues +in STL sequence containers. +* Elements in a vector_of view are not mutable, and can only be changed by +means of replace and modify member functions. + +Having these restrictions into account, vector of views are models of +__SGI_RANDOM_ACCESS_CONTAINER__ and __SGI_BACK_INSERTION_SEQUENCE__. Although these views +do not model __SGI_FRONT_INSERTION_SEQUENCE__, because front insertion and deletion +take linear time, front operations are nonetheless provided to match the interface +of list_of views. We only describe those types and operations that are either +not present in the concepts modeled or do not exactly conform to the requirements +for these types of containers. + + + namespace boost { + namespace bimaps { + namespace views { + + template< ``['-implementation defined parameter list-]`` > + class ``['-implementation defined view name-]`` + { + public: + + // types + + typedef ``['-unspecified-]`` value_type; + typedef ``['-unspecified-]`` allocator_type; + typedef ``['-unspecified-]`` reference; + typedef ``['-unspecified-]`` const_reference; + typedef ``['-unspecified-]`` iterator; + typedef ``['-unspecified-]`` const_iterator; + typedef ``['-unspecified-]`` size_type; + typedef ``['-unspecified-]`` difference_type; + typedef ``['-unspecified-]`` pointer; + typedef ``['-unspecified-]`` const_pointer; + typedef ``['-unspecified-]`` reverse_iterator; + typedef ``['-unspecified-]`` const_reverse_iterator; + + typedef ``['-unspecified-]`` info_type; + + // construct / copy / destroy + + this_type & operator=(this_type & x); + + template< class InputIterator > + void ``[link reference_vector_of_assign_iterator_iterator assign]``(InputIterator first, InputIterator last); + + void ``[link reference_vector_of_assign_size_value assign]``(size_type n, const value_type & value); + + allocator_type get_allocator() const; + + // iterators + + iterator begin(); + const_iterator begin() const; + + iterator end(); + const_iterator end() const; + + reverse_iterator rbegin(); + const_reverse_iterator rbegin() const; + + reverse_iterator rend(); + const_reverse_iterator rend() const; + + // capacity + + bool empty() const; + + size_type size() const; + + size_type max_size() const; + + size_type ``[link reference_vector_of_capacity capacity]``() const; + + void ``[link reference_vector_of_reserve_size reserve]``(size_type m); + + void ``[link reference_vector_of_resize_size_value resize]``(size_type n, const value_type & x = value_type()); + + // access + + const_reference operator[](size_type n) const; + + const_reference at(size_type n) const; + + const_reference front() const; + + const_reference back() const; + + // modifiers + + std::pair ``[link reference_vector_of_push_front_value push_front]``(const value_type & x); + void pop_front(); + + std::pair ``[link reference_vector_of_push_back_value push_back]``(const value_type & x); + void pop_back(); + + std::pair ``[link reference_vector_of_insert_iterator_value insert]``(iterator position, const value_type & x); + + void ``[link reference_vector_of_insert_iterator_size_value insert]``(iterator position, size_type m, const value_type & x); + + template< class InputIterator> + void ``[link reference_vector_of_insert_iterator_iterator_iterator insert]``(iterator position, InputIterator first, InputIterator last); + + iterator ``[link reference_vector_of_erase_iterator erase]``(iterator position); + iterator ``[link reference_vector_of_erase_iterator_iterator erase]``(iterator first, iterator last); + + bool ``[link reference_vector_of_replace_iterator_value replace]``(iterator position, const value_type & x); + + // Only in map views + // { + + template< class CompatibleKey > + bool ``[link reference_vector_of_replace_key_iterator_key replace_key]``(iterator position, const CompatibleKey & x); + + template< class CompatibleData > + bool ``[link reference_vector_of_replace_data_iterator_data replace_data]``(iterator position, const CompatibleData & x); + + template< class KeyModifier > + bool ``[link reference_vector_of_modify_key_iterator_modifier modify_key]``(iterator position, KeyModifier mod); + + template< class DataModifier > + bool ``[link reference_vector_of_modify_data_iterator_modifier modify_data]``(iterator position, DataModifier mod); + + // } + + + void clear(); + + // list operations + + void ``[link reference_vector_of_splice_iterator_this splice]``(iterator position, this_type & x); + void ``[link reference_vector_of_splice_iterator_this_iterator splice]``(iterator position, this_type & x, iterator i); + void ``[link reference_vector_of_splice_iterator_this_iterator_iterator splice]``( + iterator position, this_type & x, iterator first, iterator last); + + void ``[link reference_vector_of_remove_value remove]``(const value_type & value); + + template< class Predicate > + void ``[link reference_vector_of_remove_if_predicate remove_if]``(Predicate pred); + + void ``[link reference_vector_of_unique unique]``(); + + template< class BinaryPredicate > + void ``[link reference_vector_of_unique_predicate unique]``(BinaryPredicate binary_pred); + + void ``[link reference_vector_of_merge_this merge]``(this_type & x); + + template< typename Compare > + void ``[link reference_vector_of_merge_this_compare merge]``(this_type & x, Compare comp); + + void ``[link reference_vector_of_sort sort]``(); + + template< typename Compare > + void ``[link reference_vector_of_sort_compare sort]``(Compare comp); + + void ``[link reference_vector_of_reverse reverse]``(); + + // rearrange operations + + void ``[link reference_vector_of_relocate_iterator_iterator relocate]``(iterator position, iterator i); + void ``[link reference_vector_of_relocate_iterator_iterator_iterator relocate]``(iterator position, iterator first, iterator last); + }; + + // view comparison + + bool operator==(const this_type & v1, const this_type & v2 ); + bool operator< (const this_type & v1, const this_type & v2 ); + bool operator!=(const this_type & v1, const this_type & v2 ); + bool operator> (const this_type & v1, const this_type & v2 ); + bool operator>=(const this_type & v1, const this_type & v2 ); + bool operator<=(const this_type & v1, const this_type & v2 ); + + } // namespace views + } // namespace bimap + } // namespace boost + + + +In the case of a `bimap< vector_of, ... >` + +In the set view: + + typedef signature-compatible with relation< Left, ... > key_type; + typedef signature-compatible with relation< Left, ... > value_type; + +In the left map view: + + typedef Left key_type; + typedef ... data_type; + + typedef signature-compatible with std::pair< Left, ... > value_type; + +In the right map view: + + typedef ... key_type; + typedef Left data_type; + + typedef signature-compatible with std::pair< ... , Left > value_type; + + +[#vector_of_complexity_signature] + +[section Complexity signature] + +Here and in the descriptions of operations of `vector_of` views, we adopt +the scheme outlined in the +[link complexity_signature_explanation complexity signature section]. +The complexity signature of `vector_of` view is: + +* copying: `c(n) = n * log(n)`, +* insertion: `i(n) = 1` (amortized constant), +* hinted insertion: `h(n) = 1` (amortized constant), +* deletion: `d(n) = m`, where m is the distance from the deleted element to the +end of the sequence, +* replacement: `r(n) = 1` (constant), +* modifying: `m(n) = 1` (constant). + +The following expressions are also used as a convenience for writing down some +of the complexity formulas: + +[blurb +`shl(a,b) = a+b` if a is nonzero, 0 otherwise. +`rel(a,b,c) =` if `a + void assign(InputIterator first, InputIterator last); + +* [*Requires: ] `InputIterator` is a model of __SGI_INPUT_ITERATOR__ over elements +of type `value_type` or a type convertible to `value_type`. `first` and `last` are +not iterators into any view of the `bimap` to which this +view belongs. `last` is reachable from `first`. +* [*Effects: ] `clear(); insert(end(),first,last);` + + +[#reference_vector_of_assign_size_value] + + void assign(size_type n, const value_type & value); + +* [*Effects: ] `clear(); for(size_type i = 0; i < n; ++n) push_back(v);` + +[endsect] + +[section Capacity operations] + +[#reference_vector_of_capacity] + + size_type capacity() const; + +* [*Returns:] The total number of elements `c` such that, when `size() < c`, +back insertions happen in constant time (the general case as described by +i(n) is ['amortized] constant time.) +* [*Note:] Validity of iterators and references to elements is preserved +in all insertions, regardless of the capacity status. + + +[#reference_vector_of_reserve_size] + + void reserve(size_type m); + +* [*Effects:] If the previous value of `capacity()` was greater than or equal +to `m`, nothing is done; otherwise, the internal capacity is changed so that +`capacity()>=m`. +* [*Complexity:] If the capacity is not changed, constant; otherwise O(n). +* [*Exception safety:] If the capacity is not changed, nothrow; otherwise, strong. + + +[#reference_vector_of_resize_size_value] + + void resize(size_type n, const value_type & x = value_type()); + +* [*Effects: ] `if( n > size() ) insert(end(), n-size(), x);` +`else if( n push_front(const value_type & x); + +* [*Effects:] Inserts x at the beginning of the sequence if no other view +of the `bimap` bans the insertion. +* [*Returns:] The return value is a pair `p`. `p.second` is `true` if and only if +insertion took place. On successful insertion, `p.first` points to the element +inserted; otherwise, `p.first` points to an element that caused the insertion +to be banned. Note that more than one element can be causing insertion not +to be allowed. +* [link vector_of_complexity_signature [*Complexity:]] O(n+I(n)). +* [*Exception safety:] Strong. + + +[#reference_vector_of_push_back_value] + + std::pair push_back(const value_type & x); + +* [*Effects:] Inserts `x` at the end of the sequence if no other view of +the `bimap` bans the insertion. +* [*Returns:] The return value is a pair `p`. `p.second` is `true` if and only +if insertion took place. On successful insertion, `p.first` points to the +element inserted; otherwise, `p.first` points to an element that caused +the insertion to be banned. Note that more than one element can be +causing insertion not to be allowed. +* [link vector_of_complexity_signature [*Complexity:]] O(I(n)). +* [*Exception safety:] Strong. + + +[#reference_vector_of_insert_iterator_value] + + std::pair insert(iterator position, const value_type & x); + +* [*Requires: ] `position` is a valid iterator of the view. +* [*Effects:] Inserts `x` before position if insertion is allowed by all +other views of the `bimap`. +* [*Returns:] The return value is a pair `p`. `p.second` is `true` if and only +if insertion took place. On successful insertion, `p.first` points to the +element inserted; otherwise, `p.first` points to an element that caused the +insertion to be banned. Note that more than one element can be causing +insertion not to be allowed. +* [link vector_of_complexity_signature [*Complexity:]] O(shl(end()-position,1) + I(n)). +* [*Exception safety:] Strong. + + +[#reference_vector_of_insert_iterator_size_value] + + void insert(iterator position, size_type m, const value_type & x); + +* [*Requires: ] `position` is a valid iterator of the view. +* [*Effects: ] `for(size_type i = 0; i < m; ++i) insert(position, x);` +* [link vector_of_complexity_signature +[*Complexity:]] O(shl(end()-position,m) + m*I(n+m)). + + +[#reference_vector_of_insert_iterator_iterator_iterator] + + template< class InputIterator > + void insert(iterator position, InputIterator first, InputIterator last); + +* [*Requires: ] `position` is a valid iterator of the view. `InputIterator` +is a model of __SGI_INPUT_ITERATOR__ over elements of type `value_type` or a type +convertible to `value_type`. `first` and `last` are not iterators into any view +of the `bimap` to which this view belongs. `last` is reachable +from `first`. +* [*Effects: ] `while(first!=last)insert(position,*first++);` +* [link vector_of_complexity_signature +[*Complexity:]] O(shl(end()-position,m) + m*I(n+m)), where m is the number +of elements in `[first,last)`. +* [*Exception safety:] Basic. + + +[#reference_vector_of_erase_iterator] + + iterator erase(iterator position); + +* [*Requires: ] `position` is a valid dereferenceable iterator of the view. +* [*Effects:] Deletes the element pointed to by `position`. +* [*Returns:] An iterator pointing to the element immediately following the +one that was deleted, or `end()` if no such element exists. +* [link vector_of_complexity_signature [*Complexity:]] O(D(n)). +* [*Exception safety:] nothrow. + + +[#reference_vector_of_erase_iterator_iterator] + + iterator erase(iterator first, iterator last); + +* [*Requires: ] `[first,last)` is a valid range of the view. +* [*Effects:] Deletes the elements in `[first,last)`. +* [*Returns:] last. +* [link vector_of_complexity_signature +[*Complexity:]] O(m*D(n)), where m is the number of elements in `[first,last)`. +* [*Exception safety:] nothrow. + + +[#reference_vector_of_replace_iterator_value] + + bool replace(iterator position, const value_type & x); + +* [*Requires: ] `position` is a valid dereferenceable iterator of the view. +* [*Effects:] Assigns the value x to the element pointed to by position into +the `bimap` to which the view belongs if replacing is allowed +by all other views of the `bimap`. +* [*Postconditions:] Validity of position is preserved in all cases. +* [*Returns: ] `true` if the replacement took place, `false` otherwise. +* [link vector_of_complexity_signature +[*Complexity:]] O(R(n)). +* [*Exception safety:] Strong. If an exception is thrown by some user-provided +operation the `bimap` to which the view belongs remains in its +original state. + + + +[#reference_vector_of_replace_key_iterator_key] + + template< class CompatibleKey > + bool replace_key(iterator position, const CompatibleKey & x); + +* [*Requires: ] `position` is a valid dereferenceable iterator of the set view. +`CompatibleKey` can be assigned to `key_type`. +* [*Effects:] Assigns the value `x` to `e.first`, where `e` is the element pointed +to by `position` into the `bimap` to which the set view belongs if replacing is allowed by +all other views of the `bimap`. +* [*Postconditions:] Validity of position is preserved in all cases. +* [*Returns: ] `true` if the replacement took place, `false` otherwise. +* [link vector_of_complexity_signature +[*Complexity:]] O(R(n)). +* [*Exception safety:] Strong. If an exception is thrown by some user-provided +operation, the `bimap` to which the set view belongs remains in +its original state. + + +[#reference_vector_of_replace_data_iterator_data] + + template< class CompatibleData > + bool replace_data(iterator position, const CompatibleData & x); + +* [*Requires: ] `position` is a valid dereferenceable iterator of the set view. +`CompatibleKey` can be assigned to `data_type`. +* [*Effects:] Assigns the value `x` to `e.second`, where `e` is the element pointed +to by `position` into the `bimap` to which the set view belongs if replacing is allowed by +all other views of the `bimap`. +* [*Postconditions:] Validity of position is preserved in all cases. +* [*Returns: ] `true` if the replacement took place, `false` otherwise. +* [link vector_of_complexity_signature +[*Complexity:]] O(R(n)). +* [*Exception safety:] Strong. If an exception is thrown by some user-provided +operation, the `bimap` to which the set view belongs remains in +its original state. + + +[#reference_vector_of_modify_key_iterator_modifier] + + template< class KeyModifier > + bool modify_key(iterator position, KeyModifier mod); + +* [*Requires: ] `KeyModifier` is a model of __SGI_UNARY_FUNCTION__ accepting arguments of +type: `key_type&`; `position` is a valid dereferenceable iterator of the view. +* [*Effects:] Calls `mod(e.first)` where e is the element pointed to by position and +rearranges `*position` into all the views of the `bimap`. +If the rearrangement fails, the element is erased. +It is successful if the rearrangement is allowed by all other views of the `bimap`. +* [*Postconditions:] Validity of `position` is preserved if the operation succeeds. +* [*Returns: ] `true` if the operation succeeded, `false` otherwise. +* [link vector_of_complexity_signature +[*Complexity:]] O(M(n)). +* [*Exception safety:] Basic. If an exception is thrown by some user-provided +operation (except possibly mod), then the element pointed to by position is erased. +* [*Note:] Only provided for map views. + + +[#reference_vector_of_modify_data_iterator_modifier] + + template< class DataModifier > + bool modify_data(iterator position, DataModifier mod); + +* [*Requires: ] `DataModifier` is a model of __SGI_UNARY_FUNCTION__ accepting arguments of +type: `data_type&`; `position` is a valid dereferenceable iterator of the view. +* [*Effects:] Calls `mod(e.second)` where e is the element pointed to by position and +rearranges `*position` into all the views of the `bimap`. +If the rearrangement fails, the element is erased. +It is successful if the rearrangement is allowed by all other views of the `bimap`. +* [*Postconditions:] Validity of `position` is preserved if the operation succeeds. +* [*Returns: ] `true` if the operation succeeded, `false` otherwise. +* [link vector_of_complexity_signature +[*Complexity:]] O(M(n)). +* [*Exception safety:] Basic. If an exception is thrown by some user-provided +operation (except possibly mod), then the element pointed to by position is erased. +* [*Note:] Only provided for map views. + +[/ +[#reference_vector_of_modify_iterator_modifier] + + template< class Modifier > + bool modify(iterator position, Modifier mod); + +* [*Requires: ] `Modifier` is a model of __SGI_BINARY_FUNCTION__ accepting arguments of +type: `first_type&` and `second_type&` for ['Map View] or `left_type&` and `right_type&` +for ['Set View]; `position` is a valid dereferenceable iterator of the view. +* [*Effects:] Calls `mod(e.first,e.second)` for ['Map View:] or calls `mod(e.left,e.right)` +for ['Set View] where e is the element pointed to by `position` and +rearranges `*position` into all the views of the `bimap`. +Rearrangement on `vector_of` views does not change the position of the +element with respect to the view; rearrangement on other views may or +might not suceed. If the rearrangement fails, the element is erased. +* [*Postconditions:] Validity of `position` is preserved if the operation succeeds. +* [*Returns: ] `true` if the operation succeeded, `false` otherwise. +* [link vector_of_complexity_signature [*Complexity:]] O(M(n)). +* [*Exception safety:] Basic. If an exception is thrown by some user-provided +operation (except possibly `mod`), then the element pointed to by position +is erased. +] + + +[endsect] + +[section List operations] + +`vector_of` views replicate the interface of `list_of` views, which +in turn includes the list operations provided by `std::list`. The syntax and +behavior of these operations exactly matches those of `list_of` views, but +the associated complexity bounds differ in general. + + +[#reference_vector_of_splice_iterator_this] + + void splice(iterator position, this_type & x); + +* [*Requires: ] `position` is a valid iterator of the view. `&x!=this`. +* [*Effects:] Inserts the contents of `x` before position, in the same order +as they were in `x`. Those elements successfully inserted are erased from `x`. +* [link vector_of_complexity_signature +[*Complexity:]] O(shl(end()-position,x.size()) + x.size()*I(n+x.size()) + x.size()*D(x.size())). +* [*Exception safety:] Basic. + + +[#reference_vector_of_splice_iterator_this_iterator] + + void splice(iterator position, this_type & x,iterator i); + +* [*Requires: ] `position` is a valid iterator of the view. `i` is a valid +dereferenceable iterator `x`. +* [*Effects:] Inserts the element pointed to by `i` before `position`: if +insertion is successful, the element is erased from `x`. In the special +case `&x==this`, no copy or deletion is performed, and the operation is +always successful. If `position==i`, no operation is performed. +* [*Postconditions:] If `&x==this`, no iterator or reference is invalidated. +* [link vector_of_complexity_signature +[*Complexity:]] If `&x==this`, O(rel(position,i,i+1)); +otherwise O(shl(end()-position,1) + I(n) + D(n)). +* [*Exception safety:] If `&x==this`, nothrow; otherwise, strong. + + +[#reference_vector_of_splice_iterator_this_iterator_iterator] + + void splice(iterator position, this_type & x, iterator first, iterator last); + +* [*Requires: ] `position` is a valid iterator of the view. `first` and +`last` are valid iterators of `x`. `last` is reachable from `first`. `position` is +not in the range `[first,last)`. +* [*Effects:] For each element in the range `[first,last)`, insertion is +tried before `position`; if the operation is successful, the element is +erased from `x`. In the special case `&x==this`, no copy or deletion is +performed, and insertions are always successful. +* [*Postconditions:] If `&x==this`, no iterator or reference is invalidated. +* [link vector_of_complexity_signature +[*Complexity:]] If `&x==this`, O(rel(position,first,last)); +otherwise O(shl(end()-position,m) + m*I(n+m) + m*D(x.size())) +where m is the number of elements in `[first,last)`. +* [*Exception safety:] If `&x==this`, nothrow; otherwise, basic. + + +[#reference_vector_of_remove_value] + + void remove(const value_type & value); + +* [*Effects:] Erases all elements of the view which compare equal to `value`. +* [link vector_of_complexity_signature +[*Complexity:]] O(n + m*D(n)), where m is the number of elements erased. +* [*Exception safety:] Basic. + + +[#reference_vector_of_remove_if_predicate] + + template< class Predicate > + void remove_if(Predicate pred); + +* [*Effects:] Erases all elements `x` of the view for which `pred(x)` holds. +* [link vector_of_complexity_signature +[*Complexity:]] O(n + m*D(n)), where m is the number of elements erased. +* [*Exception safety:] Basic. + + +[#reference_vector_of_unique] + + void unique(); + +* [*Effects:] Eliminates all but the first element from every consecutive +group of equal elements referred to by the iterator `i` in the range +`[first+1,last)` for which `*i==*(i-1)`. +* [link vector_of_complexity_signature +[*Complexity:]] O(n + m*D(n)), where m is the number of elements erased. +* [*Exception safety:] Basic. + + +[#reference_vector_of_unique_predicate] + + template< class BinaryPredicate > + void unique(BinaryPredicate binary_pred); + +* [*Effects:] Eliminates all but the first element from every consecutive +group of elements referred to by the iterator i in the range `[first+1,last)` +for which `binary_pred(*i, *(i-1))` holds. +* [link vector_of_complexity_signature +[*Complexity:]] O(n + m*D(n)), where m is the number of elements erased. +* [*Exception safety:] Basic. + + +[#reference_vector_of_merge_this] + + void merge(this_type & x); + +* [*Requires: ] `std::less` is a __SGI_STRICT_WEAK_ORDERING__ over +`value_type`. Both the view and `x` are sorted according to `std::less`. +* [*Effects:] Attempts to insert every element of x into the corresponding +position of the view (according to the order). Elements successfully +inserted are erased from `x`. The resulting sequence is stable, i.e. equivalent +elements of either container preserve their relative position. In the special +case `&x==this`, no operation is performed. +* [*Postconditions:] Elements in the view and remaining elements in `x` are +sorted. Validity of iterators to the view and of non-erased elements of `x` +references is preserved. +* [link vector_of_complexity_signature +[*Complexity:]] If `&x==this`, constant; +otherwise O(n + x.size()*I(n+x.size()) + x.size()*D(x.size())). +* [*Exception safety:] If `&x==this`, nothrow; otherwise, basic. + + +[#reference_vector_of_merge_this_compare] + + template< class Compare > + void merge(this_type & x, Compare comp); + +* [*Requires: ] `Compare` is a __SGI_STRICT_WEAK_ORDERING__ over `value_type`. +Both the view and `x` are sorted according to comp. +* [*Effects:] Attempts to insert every element of `x` into the corresponding +position of the view (according to `comp`). Elements successfully inserted +are erased from `x`. The resulting sequence is stable, i.e. equivalent +elements of either container preserve their relative position. In the +special case `&x==this`, no operation is performed. +* [*Postconditions:] Elements in the view and remaining elements in `x` are +sorted according to `comp`. Validity of iterators to the view and of +non-erased elements of `x` references is preserved. +* [link vector_of_complexity_signature +[*Complexity:]] If `&x==this`, constant; +otherwise O(n + x.size()*I(n+x.size()) + x.size()*D(x.size())). +* [*Exception safety:] If `&x==this`, nothrow; otherwise, basic. + + +[#reference_vector_of_sort] + + void sort(); + +* [*Requires: ] `std::less` is a __SGI_STRICT_WEAK_ORDERING__ over `value_type`. +* [*Effects:] Sorts the view according to `std::less`. +The sorting is stable, i.e. equivalent elements preserve their relative position. +* [*Postconditions:] Validity of iterators and references is preserved. +* [*Complexity:] O(n*log(n)). +* [*Exception safety:] Basic. + + +[#reference_vector_of_sort_compare] + + template< class Compare > + void sort(Compare comp); + +* [*Requires:] Compare is a __SGI_STRICT_WEAK_ORDERING__ over `value_type`. +* [*Effects:] Sorts the view according to `comp`. The sorting is stable, i.e. +equivalent elements preserve their relative position. +* [*Postconditions:] Validity of iterators and references is preserved. +* [*Complexity:] O(n*log(n)). +* [*Exception safety:] Basic. + + +[#reference_vector_of_reverse] + + void reverse(); + +* [*Effects:] Reverses the order of the elements in the view. +* [*Postconditions:] Validity of iterators and references is preserved. +* [*Complexity:] O(n). +* [*Exception safety:] nothrow. + + +[endsect] + +[section Rearrange operations] + +These operations, without counterpart in `std::list` (although splice provides +partially overlapping functionality), perform individual and global repositioning +of elements inside the index. + + +[#reference_vector_of_relocate_iterator_iterator] + + void relocate(iterator position, iterator i); + +* [*Requires: ] `position` is a valid iterator of the view. `i` is a valid +dereferenceable iterator of the view. +* [*Effects:] Inserts the element pointed to by `i` before `position`. +If `position==i`, no operation is performed. +* [*Postconditions:] No iterator or reference is invalidated. +* [*Complexity:] Constant. +* [*Exception safety:] nothrow. + + +[#reference_vector_of_relocate_iterator_iterator_iterator] + + void relocate(iterator position, iterator first, iterator last); + +* [*Requires: ] `position` is a valid iterator of the view. `first` and `last` are +valid iterators of the view. `last` is reachable from `first`. `position` is not +in the range `[first,last)`. +* [*Effects:] The range of elements `[first,last)` is repositioned just before +`position`. +* [*Postconditions:] No iterator or reference is invalidated. +* [*Complexity:] Constant. +* [*Exception safety:] nothrow. + + +[endsect] + + +[section Serialization] + +Views cannot be serialized on their own, but only as part of the `bimap` +into which they are embedded. In describing the additional preconditions and guarantees +associated to `vector_of` views with respect to serialization of their embedding +containers, we use the concepts defined in the `bimap` serialization section. + +[blurb [*Operation:] saving of a `bimap` b to an output archive (XML archive) ar.] + +* [*Requires:] No additional requirements to those imposed by the container. + + +[blurb [*Operation:] loading of a `bimap` b' from an input archive (XML archive) ar.] + +* [*Requires:] No additional requirements to those imposed by the container. +* [*Postconditions:] On successful loading, each of the elements of `[begin(), end())` is a +restored copy of the corresponding element in `[m.get().begin(), m.get().end())`, +where `i` is the position of the `vector_of` view in the container. + + + +[blurb [*Operation:] saving of an `iterator` or `const_iterator` `it` to an output archive (XML archive) ar.] + +* [*Requires: ] `it` is a valid iterator of the view. The associated `bimap` +has been previously saved. + + + +[blurb [*Operation:] loading of an `iterator` or `const_iterator` `it`' from an input archive (XML archive) ar.] + +* [*Postconditions:] On successful loading, if it was dereferenceable then `*it`' is the +restored copy of `*it`, otherwise `it`'`==end()`. +* [*Note:] It is allowed that it be a `const_iterator` and the restored `it`' an `iterator`, +or viceversa. + + +[endsect] +[endsect] + + +[endsect] \ No newline at end of file diff --git a/doc/release_notes.qbk b/doc/release_notes.qbk new file mode 100755 index 0000000..e093aa2 --- /dev/null +++ b/doc/release_notes.qbk @@ -0,0 +1,19 @@ +[/license + +Boost.Bimap + +Copyright (c) 2006-2007 Matias Capeletto + +Distributed under the Boost Software License, Version 1.0. +(See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt) + +] + +[/ QuickBook Document version 1.4 ] + +[section Release notes] + +Not yet released. + +[endsect] \ No newline at end of file diff --git a/doc/test_suite.qbk b/doc/test_suite.qbk new file mode 100755 index 0000000..c6213b8 --- /dev/null +++ b/doc/test_suite.qbk @@ -0,0 +1,147 @@ +[/license + +Boost.Bimap + +Copyright (c) 2006-2007 Matias Capeletto + +Distributed under the Boost Software License, Version 1.0. +(See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt) + +] + +[/ QuickBook Document version 1.4 ] + +[section Test suite] + +The Boost.Bimap test suite exercises the whole spectrum of functionalities provided by the library. +Although the tests are not meant to serve as a learning guide, the interested reader may find it +useful to inspect the source code to gain familiarity with some of the least common features +offered by Boost.Bimap. + +[table +[[Program ][Description ] +] +[[[@../../test/test_tagged.cpp + test_tagged.cpp ]] + [Tagged idiom checks ]] + +[[[@../../test/test_mutant.cpp + test_mutant.cpp ]] + [Test the mutant idiom ]] + +[[[@../../test/test_structured_pair.cpp + test_structured_pair.cpp ]] + [Test structured pair class ]] + +[[[@../../test/test_mutant_relation.cpp + test_mutant_relation.cpp ]] + [Test the relation class ]] + +[[[@../../test/test_bimap_set_of.cpp + test_bimap_set_of.cpp ]] + [Library interface check ]] + +[[[@../../test/test_bimap_multiset_of.cpp + test_bimap_multiset_of.cpp ]] + [Library interface check ]] + +[[[@../../test/test_bimap_unordered_set_of.cpp + test_bimap_unordered_set_of.cpp ]] + [Library interface check ]] + +[[[@../../test/test_bimap_unordered_multiset_of.cpp + test_bimap_unordered_multiset_of.cpp ]] + [Library interface check ]] + +[[[@../../test/test_bimap_list_of.cpp + test_bimap_list_of.cpp ]] + [Library interface check ]] + +[[[@../../test/test_bimap_vector_of.cpp + test_bimap_vector_of.cpp ]] + [Library interface check ]] + +[[[@../../test/test_bimap_convenience_header.cpp + test_bimap_convenience_header.cpp ]] + [Library interface check ]] + +[[[@../../test/test_bimap_ordered.cpp + test_bimap_ordered.cpp ]] + [Test set and multiset based bimaps ]] + +[[[@../../test/test_bimap_unordered.cpp + test_bimap_unordered.cpp ]] + [Test unordered_set and unordered_multiset based bimaps ]] + +[[[@../../test/test_bimap_sequenced.cpp + test_bimap_sequenced.cpp ]] + [Test list and vector based bimaps ]] + +[[[@../../test/test_bimap_unconstrained.cpp + test_bimap_unconstrained.cpp ]] + [Test bimaps with unconstrained views ]] + +[[[@../../test/test_bimap_serialization.cpp + test_bimap_serialization.cpp ]] + [Serialization support checks ]] + +[[[@../../test/test_bimap_property_map.cpp + test_bimap_property_map.cpp ]] + [Property map concepts for the set and unordered set views ]] + +[[[@../../test/test_bimap_modify.cpp + test_bimap_modify.cpp ]] + [`replace`, `modify` and `operator[]` ]] + +[[[@../../test/test_bimap_lambda.cpp + test_bimap_lambda.cpp ]] + [Test lambda modified idom support ]] + +[[[@../../test/test_bimap_assign.cpp + test_bimap_assign.cpp ]] + [Test Boost.Assign support ]] + +[[[@../../test/test_bimap_project.cpp + test_bimap_project.cpp ]] + [Projection of iterators support ]] + +[[[@../../test/test_bimap_operator_bracket.cpp + test_bimap_operator_bracket.cpp ]] + [`operator[]` and `at()` functions ]] + +[[[@../../test/test_bimap_info.cpp + test_bimap_info.cpp ]] + [Information hooking support ]] + +[[[@../../test/test_bimap_extra.cpp + test_bimap_extra.cpp ]] + [Additional checks ]] + +[[[@../../test/compile_fail/test_bimap_info_1.cpp + test_bimap_info_1.cpp ]] + [Information hooking compilation fail test ]] + +[[[@../../test/compile_fail/test_bimap_info_2.cpp + test_bimap_info_2.cpp ]] + [Information hooking compilation fail test ]] + +[[[@../../test/compile_fail/test_bimap_info_3.cpp + test_bimap_info_3.cpp ]] + [Information hooking compilation fail test ]] + +[[[@../../test/compile_fail/test_bimap_mutable_1.cpp + test_bimap_mutable_1.cpp ]] + [Mutable members compilation fail test ]] + +[[[@../../test/compile_fail/test_bimap_mutable_2.cpp + test_bimap_mutable_2.cpp ]] + [Mutable members compilation fail test ]] + +[[[@../../test/compile_fail/test_bimap_mutable_3.cpp + test_bimap_mutable_3.cpp ]] + [Mutable members compilation fail test ]] + +] + +[endsect] \ No newline at end of file diff --git a/doc/toolbox.qbk b/doc/toolbox.qbk new file mode 100755 index 0000000..3ced874 --- /dev/null +++ b/doc/toolbox.qbk @@ -0,0 +1,75 @@ +[/license + +Boost.Bimap + +Copyright (c) 2006-2007 Matias Capeletto + +Distributed under the Boost Software License, Version 1.0. +(See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt) + +] + +[/ QuickBook Document version 1.4 ] + +[section Bimap Toolbox] + +[section Mutant] + +[tip +A mutant class defines storage compatible views in its declaration. +You can the use the mutate(m) function to get a view of the +data with zero overhead. +] + +__UNDER_CONSTRUCTION__ + +[endsect] + +[section Structured_pair] + +[tip +A structured pair allows you to control the order of the two types. +You can instantiate it so the ['second] member appears in the first +position. +] + +__UNDER_CONSTRUCTION__ + + +[endsect] + +[section Tagged] + +[tip +Tagged idiom and support metafunctions. +] + +__UNDER_CONSTRUCTION__ + + +[endsect] + +[section Relation] + +[tip +The bidirectional std::pair cousin. +] + +__UNDER_CONSTRUCTION__ + +[endsect] + +[section Container_adaptor] + +[tip +Easy way to adapt a container so it behaves different in some aspect. +It is the same concept that is use in iterator_adaptor. +] + +__UNDER_CONSTRUCTION__ + +[endsect] + + +[endsect] diff --git a/doc/tutorial.qbk b/doc/tutorial.qbk new file mode 100755 index 0000000..2207d71 --- /dev/null +++ b/doc/tutorial.qbk @@ -0,0 +1,1057 @@ +[/license + +Boost.Bimap + +Copyright (c) 2006-2007 Matias Capeletto + +Distributed under the Boost Software License, Version 1.0. +(See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt) + +] + +[/ QuickBook Document version 1.4 ] + +[section The tutorial] + +[section Roadmap] + +# Boost.Bimap is intuitive because it is based on the standard +template library. New concepts are however presented to extend the +standard maps to bidirectional maps. The first step is to gain a +firm grasp of the bimap framework. The first section +([link boost_bimap.the_tutorial.discovering_the_bimap_framework Discovering the bimap framework]) +aims to explain this. + +# Boost.Bimap offers much more than just a one-to-one ordered unique +bidirectional map. It is possible to control the collection type of each side +of the relationship that the bimap represents, giving one-to-many +containers, hashed bidirectional containers and others that may be more +suitable to the the task at hand. The second section +([link boost_bimap.the_tutorial.controlling_collection_types Controlling collection types]) +explains how to instantiate a bimap with different collection constraints. + +# The section +([link boost_bimap.the_tutorial.the_collection_of_relations_type The "collection of relations" type]) +explains how to create new types of bidirectional maps using custom collection types. + +# In the section [link boost_bimap.the_tutorial.differences_with_standard_maps Differences with standard maps] we will learn about the subtle differences between a bimap map view and a standard map. + +# The section [link boost_bimap.the_tutorial.useful_functions Useful functions] provides information +about functions of a bimap that are not found in the STL. + +# The types of a bimap can be tagged so that each side is accessible +by something closer to the problem than left and right. This leads to +more readable, self-documenting code. The fourth section +([link boost_bimap.the_tutorial.bimaps_with_user_defined_names Bimaps with user defined names]) shows +how to use this feature. + +# The bimap mapping framework allows to disable a view of a bimap, including the standard +mapping containers as a particular case. The section +[link boost_bimap.the_tutorial.unconstrained_sets Unconstrained Sets] explains how they work. + +# The section [link boost_bimap.the_tutorial.additional_information Additional information] +explains how to attach information to each relation of a bimap. + +# The final section +([link boost_bimap.the_tutorial.complete_instantiation_scheme Complete Instantiation Scheme]) +summarizes bimap instantiation and explains how change the allocator type to be used. + +[endsect] + +[section Discovering the bimap framework] + +[section Interpreting bidirectional maps] + +One way to interpret bidirectional maps is as a function between two +collections of data, lets call them the left and the right collection. +An element in this bimap is a relation between an element from the left +collection and an element from the right collection. +The types of both collections defines the bimap behaviour. We can view +the stored data from the left side, as a mapping between keys from the +left collection and data from the right one, or from the right side, as +a mapping between keys from the right collection and data from the +left collection. + +[endsect] + +[section Standard mapping framework] + +Relationships between data in the STL are represented by maps. A +standard map is a directed relation of keys from a left collection and +data from a right unconstrained collection. +The following diagram shows the relationship represented and the +user's viewpoint. + +__STANDARD_MAPPING_FRAMEWORK__ + +The left collection type depends on the selected map type. For example if the the map type is `std::multimap` the collection type of X is a `multiset_of`. +The following table shows the equivalent types for the std associative containers. + +[table std associative containers +[[container ][left collection type ][right collection type]] +[[`map` ][`set_of` ][no constraints ]] +[[`multimap` ][`multiset_of` ][no constraints ]] +[[`unordered_map` ][`unordered_set_of` ][no constraints ]] +[[`unordered_multimap`][`unordered_multiset_of` ][no constraints ]] +] + +[endsect] + +[section Bimap mapping framework] + +Boost.Bimap design is based on the STL, and extends the framework in a natural way. +The following diagram represents the new situation. + +__EXTENDED_MAPPING_FRAMEWORK__ + +Notice that now the `std::maps` are a particular case of a Boost.Bimap +container, where you can view only one side of the relationship and can +control the constraints of only one of the collections. Boost.Bimap +allows the user to view the relationship from three viewpoints. +You can view it from one side, obtaining a `std::map` compatible +container, or you can work directly with the whole relation. + +The next diagram shows the layout of the relation and pairs of a bimap. It is +the one from the ['one minute tutorial] + +__RELATION_AND_PAIR__ + +Bimap pairs are signature-compatible with standard pairs but are different +from them. As you will see in other sections they can be tagged with user +defined names and additional information can be attached to them. You can +convert from `std::pairs` to bimap pairs directly but the reverse conversion +is not provided. This mean that you can insert elements in a bimap using +algorithms like `std::copy` from containers `like std::map`, or use `std::make_pair` +to add new elements. However it is best to use `bm.left.insert( bm_type::left_value_type(f,s) )` instead of `bm.insert( std::make_pair(f,s) )` to avoid an extra call to the +copy constructor of each type. + +The following code snippet shows the relation between a bimap and standard +maps. + +[note +You have to used references to views, and not directly views object. +Views cannot be constructed as separate objects from the container they +belong to, so the following: +`` +// Wrong: we forgot the & after bm_type::left_type +bm_type::left_map lm = bm.left; +`` +does not compile, since it is trying to construct the view object `lm`. +This is a common source of errors in user code. +] + +[@../../example/standard_map_comparison.cpp Go to source code] + +[import ../example/standard_map_comparison.cpp] + +[code_standard_map_comparison] + +[endsect] + +[endsect] + +[section Controlling collection types] + +[section Freedom of choice] + +As has already been said, in STL maps, you can only control the +constraints from one of the collections, namely the one that you are +viewing. In Boost.Bimap, you can control both and it is as easy as using the STL. + +__EXTENDED_MAPPING_FRAMEWORK__ + +The idea is to use the same constraint names that are used in the +standard. If you don't specify the collection type, Boost.Bimap assumes +that the collection is a set. The instantiation of a bimap with custom +collection types looks like this: + + typedef bimap< ``*CollectionType*``_of, ``*CollectionType*``_of > bm_type; + +The following is the list of all supported collection types. + + +[table Collection of Key Types +[[name ][Features ][map view type ]] +[[`set_of` ][['ordered, unique]][`map` ]] +[[`multiset_of` ][['ordered ]][`multimap` ]] +[[`unordered_set_of` ][['hashed, unique ]][`unordered_map` ]] +[[`unordered_multiset_of`][['hashed ]][`unordered_multimap` ]] +[[`list_of` ][['sequenced ]][`list_map` ]] +[[`vector_of` ][['random access ]][`vector_map` ]] +[[`unconstrained_set_of` ][['unconstrained ]][['can not be viewed] ]] +] + + +`list_of` and `vector_of` map views are not associated with any existing STL +associative containers. They are two examples of unsorted associative +containers. `unconstrained_set_of` allow the user to ignore a view. This +will be explained later. + +__BIMAP_STRUCTURES__ + +The selection of the collection type affects the possible operations that you +can perform with each side of the bimap and the time it takes to do +each. If we have: + + typedef bimap< ``*CollectionType*``_of, ``*CollectionType*``_of > bm_type; + bm_type bm; + +The following now describes the resulting map views of the bidirectional +map. + +* `bm.left` is signature-compatible with *LeftMapType*`` +* `bm.right` is signature-compatible with *RightMapType*`` + +[endsect] + +[section Configuration parameters] + +Each collection type template has different parameters to control its +behaviour. For example, in `set_of` specification, you can pass a Functor +type that compares two types. All of these parameters are exactly the +same as those of the standard library container, except for the +allocator type. You will learn later how to change the allocator for a +bimap. + +The following table lists the meanings of each collection type's parameters. + +[table +[[name ][Additional Parameters]] + +[[`set_of` + + `multiset_of` ] + +[[*KeyComp ] is a Functor that compares two types using a less-than operator. +By default, this is `std::less`. ]] + +[[`unordered_set_of` + + `unordered_multiset_of`] + +[[*HashFunctor ] converts a `T` object into an `std::size_t` value. By default it is `boost::hash`. + + [*EqualKey ] is a Functor that tests two types for equality. By default, the +equality operator is `std::equal_to`. ]] +[[`list_of` ][No additional parameters.]] +[[`vector_of` ][No additional parameters.]] +[[`unconstrained_set_of` ][No additional parameters.]] +] + +[endsect] + +[section Examples] + +[heading Countries Populations] + +We want to store countries populations. +The requeriments are: + +# Get a list of countries in decresing order of their populations. +# Given a countrie, get their population. + +Lets create the appropiate bimap. + + typedef bimap< + + unordered_set_of< std::string >, + multiset_of< long, std::greater > + + > populations_bimap; + +First of all countries names are unique identifiers, while two countries +may have the same population. This is why we choose *multi*`set_of` for +populations. + +Using a `multiset_of` for population allow us to iterate over the data. +Since listing countries ordered by their names is not a requisite, we can +use an `unordered_set_of` that allows constant order look up. + +And now lets use it in a complete example + +[@../../example/population_bimap.cpp Go to source code] + +[import ../example/population_bimap.cpp] + +[code_population_bimap] + + +[heading Repetitions counter] + +We want to count the repetitions for each word in a text and print them +in order of appearance. + +[@../../example/repetitions_counter.cpp Go to source code] + +[import ../example/repetitions_counter.cpp] + +[code_repetitions_counter] + +[endsect] + +[endsect] + +[section The collection of relations type] + +[section A new point of view] + +Being able to change the collection type of the bimap relation view is another +very important feature. Remember that this view allows the user to see +the container as a group of the stored relations. This view has set +semantics instead of map semantics. + +__COLLECTION_TYPE_OF_RELATION__ + +By default, Boost.Bimap will base the collection type of the relation on the +type of the left collection. If the left collection type is a set, then the collection +type of the relation will be a set with the same order as the left view. + +In general, Boost.Bimap users will base the collection type of a relation on +the type of the collection on one of the two sides. However there are times +where it is useful to give this collection other constraints or simply to order +it differently. The user is allowed to choose between: + +* left_based +* right_based +* set_of_relation<> +* multiset_of_relation<> +* unordered_set_of_relation<> +* unordered_multiset_of_relation<> +* list_of_relation +* vector_of_relation +* unconstrained_set_of_relation + +[tip +The first two options and the last produce faster bimaps, so prefer +these where possible. +] + +__MORE_BIMAP_STRUCTURES__ + +The collection type of relation can be used to create powerful containers. For +example, if you need to maximize search speed, then the best +bidirectional map possible is one that relates elements from an +`unordered_set` to another `unordered_set`. The problem is that this +container cannot be iterated. If you need to know the list of relations +inside the container, you need another collection type of relation. In this +case, a `list_of_relation` is a good choice. The resulting container +trades insertion and deletion time against fast search capabilities and +the possibility of bidirectional iteration. + +[@../../example/mighty_bimap.cpp Go to source code] + +[code_mighty_bimap] + +[endsect] + +[section Configuration parameters] + +Each collection type of relation has different parameters to control its +behaviour. For example, in the `set_of_relation` specification, you can +pass a Functor type that compares two types. All of the parameters are +exactly as in the standard library containers, except for the type, +which is set to the bimap relation and the allocator type. To help users +in the creation of each functor, the collection type of relation templates +takes an mpl lambda expression where the relation type will be evaluated +later. A placeholder named `_relation` is available to bimap users. + +The following table lists the meaning of the parameters for each collection type of +relations. + +[table +[[name ][Additional Parameters]] + +[[`left_based` ][Not a template.]] +[[`right_based` ][Not a template.]] +[[`set_of_relation` + + `multiset_of_relation` ] +[[*KeyComp ] is a Functor that compares two types using less than. By +default, the less-than operator is `std::less<_relation>`. ]] + +[[`unordered_set_of_relation` + + `unordered_multiset_of_relation`] +[[*HashFunctor ] converts the `relation` into an `std::size_t` value. By default it is `boost::hash<_relation>`. + + [*EqualKey ] is a Functor that tests two relations for equality. By default, +the equality operator is `std::equal_to<_relation>`. ]] +[[`list_of_relation` ][Not a template.]] +[[`vector_of_relation` ][Not a template.]] +[[`unconstrained_set_of_relation` ][Not a template.]] +] + +[endsect] + +[section Examples] + +Consider this example: + + template< class Rel > + struct RelOrder + { + bool operator()(Rel ra, Rel rb) const + { + return (ra.left+ra.right) < (rb.left+rb.right); + } + }; + + typedef bimap + < + multiset_of< int >, + multiset_of< int >, + set_of_relation< RelOrder<_relation> > + + > bimap_type; + +Here the bimap relation view is ordered using the information of +both sides. This container will only allow unique relations because +`set_of_relation` has been used but the elements in each side of the +bimap can be repeated. + + struct name {}; + struct phone_number {}; + + typedef bimap + < + tagged< unordered_multiset_of< string >, name >, + tagged< unordered_set_of < int >, phone_number >, + set_of_relation<> + + > bimap_type; + +In this other case the bimap will relate names to phone numbers. +Names can be repeated and phone numbers are unique. You can perform +quick searches by name or phone number and the container can be viewed +ordered using the relation view. + +[endsect] + +[endsect] + +[section Differences with standard maps] + +[section Insertion] + +Remember that a map can be interpreted as a relation between two collections. +In bimaps we have the freedom to change both collection types, imposing +constrains in each of them. Some insertions that we give for granted to +success in standard maps fails with bimaps. +For example: + + bimap bm; + + bm.left.insert(1,"orange"); + bm.left.insert(2,"orange"); // No effect! returns make_pair(iter,false) + +The insertion will only succeed if it is allowed by all views of the `bimap`. +In the next snippet we define the right collection as a multiset, when we +try to insert the same two elements the second insertion is allowed by the +left map view because both values are different and it is allowed by the +right map view because it is a non-unique collection type. + + bimap > bm; + + bm.left.insert(1,"orange"); + bm.left.insert(2,"orange"); // Insertion succeed! + +If we use a custom collection of relation type, the insertion has to be +allowed by it too. + +[endsect] + +[section iterator::value_type] + +The relations stored in the Bimap will not be in most cases modifiable +directly by iterators because both sides are used as keys of +['key-based] sets. When a `bimap` left view iterator is dereferenced +the return type is ['signature-compatible] with a +`std::pair< const A, const B >`. +However there are some collection types that are not ['key_based], for example +list_of. If a Bimap uses one of these collection types there is no problem with +modifying the data of that side. The following code is valid: + + typedef bimap< int, list_of< std::string > > bm_type; + bm_type bm; + bm.insert( bm_type::relation( 1, "one" ) ); + ... + bm.left.find(1)->second = "1"; // Valid + +In this case, when the iterator is dereferenced the return type is +['signature-compatible] with a `std::pair`. + +The following table shows the constness of the dereferenced data of each +collection type of: + +[table +[[Side collection type ][Dereferenced data]] +[[`set_of` ][['constant]]] +[[`multiset_of` ][['constant]]] +[[`unordered_set_of` ][['constant]]] +[[`unordered_multiset_of`][['constant]]] +[[`list_of` ][['mutable] ]] +[[`vector_of` ][['mutable] ]] +[[`unconstrained_set_of` ][['mutable] ]] +] + +Here are some examples. When dereferenced the iterators returns a type that +is ['signature-compatible] with these types. + +[table +[[Bimap type ][Signature-compatible types]] +[[`bimap`][ + `iterator ` *->* `relation` + + `left_iterator ` *->* `pair` + + `right_iterator` *->* `pair` +]] +[[`bimap,unordered_set_of >`][ + `iterator ` *->* `relation` + + `left_iterator ` *->* `pair` + + `right_iterator` *->* `pair` +]] +[[`bimap,list_of >`][ + `iterator ` *->* `relation` + + `left_iterator ` *->* `pair` + + `right_iterator` *->* `pair` +]] +[[`bimap,set_of >`][ + `iterator ` *->* `relation` + + `left_iterator ` *->* `pair` + + `right_iterator` *->* `pair` +]] +[[`bimap,unconstrained_set_of >`][ + `iterator ` *->* `relation` + + `left_iterator ` *->* `pair` + + `right_iterator` *->* `pair` +]] +] + +[endsect] + +[section operator\[\] and at()] + +`set_of` and `unordered_set_of` map views overload `operator[]` to retrieve the +associated data of a given key only when the other collection type is a +mutable one. In these cases it works in the same way as the standard. + + bimap< unorderd_set_of< std::string>, list_of > bm; + + bm.left["one"] = 1; // Ok + +The standard defines an access function for `map` and `unordered_map`: + + const data_type & at(const key_type & k) const; + data_type & at(const key_type & k); + +These functions look for a key and returns the associated data value, but +throws a `std::out_of_range` exception if the key is not found. + +In bimaps the constant version of these functions is given for `set_of` and +`unorderd_set_of` map views independently of the other collection type. +The mutable version is only provided when the other collection type is +mutable. + +The following examples shows the behaviour of `at(key)` + +[@../../example/at_function_examples.cpp Go to source code] + +[import ../example/at_function_examples.cpp] + +[code_at_function_first] + +[code_at_function_second] + +[/ +`set_of` and `unordered_set_of` views overload `operator[]` to retrieve the +associated data of a given key. +The symmetry of bimap imposes some constraints on `operator[]` that are +not found in `std::map` or `std::unordered_map`. If other views are unique, +`bimap::duplicate_value` is thrown whenever an assignment is attempted to +a value that is already a key in these views. As for +`bimap::value_not_found`, this exception is thrown while trying to access +a non-existent key: this behaviour differs from the standard containers, +which automatically assigns a default value to non-existent keys referred to +by `operator[]`. + + + const data_type & operator[](const typename key_type & k) const; + +[: Returns the `data_type` reference that is associated with `k`, or + throws `bimap::value_not_found` if such an element does not exist. +] + + ``['-unspecified data_type proxy-]`` operator[](const typename key_type & k); + +[: Returns a proxy to a `data_type` associated with `k` and the + bimap. The proxy behaves as a reference to the `data_type` object. If this + proxy is read and `k` was not in the bimap, the bimap::value_not_found is + thrown. If it is written then `bimap::duplicate_value` is thrown if the + assignment is not allowed by one of the other views of the `bimap`. +] + + +The following example shows the behaviour of `operator[]` + + bimap bm; + + bm.left[1] = "one"; // Ok + + bm.right["two"] = 2; // Ok + + if( bm.left[3] == "three" ) // throws bimap::value_not_found + { + ... + } + + bm.left[3] = "one"; // throws bimap::duplicate_value +] + +[endsect] + +[section Complexity of operations] + +The complexity of some operations is different in bimaps. Read +[link complexity_signature_explanation the reference] to find the +complexity of each function. + +[endsect] + +[endsect] + +[section Useful functions] + +[section Projection of iterators] + +Iterators can be projected to any of the three views of the bimap. +A bimap provides three member functions to cope with projection: `project_left`, +`project_right` and `project_up`, with projects iterators to the ['left map view], +the ['right map view] and the ['collection of relations view]. These functions +take any iterator from the bimap and retrieve an iterator over the projected view +pointing to the same element. + +[import ../example/projection.cpp] + +Here is an example that uses projection: + +[@../../example/projection.cpp Go to source code] + +[code_projection_years] + +[endsect] + +[section replace and modify] + +[import ../example/tutorial_modify_and_replace.cpp] + +These functions are members of the views of a bimap that are not founded in +their standard counterparts. + +The `replace` family member functions performs in-place replacement of a given +element as the following example shows: + +[@../../example/tutorial_modify_and_replace.cpp Go to source code] + +[code_tutorial_replace] + +`replace` functions performs this substitution in such a manner that: + +* The complexity is constant time if the changed element retains its original order +with respect to all views; it is logarithmic otherwise. +* Iterator and reference validity are preserved. +* The operation is strongly exception-safe, i.e. the `bimap` remains unchanged if +some exception (originated by the system or the user's data types) is thrown. + +`replace` functions are powerful operations not provided by standard STL containers, +and one that is specially handy when strong exception-safety is required. + +The observant reader might have noticed that the convenience of replace comes at a +cost: namely the whole element has to be copied ['twice] to do the updating (when +retrieving it and inside `replace`). If elements are expensive to copy, this may +be quite a computational cost for the modification of just a tiny part of the +object. To cope with this situation, Boost.Bimap provides an alternative +updating mechanism: `modify` functions. + +`modify` functions accepts a functor (or pointer to function) taking a reference +to the data to be changed, thus eliminating the need for spurious copies. Like +`replace` functions, `modify` functions does preserve the internal orderings of +all the indices of the `bimap`. However, the semantics of modify functions are not +entirely equivalent to replace functions. Consider what happens if a collision occurs +as a result of modifying the element, i.e. the modified element clashes with another +with respect to some unique view. In the case of `replace` functions, the original +value is kept and the method returns without altering the container, but `modify` +functions cannot afford such an approach, since the modifying functor leaves no +trace of the previous value of the element. Integrity constraints thus lead to the +following policy: when a collision happens in the process of calling a modify functions, +the element is erased and the method returns false. This difference in behavior +between `replace` and `modify` functions has to be considered by the programmer on +a case-by-case basis. + +Boost.Bimap defines new placeholders named `_key` and `_data` to allow a sounder solution. +You have to include `` to use them. + +[/ +Boost.Bimap defines new placeholders to allow a sounder solution. For +pairs, two new placeholders are instantiated: `_first` and `_second`, and +for a relation, two more complete the set: `_left` and `_right`. +] + +[@../../example/tutorial_modify_and_replace.cpp Go to source code] + +[code_tutorial_modify] + +[endsect] + +[section Retrieval of ranges] + +[import ../example/tutorial_range.cpp] + +Standard `lower_bound` and `upper_bound` functions can be used to lookup for +all the elements in a given range. + +Suppose we want to retrieve the elements from a `bimap` +where the left value is in the range `[20,50]` + +[code_tutorial_range_standard_way] + +Subtle changes to the code are required when strict inequalities are considered. +To retrieve the elements greater than 20 and less than 50, the code has to be +rewritten as + +[code_tutorial_range_standard_way_subtle_changes] + +To add to this complexity, the careful programmer has to take into account that +the lower and upper bounds of the interval searched be compatible: for instance, +if the lower bound is 50 and the upper bound is 20, the iterators `iter_first` and +`iter_second` produced by the code above will be in reverse order, with possibly +catastrophic results if a traversal from `iter_first` to `iter_second` is tried. +All these details make range searching a tedious and error prone task. + +The range member function, often in combination with lambda expressions, +can greatly help alleviate this situation: + +[code_tutorial_range] + +`range` simply accepts predicates specifying the lower and upper bounds of +the interval searched. Please consult the reference for a detailed explanation +of the permissible predicates passed to range. + +One or both bounds can be omitted with the special unbounded marker: + +[code_tutorial_range_unbounded] + +[@../../example/tutorial_range.cpp Go to source code] + +[endsect] + +[endsect] + +[section Bimaps with user defined names] + +[import ../example/user_defined_names.cpp] + +In the following example, the library user inserted comments to guide +future programmers: + +[@../../example/user_defined_names.cpp Go to source code] + +[code_user_defined_names_untagged_version] + +In Boost.Bimap there is a better way to document the code and +in the meantime helping you to write more mantainable and readable code. +You can tag the two collections of the bimap so they can be +accessed by more descriptive names. + +__TAGGED__ + +A tagged type is a type that has been labelled using a tag. A tag is any +valid C++ type. In a bimap, the types are always tagged. If you do not +specify your own tag, the container uses `member_at::left` and +`member_at::right` to tag the left and right sides respectively. In order +to specify a custom tag, the type of each side has to be tagged. +Tagging a type is very simple: + + typedef tagged< int, a_tag > tagged_int; + +Now we can rewrite the example: + +[@../../example/user_defined_names.cpp Go to source code] + +[code_user_defined_names_tagged_version] + +Here is a list of common structures in both tagged and untagged versions. +Remember that when the bimap has user defined tags you can still use +the untagged version structures. + + + struct Left {}; + struct Right {}; + typedef bimap< + multiset_of< tagged< int, Left > >, + unordered_set_of< tagged< int, Right > > + > bm_type; + + bm_type bm; + + //... + + bm_type::iterator iter = bm.begin(); + bm_type::left_iterator left_iter = bm.left.begin(); + bm_type::right_iterator right_iter = bm.right.begin(); + + + +[table Equivalence of expresions using user defined names +[[Untagged version] [Tagged version] ] +[[`bm.left`] [`bm.by()`] ] +[[`bm.right`] [`bm.by()`] ] +[[`bm_type::left_map`] [`bm::map_by::type`] ] +[[`bm_type::right_value_type`] [`bm::map_by::value_type`] ] +[[`bm_type::left_iterator`] [`bm::map_by::iterator`] ] +[[`bm_type::right_const_iterator`][`bm::map_by::const_iterator`]] +[[`iter->left`] [`iter->get()`] ] +[[`iter->right`] [`iter->get()`] ] +[[`left_iter->first`] [`left_iter->get()`] ] +[[`left_iter->second`] [`left_iter->get()`] ] +[[`right_iter->first`] [`right_iter->get()`] ] +[[`right_iter->second`] [`right_iter->get()`] ] +[[`bm.project_left(iter)`] [`bm.project(iter)`] ] +[[`bm.project_right(iter)`] [`bm.project(iter)`] ] +] + +[endsect] + +[section Unconstrained Sets] + +Unconstrained sets allow the user to disable one of the views of a +bimap. Doing so makes the bimap operations execute faster and reduces +memory consumption. This completes the bidirectional mapping framework +by including unidirectional mappings as a particular case. + +Unconstrained sets are useful for the following reasons: + +* A bimap type has stronger guarantees than its standard equivalent, +and includes some useful functions (replace, modify) that the standard +does not have. +* You can view the mapping as a collection of relations. +* Using this kind of map makes the code very extensible. If, at any +moment of the development, the need to perform searches from the right +side of the mapping arises, the only necessary change is to the `typedef`. + +[import ../example/unconstrained_collection.cpp] + +Given this bimap instance, + +[code_unconstrained_collection_bimap] + +or this standard map one + +[code_unconstrained_collection_map] + +The following code snippet is valid + +[code_unconstrained_collection_common] + +But using a bimap has some benefits + +[code_unconstrained_collection_only_for_bimap] + +[@../../example/unconstrained_collection.cpp Go to source code] + +[endsect] + +[section Additional information] + +[import ../example/tutorial_info_hook.cpp] + +Bidirectional maps may have associated information about each relation. +Suppose we want to represent a books and author bidirectional map. + +[code_tutorial_info_hook_nothing] + +Suppose now that we want to store abstract of each book. +We have two options: + +# Books name are unique identifiers, so we can create a separate +`std::map< string, string >` that relates books names with abstracts. +# We can use __BOOST_MULTI_INDEX__ for the new beast. + +Option 1 is the wrong approach, if we go this path we lost what bimap has +won us. We now have to maintain the logic of two interdependent containers, +there is an extra string stored for each book name, and the performance will +be worse. This is far away from being a good solution. + +Option 2 is correct. We start thinking books as entries in a table. So it +makes sense to start using Boost.MultiIndex. We can then add the year +of publication, the price, etc... and we can index this new items too. So +Boost.MultiIndex is a sound solution for our problem. + +The thing is that there are cases where we want to maintain bimap +semantics (use `at()` to find an author given a book name and the other way +around) and add information about the relations that we are sure we will not +want to index later (like the abstracts). Option 1 is not possible, option 2 +neither. + +Boost.Bimap provides support for this kind of situations by means of +an embedded information member. +You can pass an extra parameter to a bimap: `with_info< InfoType >` +and an `info` member of type `InfoType` will appear in the relation and bimap +pairs. + +__RELATION_AND_PAIR_WITH_INFO__ + +Relations and bimap pairs constructors will take an extra argument. +If only two arguments are used, the information will be initialized with +their default constructor. + +[code_tutorial_info_hook_first] + +Contrary to the two key types, the information will be mutable using iterators. + +[code_tutorial_info_hook_mutable] + +A new function is included in ['unique] map views: `info_at(key)`, that mimics the +standard `at(key)` function but returned the associated information instead of +the data. + +[code_tutorial_info_hook_info_at] + +The info member can be tagged just as the left or the right member. The following +is a rewrite of the above example using user defined names: + +[code_tutorial_info_hook_tagged_info] + +[@../../example/tutorial_info_hook.cpp Go to source code] + +[endsect] + +[section Complete instantiation scheme] + +To summarize, this is the complete instantiation scheme. + + typedef bimap + < + LeftCollectionType, RightCollectionType + + [ , SetTypeOfRelation ] // Default to left_based + [ , with_info< Info > ] // Default to no info + [ , Allocator ] // Default to std::allocator<> + + > bm; + +`{Side}CollectionType` can directly be a type. This defaults to +`set_of`, or can be a `{CollectionType}_of` specification. +Additionally, the type of this two parameters can be tagged to specify +user defined names instead of the usual `member_at::-Side-` tags. + +The possibles way to use the first parameter are: + + bimap< Type, R > + +* Left type: `Type` +* Left collection type: `set_of< Type >` +* Left tag: `member_at::left` + + bimap< `['CollectionType]`_of< Type >, R > + +* Left type: `Type` +* Left collection type: ['CollectionType]`_of< LeftType >` +* Left tag: `member_at::left` + + bimap< tagged< Type, Tag >, R > + +* Left type: `Type` +* Left collection type: `set_of< LeftType >` +* Left tag: `Tag` + + bimap< `['CollectionType]`_of< tagged< Type, Tag > >, R > + +* Left type: `Type` +* Left collection type: ['CollectionType]`_of< LeftType >` +* Left tag: `Tag` + +The same options are available for the second parameter. + +The last three parameters are used to specify the collection type of the relation, +the information member and the allocator type. + +If you want to specify a custom allocator type while relying on the default +value of CollectionTypeOfRelation, you can do so by simply writing +`bimap`. Boost.Bimap's internal +machinery detects that the third parameter in this case does not refer +to the relation type but rather to an allocator. + +The following are the possible ways of instantiating the last three parameters +of a bimap. You can ignore some of the parameter but the order must be respected. + + + bimap< L, R > + +* set_of_relation_type: based on the left key type +* info: no info +* allocator: std::allocator + + + bimap< L, R ,SetOfRelationType> + +* set_of_relation_type: SetOfRelationType +* info: no info +* allocator: std::allocator + + + bimap< L, R , SetOfRelationType, with_info > + +* set_of_relation_type: SetOfRelationType +* info: Info +* allocator: std::allocator + + + bimap< L, R , SetOfRelationType, with_info, Allocator> + +* set_of_relation_type: SetOfRelationType +* info: Info +* allocator: Allocator + + + bimap< L, R , SetOfRelationType, Allocator> + +* set_of_relation_type: SetOfRelationType +* info: no info +* allocator: Allocator + + + bimap< L, R , with_info > + +* set_of_relation_type: based on the left key type +* info: Info +* allocator: std::allocator + + + bimap< L, R , with_info, Allocator> + +* set_of_relation_type: based on the left key type +* allocator: Allocator + + + bimap< L, R , Allocator> + +* set_of_relation_type: based on the left key type +* info: no info +* allocator: Allocator + + + + +[endsect] + +[endsect] diff --git a/example/Jamfile.v2 b/example/Jamfile.v2 new file mode 100755 index 0000000..4241629 --- /dev/null +++ b/example/Jamfile.v2 @@ -0,0 +1,50 @@ +# Boost.Bimap +# +# Copyright (c) 2006-2007 Matias Capeletto +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +# bring in rules for testing +import testing ; + +test-suite "examples" + : + [ compile mighty_bimap.cpp ] + [ run simple_bimap.cpp ] + [ run tagged_simple_bimap.cpp ] + [ run step_by_step.cpp ] + [ run population_bimap.cpp ] + [ run repetitions_counter.cpp ] + [ compile user_defined_names.cpp ] + [ run standard_map_comparison.cpp ] + [ run at_function_examples.cpp ] + [ run tutorial_modify_and_replace.cpp ] + [ run tutorial_range.cpp ] + [ run unconstrained_collection.cpp ] + [ run tutorial_info_hook.cpp ] + [ run projection.cpp ] + ; + +test-suite "bimap_and_boost" + : + [ run bimap_and_boost/property_map.cpp ] + [ run bimap_and_boost/range.cpp ] + [ run bimap_and_boost/foreach.cpp ] + [ run bimap_and_boost/lambda.cpp ] + [ run bimap_and_boost/assign.cpp ] + [ run bimap_and_boost/xpressive.cpp ] + [ run bimap_and_boost/typeof.cpp ] + [ run bimap_and_boost/serialization.cpp + /boost/serialization//boost_serialization ] + ; + +test-suite "mi_to_b_path" + : + [ compile mi_to_b_path/bidirectional_map.cpp ] + [ run mi_to_b_path/hashed_indices.cpp ] + [ compile mi_to_b_path/tagged_bidirectional_map.cpp ] + [ compile mi_to_b_path/mi_bidirectional_map.cpp ] + [ run mi_to_b_path/mi_hashed_indices.cpp ] + ; diff --git a/example/at_function_examples.cpp b/example/at_function_examples.cpp new file mode 100755 index 0000000..c0b916f --- /dev/null +++ b/example/at_function_examples.cpp @@ -0,0 +1,97 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +// Boost.Bimap Example +//----------------------------------------------------------------------------- + +#include + +#include +#include +#include + +#include +#include +#include +#include + +using namespace boost::bimaps; + +void first_bimap() +{ + //[ code_at_function_first + + typedef bimap< set_of< std::string >, list_of< int > > bm_type; + bm_type bm; + + try + { + bm.left.at("one") = 1; // throws std::out_of_range + } + catch( std::out_of_range & e ) {} + + assert( bm.empty() ); + + bm.left["one"] = 1; // Ok + + assert( bm.left.at("one") == 1 ); // Ok + //] +} + +void second_bimap() +{ + //[ code_at_function_second + + typedef bimap< multiset_of, unordered_set_of > bm_type; + bm_type bm; + + //<- + /* + //-> + bm.right[1] = "one"; // compilation error + //<- + */ + //-> + + bm.right.insert( bm_type::right_value_type(1,"one") ); + + assert( bm.right.at(1) == "one" ); // Ok + + try + { + std::cout << bm.right.at(2); // throws std::out_of_range + } + catch( std::out_of_range & e ) {} + + //<- + /* + //-> + bm.right.at(1) = "1"; // compilation error + //<- + */ + //-> + + //] +} + +int main() +{ + first_bimap(); + second_bimap(); + return 0; +} + diff --git a/example/bimap_and_boost/assign.cpp b/example/bimap_and_boost/assign.cpp new file mode 100755 index 0000000..7c7652b --- /dev/null +++ b/example/bimap_and_boost/assign.cpp @@ -0,0 +1,79 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +// Boost.Bimap Example +//----------------------------------------------------------------------------- + +#include + +#include + +#include +#include + +#include +#include +#include + +using namespace boost::bimaps; +using namespace boost; + + +int main() +{ + //[ code_bimap_and_boost_assign + + typedef bimap< multiset_of< int >, list_of< std::string > > bm_type; + + // We can use assign::list_of to initialize the container. + + bm_type bm = assign::list_of< bm_type::relation > /*< + Note that `bm_type::relation` has to be used instead of `bm_type::value_type`. + Contrary to `value_type`, `relation` type stores the elements as non const, a + requirement of `assign::list_of` >*/ + ( 1, "one" ) + ( 2, "two" ) + ( 3, "three" ); + + // The left map view is a multiset, again we use insert + + assign::insert( bm.left ) + ( 4, "four" ) + ( 5, "five" ) + ( 6, "six" ); + + // The right map view is a list so we use push_back here + // Note the order of the elements in the list! + + assign::push_back( bm.right ) + ( "seven" , 7 ) + ( "eight" , 8 ); + + assign::push_front( bm.right ) + ( "nine" , 9 ) + ( "ten" , 10 ) + ( "eleven", 11 ); + + // Since it is left_based the main view is a multiset, so we use insert + + assign::insert( bm ) + ( 12, "twelve" ) + ( 13, "thirteen" ); + //] + + return 0; +} diff --git a/example/bimap_and_boost/foreach.cpp b/example/bimap_and_boost/foreach.cpp new file mode 100755 index 0000000..6fc1514 --- /dev/null +++ b/example/bimap_and_boost/foreach.cpp @@ -0,0 +1,106 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +// Boost.Bimap Example +//----------------------------------------------------------------------------- + +#include + +#include +#include + +#include + +#include +#include +#include + +using namespace boost::bimaps; + + +int main() +{ + //[ code_bimap_and_boost_foreach + + typedef bimap< std::string, list_of > bm_type; + + bm_type bm; + bm.insert( bm_type::value_type("1", 1) ); + bm.insert( bm_type::value_type("2", 2) ); + bm.insert( bm_type::value_type("3", 4) ); + bm.insert( bm_type::value_type("4", 2) ); + + BOOST_FOREACH( bm_type::left_reference p, bm.left ) + { + ++p.second; /*< We can modify the right element because we have + use a mutable collection type in the right side. >*/ + } + + BOOST_FOREACH( bm_type::right_const_reference p, bm.right ) + { + std::cout << p.first << "-->" << p.second << std::endl; + } + + //] + + // More examples + + BOOST_FOREACH( bm_type::right_reference p, bm.right ) + { + ++p.first; + } + + BOOST_FOREACH( bm_type::left_const_reference p, bm.left ) + { + std::cout << p.first << "-->" << p.second << std::endl; + } + + BOOST_FOREACH( bm_type::reference p, bm ) + { + ++p.right; + } + + const bm_type & cbm = bm; + BOOST_FOREACH( bm_type::const_reference p, cbm ) + { + std::cout << p.left << "-->" << p.right << std::endl; + } + + BOOST_FOREACH( bm_type::const_reference p, bm ) + { + std::cout << p.left << "-->" << p.right << std::endl; + } + + //[ code_bimap_and_boost_foreach_using_range + + BOOST_FOREACH( bm_type::left_reference p, + ( bm.left.range( "1" <= _key, _key < "3" ) )) + { + ++p.second; + } + + BOOST_FOREACH( bm_type::left_const_reference p, + ( bm.left.range( "1" <= _key, _key < "3" ) )) + { + std::cout << p.first << "-->" << p.second << std::endl; + } + //] + + return 0; +} + + diff --git a/example/bimap_and_boost/lambda.cpp b/example/bimap_and_boost/lambda.cpp new file mode 100755 index 0000000..765503d --- /dev/null +++ b/example/bimap_and_boost/lambda.cpp @@ -0,0 +1,49 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +// Boost.Bimap Example +//----------------------------------------------------------------------------- + +#include + +#include + +#include +#include + +using namespace boost::bimaps; + +int main() +{ + //[ code_bimap_and_boost_lambda + + typedef bimap< std::string, int > bm_type; + + bm_type bm; + bm.insert( bm_type::value_type("one",1) ); + bm.insert( bm_type::value_type("two",2) ); + + bm.right.range( 5 < _key, _key < 10 ); + + bm.left.modify_key( bm.left.find("one"), _key = "1" ); + + bm.left.modify_data( bm.left.begin(), _data *= 10 ); + //] + return 0; +} + + diff --git a/example/bimap_and_boost/property_map.cpp b/example/bimap_and_boost/property_map.cpp new file mode 100755 index 0000000..298bae8 --- /dev/null +++ b/example/bimap_and_boost/property_map.cpp @@ -0,0 +1,59 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +// Boost.Bimap Example +//----------------------------------------------------------------------------- + +#include + +#include +#include + +#include +#include +#include + +using namespace boost::bimaps; + +//[ code_bimap_and_boost_property_map + +template +void foo(AddressMap & address_map) +{ + typedef typename boost::property_traits::value_type value_type; + typedef typename boost::property_traits::key_type key_type; + + value_type address; + key_type fred = "Fred"; + std::cout << get(address_map, fred); +} + +int main() +{ + typedef bimap > Name2Address; + typedef Name2Address::value_type location; + + Name2Address name2address; + name2address.insert( location("Fred", "710 West 13th Street") ); + name2address.insert( location( "Joe", "710 West 13th Street") ); + + foo( name2address.left ); + + return 0; +} +//] + diff --git a/example/bimap_and_boost/range.cpp b/example/bimap_and_boost/range.cpp new file mode 100755 index 0000000..605e86a --- /dev/null +++ b/example/bimap_and_boost/range.cpp @@ -0,0 +1,121 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +// Boost.Bimap Example +//----------------------------------------------------------------------------- + +#include + +#include + +#include +#include + +//[ code_bimap_and_boost_range_functions + +template< class ForwardReadableRange, class UnaryFunctor > +UnaryFunctor for_each(const ForwardReadableRange & r, UnaryFunctor func) +{ + typedef typename + boost::range_const_iterator::type const_iterator; + + for(const_iterator i= boost::begin(r), iend= boost::end(r); i!=iend; ++i ) + { + func(*i); + } + + return func; +} + +template< class ForwardReadableRange, class Predicate > +typename boost::range_difference::type + count_if(const ForwardReadableRange & r, Predicate pred) +{ + typedef typename + boost::range_const_iterator::type const_iterator; + + typename boost::range_difference::type c = 0; + + for( const_iterator i = boost::begin(r), iend = boost::end(r); i != iend; ++i ) + { + if( pred(*i) ) ++c; + } + + return c; +} +//] + +#include +#include +#include +#include + +using namespace boost::bimaps; +using namespace boost; + +//[ code_bimap_and_boost_range + +struct pair_printer +{ + pair_printer(std::ostream & o) : os(o) {} + template< class Pair > + void operator()(const Pair & p) + { + os << "(" << p.first << "," << p.second << ")"; + } + private: + std::ostream & os; +}; + +struct second_extractor +{ + template< class Pair > + const typename Pair::second_type & operator()(const Pair & p) + { + return p.second; + } +}; + +int main() +{ + typedef bimap< double, multiset_of > bm_type; + + bm_type bm; + bm.insert( bm_type::value_type(2.5 , 1) ); + bm.insert( bm_type::value_type(3.1 , 2) ); + //... + bm.insert( bm_type::value_type(6.4 , 4) ); + bm.insert( bm_type::value_type(1.7 , 2) ); + + // Print all the elements of the left map view + + for_each( bm.left, pair_printer(std::cout) ); + + // Print a range of elements of the right map view + + for_each( bm.right.range( 2 <= _key, _key < 6 ), pair_printer(std::cout) ); + + // Count the number of elements where the data is equal to 2 from a + // range of elements of the left map view + + count_if( bm.left.range( 2.3 < _key, _key < 5.4 ), + bind( second_extractor(), _1 ) == 2 ); + + return 0; +} +//] + diff --git a/example/bimap_and_boost/serialization.cpp b/example/bimap_and_boost/serialization.cpp new file mode 100755 index 0000000..f4791a1 --- /dev/null +++ b/example/bimap_and_boost/serialization.cpp @@ -0,0 +1,89 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +// Boost.Bimap Example +//----------------------------------------------------------------------------- + +#include + +#include +#include +#include + +#include + +#include +#include + +using namespace boost::bimaps; + +int main() +{ + //[ code_bimap_and_boost_serialization + + typedef bimap< std::string, int > bm_type; + + // Create a bimap and serialize it to a file + { + bm_type bm; + bm.insert( bm_type::value_type("one",1) ); + bm.insert( bm_type::value_type("two",2) ); + + std::ofstream ofs("data"); + boost::archive::text_oarchive oa(ofs); + + oa << const_cast(bm); /*< + We must do a const cast because Boost.Serialization archives + only save const objects. Read Boost.Serializartion docs for the + rationale behind this decision >*/ + + /*<< We can only serialize iterators if the bimap was serialized first. + Note that the const cast is not requiered here because we create + our iterators as const. >>*/ + const bm_type::left_iterator left_iter = bm.left.find("two"); + oa << left_iter; + + const bm_type::right_iterator right_iter = bm.right.find(1); + oa << right_iter; + } + + // Load the bimap back + { + bm_type bm; + + std::ifstream ifs("data", std::ios::binary); + boost::archive::text_iarchive ia(ifs); + + ia >> bm; + + assert( bm.size() == 2 ); + + bm_type::left_iterator left_iter; + ia >> left_iter; + + assert( left_iter->first == "two" ); + + bm_type::right_iterator right_iter; + ia >> right_iter; + + assert( right_iter->first == 1 ); + } + //] + + return 0; +} + diff --git a/example/bimap_and_boost/typeof.cpp b/example/bimap_and_boost/typeof.cpp new file mode 100755 index 0000000..3cd99c6 --- /dev/null +++ b/example/bimap_and_boost/typeof.cpp @@ -0,0 +1,86 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +// Boost.Bimap Example +//----------------------------------------------------------------------------- + +#include + +#include +#include +#include + +#include + +using namespace boost::bimaps; + +struct name {}; +struct number {}; + +void using_auto() +{ + //[ code_bimap_and_boost_typeof_first + + typedef bimap< tagged, tagged > bm_type; + bm_type bm; + bm.insert( bm_type::value_type("one" ,1) ); + bm.insert( bm_type::value_type("two" ,2) ); + //] + + //[ code_bimap_and_boost_typeof_using_auto + + for( BOOST_AUTO(iter, bm.by().begin()); iter!=bm.by().end(); ++iter) + { + std::cout << iter->first << " --> " << iter->second << std::endl; + } + + BOOST_AUTO( iter, bm.by().find(2) ); + std::cout << "2: " << iter->get(); + //] +} + +void not_using_auto() +{ + typedef bimap< tagged, tagged > bm_type; + bm_type bm; + bm.insert( bm_type::value_type("one" ,1) ); + bm.insert( bm_type::value_type("two" ,2) ); + + //[ code_bimap_and_boost_typeof_not_using_auto + + for( bm_type::map_by::iterator iter = bm.by().begin(); + iter!=bm.by().end(); ++iter) + { + std::cout << iter->first << " --> " << iter->second << std::endl; + } + + bm_type::map_by::iterator iter = bm.by().find(2); + std::cout << "2: " << iter->get(); + //] +} + +int main() +{ + using_auto(); + not_using_auto(); + + return 0; +} + + + + diff --git a/example/bimap_and_boost/xpressive.cpp b/example/bimap_and_boost/xpressive.cpp new file mode 100755 index 0000000..cad0476 --- /dev/null +++ b/example/bimap_and_boost/xpressive.cpp @@ -0,0 +1,57 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +// Boost.Bimap Example +//----------------------------------------------------------------------------- + +#include + +#include + +#include + +#include +#include + +using namespace boost::bimaps; +using namespace boost::xpressive; +namespace xp = boost::xpressive; + +int main() +{ + //[ code_bimap_and_boost_xpressive + + typedef bimap< std::string, int > bm_type; + bm_type bm; + + std::string rel_str("one <--> 1 two <--> 2 three <--> 3"); + + sregex rel = ( (s1= +_w) >> " <--> " >> (s2= +_d) ) + [ + xp::ref(bm)->*insert( construct(s1, as(s2)) ) + ]; + + sregex relations = rel >> *(+_s >> rel); + + regex_match(rel_str, relations); + + assert( bm.size() == 3 ); + //] + + return 0; +} + diff --git a/example/mi_to_b_path/bidirectional_map.cpp b/example/mi_to_b_path/bidirectional_map.cpp new file mode 100755 index 0000000..20edf94 --- /dev/null +++ b/example/mi_to_b_path/bidirectional_map.cpp @@ -0,0 +1,87 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +// Boost.Bimap Example +//----------------------------------------------------------------------------- +// This example shows how to construct a bidirectional map with +// multi_index_container. +// By a bidirectional map we mean a container of elements of +// std::pair such that no two elements exists with +// the same first or second value (std::map only guarantees uniqueness of the +// first member). +// Fast lookup is provided for both keys. The program features a tiny +// Spanish-English dictionary with online query of words in both languages. + +#include + +//[ code_mi_to_b_path_bidirectional_map + +#include +#include +#include + +using namespace boost::bimaps; + +// A dictionary is a bidirectional map from strings to strings + +typedef bimap dictionary; +typedef dictionary::value_type translation; + +int main() +{ + dictionary d; + + // Fill up our microdictionary. + // first members Spanish, second members English. + + d.insert( translation("hola" ,"hello" )); + d.insert( translation("adios","goodbye")); + d.insert( translation("rosa" ,"rose" )); + d.insert( translation("mesa" ,"table" )); + + std::cout << "enter a word" << std::endl; + std::string word; + std::getline(std::cin,word); + + // search the queried word on the from index (Spanish) + + dictionary::left_const_iterator it = d.left.find(word); + + if( it != d.left.end() ) + { + // the second part of the element is the equivalent in English + + std::cout << word << " is said " + << it->second /*< `it` is an iterator of the left view, so + `it->second` refers to the right element of + the relation, the word in english >*/ + << " in English" << std::endl; + } + else + { + // word not found in Spanish, try our luck in English + + dictionary::right_const_iterator it2 = d.right.find(word); + if( it2 != d.right.end() ) + { + std::cout << word << " is said " + << it2->second /*< `it2` is an iterator of the right view, so + `it2->second` refers to the left element of + the relation, the word in spanish >*/ + << " in Spanish" << std::endl; + } + else + { + std::cout << "No such word in the dictionary" << std::endl; + } + } + + return 0; +} +//] diff --git a/example/mi_to_b_path/hashed_indices.cpp b/example/mi_to_b_path/hashed_indices.cpp new file mode 100755 index 0000000..22bb391 --- /dev/null +++ b/example/mi_to_b_path/hashed_indices.cpp @@ -0,0 +1,94 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +// Boost.Bimap Example +//----------------------------------------------------------------------------- +// Hashed indices can be used as an alternative to ordered indices when fast +// lookup is needed and sorting information is of no interest. The example +// features a word counter where duplicate entries are checked by means of a +// hashed index. + +#include + +//[ code_mi_to_b_path_hashed_indices + +#include +#include + +#include + +#include +#include +#include +#include + +using namespace boost::bimaps; + +struct word {}; +struct occurrences {}; + +typedef bimap +< + + multiset_of< tagged, std::greater >, +unordered_set_of< tagged< std::string, word> > + +> word_counter; + +typedef boost::tokenizer > text_tokenizer; + +int main() +{ + + std::string text= + "Relations between data in the STL are represented with maps." + "A map is a directed relation, by using it you are representing " + "a mapping. In this directed relation, the first type is related to " + "the second type but it is not true that the inverse relationship " + "holds. This is useful in a lot of situations, but there are some " + "relationships that are bidirectional by nature."; + + // feed the text into the container + + word_counter wc; + text_tokenizer tok(text,boost::char_separator(" \t\n.,;:!?'\"-")); + unsigned int total_occurrences = 0; + + for( text_tokenizer::const_iterator it = tok.begin(), it_end = tok.end(); + it != it_end ; ++it ) + { + ++total_occurrences; + + word_counter::map_by::iterator wit = + wc.by().insert( + word_counter::map_by::value_type(0,*it) + ).first; + + wc.by().modify_key( wit, ++_key); + } + + // list words by frequency of appearance + + std::cout << std::fixed << std::setprecision(2); + + for( word_counter::map_by::const_iterator + wit = wc.by().begin(), + wit_end = wc.by().end(); + + wit != wit_end; ++wit ) + { + std::cout << std::setw(15) << wit->get() << ": " + << std::setw(5) + << 100.0 * wit->get() / total_occurrences << "%" + << std::endl; + } + + return 0; +} +//] diff --git a/example/mi_to_b_path/mi_bidirectional_map.cpp b/example/mi_to_b_path/mi_bidirectional_map.cpp new file mode 100755 index 0000000..27045d0 --- /dev/null +++ b/example/mi_to_b_path/mi_bidirectional_map.cpp @@ -0,0 +1,107 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +/****************************************************************************** +Boost.MultiIndex +******************************************************************************/ + +#include + +//[ code_mi_to_b_path_mi_bidirectional_map + +#include +#include + +#include +#include +#include + +using namespace boost; +using namespace boost::multi_index; + +// tags for accessing both sides of a bidirectional map + +struct from {}; +struct to {}; + +// The class template bidirectional_map wraps the specification +// of a bidirectional map based on multi_index_container. + +template +struct bidirectional_map +{ + typedef std::pair value_type; + + typedef multi_index_container< + value_type, + indexed_by + < + ordered_unique + < + tag, member + >, + ordered_unique + < + tag, member + > + > + + > type; + +}; + +// A dictionary is a bidirectional map from strings to strings + +typedef bidirectional_map::type dictionary; + +int main() +{ + dictionary d; + + // Fill up our microdictionary. + // first members Spanish, second members English. + + d.insert(dictionary::value_type("hola","hello")); + d.insert(dictionary::value_type("adios","goodbye")); + d.insert(dictionary::value_type("rosa","rose")); + d.insert(dictionary::value_type("mesa","table")); + + std::cout << "enter a word" << std::endl; + std::string word; + std::getline(std::cin,word); + + // search the queried word on the from index (Spanish) + + dictionary::iterator it = d.get().find(word); + + if( it != d.end() ) + { + // the second part of the element is the equivalent in English + + std::cout << word << " is said " + << it->second << " in English" << std::endl; + } + else + { + // word not found in Spanish, try our luck in English + + dictionary::index_iterator::type it2 = d.get().find(word); + if( it2 != d.get().end() ) + { + std::cout << word << " is said " + << it2->first << " in Spanish" << std::endl; + } + else + { + std::cout << "No such word in the dictionary" << std::endl; + } + } + + return 0; +} +//] diff --git a/example/mi_to_b_path/mi_hashed_indices.cpp b/example/mi_to_b_path/mi_hashed_indices.cpp new file mode 100755 index 0000000..f91b835 --- /dev/null +++ b/example/mi_to_b_path/mi_hashed_indices.cpp @@ -0,0 +1,100 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +/***************************************************************************** +Boost.MultiIndex +*****************************************************************************/ + +#include + +//[ code_mi_to_b_path_mi_hashed_indices + +#include +#include + +#include + +#include +#include +#include +#include +#include + +using namespace boost::multi_index; +namespace bl = boost::lambda; + +// word_counter keeps the ocurrences of words inserted. A hashed +// index allows for fast checking of preexisting entries. + +struct word_counter_entry +{ + std::string word; + unsigned int occurrences; + + word_counter_entry( std::string word_ ) : word(word_), occurrences(0) {} +}; + +typedef multi_index_container +< + word_counter_entry, + indexed_by + < + ordered_non_unique + < + BOOST_MULTI_INDEX_MEMBER( + word_counter_entry,unsigned int,occurrences), + std::greater + >, + hashed_unique + < + BOOST_MULTI_INDEX_MEMBER(word_counter_entry,std::string,word) + > + > + +> word_counter; + +typedef boost::tokenizer > text_tokenizer; + +int main() +{ + std::string text= + "En un lugar de la Mancha, de cuyo nombre no quiero acordarme... " + "...snip..." + "...no se salga un punto de la verdad."; + + // feed the text into the container + + word_counter wc; + text_tokenizer tok(text,boost::char_separator(" \t\n.,;:!?'\"-")); + unsigned int total_occurrences = 0; + + for( text_tokenizer::iterator it = tok.begin(), it_end = tok.end(); + it != it_end ; ++it ) + { + ++total_occurrences; + word_counter::iterator wit = wc.insert(*it).first; + wc.modify_key( wit, ++ bl::_1 ); + } + + // list words by frequency of appearance + + std::cout << std::fixed << std::setprecision(2); + + for( word_counter::iterator wit = wc.begin(), wit_end=wc.end(); + wit != wit_end; ++wit ) + { + std::cout << std::setw(11) << wit->word << ": " + << std::setw(5) + << 100.0 * wit->occurrences / total_occurrences << "%" + << std::endl; + } + + return 0; +} +//] diff --git a/example/mi_to_b_path/tagged_bidirectional_map.cpp b/example/mi_to_b_path/tagged_bidirectional_map.cpp new file mode 100755 index 0000000..4c0ddb6 --- /dev/null +++ b/example/mi_to_b_path/tagged_bidirectional_map.cpp @@ -0,0 +1,90 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +// Boost.Bimap Example +//----------------------------------------------------------------------------- +// This example shows how to construct a bidirectional map with +// multi_index_container. +// By a bidirectional map we mean a container of elements of +// std::pair such that no two elements exists with +// the same first or second value (std::map only guarantees uniqueness of the +// first member). +// Fast lookup is provided for both keys. The program features a tiny +// Spanish-English dictionary with online query of words in both languages. + +//[ code_mi_to_b_path_tagged_bidirectional_map + +#include + +#include + +using namespace boost::bimaps; + +// tags + +struct spanish {}; +struct english {}; + +// A dictionary is a bidirectional map from strings to strings + +typedef bimap +< + tagged< std::string,spanish >, tagged< std::string,english > + +> dictionary; + +typedef dictionary::value_type translation; + +int main() +{ + dictionary d; + + // Fill up our microdictionary. + // first members Spanish, second members English. + + d.insert( translation("hola" ,"hello" )); + d.insert( translation("adios","goodbye")); + d.insert( translation("rosa" ,"rose" )); + d.insert( translation("mesa" ,"table" )); + + std::cout << "enter a word" << std::endl; + std::string word; + std::getline(std::cin,word); + + // search the queried word on the from index (Spanish) */ + + dictionary::map_by::const_iterator it = + d.by().find(word); + + if( it != d.by().end() ) + { + std::cout << word << " is said " + << it->get() << " in English" << std::endl; + } + else + { + // word not found in Spanish, try our luck in English + + dictionary::map_by::const_iterator it2 = + d.by().find(word); + + if( it2 != d.by().end() ) + { + std::cout << word << " is said " + << it2->get() << " in Spanish" << std::endl; + } + else + { + std::cout << "No such word in the dictionary" << std::endl; + } + } + + return 0; +} +//] diff --git a/example/mighty_bimap.cpp b/example/mighty_bimap.cpp new file mode 100755 index 0000000..8641ad3 --- /dev/null +++ b/example/mighty_bimap.cpp @@ -0,0 +1,109 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +// Boost.Bimap Example +//----------------------------------------------------------------------------- +// This is the translator example from the tutorial. +// In this example the set type of relation is changed to allow the iteration +// of the container. + +#include + +//[ code_mighty_bimap + +#include +#include +#include +#include +#include + +struct english {}; +struct spanish {}; + +int main() +{ + using namespace boost::bimaps; + + typedef bimap + < + unordered_set_of< tagged< std::string, spanish > >, + unordered_set_of< tagged< std::string, english > >, + list_of_relation + + > translator; + + translator trans; + + // We have to use `push_back` because the collection of relations is + // a `list_of_relation` + + trans.push_back( translator::value_type("hola" ,"hello" ) ); + trans.push_back( translator::value_type("adios" ,"goodbye" ) ); + trans.push_back( translator::value_type("rosa" ,"rose" ) ); + trans.push_back( translator::value_type("mesa" ,"table" ) ); + + std::cout << "enter a word" << std::endl; + std::string word; + std::getline(std::cin,word); + + // Search the queried word on the from index (Spanish) + + translator::map_by::const_iterator is + = trans.by().find(word); + + if( is != trans.by().end() ) + { + std::cout << word << " is said " + << is->get() + << " in English" << std::endl; + } + else + { + // Word not found in Spanish, try our luck in English + + translator::map_by::const_iterator ie + = trans.by().find(word); + + if( ie != trans.by().end() ) + { + std::cout << word << " is said " + << ie->get() + << " in Spanish" << std::endl; + } + else + { + // Word not found, show the possible translations + + std::cout << "No such word in the dictionary" << std::endl; + std::cout << "These are the possible translations" << std::endl; + + for( translator::const_iterator + i = trans.begin(), + i_end = trans.end(); + + i != i_end ; ++i ) + { + std::cout << i->get() + << " <---> " + << i->get() + << std::endl; + } + } + } + return 0; +} +//] diff --git a/example/population_bimap.cpp b/example/population_bimap.cpp new file mode 100755 index 0000000..84c5ecc --- /dev/null +++ b/example/population_bimap.cpp @@ -0,0 +1,121 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +// Boost.Bimap Example +//----------------------------------------------------------------------------- + +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +using namespace boost::bimaps; +using namespace boost; +using namespace std; + +int main() +{ + { + + typedef bimap< + + string, + multiset_of< optional > + + > bm_type; + + bm_type bm; + + assign::insert( bm ) + + ( "John" , string("lazarus" ) ) + ( "Peter", string("vinicius") ) + ( "Simon", string("vinicius") ) + ( "Brian", none ) + ; + + cout << "John is working in " + << bm.left.at( "John" ).get_value_or( "no project" ) + << endl; + + cout << "Project vinicius is being developed by " << endl; + BOOST_FOREACH( bm_type::right_reference rp, + bm.right.equal_range( std::string("vinicius") ) ) + { + cout << rp.second << endl; + } + + cout << "This workers need a project " << endl; + BOOST_FOREACH( bm_type::right_reference rp, + bm.right.equal_range(none) ) + { + cout << rp.second << endl; + } + +} + + //[ code_population_bimap + + typedef bimap< + + unordered_set_of< std::string >, + multiset_of< long, std::greater > + + > population_bimap; + + typedef population_bimap::value_type population; + + population_bimap pop; + pop.insert( population("China", 1321000000) ); + pop.insert( population("India", 1129000000) ); + pop.insert( population("United States", 301950000) ); + pop.insert( population("Indonesia", 234950000) ); + pop.insert( population("Brazil", 186500000) ); + pop.insert( population("Pakistan", 163630000) ); + + std::cout << "Countries by their population:" << std::endl; + + // First requirement + /*<< The right map view works like a + `std::multimap< long, std::string, std::greater >`, + We can iterate over it to print the results in the required order. >>*/ + for( population_bimap::right_const_iterator + i = pop.right.begin(), iend = pop.right.end(); + i != iend ; ++i ) + { + std::cout << i->second << " with " << i->first << std::endl; + } + + // Second requirement + /*<< The left map view works like a `std::unordered_map< std::string, long >`, + given the name of the country we can use it to search for the population + in constant time >>*/ + std::cout << "Population of China: " << pop.left.at("China") << std::endl; + //] + + return 0; +} + diff --git a/example/projection.cpp b/example/projection.cpp new file mode 100755 index 0000000..7fa3489 --- /dev/null +++ b/example/projection.cpp @@ -0,0 +1,60 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +// Boost.Bimap Example +//----------------------------------------------------------------------------- + +#include + +#include +#include + +#include +#include +using namespace boost::bimaps; + +void years_example() +{ + //[ code_projection_years + + typedef bimap > > bm_type; + + bm_type bm; + bm.insert( bm_type::value_type("John" ,34) ); + bm.insert( bm_type::value_type("Peter",24) ); + bm.insert( bm_type::value_type("Mary" ,12) ); + + // Find the name of the next younger person after Peter + + bm_type::left_const_iterator name_iter = bm.left.find("Peter"); + + bm_type::right_const_iterator years_iter = bm.project_right(name_iter); + + ++years_iter; + + std::cout << "The next younger person after Peter is " << years_iter->second; + //] +} + +int main() +{ + years_example(); + + return 0; +} + + diff --git a/example/repetitions_counter.cpp b/example/repetitions_counter.cpp new file mode 100755 index 0000000..5d93985 --- /dev/null +++ b/example/repetitions_counter.cpp @@ -0,0 +1,91 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +// Boost.Bimap Example +//----------------------------------------------------------------------------- + +#include + +#include +#include + +#include +#include +#include + +using namespace boost::bimaps; + +struct counter { + counter() : c(0) {} + counter& operator++() { ++c; return *this; } + unsigned int operator++(int) { return c++; } + operator const unsigned int() const { return c; } + private: + unsigned int c; +}; + +int main() +{ + //[ code_repetitions_counter + + typedef bimap + < + unordered_set_of< std::string >, + list_of< counter > /*< `counter` is an integer that is initialized + in zero in the constructor >*/ + + > word_counter; + + typedef boost::tokenizer > text_tokenizer; + + std::string text= + "Relations between data in the STL are represented with maps." + "A map is a directed relation, by using it you are representing " + "a mapping. In this directed relation, the first type is related to " + "the second type but it is not true that the inverse relationship " + "holds. This is useful in a lot of situations, but there are some " + "relationships that are bidirectional by nature."; + + // feed the text into the container + word_counter wc; + text_tokenizer tok(text,boost::char_separator(" \t\n.,;:!?'\"-")); + + for( text_tokenizer::const_iterator it = tok.begin(), it_end = tok.end(); + it != it_end ; ++it ) + { + /*<< Because the right collection type is `list_of`, the right data + is not used a key and can be modified in the same way as with + standard maps. >>*/ + ++ wc.left[*it]; + } + + // list words with counters by order of appearance + /*<< When we insert the elements using the left map view, the element + is inserted at the end of the list. >>*/ + for( word_counter::right_const_iterator + wit = wc.right.begin(), wit_end = wc.right.end(); + + wit != wit_end; ++wit ) + { + std::cout << wit->second << ": " << wit->first; + } + //] + + return 0; +} + + diff --git a/example/simple_bimap.cpp b/example/simple_bimap.cpp new file mode 100755 index 0000000..28d1e72 --- /dev/null +++ b/example/simple_bimap.cpp @@ -0,0 +1,82 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +// Boost.Bimap Example +//----------------------------------------------------------------------------- + +#include + +//[ code_simple_bimap + +#include +#include + +#include + +template< class MapType > +void print_map(const MapType & map, + const std::string & separator, + std::ostream & os ) +{ + typedef typename MapType::const_iterator const_iterator; + + for( const_iterator i = map.begin(), iend = map.end(); i != iend; ++i ) + { + os << i->first << separator << i->second << std::endl; + } +} + +int main() +{ + // Soccer World cup + + typedef boost::bimap< std::string, int > results_bimap; + typedef results_bimap::value_type position; + + results_bimap results; + results.insert( position("Argentina" ,1) ); + results.insert( position("Spain" ,2) ); + results.insert( position("Germany" ,3) ); + results.insert( position("France" ,4) ); + + std::cout << "The number of countries is " << results.size() + << std::endl; + + std::cout << "The winner is " << results.right.at(1) + << std::endl + << std::endl; + + std::cout << "Countries names ordered by their final position:" + << std::endl; + + // results.right works like a std::map< int, std::string > + + print_map( results.right, ") ", std::cout ); + + std::cout << std::endl + << "Countries names ordered alphabetically along with" + "their final position:" + << std::endl; + + // results.left works like a std::map< std::string, int > + + print_map( results.left, " ends in position ", std::cout ); + + return 0; +} +//] + diff --git a/example/standard_map_comparison.cpp b/example/standard_map_comparison.cpp new file mode 100755 index 0000000..4a757f5 --- /dev/null +++ b/example/standard_map_comparison.cpp @@ -0,0 +1,93 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +// Boost.Bimap Example +//----------------------------------------------------------------------------- + +#include + +#include +#include + +#include +#include + +using namespace boost::bimaps; + +//[ code_standard_map_comparison + +template< class Map, class CompatibleKey, class CompatibleData > +void use_it( Map & m, + const CompatibleKey & key, + const CompatibleData & data ) +{ + typedef typename Map::value_type value_type; + typedef typename Map::const_iterator const_iterator; + + m.insert( value_type(key,data) ); + const_iterator iter = m.find(key); + if( iter != m.end() ) + { + assert( iter->first == key ); + assert( iter->second == data ); + + std::cout << iter->first << " --> " << iter->second; + } + m.erase(key); +} + +int main() +{ + typedef bimap< set_of, set_of > bimap_type; + bimap_type bm; + + // Standard map + { + typedef std::map< std::string, int > map_type; + map_type m; + + use_it( m, "one", 1 ); + } + + // Left map view + { + typedef bimap_type::left_map map_type; + map_type & m = bm.left; + + use_it( m, "one", 1 ); + } + + // Reverse standard map + { + typedef std::map< int, std::string > reverse_map_type; + reverse_map_type rm; + + use_it( rm, 1, "one" ); + } + + // Right map view + { + typedef bimap_type::right_map reverse_map_type; + reverse_map_type & rm = bm.right; + + use_it( rm, 1, "one" ); + } + + return 0; +} +//] + diff --git a/example/step_by_step.cpp b/example/step_by_step.cpp new file mode 100755 index 0000000..bd8dd03 --- /dev/null +++ b/example/step_by_step.cpp @@ -0,0 +1,102 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +// Boost.Bimap Example +//----------------------------------------------------------------------------- + +#include + +#include +#include + +// A convinience header is avaiable in the boost directory: +#include + +int main() +{ + //[ code_step_by_step_definition + + typedef boost::bimap< int, std::string > bm_type; + bm_type bm; + //] + + //[ code_step_by_step_set_of_relations_view + + bm.insert( bm_type::value_type(1, "one" ) ); + bm.insert( bm_type::value_type(2, "two" ) ); + + std::cout << "There are " << bm.size() << "relations" << std::endl; + + for( bm_type::const_iterator iter = bm.begin(), iend = bm.end(); + iter != iend; ++iter ) + { + // iter->left : data : int + // iter->right : data : std::string + + std::cout << iter->left << " <--> " << iter->right << std::endl; + } + //] + + //[ code_step_by_step_left_map_view + + /*<< The type of `bm.left` is `bm_type::left_map` and the type + of `bm.right` is `bm_type::right_map` >>*/ + typedef bm_type::left_map::const_iterator left_const_iterator; + + for( left_const_iterator left_iter = bm.left.begin(), iend = bm.left.end(); + left_iter != iend; ++left_iter ) + { + // left_iter->first : key : int + // left_iter->second : data : std::string + + std::cout << left_iter->first << " --> " << left_iter->second << std::endl; + } + + /*<< `bm_type::left_`\ -type- can be used as a shortcut for the more verbose + `bm_type::left_map::`\ -type- >>*/ + bm_type::left_const_iterator left_iter = bm.left.find(2); + assert( left_iter->second == "two" ); + + /*<< This line produces the same effect of + `bm.insert( bm_type::value_type(3,"three") );` >>*/ + bm.left.insert( bm_type::left_value_type( 3, "three" ) ); + //] + + + + //[ code_step_by_step_right_map_view + + bm_type::right_const_iterator right_iter = bm.right.find("two"); + + // right_iter->first : key : std::string + // right_iter->second : data : int + + assert( right_iter->second == 2 ); + + assert( bm.right.at("one") == 1 ); + + bm.right.erase("two"); + + /*<< This line produces the same effect of + `bm.insert( bm_type::value_type(4,"four") );` >>*/ + bm.right.insert( bm_type::right_value_type( "four", 4 ) ); + //] + + return 0; +} +//] + diff --git a/example/tagged_simple_bimap.cpp b/example/tagged_simple_bimap.cpp new file mode 100755 index 0000000..b702bc8 --- /dev/null +++ b/example/tagged_simple_bimap.cpp @@ -0,0 +1,86 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +// Boost.Bimap Example +//----------------------------------------------------------------------------- + +#include + +//[ code_tagged_simple_bimap + +#include + +#include + +struct country {}; +struct place {}; + +int main() +{ + using namespace boost::bimaps; + + // Soccer World cup. + + typedef bimap + < + tagged< std::string, country >, + tagged< int , place > + + > results_bimap; + + typedef results_bimap::value_type position; + + results_bimap results; + results.insert( position("Argentina" ,1) ); + results.insert( position("Spain" ,2) ); + results.insert( position("Germany" ,3) ); + results.insert( position("France" ,4) ); + + std::cout << "Countries names ordered by their final position:" + << std::endl; + + /*<< `results.by()` is equivalent to `results.right` >>*/ + for( results_bimap::map_by::const_iterator + i = results.by().begin(), + iend = results.by().end() ; + i != iend; ++i ) + { + /*<< `get` works for each view of the bimap >>*/ + std::cout << i->get() << ") " + << i->get() << std::endl; + } + + std::cout << std::endl + << "Countries names ordered alfabetically along with" + "their final position:" + << std::endl; + + /*<< `results.by()` is equivalent to `results.left` >>*/ + for( results_bimap::map_by::const_iterator + i = results.by().begin(), + iend = results.by().end() ; + i != iend; ++i ) + { + std::cout << i->get() << " ends " + << i->get() << "º" + << std::endl; + } + + return 0; +} +//] + diff --git a/example/tutorial_info_hook.cpp b/example/tutorial_info_hook.cpp new file mode 100755 index 0000000..92f8c74 --- /dev/null +++ b/example/tutorial_info_hook.cpp @@ -0,0 +1,163 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +// Boost.Bimap Example +//----------------------------------------------------------------------------- + +#include + +#include +#include + +#include +#include + +using namespace boost::bimaps; + + +void tutorial_about_info_hook() +{ + //[ code_tutorial_info_hook_first + + typedef bimap< + + multiset_of< std::string >, // author + set_of< std::string >, // title + + with_info< std::string > // abstract + + > bm_type; + typedef bm_type::value_type book; + + bm_type bm; + + bm.insert( + + book( "Bjarne Stroustrup" , "The C++ Programming Language", + + "For C++ old-timers, the first edition of this book is" + "the one that started it all—the font of our knowledge." ) + ); + + + // Print the author of the bible + std::cout << bm.right.at("The C++ Programming Language"); + + // Print the abstract of this book + bm_type::left_iterator i = bm.left.find("Bjarne Stroustrup"); + std::cout << i->info; + //] + + // Contrary to the two key types, the information will be mutable + // using iterators. + + //[ code_tutorial_info_hook_mutable + + i->info += "More details about this book"; + //] + + // A new function is included in unique map views: info_at(key), that + // mimics the standard at(key) function but returned the associated + // information instead of the data. + + //[ code_tutorial_info_hook_info_at + + // Print the new abstract + std::cout << bm.right.info_at("The C++ Programming Language"); + //] +} + +struct author {}; +struct title {}; +struct abstract {}; + +void tutorial_about_tagged_info_hook() +{ + //[ code_tutorial_info_hook_tagged_info + + typedef bimap< + + multiset_of< tagged< std::string, author > >, + set_of< tagged< std::string, title > >, + + with_info< tagged< std::string, abstract > > + + > bm_type; + typedef bm_type::value_type book; + + bm_type bm; + + bm.insert( + + book( "Bjarne Stroustrup" , "The C++ Programming Language", + + "For C++ old-timers, the first edition of this book is" + "the one that started it all—the font of our knowledge." ) + ); + + // Print the author of the bible + std::cout << bm.by().at("The C++ Programming Language"); + + // Print the abstract of this book + bm_type::map_by<author>::iterator i = bm.by<author>().find("Bjarne Stroustrup"); + std::cout << i->get<abstract>(); + + // Contrary to the two key types, the information will be mutable + // using iterators. + + i->get<abstract>() += "More details about this book"; + + // Print the new abstract + std::cout << bm.by<title>().info_at("The C++ Programming Language"); + //] +} + + +void bimap_without_an_info_hook() +{ + //[ code_tutorial_info_hook_nothing + + typedef bimap< + + multiset_of< std::string >, // author + set_of< std::string > // title + + > bm_type; + typedef bm_type::value_type book; + + bm_type bm; + + bm.insert( book( "Bjarne Stroustrup" , "The C++ Programming Language" ) ); + bm.insert( book( "Scott Meyers" , "Effective C++" ) ); + bm.insert( book( "Andrei Alexandrescu" , "Modern C++ Design" ) ); + + // Print the author of Modern C++ + std::cout << bm.right.at( "Modern C++ Design" ); + //] +} + + +int main() +{ + tutorial_about_info_hook(); + tutorial_about_tagged_info_hook(); + bimap_without_an_info_hook(); + + return 0; +} + + diff --git a/example/tutorial_modify_and_replace.cpp b/example/tutorial_modify_and_replace.cpp new file mode 100755 index 0000000..c9017cd --- /dev/null +++ b/example/tutorial_modify_and_replace.cpp @@ -0,0 +1,118 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +// Boost.Bimap Example +//----------------------------------------------------------------------------- + +#include <boost/config.hpp> + +#include <string> +#include <iostream> + +#include <boost/bimap/bimap.hpp> +#include <boost/bimap/support/lambda.hpp> + +using namespace boost::bimaps; + +void test_replace() +{ + //[ code_tutorial_replace + + typedef bimap< int, std::string > bm_type; + bm_type bm; + + bm.insert( bm_type::value_type(1,"one") ); + + // Replace (1,"one") with (1,"1") using the right map view + { + bm_type::right_iterator it = bm.right.find("one"); + + bool successful_replace = bm.right.replace_key( it, "1" ); + + assert( successful_replace ); + } + + bm.insert( bm_type::value_type(2,"two") ); + + // Fail to replace (1,"1") with (1,"two") using the left map view + { + assert( bm.size() == 2 ); + + bm_type::left_iterator it = bm.left.find(1); + + bool successful_replace = bm.left.replace_data( it, "two" ); + + /*<< `it` is still valid here, and the bimap was left unchanged >>*/ + assert( ! successful_replace ); + assert( bm.size() == 2 ); + } + //] +} + +void test_modify() +{ + //[ code_tutorial_modify + + typedef bimap< int, std::string > bm_type; + bm_type bm; + bm.insert( bm_type::value_type(1,"one") ); + + // Modify (1,"one") to (1,"1") using the right map view + { + bm_type::right_iterator it = bm.right.find("one"); + + bool successful_modify = bm.right.modify_key( it , _key = "1" ); + + assert( successful_modify ); + } + + bm.insert( bm_type::value_type(2,"two") ); + + // Fail to modify (1,"1") to (1,"two") using the left map view + { + assert( bm.size() == 2 ); + + bm_type::left_iterator it = bm.left.find(1); + + bool successful_modify = bm.left.modify_data( it, _data = "two" ); + + /*<< `it` is not longer valid and `(1,"1")` is removed from the bimap >>*/ + assert( ! successful_modify ); + assert( bm.size() == 1 ); + } + //] + + /* + // Modify (2,"two") to (3,"two") using the set of relations view + { + bm_type::iterator it = bm.begin(); + + bool successful_modify = bm.modify( it, ++_left ); + + assert( successful_modify ); + } + */ +} + +int main() +{ + test_replace(); + test_modify(); + return 0; +} +//] + diff --git a/example/tutorial_range.cpp b/example/tutorial_range.cpp new file mode 100755 index 0000000..543ca96 --- /dev/null +++ b/example/tutorial_range.cpp @@ -0,0 +1,100 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +// Boost.Bimap Example +//----------------------------------------------------------------------------- + +#include <boost/config.hpp> + +#include <string> +#include <iostream> + +#include <boost/bimap/bimap.hpp> +#include <boost/bimap/support/lambda.hpp> + +using namespace boost::bimaps; + +void using_upper_and_lower_bound() +{ + //[ code_tutorial_range_standard_way + + typedef bimap<int,std::string> bm_type; + bm_type bm; + + // ... + + bm_type::left_iterator iter_first = bm.left.lower_bound(20); + bm_type::left_iterator iter_second = bm.left.upper_bound(50); + + // range [iter_first,iter_second) contains the elements in [20,50] + //] + + // Subtle changes + { + //[ code_tutorial_range_standard_way_subtle_changes + + bm_type::left_iterator iter_first = bm.left.upper_bound(20); + bm_type::left_iterator iter_second = bm.left.lower_bound(50); + + // range [iter_first,iter_second) contains the elements in (20,50) + //] + } +} + +void using_range() +{ + //[ code_tutorial_range + + typedef bimap<int,std::string> bm_type; + bm_type bm; + + // ... + + /*<< `range_type` is a handy typedef equal to `std::pair<iterator,iterator>`. + `const_range_type` is provided too, and it is equal to + `std::pair<const_iterator,const_iterator>` >>*/ + bm_type::left_range_type r; + + /*<< _key is a Boost.Lambda placeholder. To use it you have to include + `<boost/bimap/support/lambda.hpp>` >>*/ + r = bm.left.range( 20 <= _key, _key <= 50 ); // [20,50] + + r = bm.left.range( 20 < _key, _key < 50 ); // (20,50) + + r = bm.left.range( 20 <= _key, _key < 50 ); // [20,50) + //] + + //[ code_tutorial_range_unbounded + + r = bm.left.range( 20 <= _key, unbounded ); // [20,inf) + + r = bm.left.range( unbounded , _key < 50 ); // (-inf,50) + + /*<< This is equivalent to std::make_pair(s.begin(),s.end()) >>*/ + r = bm.left.range( unbounded , unbounded ); // (-inf,inf) + //] +} + +int main() +{ + using_upper_and_lower_bound(); + using_range(); + + return 0; +} + + diff --git a/example/unconstrained_collection.cpp b/example/unconstrained_collection.cpp new file mode 100755 index 0000000..5248f74 --- /dev/null +++ b/example/unconstrained_collection.cpp @@ -0,0 +1,94 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +// Boost.Bimap Example +//----------------------------------------------------------------------------- + +#include <boost/config.hpp> + +#include <string> +#include <iostream> + +#include <map> +#include <boost/bimap/bimap.hpp> +#include <boost/bimap/unconstrained_set_of.hpp> +#include <boost/bimap/support/lambda.hpp> + +using namespace boost::bimaps; + +int main() +{ + // Boost.Bimap + { + //[ code_unconstrained_collection_bimap + + typedef bimap< std::string, unconstrained_set_of<int> > bm_type; + typedef bm_type::left_map map_type; + + bm_type bm; + map_type & m = bm.left; + //] + + //[ code_unconstrained_collection_common + + m["one"] = 1; + + assert( m.find("one") != m.end() ); + + for( map_type::iterator i = m.begin(), iend = m.end(); i != iend; ++i ) + { + /*<< The right collection of the bimap is mutable so its elements + can be modified using iterators. >>*/ + ++(i->second); + } + + m.erase("one"); + //] + + m["one"] = 1; + m["two"] = 2; + + //[ code_unconstrained_collection_only_for_bimap + typedef map_type::const_iterator const_iterator; + typedef std::pair<const_iterator,const_iterator> const_range; + + /*<< This range is a model of BidirectionalRange, read the docs of + Boost.Range for more information. >>*/ + const_range r = m.range( "one" <= _key, _key <= "two" ); + for( const_iterator i = r.first; i != r.second; ++i ) + { + std::cout << i->first << "-->" << i->second << std::endl; + } + + m.modify_key( m.begin(), _key = "1" ); + //] + } + + // Standard map + { + //[ code_unconstrained_collection_map + + typedef std::map< std::string, int > map_type; + + map_type m; + //] + } + + return 0; +} + + diff --git a/example/user_defined_names.cpp b/example/user_defined_names.cpp new file mode 100755 index 0000000..24db784 --- /dev/null +++ b/example/user_defined_names.cpp @@ -0,0 +1,142 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +// Boost.Bimap Example +//----------------------------------------------------------------------------- + +#include <boost/config.hpp> + +#include <string> +#include <iostream> + +#include <boost/bimap/bimap.hpp> +#include <boost/bimap/multiset_of.hpp> + +using namespace boost::bimaps; + +void untagged_version() +{ + //[ code_user_defined_names_untagged_version + + typedef bimap + < + multiset_of<std::string>, + int + + > People; + + People people; + + // ... + + int user_id; + std::cin >> user_id; + + // people.right : map<id,name> + + People::right_const_iterator id_iter = people.right.find(user_id); + if( id_iter != people.right.end() ) + { + // first : id + // second : name + + std::cout << "name: " << id_iter->second << std::endl + << "id: " << id_iter->first << std::endl; + } + else + { + std::cout << "Unknown id, users are:" << std::endl; + + // people.left : map<name,id> + + for( People::left_const_iterator + name_iter = people.left.begin(), + iend = people.left.end(); + + name_iter != iend; ++name_iter ) + { + // first : name + // second : id + + std::cout << "name: " << name_iter->first << std::endl + << "id: " << name_iter->second << std::endl; + } + } + //] +} + +struct id {}; +struct name {}; + +void tagged_version() +{ + //[ code_user_defined_names_tagged_version + + //<- + /* + //-> + struct id {}; // Tag for the identification number + struct name {}; // Tag for the name of the person + //<- + */ + //-> + + typedef bimap + < + tagged< int , id > , + multiset_of< tagged< std::string, name > > + + > People; + + People people; + + // ... + + int user_id; + std::cin >> user_id; + + People::map_by<id>::const_iterator id_iter = people.by<id>().find(user_id); + if( id_iter != people.by<id>().end() ) + { + std::cout << "name: " << id_iter->get<name>() << std::endl + << "id: " << id_iter->get<id>() << std::endl; + } + else + { + std::cout << "Unknown id, users are:" << std::endl; + + for( People::map_by<name>::const_iterator + name_iter = people.by<name>().begin(), + iend = people.by<name>().end(); + + name_iter != iend; ++name_iter ) + { + std::cout << "name: " << name_iter->get<name>() << std::endl + << "id: " << name_iter->get<id>() << std::endl; + } + } + //] +} + +int main() +{ + untagged_version(); + tagged_version(); + + return 0; +} + diff --git a/index.html b/index.html new file mode 100755 index 0000000..84be2fc --- /dev/null +++ b/index.html @@ -0,0 +1,9 @@ +<html> +<head> +<meta http-equiv="refresh" content="0; URL=doc/html/index.html"> +</head> +<body> +Automatic redirection failed, please go to the +<a href="doc/html/index.html">Boost.Bimap documentation</a>. +</body> +</html> diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 new file mode 100755 index 0000000..091e875 --- /dev/null +++ b/test/Jamfile.v2 @@ -0,0 +1,80 @@ +# Boost.Bimap +# +# Copyright (c) 2006-2007 Matias Capeletto +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +# bring in rules for testing +import testing ; + + +test-suite "tagged_test" + : + [ run test_tagged.cpp ] + ; + + +test-suite "relation_test" + : + [ run test_structured_pair.cpp ] + [ run test_mutant.cpp ] + [ run test_mutant_relation.cpp ] + ; + + +test-suite "bimap_test" + : + + # Check library user interface + [ run test_bimap_set_of.cpp ] + [ run test_bimap_multiset_of.cpp ] + [ run test_bimap_unordered_set_of.cpp ] + [ run test_bimap_unordered_multiset_of.cpp ] + [ run test_bimap_list_of.cpp ] + [ run test_bimap_vector_of.cpp ] + + # Test bimap container + [ run test_bimap_ordered.cpp ] + [ run test_bimap_unordered.cpp ] + [ run test_bimap_sequenced.cpp ] + [ run test_bimap_unconstrained.cpp ] + [ run test_bimap_assign.cpp ] + [ run test_bimap_property_map.cpp ] + [ run test_bimap_modify.cpp ] + [ run test_bimap_range.cpp ] + [ run test_bimap_operator_bracket.cpp ] + [ run test_bimap_lambda.cpp ] + [ run test_bimap_mutable.cpp ] + [ run test_bimap_extra.cpp ] + [ run test_bimap_convenience_header.cpp ] + [ run test_bimap_project.cpp ] + [ run test_bimap_serialization.cpp + /boost/serialization//boost_serialization ] + [ run test_bimap_info.cpp ] + ; + +test-suite "compile_fail_test" + : + + [ compile-fail compile_fail/test_bimap_mutable_1.cpp ] + [ compile-fail compile_fail/test_bimap_mutable_2.cpp ] + [ compile-fail compile_fail/test_bimap_mutable_3.cpp ] + [ compile-fail compile_fail/test_bimap_info_1.cpp ] + [ compile-fail compile_fail/test_bimap_info_2.cpp ] + [ compile-fail compile_fail/test_bimap_info_3.cpp ] + ; + +test-suite "bimap_and_boost" + : + [ run ../example/bimap_and_boost/property_map.cpp ] + [ run ../example/bimap_and_boost/range.cpp ] + [ run ../example/bimap_and_boost/foreach.cpp ] + [ run ../example/bimap_and_boost/lambda.cpp ] + [ run ../example/bimap_and_boost/assign.cpp ] + [ run ../example/bimap_and_boost/xpressive.cpp ] + [ run ../example/bimap_and_boost/typeof.cpp ] + [ compile ../example/bimap_and_boost/serialization.cpp + /boost/serialization//boost_serialization ] + ; diff --git a/test/compile_fail/test_bimap_info_1.cpp b/test/compile_fail/test_bimap_info_1.cpp new file mode 100755 index 0000000..e253619 --- /dev/null +++ b/test/compile_fail/test_bimap_info_1.cpp @@ -0,0 +1,49 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +#include <boost/config.hpp> + +// Boost.Test +#include <boost/test/minimal.hpp> + +// Boost.Bimap +#include <boost/bimap/bimap.hpp> +#include <boost/bimap/list_of.hpp> + + +void test_bimap_info_1() +{ + using namespace boost::bimaps; + + typedef bimap< int, list_of<int>, with_info<int> > bm_type; + bm_type bm; + bm.insert( bm_type::value_type(1,1) ); + + // fail test + { + const bm_type & cbm = bm; + cbm.begin()->info = 10; + } +} + + +int test_main( int, char* [] ) +{ + test_bimap_info_1(); + return 0; +} + diff --git a/test/compile_fail/test_bimap_info_2.cpp b/test/compile_fail/test_bimap_info_2.cpp new file mode 100755 index 0000000..339344e --- /dev/null +++ b/test/compile_fail/test_bimap_info_2.cpp @@ -0,0 +1,48 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +#include <boost/config.hpp> + +// Boost.Test +#include <boost/test/minimal.hpp> + +// Boost.Bimap +#include <boost/bimap/bimap.hpp> +#include <boost/bimap/list_of.hpp> + + +void test_bimap_info_2() +{ + using namespace boost::bimaps; + + typedef bimap< int, list_of<int> > bm_type; + bm_type bm; + bm.insert( bm_type::value_type(1,1) ); + + // fail test + { + bm.begin()->info; + } +} + + +int test_main( int, char* [] ) +{ + test_bimap_info_2(); + return 0; +} + diff --git a/test/compile_fail/test_bimap_info_3.cpp b/test/compile_fail/test_bimap_info_3.cpp new file mode 100755 index 0000000..4dea3b5 --- /dev/null +++ b/test/compile_fail/test_bimap_info_3.cpp @@ -0,0 +1,48 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +#include <boost/config.hpp> + +// Boost.Test +#include <boost/test/minimal.hpp> + +// Boost.Bimap +#include <boost/bimap/bimap.hpp> +#include <boost/bimap/list_of.hpp> + + +void test_bimap_info_3() +{ + using namespace boost::bimaps; + + typedef bimap< int, list_of<int> > bm_type; + bm_type bm; + bm.insert( bm_type::value_type(1,1) ); + + // fail test + { + bm.left.info_at(1); + } +} + + +int test_main( int, char* [] ) +{ + test_bimap_info_3(); + return 0; +} + diff --git a/test/compile_fail/test_bimap_mutable_1.cpp b/test/compile_fail/test_bimap_mutable_1.cpp new file mode 100755 index 0000000..03587e1 --- /dev/null +++ b/test/compile_fail/test_bimap_mutable_1.cpp @@ -0,0 +1,49 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +#include <boost/config.hpp> + +// Boost.Test +#include <boost/test/minimal.hpp> + +// Boost.Bimap +#include <boost/bimap/bimap.hpp> +#include <boost/bimap/list_of.hpp> + + +void test_bimap_mutable_1() +{ + using namespace boost::bimaps; + + typedef bimap< int, list_of<int> > bm_type; + bm_type bm; + bm.insert( bm_type::value_type(1,1) ); + + // fail test + { + const bm_type & cbm = bm; + cbm.begin()->right = 10; + } +} + + +int test_main( int, char* [] ) +{ + test_bimap_mutable_1(); + return 0; +} + diff --git a/test/compile_fail/test_bimap_mutable_2.cpp b/test/compile_fail/test_bimap_mutable_2.cpp new file mode 100755 index 0000000..4693423 --- /dev/null +++ b/test/compile_fail/test_bimap_mutable_2.cpp @@ -0,0 +1,49 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +#include <boost/config.hpp> + +// Boost.Test +#include <boost/test/minimal.hpp> + +// Boost.Bimap +#include <boost/bimap/bimap.hpp> +#include <boost/bimap/list_of.hpp> + + +void test_bimap_mutable_2() +{ + using namespace boost::bimaps; + + typedef bimap< int, list_of<int> > bm_type; + bm_type bm; + bm.insert( bm_type::value_type(1,1) ); + + // fail test + { + const bm_type & cbm = bm; + cbm.left.find(1)->second = 10; + } +} + + +int test_main( int, char* [] ) +{ + test_bimap_mutable_2(); + return 0; +} + diff --git a/test/compile_fail/test_bimap_mutable_3.cpp b/test/compile_fail/test_bimap_mutable_3.cpp new file mode 100755 index 0000000..8b68990 --- /dev/null +++ b/test/compile_fail/test_bimap_mutable_3.cpp @@ -0,0 +1,48 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +#include <boost/config.hpp> + +// Boost.Test +#include <boost/test/minimal.hpp> + +// Boost.Bimap +#include <boost/bimap/bimap.hpp> +#include <boost/bimap/list_of.hpp> + + +void test_bimap_mutable_3() +{ + using namespace boost::bimaps; + + typedef bimap< int, list_of<int> > bm_type; + bm_type bm; + bm.insert( bm_type::value_type(1,1) ); + + // fail test + { + bm.right.begin()->second = 10; + } +} + + +int test_main( int, char* [] ) +{ + test_bimap_mutable_3(); + return 0; +} + diff --git a/test/test_bimap.hpp b/test/test_bimap.hpp new file mode 100755 index 0000000..5f9298c --- /dev/null +++ b/test/test_bimap.hpp @@ -0,0 +1,488 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef LIBS_BIMAP_TEST_BIMAP_TEST_HPP +#define LIBS_BIMAP_TEST_BIMAP_TEST_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include <boost/config.hpp> + +// std +#include <cassert> +#include <algorithm> + +#include <boost/lambda/lambda.hpp> + +template< class Container, class Data > +void test_container(Container & c, const Data & d) +{ + assert( d.size() > 2 ); + + c.clear(); + + BOOST_CHECK( c.size() == 0 ); + BOOST_CHECK( c.empty() ); + + c.insert( *d.begin() ); + + c.insert( ++d.begin(),d.end() ); + + BOOST_CHECK( c.size() == d.size() ); + + BOOST_CHECK( c.size() <= c.max_size() ); + BOOST_CHECK( ! c.empty() ); + + c.erase( c.begin() ); + + BOOST_CHECK( c.size() == d.size() - 1 ); + + c.erase( c.begin(), c.end() ); + + BOOST_CHECK( c.empty() ); + + c.insert( *d.begin() ); + + BOOST_CHECK( c.size() == 1 ); + + c.insert( c.begin(), *(++d.begin()) ); + + BOOST_CHECK( c.size() == 2 ); + + BOOST_CHECK( c.begin() != c.end() ); + +} + +template< class Container, class Data > +void test_sequence_container(Container & c, const Data & d) +{ + assert( d.size() > 2 ); + + c.clear(); + + BOOST_CHECK( c.size() == 0 ); + BOOST_CHECK( c.empty() ); + + c.push_front( * d.begin() ); + c.push_back ( *(++d.begin()) ); + + BOOST_CHECK( c.front() == * c.begin() ); + BOOST_CHECK( c.back () == *(++c.begin()) ); + + BOOST_CHECK( c.size() == 2 ); + + BOOST_CHECK( c.size() <= c.max_size() ); + BOOST_CHECK( ! c.empty() ); + + c.erase( c.begin() ); + + BOOST_CHECK( c.size() == 1 ); + + c.insert( c.begin(), *(++d.begin()) ); + + c.erase( c.begin(), c.end() ); + + BOOST_CHECK( c.empty() ); + + c.push_front( *d.begin() ); + + BOOST_CHECK( c.size() == 1 ); + + BOOST_CHECK( c.begin() != c.end() ); + +} + +template< class Container, class Data > +void test_associative_container(Container & c, const Data & d) +{ + assert( d.size() > 2 ); + + c.clear(); + c.insert(d.begin(),d.end()); + + for( typename Data::const_iterator di = d.begin(), de = d.end(); + di != de; ++di ) + { + BOOST_CHECK( c.find(*di) != c.end() ); + } + + typename Data::const_iterator da = d.begin(); + typename Data::const_iterator db = ++d.begin(); + + c.erase(*da); + + BOOST_CHECK( c.size() == d.size()-1 ); + + BOOST_CHECK( c.count(*da) == 0 ); + BOOST_CHECK( c.count(*db) == 1 ); + + BOOST_CHECK( c.find(*da) == c.end() ); + BOOST_CHECK( c.find(*db) != c.end() ); + + BOOST_CHECK( c.equal_range(*db).first != c.end() ); + + c.clear(); + + BOOST_CHECK( c.equal_range(*da).first == c.end() ); +} + + +template< class Container, class Data > +void test_pair_associative_container(Container & c, const Data & d) +{ + assert( d.size() > 2 ); + + c.clear(); + c.insert(d.begin(),d.end()); + + for( typename Data::const_iterator di = d.begin(), de = d.end(); + di != de; ++di ) + { + BOOST_CHECK( c.find(di->first) != c.end() ); + } + + typename Data::const_iterator da = d.begin(); + typename Data::const_iterator db = ++d.begin(); + + c.erase(da->first); + + BOOST_CHECK( c.size() == d.size()-1 ); + + BOOST_CHECK( c.count(da->first) == 0 ); + BOOST_CHECK( c.count(db->first) == 1 ); + + BOOST_CHECK( c.find(da->first) == c.end() ); + BOOST_CHECK( c.find(db->first) != c.end() ); + + BOOST_CHECK( c.equal_range(db->first).first != c.end() ); + + c.clear(); + + BOOST_CHECK( c.equal_range(da->first).first == c.end() ); +} + + +template< class Container, class Data > +void test_simple_ordered_associative_container_equality(Container & c, const Data & d) +{ + BOOST_CHECK( std::equal( c. begin(), c. end(), d. begin() ) ); + BOOST_CHECK( std::equal( c.rbegin(), c.rend(), d.rbegin() ) ); + + BOOST_CHECK( c.lower_bound( *d.begin() ) == c.begin() ); + BOOST_CHECK( c.upper_bound( *d.begin() ) == ++c.begin() ); +} + +template< class Container, class Data > +void test_simple_ordered_associative_container(Container & c, const Data & d) +{ + assert( d.size() > 2 ); + + c.clear(); + c.insert(d.begin(),d.end()); + + for( typename Data::const_iterator di = d.begin(), de = d.end(); + di != de; ++di ) + { + typename Container::const_iterator ci = c.find(*di); + BOOST_CHECK( ci != c.end() ); + + BOOST_CHECK( ! c.key_comp()(*ci,*di) ); + BOOST_CHECK( ! c.value_comp()(*ci,*di) ); + } + + test_simple_ordered_associative_container_equality(c, d); + + const Container & cr = c; + + test_simple_ordered_associative_container_equality(cr, d); + + /* + BOOST_CHECK( c.range( *c.begin() <= ::boost::lambda::_1, + ::boost::lambda::_1 <= *(++c.begin()) ). + first == c.begin() + ); + */ +} + +template< class Container, class Data > +void test_simple_unordered_associative_container(Container & c, const Data & d) +{ + c.clear(); + c.insert( d.begin(), d.end() ); + + BOOST_CHECK( c.bucket_count() * c.max_load_factor() >= d.size() ); + BOOST_CHECK( c.max_bucket_count() >= c.bucket_count() ); + + for( typename Data::const_iterator di = d.begin(), de = d.end() ; + di != de ; ++di ) + { + // non const + { + typename Container::size_type nb = c.bucket(*c.find(*di)); + + BOOST_CHECK( c.begin(nb) != c.end(nb) ); + } + + // const + { + const Container & const_c = c; + + BOOST_CHECK( + const_c.bucket_size(const_c.bucket(*di)) == 1 + ); + + typename Container::size_type nb = + const_c.bucket(*const_c.find(*di)); + + BOOST_CHECK( + const_c.begin(nb) != const_c.end(nb) + ); + } + } + + + BOOST_CHECK( c.load_factor() < c.max_load_factor() ); + + c.max_load_factor(0.75); + + BOOST_CHECK( c.max_load_factor() == 0.75 ); + + c.rehash(10); +} + + +template< class Container, class Data > +void test_pair_ordered_associative_container_equality(Container & c, const Data & d) +{ + BOOST_CHECK( std::equal( c. begin(), c. end(), d. begin() ) ); + BOOST_CHECK( std::equal( c.rbegin(), c.rend(), d.rbegin() ) ); + + BOOST_CHECK( c.lower_bound( d.begin()->first ) == c.begin() ); + BOOST_CHECK( c.upper_bound( d.begin()->first ) == ++c.begin() ); +} + +template< class Container, class Data > +void test_pair_ordered_associative_container(Container & c, const Data & d) +{ + assert( d.size() > 2 ); + + c.clear(); + c.insert(d.begin(),d.end()); + + for( typename Container::const_iterator ci = c.begin(), ce = c.end(); + ci != ce; ++ci ) + { + typename Data::const_iterator di = d.find(ci->first); + BOOST_CHECK( di != d.end() ); + BOOST_CHECK( ! c.key_comp()(di->first,ci->first) ); + BOOST_CHECK( ! c.value_comp()(*ci,*di) ); + } + + test_pair_ordered_associative_container_equality(c, d); + + const Container & cr = c; + + test_pair_ordered_associative_container_equality(cr, d); + + BOOST_CHECK( c.range( c.begin()->first <= ::boost::lambda::_1, + ::boost::lambda::_1 <= (++c.begin())->first ). + first == c.begin() + ); +} + + +template< class Container, class Data > +void test_pair_unordered_associative_container(Container & c, const Data & d) +{ + c.clear(); + c.insert( d.begin(), d.end() ); + + BOOST_CHECK( c.bucket_count() * c.max_load_factor() >= d.size() ); + BOOST_CHECK( c.max_bucket_count() >= c.bucket_count() ); + + for( typename Data::const_iterator di = d.begin(), de = d.end() ; + di != de ; ++di ) + { + // non const + { + typename Container::size_type nb = + c.bucket(c.find(di->first)->first); + + BOOST_CHECK( c.begin(nb) != c.end(nb) ); + } + + // const + { + const Container & const_c = c; + + BOOST_CHECK( const_c.bucket_size(const_c.bucket(di->first)) == 1 ); + + typename Container::size_type nb = + const_c.bucket(const_c.find(di->first)->first); + + BOOST_CHECK( const_c.begin(nb) != const_c.end(nb) ); + } + } + + + BOOST_CHECK( c.load_factor() < c.max_load_factor() ); + + c.max_load_factor(0.75); + + BOOST_CHECK( c.max_load_factor() == 0.75 ); + + c.rehash(10); +} + + +template< class Container, class Data > +void test_unique_container(Container & c, Data & d) +{ + c.clear(); + c.insert(d.begin(),d.end()); + c.insert(*d.begin()); + BOOST_CHECK( c.size() == d.size() ); +} + +template< class Container, class Data > +void test_non_unique_container(Container & c, Data & d) +{ + c.clear(); + c.insert(d.begin(),d.end()); + c.insert(*d.begin()); + BOOST_CHECK( c.size() == (d.size()+1) ); +} + + + +template< class Bimap, class Data, class LeftData, class RightData > +void test_basic_bimap( Bimap & b, + const Data & d, + const LeftData & ld, const RightData & rd) +{ + using namespace boost::bimaps; + + test_container(b,d); + + BOOST_CHECK( & b.left == & b.template by<member_at::left >() ); + BOOST_CHECK( & b.right == & b.template by<member_at::right>() ); + + test_container(b.left , ld); + test_container(b.right, rd); +} + +template< class LeftTag, class RightTag, class Bimap, class Data > +void test_tagged_bimap(Bimap & b, + const Data & d) +{ + using namespace boost::bimaps; + + BOOST_CHECK( &b.left == & b.template by<LeftTag >() ); + BOOST_CHECK( &b.right == & b.template by<RightTag>() ); + + b.clear(); + b.insert( *d.begin() ); + + BOOST_CHECK( + b.begin()->template get<LeftTag>() == + b.template by<RightTag>().begin()->template get<LeftTag>() + ); + + BOOST_CHECK( + b.begin()->template get<RightTag>() == + b.template by<LeftTag>().begin()->template get<RightTag>() + ); + + // const test + { + + const Bimap & bc = b; + + BOOST_CHECK( &bc.left == & bc.template by<LeftTag>() ); + BOOST_CHECK( &bc.right == & bc.template by<RightTag>() ); + + BOOST_CHECK( bc.begin()->template get<LeftTag>() == + bc.template by<RightTag>().begin()->template get<LeftTag>() ); + + BOOST_CHECK( bc.begin()->template get<RightTag>() == + bc.template by<LeftTag>().begin()->template get<RightTag>() ); + } +} + + +template< class Bimap, class Data, class LeftData, class RightData > +void test_set_set_bimap(Bimap & b, + const Data & d, + const LeftData & ld, const RightData & rd) +{ + using namespace boost::bimaps; + + test_basic_bimap(b,d,ld,rd); + + test_associative_container(b,d); + test_simple_ordered_associative_container(b,d); + + test_pair_associative_container(b.left, ld); + test_pair_ordered_associative_container(b.left, ld); + test_unique_container(b.left, ld); + + test_pair_associative_container(b.right, rd); + test_pair_ordered_associative_container(b.right, rd); + test_unique_container(b.right, rd); + +} + + +template< class Bimap, class Data, class LeftData, class RightData > +void test_multiset_multiset_bimap(Bimap & b, + const Data & d, + const LeftData & ld, const RightData & rd) +{ + using namespace boost::bimaps; + + test_basic_bimap(b,d,ld,rd); + test_associative_container(b,d); + test_simple_ordered_associative_container(b,d); + + test_pair_associative_container(b.left, ld); + test_pair_ordered_associative_container(b.left, ld); + test_non_unique_container(b.left, ld); + + test_pair_associative_container(b.right, rd); + test_pair_ordered_associative_container(b.right, rd); + test_non_unique_container(b.right, rd); +} + +template< class Bimap, class Data, class LeftData, class RightData > +void test_unordered_set_unordered_multiset_bimap(Bimap & b, + const Data & d, + const LeftData & ld, + const RightData & rd) +{ + using namespace boost::bimaps; + + test_basic_bimap(b,d,ld,rd); + test_associative_container(b,d); + test_simple_unordered_associative_container(b,d); + + test_pair_associative_container(b.left, ld); + test_pair_unordered_associative_container(b.left, ld); + test_unique_container(b.left, ld); + + test_pair_associative_container(b.right, rd); + test_pair_unordered_associative_container(b.right, rd); + + // Caution, this side is a non unique container, but the other side is a + // unique container so, the overall bimap is a unique one. + test_unique_container(b.right, rd); +} + +#endif // LIBS_BIMAP_TEST_BIMAP_TEST_HPP + diff --git a/test/test_bimap_assign.cpp b/test/test_bimap_assign.cpp new file mode 100755 index 0000000..2d8f372 --- /dev/null +++ b/test/test_bimap_assign.cpp @@ -0,0 +1,89 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +#include <boost/config.hpp> + +// Boost.Test +#include <boost/test/minimal.hpp> + +// std +#include <sstream> +#include <algorithm> +#include <set> + +// Boost +#include <boost/assign/list_of.hpp> +#include <boost/assign/list_inserter.hpp> + +// Boost.Bimap +#include <boost/bimap/list_of.hpp> +#include <boost/bimap/unordered_multiset_of.hpp> +#include <boost/bimap/vector_of.hpp> +#include <boost/bimap/bimap.hpp> + +namespace ba = boost::assign; + + +void test_bimap_assign() +{ + using namespace boost::bimaps; + + // test + { + typedef bimap< list_of<int>, double > bm_type; + bm_type bm = ba::list_of< bm_type::relation >(1,0.1)(2,0.2)(3,0.3); + ba::push_back( bm )(4,0.4)(5,0.5); + ba::insert( bm.right )(0.5,5)(0.6,6); + ba::push_back( bm.left )(6,0.6)(7,0.7); + } + + // test + { + typedef bimap< unordered_multiset_of<int>, vector_of<double>, + list_of_relation > bm_type; + bm_type bm = ba::list_of< bm_type::relation >(1,0.1)(2,0.2)(3,0.3); + ba::push_front( bm )(4,0.4)(5,0.5); + ba::push_back( bm.right )(0.6,6)(0.7,7); + ba::insert( bm.left )(8,0.8)(9,0.9); + } + + // test + { + typedef bimap< int, vector_of<double>, right_based > bm_type; + bm_type bm = ba::list_of< bm_type::relation >(1,0.1)(2,0.2)(3,0.3); + ba::push_back( bm )(4,0.4)(5,0.5); + ba::push_back( bm.right )(0.6,6)(0.7,7); + ba::insert( bm.left )(8,0.8)(9,0.9); + } + + // test + { + typedef bimap< int, vector_of<double>, set_of_relation<> > bm_type; + bm_type bm = ba::list_of< bm_type::relation >(1,0.1)(2,0.2)(3,0.3); + ba::insert( bm )(4,0.4)(5,0.5); + ba::push_back( bm.right )(0.6,6)(0.7,7); + ba::insert( bm.left )(8,0.8)(9,0.9); + } +} + + +int test_main( int, char* [] ) +{ + test_bimap_assign(); + return 0; +} + diff --git a/test/test_bimap_convenience_header.cpp b/test/test_bimap_convenience_header.cpp new file mode 100755 index 0000000..b6667ab --- /dev/null +++ b/test/test_bimap_convenience_header.cpp @@ -0,0 +1,38 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +#include <boost/config.hpp> + +// Boost.Test +#include <boost/test/minimal.hpp> + +#include <boost/bimap.hpp> + +void test_bimap_convenience_header() +{ + typedef boost::bimap< int, double > bm_type; + bm_type bm; + bm.insert( bm_type::value_type(1,0.1) ); + BOOST_CHECK( bm.right.at(0.1) == 1 ); +} + +int test_main( int, char* [] ) +{ + test_bimap_convenience_header(); + return 0; +} + diff --git a/test/test_bimap_extra.cpp b/test/test_bimap_extra.cpp new file mode 100755 index 0000000..61492c7 --- /dev/null +++ b/test/test_bimap_extra.cpp @@ -0,0 +1,89 @@ + // Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +#include <boost/config.hpp> + +// Boost.Test +#include <boost/test/minimal.hpp> + +#include <boost/static_assert.hpp> +#include <boost/type_traits/is_same.hpp> + +// Boost.Bimap +#include <boost/bimap/support/lambda.hpp> +#include <boost/bimap/bimap.hpp> +#include <boost/bimap/list_of.hpp> + +// Support metafunctions +#include <boost/bimap/support/data_type_by.hpp> +#include <boost/bimap/support/key_type_by.hpp> +#include <boost/bimap/support/map_type_by.hpp> +#include <boost/bimap/support/value_type_by.hpp> +#include <boost/bimap/support/iterator_type_by.hpp> + +using namespace boost::bimaps; +using namespace boost::bimaps::support; + +typedef bimap<int, unconstrained_set_of<double> > bm_type; + + +namespace support_metafunctions_test { + + typedef boost::is_same + < + data_type_by< member_at::left , bm_type >::type, + key_type_by < member_at::right, bm_type >::type + + >::type test_metafunction_1; + BOOST_STATIC_ASSERT(test_metafunction_1::value); + + typedef boost::is_same + < + data_type_by< member_at::right, bm_type >::type, + key_type_by < member_at::left , bm_type >::type + + >::type test_metafunction_2; + BOOST_STATIC_ASSERT(test_metafunction_2::value); + + typedef boost::is_same + < + map_type_by < member_at::left , bm_type >::type::value_type, + value_type_by< member_at::left , bm_type >::type + + >::type test_metafunction_3; + BOOST_STATIC_ASSERT(test_metafunction_3::value); + +} // namespace support_metafunctions_test + +void test_bimap_extra() +{ + // extra tests + // --------------------------------------------------------------- + // This section test small things... when a group of this checks + // can be related it is moved to a separate unit test file. + + + +} + + +int test_main( int, char* [] ) +{ + test_bimap_extra(); + return 0; +} + diff --git a/test/test_bimap_info.cpp b/test/test_bimap_info.cpp new file mode 100755 index 0000000..c1ef479 --- /dev/null +++ b/test/test_bimap_info.cpp @@ -0,0 +1,126 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +#include <boost/config.hpp> + +// Boost.Test +#include <boost/test/minimal.hpp> + +#include <boost/config.hpp> + +#include <string> + +#include <boost/bimap/bimap.hpp> +#include <boost/bimap/unordered_set_of.hpp> + + +int test_bimap_info() +{ + using namespace boost::bimaps; + + typedef bimap< double, unordered_set_of<int>, with_info<std::string> > bm_type; + + bm_type bm; + const bm_type & cbm = bm; + + // Insertion with info + bm .insert( bm_type:: value_type(1.1 , 1, "one" ) ); + bm.left .insert( bm_type:: left_value_type(2.2 , 2, "two" ) ); + bm.right.insert( bm_type::right_value_type( 3 , 3.3, "three" ) ); + + bm.begin()->info = "1"; + BOOST_CHECK( bm.right.find(1)->info == "1" ); + + bm.left.find(2.2)->info = "2"; + BOOST_CHECK( bm.right.find(2)->info == "2" ); + + bm.right.find(3)->info = "3"; + BOOST_CHECK( bm.right.find(3)->info == "3" ); + + // Empty info insert + bm .insert( bm_type:: value_type(4.4 , 4) ); + bm. left.insert( bm_type:: left_value_type(5.5 , 5) ); + bm.right.insert( bm_type::right_value_type( 6 , 6.6) ); + + BOOST_CHECK( bm.right.find(4)->info == "" ); + + bm.left.info_at(4.4) = "4"; + BOOST_CHECK( bm.right.info_at(4) == "4" ); + BOOST_CHECK( cbm.right.info_at(4) == "4" ); + + bm.right.info_at(5) = "5"; + BOOST_CHECK( bm.left.info_at(5.5) == "5" ); + BOOST_CHECK( cbm.left.info_at(5.5) == "5" ); + + return 0; +} + + +struct left {}; +struct right {}; +struct info {}; + +int test_tagged_bimap_info() +{ + using namespace boost::bimaps; + + typedef bimap< tagged<int,left>, + tagged<int,right>, + with_info<tagged<int,info> > > bm_type; + + bm_type bm; + const bm_type & cbm = bm; + + bm .insert( bm_type:: value_type(1,1,1) ); + bm.left .insert( bm_type:: left_value_type(2,2,2) ); + bm.right.insert( bm_type::right_value_type(3,3,3) ); + + bm.begin()->get<info>() = 10; + BOOST_CHECK( bm.right.find(1)->get<info>() == 10 ); + BOOST_CHECK( cbm.right.find(1)->get<info>() == 10 ); + + bm.left.find(2)->get<info>() = 20; + BOOST_CHECK( bm.right.find(2)->get<info>() == 20 ); + BOOST_CHECK( cbm.right.find(2)->get<info>() == 20 ); + + bm.right.find(3)->get<info>() = 30; + BOOST_CHECK( bm.right.find(3)->get<info>() == 30 ); + BOOST_CHECK( cbm.right.find(3)->get<info>() == 30 ); + + // Empty info insert + bm .insert( bm_type:: value_type(4,4) ); + bm. left.insert( bm_type:: left_value_type(5,5) ); + bm.right.insert( bm_type::right_value_type(6,6) ); + + bm.left.info_at(4) = 4; + BOOST_CHECK( bm.right.info_at(4) == 4 ); + BOOST_CHECK( cbm.right.info_at(4) == 4 ); + + bm.right.info_at(5) = 5; + BOOST_CHECK( bm.left.info_at(5) == 5 ); + BOOST_CHECK( cbm.left.info_at(5) == 5 ); + + return 0; +} + +int test_main( int, char* [] ) +{ + test_bimap_info(); + test_tagged_bimap_info(); + return 0; +} + diff --git a/test/test_bimap_lambda.cpp b/test/test_bimap_lambda.cpp new file mode 100755 index 0000000..81b1e73 --- /dev/null +++ b/test/test_bimap_lambda.cpp @@ -0,0 +1,47 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +#include <boost/config.hpp> + +// Boost.Test +#include <boost/test/minimal.hpp> + +// Boost.Bimap +#include <boost/bimap/support/lambda.hpp> +#include <boost/bimap/bimap.hpp> + +void test_bimap_lambda() +{ + using namespace boost::bimaps; + + typedef bimap<int,double> bm; + + bm b; + b.insert( bm::value_type(1,0.1) ); + + BOOST_CHECK( b.size() == 1 ); + BOOST_CHECK( b.left.modify_key ( b.left.begin(), _key = 2 ) ); + BOOST_CHECK( b.left.modify_data( b.left.begin(), _data = 0.2 ) ); + BOOST_CHECK( b.left.range( _key >= 1, _key < 3 ).first == b.left.begin() ); +} + +int test_main( int, char* [] ) +{ + test_bimap_lambda(); + return 0; +} + diff --git a/test/test_bimap_list_of.cpp b/test/test_bimap_list_of.cpp new file mode 100755 index 0000000..e01569a --- /dev/null +++ b/test/test_bimap_list_of.cpp @@ -0,0 +1,32 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +#include <boost/config.hpp> + +// Boost.Test +#include <boost/test/minimal.hpp> + +#include <boost/bimap/list_of.hpp> + +int test_main( int, char* [] ) +{ + typedef boost::bimaps::list_of<int> set_type; + typedef boost::bimaps::list_of_relation set_type_of_relation; + + return 0; +} + diff --git a/test/test_bimap_modify.cpp b/test/test_bimap_modify.cpp new file mode 100755 index 0000000..ed0d15e --- /dev/null +++ b/test/test_bimap_modify.cpp @@ -0,0 +1,183 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +#include <boost/config.hpp> + +// Boost.Test +#include <boost/test/minimal.hpp> + +// Boost.Bimap +#include <boost/bimap/support/lambda.hpp> +#include <boost/bimap/bimap.hpp> + +struct id{}; + +void test_bimap_modify() +{ + using namespace boost::bimaps; + + typedef bimap<int,long> bm; + + bm b; + b.insert( bm::value_type(2,200) ); + + BOOST_CHECK( b.left.at(2) == 200 ); + + bool result; + + // replace + //---------------------------------------------------------------------- + + // successful replace in left map view + { + bm::left_iterator i = b.left.begin(); + + result = b.left.replace( i, bm::left_value_type(1,100) ); + + BOOST_CHECK( result ); + BOOST_CHECK( b.size() == 1 ); + BOOST_CHECK( i->first == 1 && i->second == 100 ); + BOOST_CHECK( b.left.at(1) == 100 ); + + result = b.left.replace_key( i, 2 ); + + BOOST_CHECK( result ); + BOOST_CHECK( b.size() == 1 ); + BOOST_CHECK( i->first == 2 && i->second == 100 ); + BOOST_CHECK( b.left.at(2) == 100 ); + + result = b.left.replace_data( i, 200 ); + + BOOST_CHECK( result ); + BOOST_CHECK( b.size() == 1 ); + BOOST_CHECK( i->first == 2 && i->second == 200 ); + BOOST_CHECK( b.left.at(2) == 200 ); + } + + // successful replace in right map view + { + bm::right_iterator i = b.right.begin(); + + result = b.right.replace( i, bm::right_value_type(100,1) ); + + BOOST_CHECK( result ); + BOOST_CHECK( b.size() == 1 ); + BOOST_CHECK( i->first == 100 && i->second == 1 ); + BOOST_CHECK( b.right.at(100) == 1 ); + + result = b.right.replace_key( i, 200 ); + + BOOST_CHECK( result ); + BOOST_CHECK( b.size() == 1 ); + BOOST_CHECK( i->first == 200 && i->second == 1 ); + BOOST_CHECK( b.right.at(200) == 1 ); + + result = b.right.replace_data( i, 2 ); + + BOOST_CHECK( result ); + BOOST_CHECK( b.size() == 1 ); + BOOST_CHECK( i->first == 200 && i->second == 2 ); + BOOST_CHECK( b.right.at(200) == 2 ); + } + + // successful replace in set of relations view + { + bm::iterator i = b.begin(); + + result = b.replace( i, bm::value_type(1,100) ); + + BOOST_CHECK( result ); + BOOST_CHECK( b.size() == 1 ); + BOOST_CHECK( i->left == 1 && i->right == 100 ); + BOOST_CHECK( b.left.at(1) == 100 ); + + result = b.replace_left( i, 2 ); + + BOOST_CHECK( result ); + BOOST_CHECK( b.size() == 1 ); + BOOST_CHECK( i->left == 2 && i->right == 100 ); + BOOST_CHECK( b.left.at(2) == 100 ); + + result = b.replace_right( b.begin(), 200 ); + + BOOST_CHECK( result ); + BOOST_CHECK( b.size() == 1 ); + BOOST_CHECK( i->left == 2 && i->right == 200 ); + BOOST_CHECK( b.left.at(2) == 200 ); + + } + + b.clear(); + b.insert( bm::value_type(1,100) ); + b.insert( bm::value_type(2,200) ); + + // fail to replace in left map view + { + bm::left_iterator i = b.left.begin(); + + result = b.left.replace( i, bm::left_value_type(2,100) ); + + BOOST_CHECK( ! result ); + BOOST_CHECK( b.size() == 2 ); + BOOST_CHECK( i->first == 1 && i->second == 100 ); + BOOST_CHECK( b.left.at(1) == 100 ); + BOOST_CHECK( b.left.at(2) == 200 ); + + + // Add checks for replace_key and replace_data + } + + // Add checks for fail to replace in right map view + + // Add checks for fail to replace in set of relations view + + + // modify + // ---------------------------------------------------------------------- + + b.clear(); + b.insert( bm::value_type(1,100) ); + + // successful modify in left map view + { + result = b.left.modify_key( b.left.begin(), _key = 2 ); + + BOOST_CHECK( result ); + BOOST_CHECK( b.size() == 1 ); + BOOST_CHECK( b.left.at(2) == 100 ); + + result = b.left.modify_data( b.left.begin() , _data = 200 ); + + BOOST_CHECK( result ); + BOOST_CHECK( b.size() == 1 ); + BOOST_CHECK( b.left.at(2) == 200 ); + } + + // Add checks for successful modify in right map view + + // Add checks for fails to modify in left map view + + +} + +int test_main( int, char* [] ) +{ + test_bimap_modify(); + + return 0; +} + diff --git a/test/test_bimap_multiset_of.cpp b/test/test_bimap_multiset_of.cpp new file mode 100755 index 0000000..5b86bd6 --- /dev/null +++ b/test/test_bimap_multiset_of.cpp @@ -0,0 +1,32 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +#include <boost/config.hpp> + +// Boost.Test +#include <boost/test/minimal.hpp> + +#include <boost/bimap/multiset_of.hpp> + +int test_main( int, char* [] ) +{ + typedef boost::bimaps::multiset_of<int> set_type; + typedef boost::bimaps::multiset_of_relation<> set_type_of_relation; + + return 0; +} + diff --git a/test/test_bimap_mutable.cpp b/test/test_bimap_mutable.cpp new file mode 100755 index 0000000..4a04f7b --- /dev/null +++ b/test/test_bimap_mutable.cpp @@ -0,0 +1,109 @@ + // Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +#include <boost/config.hpp> + +// Boost.Test +#include <boost/test/minimal.hpp> + +// Boost.Bimap +#include <boost/bimap/bimap.hpp> +#include <boost/bimap/list_of.hpp> +#include <boost/bimap/vector_of.hpp> +#include <boost/bimap/unconstrained_set_of.hpp> + +using namespace boost::bimaps; + +template< class BimapType > +void test_bimap_mutable() +{ + typedef BimapType bm_type; + + bm_type bm; + bm.insert( BOOST_DEDUCED_TYPENAME bm_type::value_type(1,0.1) ); + + const bm_type & cbm = bm; + + // Map Mutable Iterator test + { + + BOOST_DEDUCED_TYPENAME bm_type::left_iterator iter = bm.left.begin(); + iter->second = 0.2; + BOOST_CHECK( iter->second == bm.left.begin()->second ); + + BOOST_DEDUCED_TYPENAME bm_type::left_const_iterator citer = bm.left.begin(); + BOOST_CHECK( citer->second == bm.left.begin()->second ); + + BOOST_DEDUCED_TYPENAME bm_type::left_const_iterator cciter = cbm.left.begin(); + BOOST_CHECK( cciter->second == cbm.left.begin()->second ); + + } + + // Set Mutable Iterator test + { + + BOOST_DEDUCED_TYPENAME bm_type::iterator iter = bm.begin(); + iter->right = 0.1; + BOOST_CHECK( iter->right == bm.begin()->right ); + + BOOST_DEDUCED_TYPENAME bm_type::const_iterator citer = bm.begin(); + BOOST_CHECK( citer->right == bm.begin()->right ); + + BOOST_DEDUCED_TYPENAME bm_type::const_iterator cciter = cbm.begin(); + BOOST_CHECK( cciter->left == cbm.begin()->left ); + + } + + // Map Assignable Reference test + { + + BOOST_DEDUCED_TYPENAME bm_type::left_reference r = *bm.left.begin(); + r.second = 0.2; + BOOST_CHECK( r == *bm.left.begin() ); + + BOOST_DEDUCED_TYPENAME bm_type::left_const_reference cr = *bm.left.begin(); + BOOST_CHECK( cr == *bm.left.begin() ); + + BOOST_DEDUCED_TYPENAME bm_type::left_const_reference ccr = *cbm.left.begin(); + BOOST_CHECK( ccr == *cbm.left.begin() ); + + } + + // Set Assignable Reference test + { + + BOOST_DEDUCED_TYPENAME bm_type::reference r = *bm.begin(); + r.right = 0.1; + BOOST_CHECK( r == *bm.begin() ); + + BOOST_DEDUCED_TYPENAME bm_type::const_reference cr = *bm.begin(); + BOOST_CHECK( cr == *bm.begin() ); + + BOOST_DEDUCED_TYPENAME bm_type::const_reference ccr = *cbm.begin(); + BOOST_CHECK( ccr == *bm.begin() ); + + } +} + +int test_main( int, char* [] ) +{ + test_bimap_mutable< bimap< int, list_of<double> > >(); + test_bimap_mutable< bimap< int, vector_of<double> > >(); + test_bimap_mutable< bimap< int, unconstrained_set_of<double> > >(); + return 0; +} + diff --git a/test/test_bimap_operator_bracket.cpp b/test/test_bimap_operator_bracket.cpp new file mode 100755 index 0000000..6a39d17 --- /dev/null +++ b/test/test_bimap_operator_bracket.cpp @@ -0,0 +1,193 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +#include <boost/config.hpp> + +// Boost.Test +#include <boost/test/minimal.hpp> + +// Boost.Bimap +#include <boost/bimap/support/lambda.hpp> +#include <boost/bimap/bimap.hpp> +#include <boost/bimap/unordered_set_of.hpp> +#include <boost/bimap/list_of.hpp> +#include <boost/bimap/vector_of.hpp> +#include <boost/bimap/unconstrained_set_of.hpp> + + +void test_bimap_operator_bracket() +{ + using namespace boost::bimaps; + + // Simple test + { + typedef bimap< int, std::string > bm; + + bm b; + b.insert( bm::value_type(0,"0") ); + b.insert( bm::value_type(1,"1") ); + b.insert( bm::value_type(2,"2") ); + b.insert( bm::value_type(3,"3") ); + + BOOST_CHECK( b.left.at(1) == "1" ); + + // Out of range test + { + bool value_not_found_test_passed = false; + b.clear(); + try + { + bool comp; + comp = b.left.at(2) < "banana"; + } + catch( std::out_of_range & ) + { + value_not_found_test_passed = true; + } + + BOOST_CHECK( value_not_found_test_passed ); + } + } + + // Mutable data test (1) + { + typedef bimap<int, list_of<std::string> > bm; + bm b; + + // Out of range test + { + bool value_not_found_test_passed = false; + b.clear(); + try + { + bool comp; + comp = b.left.at(1) < "banana"; + } + catch( std::out_of_range & ) + { + value_not_found_test_passed = true; + } + + BOOST_CHECK( value_not_found_test_passed ); + + } + + // Out of range test (const version) + { + bool value_not_found_test_passed = false; + b.clear(); + try + { + const bm & cb(b); + bool comp; + comp = cb.left.at(1) < "banana"; + } + catch( std::out_of_range & ) + { + value_not_found_test_passed = true; + } + + BOOST_CHECK( value_not_found_test_passed ); + } + + BOOST_CHECK( b.left[1] == "" ); + BOOST_CHECK( b.left.at(1) == "" ); + b.left[2] = "two"; + BOOST_CHECK( b.left.at(2) == "two" ); + b.left[2] = "<<two>>"; + BOOST_CHECK( b.left.at(2) == "<<two>>" ); + b.left.at(2) = "two"; + BOOST_CHECK( b.left.at(2) == "two" ); + + } + + // Mutable data test (2) + { + typedef bimap< vector_of<int>, unordered_set_of<std::string> > bm; + bm b; + + // Out of range test + { + bool value_not_found_test_passed = false; + b.clear(); + try + { + bool comp; + comp = b.right.at("banana") < 1; + } + catch( std::out_of_range & ) + { + value_not_found_test_passed = true; + } + BOOST_CHECK( value_not_found_test_passed ); + } + + // Out of range test (const version) + { + bool value_not_found_test_passed = false; + b.clear(); + try + { + const bm & cb(b); + bool comp; + comp = cb.right.at("banana") < 1; + } + catch( std::out_of_range & ) + { + value_not_found_test_passed = true; + } + + BOOST_CHECK( value_not_found_test_passed ); + } + + b.right["one"]; + BOOST_CHECK( b.size() == 1 ); + b.right["two"] = 2; + BOOST_CHECK( b.right.at("two") == 2 ); + b.right["two"] = -2; + BOOST_CHECK( b.right.at("two") == -2 ); + b.right.at("two") = 2; + BOOST_CHECK( b.right.at("two") == 2 ); + } + + // Mutable data test (3) + { + typedef bimap< unconstrained_set_of<int>, + unordered_set_of<std::string>, + right_based > bm; + + bm b; + + b.right["one"]; + BOOST_CHECK( b.size() == 1 ); + b.right["two"] = 2; + BOOST_CHECK( b.right.at("two") == 2 ); + b.right["two"] = -2; + BOOST_CHECK( b.right.at("two") == -2 ); + b.right.at("two") = 2; + BOOST_CHECK( b.right.at("two") == 2 ); + } + +} + +int test_main( int, char* [] ) +{ + test_bimap_operator_bracket(); + + return 0; +} + diff --git a/test/test_bimap_ordered.cpp b/test/test_bimap_ordered.cpp new file mode 100755 index 0000000..4b8fb82 --- /dev/null +++ b/test/test_bimap_ordered.cpp @@ -0,0 +1,176 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +#include <boost/config.hpp> + +#define BOOST_BIMAP_DISABLE_SERIALIZATION + +// Boost.Test +#include <boost/test/minimal.hpp> + +// std +#include <set> +#include <map> +#include <string> +#include <functional> + +// Set type specifications +#include <boost/bimap/set_of.hpp> +#include <boost/bimap/multiset_of.hpp> + +// bimap container +#include <boost/bimap/bimap.hpp> + +#include <libs/bimap/test/test_bimap.hpp> + +struct left_tag {}; +struct right_tag {}; + +void test_bimap() +{ + using namespace boost::bimaps; + + typedef std::map<int,double> left_data_type; + left_data_type left_data; + left_data.insert( left_data_type::value_type(1,0.1) ); + left_data.insert( left_data_type::value_type(2,0.2) ); + left_data.insert( left_data_type::value_type(3,0.3) ); + left_data.insert( left_data_type::value_type(4,0.4) ); + + typedef std::map<double,int> right_data_type; + right_data_type right_data; + right_data.insert( right_data_type::value_type(0.1,1) ); + right_data.insert( right_data_type::value_type(0.2,2) ); + right_data.insert( right_data_type::value_type(0.3,3) ); + right_data.insert( right_data_type::value_type(0.4,4) ); + + + //-------------------------------------------------------------------- + { + typedef bimap< int, double > bm_type; + + std::set< bm_type::value_type > data; + data.insert( bm_type::value_type(1,0.1) ); + data.insert( bm_type::value_type(2,0.2) ); + data.insert( bm_type::value_type(3,0.3) ); + data.insert( bm_type::value_type(4,0.4) ); + + bm_type bm; + test_set_set_bimap(bm,data,left_data,right_data); + } + //-------------------------------------------------------------------- + + + //-------------------------------------------------------------------- + { + typedef bimap + < + multiset_of< tagged<int, left_tag > >, + multiset_of< tagged<double, right_tag > >, + multiset_of_relation< std::less< _relation > > + + > bm_type; + + std::set< bm_type::value_type > data; + data.insert( bm_type::value_type(1,0.1) ); + data.insert( bm_type::value_type(2,0.2) ); + data.insert( bm_type::value_type(3,0.3) ); + data.insert( bm_type::value_type(4,0.4) ); + + bm_type bm; + + test_multiset_multiset_bimap(bm,data,left_data,right_data); + test_tagged_bimap<left_tag,right_tag>(bm,data); + } + //-------------------------------------------------------------------- + + + //-------------------------------------------------------------------- + { + typedef bimap<int,double,right_based> bm_type; + + std::set< bm_type::value_type > data; + data.insert( bm_type::value_type(1,0.1) ); + data.insert( bm_type::value_type(2,0.2) ); + data.insert( bm_type::value_type(3,0.3) ); + data.insert( bm_type::value_type(4,0.4) ); + + bm_type bm; + + test_set_set_bimap(bm,data,left_data,right_data); + } + //-------------------------------------------------------------------- + + + //-------------------------------------------------------------------- + { + typedef bimap + < + multiset_of< int, std::greater<int> >, set_of<std::string> , + multiset_of_relation< std::greater< _relation > > + + > bimap_type; + + bimap_type b1; + + b1.insert( bimap_type::value_type(1,"one") ); + + bimap_type b2( b1 ); + + BOOST_CHECK( b1 == b2 ); + BOOST_CHECK( ! ( b1 != b2 ) ); + BOOST_CHECK( b1 <= b2 ); + BOOST_CHECK( b1 >= b2 ); + BOOST_CHECK( ! ( b1 < b2 ) ); + BOOST_CHECK( ! ( b1 > b2 ) ); + + b1.insert( bimap_type::value_type(2,"two") ); + + b2 = b1; + BOOST_CHECK( b2 == b1 ); + + b1.insert( bimap_type::value_type(3,"three") ); + + b2.left = b1.left; + BOOST_CHECK( b2 == b1 ); + + b1.insert( bimap_type::value_type(4,"four") ); + + b2.right = b1.right; + BOOST_CHECK( b2 == b1 ); + + b1.clear(); + b2.swap(b1); + BOOST_CHECK( b2.empty() && !b1.empty() ); + + b1.left.swap( b2.left ); + BOOST_CHECK( b1.empty() && !b2.empty() ); + + b1.right.swap( b2.right ); + BOOST_CHECK( b2.empty() && !b1.empty() ); + } + //-------------------------------------------------------------------- + +} + + +int test_main( int, char* [] ) +{ + test_bimap(); + return 0; +} + diff --git a/test/test_bimap_project.cpp b/test/test_bimap_project.cpp new file mode 100755 index 0000000..0f7e767 --- /dev/null +++ b/test/test_bimap_project.cpp @@ -0,0 +1,143 @@ + // Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +#include <boost/config.hpp> + +// Boost.Test +#include <boost/test/minimal.hpp> + +#include <string> + +// Boost.Bimap +#include <boost/bimap/bimap.hpp> +#include <boost/bimap/list_of.hpp> + +using namespace boost::bimaps; + +struct left_tag {}; +struct right_tag {}; + +void test_bimap_project() +{ + typedef bimap + < + tagged< int , left_tag >, + list_of< tagged< std::string, right_tag > > + + > bm_type; + + bm_type bm; + + bm.insert( bm_type::value_type(1,"1") ); + bm.insert( bm_type::value_type(2,"2") ); + + bm_type:: iterator iter = bm.begin(); + bm_type:: left_iterator left_iter = bm.left.find(1); + bm_type::right_iterator right_iter = bm.right.begin(); + + const bm_type & cbm = bm; + + bm_type:: const_iterator citer = cbm.begin(); + bm_type:: left_const_iterator left_citer = cbm.left.find(1); + bm_type::right_const_iterator right_citer = cbm.right.begin(); + + // non const projection + + BOOST_CHECK( bm.project_up (bm.end()) == bm.end() ); + BOOST_CHECK( bm.project_left (bm.end()) == bm.left.end() ); + BOOST_CHECK( bm.project_right(bm.end()) == bm.right.end() ); + + BOOST_CHECK( bm.project_up (iter) == iter ); + BOOST_CHECK( bm.project_left (iter) == left_iter ); + BOOST_CHECK( bm.project_right(iter) == right_iter ); + + BOOST_CHECK( bm.project_up (left_iter) == iter ); + BOOST_CHECK( bm.project_left (left_iter) == left_iter ); + BOOST_CHECK( bm.project_right(left_iter) == right_iter ); + + BOOST_CHECK( bm.project_up (right_iter) == iter ); + BOOST_CHECK( bm.project_left (right_iter) == left_iter ); + BOOST_CHECK( bm.project_right(right_iter) == right_iter ); + + bm.project_up ( left_iter)->right = "u"; + bm.project_left (right_iter)->second = "l"; + bm.project_right( iter)->first = "r"; + + // const projection + + BOOST_CHECK( cbm.project_up (cbm.end()) == cbm.end() ); + BOOST_CHECK( cbm.project_left (cbm.end()) == cbm.left.end() ); + BOOST_CHECK( cbm.project_right(cbm.end()) == cbm.right.end() ); + + BOOST_CHECK( cbm.project_up (citer) == citer ); + BOOST_CHECK( cbm.project_left (citer) == left_citer ); + BOOST_CHECK( cbm.project_right(citer) == right_citer ); + + BOOST_CHECK( cbm.project_up (left_citer) == citer ); + BOOST_CHECK( cbm.project_left (left_citer) == left_citer ); + BOOST_CHECK( cbm.project_right(left_citer) == right_citer ); + + BOOST_CHECK( cbm.project_up (right_citer) == citer ); + BOOST_CHECK( cbm.project_left (right_citer) == left_citer ); + BOOST_CHECK( cbm.project_right(right_citer) == right_citer ); + + // mixed projection + + BOOST_CHECK( bm.project_up (left_citer) == iter ); + BOOST_CHECK( bm.project_left (left_citer) == left_iter ); + BOOST_CHECK( bm.project_right(left_citer) == right_iter ); + + BOOST_CHECK( cbm.project_up (right_iter) == citer ); + BOOST_CHECK( cbm.project_left (right_iter) == left_citer ); + BOOST_CHECK( cbm.project_right(right_iter) == right_citer ); + + bm.project_up ( left_citer)->right = "u"; + bm.project_left (right_citer)->second = "l"; + bm.project_right( citer)->first = "r"; + + // Support for tags + + BOOST_CHECK( bm.project< left_tag>(iter) == left_iter ); + BOOST_CHECK( bm.project<right_tag>(iter) == right_iter ); + + BOOST_CHECK( bm.project< left_tag>(left_iter) == left_iter ); + BOOST_CHECK( bm.project<right_tag>(left_iter) == right_iter ); + + BOOST_CHECK( bm.project< left_tag>(right_iter) == left_iter ); + BOOST_CHECK( bm.project<right_tag>(right_iter) == right_iter ); + + BOOST_CHECK( cbm.project< left_tag>(citer) == left_citer ); + BOOST_CHECK( cbm.project<right_tag>(citer) == right_citer ); + + BOOST_CHECK( cbm.project< left_tag>(left_citer) == left_citer ); + BOOST_CHECK( cbm.project<right_tag>(left_citer) == right_citer ); + + BOOST_CHECK( cbm.project< left_tag>(right_citer) == left_citer ); + BOOST_CHECK( cbm.project<right_tag>(right_citer) == right_citer ); + + bm.project< left_tag>(right_citer)->second = "l"; + bm.project<right_tag>( left_citer)->first = "r"; + +} + + +int test_main( int, char* [] ) +{ + test_bimap_project(); + return 0; +} + diff --git a/test/test_bimap_property_map.cpp b/test/test_bimap_property_map.cpp new file mode 100755 index 0000000..9a2b422 --- /dev/null +++ b/test/test_bimap_property_map.cpp @@ -0,0 +1,76 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +#include <boost/config.hpp> + +// std +#include <set> +#include <map> +#include <cstddef> +#include <cassert> +#include <algorithm> + +// Boost.Test +#include <boost/test/minimal.hpp> + +// Boost.Bimap + +#include <boost/bimap/set_of.hpp> +#include <boost/bimap/property_map/set_support.hpp> + +#include <boost/bimap/unordered_set_of.hpp> +#include <boost/bimap/property_map/unordered_set_support.hpp> + +#include <boost/bimap/bimap.hpp> + + +template <class Map> +void test_readable_property_map( + Map m, + typename boost::property_traits<Map>:: key_type const & key, + typename boost::property_traits<Map>::value_type const & value +) +{ + // TODO Add STATIC_ASSERT( + // boost::property_traits<Map>::category is readable ) + + BOOST_CHECK( get(m,key) == value ); + //BOOST_CHECK( m[key] == value ); +} + + +void test_bimap_property_map() +{ + using namespace boost::bimaps; + + typedef bimap< set_of<int>, unordered_set_of<double> > bm; + + bm b; + b.insert( bm::value_type(1,0.1) ); + b.insert( bm::value_type(2,0.2) ); + b.insert( bm::value_type(3,0.3) ); + + test_readable_property_map(b.left , 1,0.1); + test_readable_property_map(b.right,0.1, 1); +} + +int test_main( int, char* [] ) +{ + test_bimap_property_map(); + return 0; +} + diff --git a/test/test_bimap_range.cpp b/test/test_bimap_range.cpp new file mode 100755 index 0000000..d005cd8 --- /dev/null +++ b/test/test_bimap_range.cpp @@ -0,0 +1,134 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +#include <boost/config.hpp> + +// Boost.Test +#include <boost/test/minimal.hpp> + +#include <boost/config.hpp> + +#include <algorithm> + +#include <boost/range/functions.hpp> +#include <boost/range/metafunctions.hpp> + +#include <boost/bimap/bimap.hpp> +#include <boost/bimap/multiset_of.hpp> +#include <boost/bimap/support/lambda.hpp> + + +template< class ForwardReadableRange, class UnaryFunctor > +UnaryFunctor for_each(const ForwardReadableRange & r, UnaryFunctor func) +{ + typedef typename + boost::range_const_iterator<ForwardReadableRange>::type const_iterator; + + for(const_iterator i= boost::begin(r), iend= boost::end(r); i!=iend; ++i ) + { + func(*i); + } + + return func; +} + +struct do_something_with_a_pair +{ + template< class Pair > + void operator()(const Pair & p) + { + BOOST_CHECK( p.first && p.second ); + } +}; + +int test_bimap_range() +{ + using namespace boost::bimaps; + + typedef bimap< double, multiset_of<int> > bm_type; + + + bm_type bm; + bm.insert( bm_type::value_type(1.1 , 1) ); + bm.insert( bm_type::value_type(2.2 , 2) ); + bm.insert( bm_type::value_type(3.3 , 3) ); + bm.insert( bm_type::value_type(4.4 , 4) ); + + + for_each( bm.left.range( 1.0 < _key, _key < 5.0 ), + do_something_with_a_pair() ); + + for_each( bm.right.range( unbounded, _key <= 2 ), + do_something_with_a_pair() ); + + + // left range + { + + bm_type::left_range_type r = bm.left.range( 2.0 < _key, _key < 4.0 ); + BOOST_CHECK( ! boost::empty(r) ); + BOOST_CHECK( boost::begin(r) == bm.left.upper_bound(2.0) ); + BOOST_CHECK( boost::end(r) == bm.left.lower_bound(4.0) ); + + } + + // right range + { + + bm_type::right_range_type r = bm.right.range( 2 <= _key, _key <= 3 ); + BOOST_CHECK( ! boost::empty(r) ); + BOOST_CHECK( boost::begin(r) == bm.right.lower_bound(2) ); + BOOST_CHECK( boost::end(r) == bm.right.upper_bound(3) ); + + } + + // const range from range + { + + bm_type:: left_const_range_type lr = bm. left.range( unbounded, _key < 4.0 ); + bm_type::right_const_range_type rr = bm.right.range( 2 < _key , unbounded ); + + } + + const bm_type & cbm = bm; + + // left const range + { + bm_type:: left_const_range_type r = cbm.left.range( unbounded, unbounded ); + BOOST_CHECK( ! boost::empty(r) ); + BOOST_CHECK( boost::begin(r) == cbm.left.begin() ); + + } + + // right const range + { + + bm_type::right_const_range_type r = cbm.right.range( 1 < _key, _key < 1 ); + BOOST_CHECK( boost::empty(r) ); + + } + + return 0; +} +//] + +int test_main( int, char* [] ) +{ + test_bimap_range(); + return 0; +} + diff --git a/test/test_bimap_sequenced.cpp b/test/test_bimap_sequenced.cpp new file mode 100755 index 0000000..ad4c46f --- /dev/null +++ b/test/test_bimap_sequenced.cpp @@ -0,0 +1,297 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +#include <boost/config.hpp> + +#define BOOST_BIMAP_DISABLE_SERIALIZATION + +// Boost.Test +#include <boost/test/minimal.hpp> + +// std +#include <set> +#include <map> +#include <algorithm> +#include <string> +#include <functional> + + +// Set type specifications +#include <boost/bimap/list_of.hpp> +#include <boost/bimap/vector_of.hpp> + +// bimap container +#include <boost/bimap/bimap.hpp> +#include <boost/bimap/support/lambda.hpp> + +#include <libs/bimap/test/test_bimap.hpp> + +struct left_tag {}; +struct right_tag {}; + +void test_bimap() +{ + using namespace boost::bimaps; + + typedef std::map<std::string,long> left_data_type; + left_data_type left_data; + left_data.insert( left_data_type::value_type("1",1) ); + left_data.insert( left_data_type::value_type("2",2) ); + left_data.insert( left_data_type::value_type("3",3) ); + left_data.insert( left_data_type::value_type("4",4) ); + + typedef std::map<long,std::string> right_data_type; + right_data_type right_data; + right_data.insert( right_data_type::value_type(1,"1") ); + right_data.insert( right_data_type::value_type(2,"2") ); + right_data.insert( right_data_type::value_type(3,"3") ); + right_data.insert( right_data_type::value_type(4,"4") ); + + + //-------------------------------------------------------------------- + { + typedef bimap< + list_of< std::string >, vector_of< long > + + > bm_type; + + std::set< bm_type::value_type > data; + data.insert( bm_type::value_type("1",1) ); + data.insert( bm_type::value_type("2",2) ); + data.insert( bm_type::value_type("3",3) ); + data.insert( bm_type::value_type("4",4) ); + + bm_type b; + + test_sequence_container(b,data); + test_sequence_container(b.left , left_data); + test_sequence_container(b.right,right_data); + + bm_type c; + + // Test assign + + b.clear(); + BOOST_CHECK( b.empty() ); + + b.left.assign(left_data.begin(),left_data.end()); + BOOST_CHECK( b.size() == left_data.size() ); + + b.right.assign(right_data.begin(),right_data.end()); + BOOST_CHECK( b.size() == right_data.size() ); + + b.assign(data.begin(),data.end()); + BOOST_CHECK( b.size() == data.size() ); + + // Test splice and merge + + b.clear(); + + c.left.insert(c.left.begin(),left_data.begin(),left_data.end()); + b.left.splice(b.left.begin(),c.left); + + BOOST_CHECK( c.size() == 0 ); + BOOST_CHECK( b.size() == 4 ); + + c.left.splice(c.left.begin(),b.left,++b.left.begin()); + + BOOST_CHECK( c.size() == 1 ); + + c.splice(c.begin(),b,b.begin(),b.end()); + + BOOST_CHECK( b.size() == 0 ); + + b.left.merge(c.left); + c.left.merge(b.left,std::less<std::string>()); + + b.left.sort(); + b.left.sort(std::less<std::string>()); + + b.left.unique(); + b.left.unique(std::equal_to<std::string>()); + + b.assign( data.begin(), data.end() ); + + BOOST_CHECK( std::equal( b.begin(), b.end(), data.begin() ) ); + b.reverse(); + BOOST_CHECK( std::equal( b.rbegin(), b.rend(), data.begin() ) ); + + b.sort(); + + BOOST_CHECK( std::equal( b.begin(), b.end(), data.begin() ) ); + + b.push_back( bm_type::value_type("4",4) ); + BOOST_CHECK( b.size() == 5 ); + b.unique(); + BOOST_CHECK( b.size() == 4 ); + b.remove_if( _key < bm_type::value_type("2",2) ); + BOOST_CHECK( b.size() == 3 ); + + b.merge(c); + + b.left.remove_if( _key < "3" ); + + // Test splice and merge + + b.clear(); c.clear(); + + c.left.insert(c.left.begin(),left_data.begin(),left_data.end()); + b.right.splice(b.right.begin(),c.right); + + BOOST_CHECK( c.size() == 0 ); + BOOST_CHECK( b.size() == 4 ); + + c.right.splice(c.right.begin(),b.right,++b.right.begin()); + + b.right.merge(c.right); + c.right.merge(b.right,std::less<long>()); + + b.right.sort(); + b.right.sort(std::less<long>()); + + b.right.unique(); + b.right.unique(std::equal_to<long>()); + + b.right.remove_if( _key < 3 ); + + b.clear(); + b.left.insert(b.left.begin(),left_data.begin(),left_data.end()); + + b.left.relocate(b.left.begin(), ++b.left.begin() ); + b.left.relocate(b.left.end(), b.left.begin(), ++b.left.begin() ); + + b.right.relocate(b.right.begin(), ++b.right.begin() ); + b.right.relocate(b.right.end(), b.right.begin(), ++b.right.begin() ); + + b.relocate(b.begin(), ++b.begin() ); + b.relocate(b.end(), b.begin(), ++b.begin() ); + } + //-------------------------------------------------------------------- + + + //-------------------------------------------------------------------- + { + typedef bimap + < + list_of<std::string>, list_of<long>, + vector_of_relation + + > bm_type; + + std::set< bm_type::value_type > data; + data.insert( bm_type::value_type("1",1) ); + data.insert( bm_type::value_type("2",2) ); + data.insert( bm_type::value_type("3",3) ); + data.insert( bm_type::value_type("4",4) ); + + bm_type b; + b.push_back( bm_type::value_type("1",1) ); + b.push_back( bm_type::value_type("2",2) ); + b.push_back( bm_type::value_type("3",3) ); + b.push_back( bm_type::value_type("4",4) ); + + BOOST_CHECK( std::equal( b.begin(), b.end(), data.begin() ) ); + b.reverse(); + BOOST_CHECK( std::equal( b.rbegin(), b.rend(), data.begin() ) ); + + b.sort(); + + BOOST_CHECK( std::equal( b.begin(), b.end(), data.begin() ) ); + + b.push_back( bm_type::value_type("4",4) ); + BOOST_CHECK( b.size() == 5 ); + b.unique(); + BOOST_CHECK( b.size() == 4 ); + b.remove_if( _key < bm_type::value_type("2",2) ); + BOOST_CHECK( b.size() == 3 ); + + b.relocate( b.begin(), ++b.begin() ); + b.relocate( b.end(), b.begin(), ++b.begin() ); + + b.clear(); + BOOST_CHECK( b.empty() ); + + b.left.assign(left_data.begin(),left_data.end()); + BOOST_CHECK( b.size() == left_data.size() ); + + b.right.assign(right_data.begin(),right_data.end()); + BOOST_CHECK( b.size() == right_data.size() ); + + b.assign(data.begin(),data.end()); + BOOST_CHECK( b.size() == data.size() ); + } + //-------------------------------------------------------------------- + + + //-------------------------------------------------------------------- + { + typedef bimap + < + vector_of< short >, list_of< short >, + vector_of_relation + + > bimap_type; + + bimap_type b1; + + b1.push_back( bimap_type::value_type(1,2) ); + + bimap_type b2( b1 ); + + BOOST_CHECK( b1 == b2 ); + BOOST_CHECK( ! ( b1 != b2 ) ); + BOOST_CHECK( b1 <= b2 ); + BOOST_CHECK( b1 >= b2 ); + BOOST_CHECK( ! ( b1 < b2 ) ); + BOOST_CHECK( ! ( b1 > b2 ) ); + + b1.push_back( bimap_type::value_type(2,3) ); + + b2 = b1; + BOOST_CHECK( b2 == b1 ); + + b1.push_back( bimap_type::value_type(3,4) ); + + b2.left = b1.left; + BOOST_CHECK( b2 == b1 ); + + b1.push_back( bimap_type::value_type(4,5) ); + + b2.right = b1.right; + BOOST_CHECK( b2 == b1 ); + + b1.clear(); + b2.swap(b1); + BOOST_CHECK( b2.empty() && !b1.empty() ); + + b1.left.swap( b2.left ); + BOOST_CHECK( b1.empty() && !b2.empty() ); + + b1.right.swap( b2.right ); + BOOST_CHECK( b2.empty() && !b1.empty() ); + } + //-------------------------------------------------------------------- + +} + + +int test_main( int, char* [] ) +{ + test_bimap(); + return 0; +} + diff --git a/test/test_bimap_serialization.cpp b/test/test_bimap_serialization.cpp new file mode 100755 index 0000000..dafa6e4 --- /dev/null +++ b/test/test_bimap_serialization.cpp @@ -0,0 +1,114 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +#include <boost/config.hpp> + +// std +#include <set> +#include <map> +#include <cstddef> +#include <cassert> +#include <algorithm> +#include <sstream> +#include <algorithm> + +// Boost.Test +#include <boost/test/minimal.hpp> + +// Boost +#include <boost/archive/text_oarchive.hpp> +#include <boost/archive/text_iarchive.hpp> + +// Boost.Bimap +#include <boost/bimap/bimap.hpp> + + +template< class Bimap, class Archive > +void save_bimap(const Bimap & b, Archive & ar) +{ + using namespace boost::bimaps; + + ar << b; + + const typename Bimap::left_const_iterator left_iter = b.left.begin(); + ar << left_iter; + + const typename Bimap::const_iterator iter = ++b.begin(); + ar << iter; +} + + + + +void test_bimap_serialization() +{ + using namespace boost::bimaps; + + typedef bimap<int,double> bm; + + std::set< bm::value_type > data; + data.insert( bm::value_type(1,0.1) ); + data.insert( bm::value_type(2,0.2) ); + data.insert( bm::value_type(3,0.3) ); + data.insert( bm::value_type(4,0.4) ); + + std::ostringstream oss; + + // Save it + { + bm b; + + b.insert(data.begin(),data.end()); + + boost::archive::text_oarchive oa(oss); + + save_bimap(b,oa); + } + + // Reload it + { + bm b; + + std::istringstream iss(oss.str()); + boost::archive::text_iarchive ia(iss); + + ia >> b; + + BOOST_CHECK( std::equal( b.begin(), b.end(), data.begin() ) ); + + bm::left_const_iterator left_iter; + + ia >> left_iter; + + BOOST_CHECK( left_iter == b.left.begin() ); + + bm::const_iterator iter; + + ia >> iter; + + BOOST_CHECK( iter == ++b.begin() ); + } + +} + + +int test_main( int, char* [] ) +{ + test_bimap_serialization(); + return 0; +} + diff --git a/test/test_bimap_set_of.cpp b/test/test_bimap_set_of.cpp new file mode 100755 index 0000000..c51eef8 --- /dev/null +++ b/test/test_bimap_set_of.cpp @@ -0,0 +1,32 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +#include <boost/config.hpp> + +// Boost.Test +#include <boost/test/minimal.hpp> + +#include <boost/bimap/set_of.hpp> + +int test_main( int, char* [] ) +{ + typedef boost::bimaps::set_of<int> set_type; + typedef boost::bimaps::set_of_relation<> set_type_of_relation; + + return 0; +} + diff --git a/test/test_bimap_unconstrained.cpp b/test/test_bimap_unconstrained.cpp new file mode 100755 index 0000000..fd086d9 --- /dev/null +++ b/test/test_bimap_unconstrained.cpp @@ -0,0 +1,109 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +#include <boost/config.hpp> + +// Boost.Test +#include <boost/test/minimal.hpp> + +// Boost.Bimap +#include <boost/bimap/support/lambda.hpp> +#include <boost/bimap/bimap.hpp> + + +void test_bimap_unconstrained() +{ + using namespace boost::bimaps; + + { + typedef bimap<int,double,unconstrained_set_of_relation> bm; + bm b; + b.left.insert( bm::left_value_type(2,34.4) ); + b.right.insert( bm::right_value_type(2.2,3) ); + } + + { + typedef bimap<int,unconstrained_set_of<double> > bm; + bm b; + b.insert( bm::value_type(2,34.4) ); + BOOST_CHECK( b.size() == 1 ); + } + + { + typedef bimap<unconstrained_set_of<int>, double > bm; + bm b; + b.right[2.4] = 34; + BOOST_CHECK( b.right.size() == 1 ); + } + + { + typedef bimap<unconstrained_set_of<int>, double, right_based > bm; + bm b; + b.right[2.4] = 34; + BOOST_CHECK( b.right.size() == 1 ); + } + + { + typedef bimap + < + int, + unconstrained_set_of<double>, + unconstrained_set_of_relation + + > bm; + + bm b; + b.left[2] = 34.4; + BOOST_CHECK( b.left.size() == 1 ); + } + + { + typedef bimap + < + unconstrained_set_of<int>, + double, + unconstrained_set_of_relation + + > bm; + + bm b; + b.right[2.4] = 34; + BOOST_CHECK( b.right.size() == 1 ); + } + + { + typedef bimap + < + unconstrained_set_of<int>, + unconstrained_set_of<double>, + set_of_relation<> + + > bm; + + bm b; + b.insert( bm::value_type(1,2.3) ); + BOOST_CHECK( b.size() == 1 ); + } +} + + +int test_main( int, char* [] ) +{ + test_bimap_unconstrained(); + return 0; +} + diff --git a/test/test_bimap_unordered.cpp b/test/test_bimap_unordered.cpp new file mode 100755 index 0000000..6cba88b --- /dev/null +++ b/test/test_bimap_unordered.cpp @@ -0,0 +1,167 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +#include <boost/config.hpp> + +#define BOOST_BIMAP_DISABLE_SERIALIZATION + +// Boost.Test +#include <boost/test/minimal.hpp> + +// std +#include <set> +#include <map> +#include <string> +#include <functional> + +// Set type specifications +#include <boost/bimap/unordered_set_of.hpp> +#include <boost/bimap/unordered_multiset_of.hpp> + +// bimap container +#include <boost/bimap/bimap.hpp> + +#include <libs/bimap/test/test_bimap.hpp> + +struct left_tag {}; +struct right_tag {}; + +void test_bimap() +{ + using namespace boost::bimaps; + + + typedef std::map<char,std::string> left_data_type; + left_data_type left_data; + left_data.insert( left_data_type::value_type('a',"a") ); + left_data.insert( left_data_type::value_type('b',"b") ); + left_data.insert( left_data_type::value_type('c',"c") ); + left_data.insert( left_data_type::value_type('d',"e") ); + + typedef std::map<std::string,char> right_data_type; + right_data_type right_data; + right_data.insert( right_data_type::value_type("a",'a') ); + right_data.insert( right_data_type::value_type("b",'b') ); + right_data.insert( right_data_type::value_type("c",'c') ); + right_data.insert( right_data_type::value_type("d",'e') ); + + + + //-------------------------------------------------------------------- + { + typedef bimap< + unordered_set_of<char>, unordered_multiset_of<std::string> + + > bm_type; + + std::set< bm_type::value_type > data; + data.insert( bm_type::value_type('a',"a") ); + data.insert( bm_type::value_type('b',"b") ); + data.insert( bm_type::value_type('c',"c") ); + data.insert( bm_type::value_type('d',"d") ); + + bm_type bm; + + test_unordered_set_unordered_multiset_bimap( + bm,data,left_data,right_data + ); + } + //-------------------------------------------------------------------- + + + //-------------------------------------------------------------------- + { + typedef bimap< + unordered_set_of< tagged< char , left_tag > >, + unordered_multiset_of< tagged< std::string, right_tag > > + + > bm_type; + + std::set< bm_type::value_type > data; + data.insert( bm_type::value_type('a',"a") ); + data.insert( bm_type::value_type('b',"b") ); + data.insert( bm_type::value_type('c',"c") ); + data.insert( bm_type::value_type('d',"d") ); + + bm_type bm; + + test_unordered_set_unordered_multiset_bimap( + bm,data,left_data,right_data + ); + test_tagged_bimap<left_tag,right_tag>(bm,data); + } + //-------------------------------------------------------------------- + + + //-------------------------------------------------------------------- + { + typedef bimap + < + set_of< char, std::greater<char> >, + unordered_multiset_of<std::string>, + unordered_set_of_relation<> + + > bm_type; + + std::set< bm_type::value_type > data; + data.insert( bm_type::value_type('a',"a") ); + data.insert( bm_type::value_type('b',"b") ); + data.insert( bm_type::value_type('c',"c") ); + data.insert( bm_type::value_type('d',"d") ); + + bm_type bm; + + test_basic_bimap(bm,data,left_data,right_data); + test_associative_container(bm,data); + test_simple_unordered_associative_container(bm,data); + } + //-------------------------------------------------------------------- + + + //-------------------------------------------------------------------- + { + typedef bimap + < + unordered_multiset_of< char >, + unordered_multiset_of< std::string >, + unordered_multiset_of_relation<> + + > bm_type; + + std::set< bm_type::value_type > data; + data.insert( bm_type::value_type('a',"a") ); + data.insert( bm_type::value_type('b',"b") ); + data.insert( bm_type::value_type('c',"c") ); + data.insert( bm_type::value_type('d',"d") ); + + bm_type bm; + + test_basic_bimap(bm,data,left_data,right_data); + test_associative_container(bm,data); + test_simple_unordered_associative_container(bm,data); + + } + //-------------------------------------------------------------------- +} + + +int test_main( int, char* [] ) +{ + test_bimap(); + return 0; +} + diff --git a/test/test_bimap_unordered_multiset_of.cpp b/test/test_bimap_unordered_multiset_of.cpp new file mode 100755 index 0000000..27a0764 --- /dev/null +++ b/test/test_bimap_unordered_multiset_of.cpp @@ -0,0 +1,34 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +#include <boost/config.hpp> + +// Boost.Test +#include <boost/test/minimal.hpp> + +#include <boost/bimap/unordered_multiset_of.hpp> + +int test_main( int, char* [] ) +{ + typedef boost::bimaps::unordered_multiset_of<int> set_type; + + typedef boost::bimaps:: + unordered_multiset_of_relation<> set_type_of_relation; + + return 0; +} + diff --git a/test/test_bimap_unordered_set_of.cpp b/test/test_bimap_unordered_set_of.cpp new file mode 100755 index 0000000..f3aafe8 --- /dev/null +++ b/test/test_bimap_unordered_set_of.cpp @@ -0,0 +1,32 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +#include <boost/config.hpp> + +// Boost.Test +#include <boost/test/minimal.hpp> + +#include <boost/bimap/unordered_set_of.hpp> + +int test_main( int, char* [] ) +{ + typedef boost::bimaps::unordered_set_of<int> set_type; + typedef boost::bimaps::unordered_set_of_relation<> set_type_of_relation; + + return 0; +} + diff --git a/test/test_bimap_vector_of.cpp b/test/test_bimap_vector_of.cpp new file mode 100755 index 0000000..01da850 --- /dev/null +++ b/test/test_bimap_vector_of.cpp @@ -0,0 +1,32 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +#include <boost/config.hpp> + +// Boost.Test +#include <boost/test/minimal.hpp> + +#include <boost/bimap/vector_of.hpp> + +int test_main( int, char* [] ) +{ + typedef boost::bimaps::vector_of<int> set_type; + typedef boost::bimaps::vector_of_relation set_type_of_relation; + + return 0; +} + diff --git a/test/test_mutant.cpp b/test/test_mutant.cpp new file mode 100755 index 0000000..f422d57 --- /dev/null +++ b/test/test_mutant.cpp @@ -0,0 +1,103 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +#include <boost/config.hpp> + +// Boost.Test +#include <boost/test/minimal.hpp> + +// Boost.MPL +#include <boost/mpl/list.hpp> +#include <boost/type_traits/is_same.hpp> + +// Boost.Bimap +#include <boost/bimap/relation/detail/mutant.hpp> + +using namespace boost::bimaps::relation::detail; + +// The mutant idiom is standard if only POD types are used. + +typedef double type_a; +typedef int type_b; + +const type_a value_a = 1.4; +const type_b value_b = 3; + +struct Data +{ + type_a a; + type_b b; +}; + +struct StdPairView +{ + typedef type_a first_type; + typedef type_b second_type; + type_a first; + type_b second; +}; + +struct ReverseStdPairView +{ + typedef type_a second_type; + typedef type_b first_type; + type_a second; + type_b first; +}; + + +struct MutantData +{ + typedef boost::mpl::list< StdPairView, ReverseStdPairView > mutant_views; + + MutantData(type_a ap, type_b bp) : a(ap), b(bp) {} + type_a a; + type_b b; +}; + + +void test_mutant_basic() +{ + + // mutant test + { + MutantData m(value_a,value_b); + + BOOST_CHECK( sizeof( MutantData ) == sizeof( StdPairView ) ); + + BOOST_CHECK( mutate<StdPairView>(m).first == value_a ); + BOOST_CHECK( mutate<StdPairView>(m).second == value_b ); + BOOST_CHECK( mutate<ReverseStdPairView>(m).first == value_b ); + BOOST_CHECK( mutate<ReverseStdPairView>(m).second == value_a ); + + ReverseStdPairView & rpair = mutate<ReverseStdPairView>(m); + rpair.first = value_b; + rpair.second = value_a; + + BOOST_CHECK( mutate<StdPairView>(m).first == value_a ); + BOOST_CHECK( mutate<StdPairView>(m).second == value_b ); + + BOOST_CHECK( &mutate<StdPairView>(m).first == &m.a ); + BOOST_CHECK( &mutate<StdPairView>(m).second == &m.b ); + } +} + +int test_main( int, char* [] ) +{ + test_mutant_basic(); + return 0; +} diff --git a/test/test_mutant_relation.cpp b/test/test_mutant_relation.cpp new file mode 100755 index 0000000..8e7c8f8 --- /dev/null +++ b/test/test_mutant_relation.cpp @@ -0,0 +1,241 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +#include <boost/config.hpp> + +// std +#include <string> + +// Boost.Test +#include <boost/test/minimal.hpp> + +// Boost.MPL +#include <boost/mpl/assert.hpp> +#include <boost/type_traits/is_same.hpp> + +// Boost.Bimap +#include <boost/bimap/detail/test/check_metadata.hpp> +#include <boost/bimap/tags/tagged.hpp> + +// Boost.Bimap.Relation +#include <boost/bimap/relation/mutant_relation.hpp> +#include <boost/bimap/relation/member_at.hpp> +#include <boost/bimap/relation/support/get.hpp> +#include <boost/bimap/relation/support/pair_by.hpp> +#include <boost/bimap/relation/support/pair_type_by.hpp> +#include <boost/bimap/relation/support/value_type_of.hpp> +#include <boost/bimap/relation/support/member_with_tag.hpp> +#include <boost/bimap/relation/support/is_tag_of_member_at.hpp> + +// Bimap Test Utilities +#include "test_relation.hpp" + +BOOST_BIMAP_TEST_STATIC_FUNCTION( untagged_static_test ) +{ + using namespace boost::bimaps::relation::member_at; + using namespace boost::bimaps::relation; + using namespace boost::bimaps::tags; + + struct left_data {}; + struct right_data {}; + + typedef mutant_relation< left_data, right_data > rel; + + BOOST_BIMAP_CHECK_METADATA(rel,left_value_type ,left_data); + BOOST_BIMAP_CHECK_METADATA(rel,right_value_type,right_data); + + BOOST_BIMAP_CHECK_METADATA(rel,left_tag ,left ); + BOOST_BIMAP_CHECK_METADATA(rel,right_tag,right); + + typedef tagged<left_data ,left > desired_tagged_left_type; + BOOST_BIMAP_CHECK_METADATA(rel,tagged_left_type,desired_tagged_left_type); + + typedef tagged<right_data,right> desired_tagged_right_type; + BOOST_BIMAP_CHECK_METADATA(rel,tagged_right_type,desired_tagged_right_type); + +} + +BOOST_BIMAP_TEST_STATIC_FUNCTION( tagged_static_test) +{ + using namespace boost::bimaps::relation::member_at; + using namespace boost::bimaps::relation; + using namespace boost::bimaps::tags; + + struct left_data {}; + struct right_data {}; + + struct left_tag {}; + struct right_tag {}; + + typedef mutant_relation< + tagged<left_data,left_tag>, tagged<right_data,right_tag> > rel; + + BOOST_BIMAP_CHECK_METADATA(rel,left_value_type ,left_data); + BOOST_BIMAP_CHECK_METADATA(rel,right_value_type,right_data); + + BOOST_BIMAP_CHECK_METADATA(rel,left_tag ,left_tag ); + BOOST_BIMAP_CHECK_METADATA(rel,right_tag,right_tag ); + + typedef tagged<left_data ,left_tag > desired_tagged_left_type; + BOOST_BIMAP_CHECK_METADATA(rel,tagged_left_type,desired_tagged_left_type); + + typedef tagged<right_data,right_tag> desired_tagged_right_type; + BOOST_BIMAP_CHECK_METADATA(rel,tagged_right_type,desired_tagged_right_type); +} + +struct mutant_relation_builder +{ + template< class LeftType, class RightType > + struct build + { + typedef boost::bimaps::relation:: + mutant_relation<LeftType,RightType,::boost::mpl::na,true> type; + }; +}; + +// Complex classes + +class cc1 +{ + public: + cc1(int s = 0) : a(s+100), b(s+101) {} + static int sd; + int a; + const int b; +}; + +bool operator==(const cc1 & da, const cc1 & db) +{ + return da.a == db.a && da.b == db.b; +} + +int cc1::sd = 102; + +class cc2_base +{ + public: + cc2_base(int s) : a(s+200) {} + int a; +}; + +class cc2 : public cc2_base +{ + public: + cc2(int s = 0) : cc2_base(s), b(s+201) {} + int b; +}; + +bool operator==(const cc2 & da, const cc2 & db) +{ + return da.a == db.a && da.b == db.b; +} + +class cc3_base +{ + public: + cc3_base(int s = 0) : a(s+300) {} + const int a; +}; + +class cc3 : virtual public cc3_base +{ + public: + cc3(int s = 0) : cc3_base(s), b(s+301) {} + int b; +}; + +bool operator==(const cc3 & da, const cc3 & db) +{ + return da.a == db.a && da.b == db.b; +} + +class cc4_base +{ + public: + cc4_base(int s) : a(s+400) {} + virtual ~cc4_base() {} + const int a; +}; + +class cc4 : public cc4_base +{ + public: + cc4(int s = 0) : cc4_base(s), b(s+401) {} + int b; +}; + +bool operator==(const cc4 & da, const cc4 & db) +{ + return da.a == db.a && da.b == db.b; +} + +class cc5 : public cc1, public cc3, public cc4 +{ + public: + cc5(int s = 0) : cc1(s), cc3(s), cc4(s) {} +}; + +bool operator==(const cc5 & da, const cc5 & db) +{ + return da.cc1::a == db.cc1::a && da.cc1::b == db.cc1::b && + da.cc3::a == db.cc3::a && da.cc3::b == db.cc3::b && + da.cc4::a == db.cc4::a && da.cc4::b == db.cc4::b; +} + +class cc6 +{ + public: + cc6(int s = 0) : a(s+600), b(a) {} + int a; + int & b; +}; + +bool operator==(const cc6 & da, const cc6 & db) +{ + return da.a == db.a && da.b == db.b; +} + +void test_mutant_relation() +{ + test_relation< mutant_relation_builder, char , double >( 'l', 2.5 ); + test_relation< mutant_relation_builder, double, char >( 2.5, 'r' ); + + test_relation<mutant_relation_builder, int , int >( 1 , 2 ); + + test_relation<mutant_relation_builder, std::string, int* >("left value",0); + + test_relation<mutant_relation_builder, cc1, cc2>(0,0); + test_relation<mutant_relation_builder, cc2, cc3>(0,0); + test_relation<mutant_relation_builder, cc3, cc4>(0,0); + test_relation<mutant_relation_builder, cc4, cc5>(0,0); +} + +int test_main( int, char* [] ) +{ + + // Test metadata correctness with untagged relation version + BOOST_BIMAP_CALL_TEST_STATIC_FUNCTION( tagged_static_test ); + + // Test metadata correctness with tagged relation version + BOOST_BIMAP_CALL_TEST_STATIC_FUNCTION( untagged_static_test ); + + // Test basic + test_mutant_relation(); + + return 0; +} + diff --git a/test/test_relation.hpp b/test/test_relation.hpp new file mode 100755 index 0000000..65da6b9 --- /dev/null +++ b/test/test_relation.hpp @@ -0,0 +1,191 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_BIMAP_TEST_TEST_RELATION_HPP +#define BOOST_BIMAP_TEST_TEST_RELATION_HPP + +#if defined(_MSC_VER) && (_MSC_VER>=1200) +#pragma once +#endif + +#include <boost/config.hpp> + +// Boost.Test +#include <boost/test/minimal.hpp> + +// Boost.MPL +#include <boost/mpl/assert.hpp> +#include <boost/type_traits/is_same.hpp> + +// Boost.Bimap +#include <boost/bimap/detail/test/check_metadata.hpp> +#include <boost/bimap/tags/tagged.hpp> + +// Boost.Bimap.Relation +#include <boost/bimap/relation/member_at.hpp> +#include <boost/bimap/relation/support/get.hpp> +#include <boost/bimap/relation/support/pair_by.hpp> +#include <boost/bimap/relation/support/pair_type_by.hpp> +#include <boost/bimap/relation/support/value_type_of.hpp> +#include <boost/bimap/relation/support/member_with_tag.hpp> +#include <boost/bimap/relation/support/is_tag_of_member_at.hpp> + + + +template< class Relation > +void test_relation_with_default_tags(Relation & rel, + const typename Relation::left_value_type & lv, + const typename Relation::right_value_type & rv) +{ + + using namespace boost::bimaps::relation::support; + using namespace boost::bimaps::relation; + using namespace boost::bimaps::tags; + + // It must work with normal tags + + BOOST_CHECK( pair_by<member_at::left >(rel).first == lv ); + BOOST_CHECK( pair_by<member_at::left >(rel).second == rv ); + + BOOST_CHECK( pair_by<member_at::right>(rel).first == rv ); + BOOST_CHECK( pair_by<member_at::right>(rel).second == lv ); + + BOOST_CHECK( get<member_at::left >(rel) == rel.left ); + BOOST_CHECK( get<member_at::right>(rel) == rel.right ); + + BOOST_CHECK( + get<member_at::left >(pair_by<member_at::left >(rel)) == rel.left + ); + + BOOST_CHECK( + get<member_at::right>(pair_by<member_at::left >(rel)) == rel.right + ); + + BOOST_CHECK( + get<member_at::left >(pair_by<member_at::right>(rel)) == rel.left + ); + + BOOST_CHECK( + get<member_at::right>(pair_by<member_at::right>(rel)) == rel.right + ); + +} + +template< class Relation, class LeftTag, class RightTag > +void test_relation_with_user_tags(Relation & rel, + const typename Relation::left_value_type & lv, + const typename Relation::right_value_type & rv) +{ + + using namespace boost::bimaps::relation::support; + using namespace boost::bimaps::relation; + using namespace boost::bimaps::tags; + + // And with users ones + + BOOST_CHECK( pair_by<LeftTag >(rel).first == lv ); + BOOST_CHECK( pair_by<LeftTag >(rel).second == rv ); + + BOOST_CHECK( pair_by<RightTag>(rel).first == rv ); + BOOST_CHECK( pair_by<RightTag>(rel).second == lv ); + + BOOST_CHECK( get<LeftTag >(rel) == rel.left ); + BOOST_CHECK( get<RightTag>(rel) == rel.right ); + + BOOST_CHECK( get<LeftTag >(pair_by<LeftTag >(rel)) == rel.left ); + BOOST_CHECK( get<RightTag>(pair_by<LeftTag >(rel)) == rel.right ); + + BOOST_CHECK( get<LeftTag >(pair_by<RightTag>(rel)) == rel.left ); + BOOST_CHECK( get<RightTag>(pair_by<RightTag>(rel)) == rel.right ); + + //---------------------------------------------------------------- + + BOOST_CHECK( rel.template get<LeftTag >() == rel.left ); + BOOST_CHECK( rel.template get<RightTag>() == rel.right ); + + BOOST_CHECK( pair_by<LeftTag >(rel).template get<LeftTag >()== rel.left ); + BOOST_CHECK( pair_by<LeftTag >(rel).template get<RightTag>()== rel.right); + + BOOST_CHECK( pair_by<RightTag>(rel).template get<LeftTag >()== rel.left ); + BOOST_CHECK( pair_by<RightTag>(rel).template get<RightTag>()== rel.right); +} + +struct left_user_tag {}; +struct right_user_tag {}; + +template< class RelationBuilder, class LeftData, class RightData > +void test_relation(const LeftData & lv, const RightData & rv) +{ + using namespace boost::bimaps::relation::support; + using namespace boost::bimaps::relation; + using boost::bimaps::tags::tagged; + + // Untagged test + { + typedef typename RelationBuilder::template build + < + LeftData, + RightData + + >::type rel_type; + + rel_type rel( lv, rv ); + + test_relation_with_default_tags( rel, lv, rv); + } + + // Tagged test + { + typedef typename RelationBuilder::template build + < + tagged<LeftData , left_user_tag >, + tagged<RightData, right_user_tag > + + >::type rel_type; + + rel_type rel( lv, rv ); + + test_relation_with_default_tags(rel, lv, rv ); + test_relation_with_user_tags + < + rel_type, + left_user_tag,right_user_tag + + >(rel,lv,rv); + } + + // Default Constructor, Constructor from views and some operators + { +/* + typedef typename RelationBuilder::template build + < + tagged<LeftData , left_user_tag >, + tagged<RightData, right_user_tag > + + >::type rel_type; + + typedef typename pair_type_by< left_user_tag,rel_type>::type left_pair; + typedef typename pair_type_by<right_user_tag,rel_type>::type right_pair; + + rel_type rel_from_left ( left_pair(lv,rv) ); + rel_type rel_from_right( right_pair(rv,lv) ); + + BOOST_CHECK( rel_from_left == rel_from_right ); + BOOST_CHECK( rel_from_left == rel_type(lv,rv) ); + + rel_type rel; + + rel = rel_from_left; + + BOOST_CHECK( rel == rel_from_left ); +*/ + } + +} + +#endif // BOOST_BIMAP_TEST_TEST_RELATION_HPP diff --git a/test/test_structured_pair.cpp b/test/test_structured_pair.cpp new file mode 100755 index 0000000..776661c --- /dev/null +++ b/test/test_structured_pair.cpp @@ -0,0 +1,98 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +#include <boost/config.hpp> + +// Boost.Test +#include <boost/test/minimal.hpp> + +// std +#include <utility> +#include <cstddef> + +// Boost.Static_assert +#include <boost/static_assert.hpp> + +// Boost.Bimap +#include <boost/bimap/detail/test/check_metadata.hpp> + +#include <boost/bimap/relation/structured_pair.hpp> + + +BOOST_BIMAP_TEST_STATIC_FUNCTION( static_metadata_test ) +{ + using namespace boost::bimaps::relation; + + struct data_a { char data; }; + struct data_b { double data; }; + + typedef structured_pair + < + data_a, + data_b, + normal_layout + + > sp_ab; + + typedef structured_pair + < + data_b, + data_a, + mirror_layout + + > sp_ba; + + BOOST_BIMAP_CHECK_METADATA(sp_ab, first_type , data_a); + BOOST_BIMAP_CHECK_METADATA(sp_ab, second_type, data_b); + + BOOST_BIMAP_CHECK_METADATA(sp_ba, first_type , data_b); + BOOST_BIMAP_CHECK_METADATA(sp_ba, second_type, data_a); + +} + + +void test_basic() +{ + + using namespace boost::bimaps::relation; + + // Instanciate two pairs and test the storage alignmentDataData + + typedef structured_pair< short, double, normal_layout > pair_type; + typedef structured_pair< double, short, mirror_layout > mirror_type; + + pair_type pa( 2, 3.1416 ); + mirror_type pb( 3.1416, 2 ); + + BOOST_CHECK( pa.first == pb.second ); + BOOST_CHECK( pa.second == pb.first ); + +} + + +int test_main( int, char* [] ) +{ + + BOOST_BIMAP_CALL_TEST_STATIC_FUNCTION( static_are_storage_compatible_test ); + + BOOST_BIMAP_CALL_TEST_STATIC_FUNCTION( static_metadata_test ); + + test_basic(); + + return 0; +} + diff --git a/test/test_tagged.cpp b/test/test_tagged.cpp new file mode 100755 index 0000000..334fac8 --- /dev/null +++ b/test/test_tagged.cpp @@ -0,0 +1,108 @@ +// Boost.Bimap +// +// Copyright (c) 2006-2007 Matias Capeletto +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// VC++ 8.0 warns on usage of certain Standard Library and API functions that +// can be cause buffer overruns or other possible security issues if misused. +// See http://msdn.microsoft.com/msdnmag/issues/05/05/SafeCandC/default.aspx +// But the wording of the warning is misleading and unsettling, there are no +// portable alternative functions, and VC++ 8.0's own libraries use the +// functions in question. So turn off the warnings. +#define _CRT_SECURE_NO_DEPRECATE +#define _SCL_SECURE_NO_DEPRECATE + +#include <boost/config.hpp> + +// Boost.Test +#include <boost/test/minimal.hpp> + +#include <boost/static_assert.hpp> + +// Boost.MPL +#include <boost/type_traits/is_same.hpp> +#include <boost/mpl/placeholders.hpp> +#include <boost/mpl/assert.hpp> +#include <boost/type_traits/add_const.hpp> + +// Boost.Bimap +#include <boost/bimap/detail/test/check_metadata.hpp> + +// Boost.Bimap.Tags +#include <boost/bimap/tags/tagged.hpp> +#include <boost/bimap/tags/support/default_tagged.hpp> +#include <boost/bimap/tags/support/is_tagged.hpp> +#include <boost/bimap/tags/support/overwrite_tagged.hpp> +#include <boost/bimap/tags/support/tag_of.hpp> +#include <boost/bimap/tags/support/value_type_of.hpp> +#include <boost/bimap/tags/support/apply_to_value_type.hpp> + + + + +BOOST_BIMAP_TEST_STATIC_FUNCTION( test_metafunctions ) +{ + using namespace boost::bimaps::tags::support; + using namespace boost::bimaps::tags; + using namespace boost::mpl::placeholders; + using namespace boost; + + struct tag {}; + struct value {}; + + // Test apply_to_value_type metafunction + // tagged<value,tag> ----(add_const<_>)----> tagged<value const,tag> + typedef tagged< value, tag > ttype; + typedef apply_to_value_type< add_const<_>,ttype>::type result; + typedef is_same<tagged<value const,tag>,result> compare; + BOOST_MPL_ASSERT_MSG(compare::value,tag,(result)); +} + +struct tag_a {}; +struct tag_b {}; +struct data {}; + +void test_function() +{ + + using namespace boost::bimaps::tags::support; + using namespace boost::bimaps::tags; + using boost::is_same; + + typedef tagged< data, tag_a > data_a; + typedef tagged< data, tag_b > data_b; + + BOOST_CHECK(( is_same< data_a::value_type , data >::value )); + BOOST_CHECK(( is_same< data_a::tag , tag_a >::value )); + + BOOST_CHECK(( + is_same< overwrite_tagged < data_a, tag_b >::type, data_b >::value + )); + BOOST_CHECK(( + is_same< default_tagged < data_a, tag_b >::type, data_a >::value + )); + BOOST_CHECK(( + is_same< default_tagged < data , tag_b >::type, data_b >::value + )); + + BOOST_CHECK(( is_tagged< data >::value == false )); + BOOST_CHECK(( is_tagged< data_a >::value == true )); + + BOOST_CHECK(( is_same< value_type_of<data_a>::type, data >::value )); + BOOST_CHECK(( is_same< tag_of <data_a>::type, tag_a >::value )); + +} + +int test_main( int, char* [] ) +{ + test_function(); + + // Test metanfunctions + BOOST_BIMAP_CALL_TEST_STATIC_FUNCTION( test_metafunctions ); + + return 0; +} +