Compare commits

...

185 Commits

Author SHA1 Message Date
Christopher Hite cceb28ac6b optional_optimization branch
[SVN r77091]
2012-02-22 10:37:27 +00:00
Joaquín M López Muñoz 2ef40ef45a suppressed a potential narrow conversion warning described in ticket #3365
[SVN r75643]
2011-11-24 08:07:35 +00:00
Joaquín M López Muñoz 867a0fb9c9 fixed #5741
[SVN r73498]
2011-08-03 06:31:26 +00:00
Joaquín M López Muñoz bac508586e fixed #5488
[SVN r71770]
2011-05-06 19:56:06 +00:00
Joaquín M López Muñoz 1186efb3f0 fixed problem reported at http://lists.boost.org/boost-users/2011/05/68022.php
[SVN r71671]
2011-05-02 15:06:01 +00:00
Ralf W. Grosse-Kunstleve f0c0ae11a8 boost/multi_index/detail/scope_guard.hpp: fixing typo to restore g++ (and possibly other) builds
[SVN r69720]
2011-03-08 17:33:30 +00:00
Thorsten Jørgen Ottosen ebb7d18ce6 update with make_guard_if and varients
[SVN r69632]
2011-03-07 21:50:12 +00:00
Joaquín M López Muñoz 3e9d0232d2 closed #5260
[SVN r69540]
2011-03-04 08:06:42 +00:00
Steven Watanabe 55723474d2 Revert [67111] (addition of boost/detail/iomanip.hpp) and all the commits that depend on it. ([68137], [68140], [68141], [68154], and [68165]).
[SVN r68168]
2011-01-15 08:11:51 +00:00
Bryce Adelstein-Lelbach 1bf606a75d Replacing the use of <iomanip> with <boost/detail/iomanip.hpp> across Boost.
On Linux, GNU's libstdc++, which is the default stdlib for icc and clang,
cannot parse the <iomanip> header in version 4.5+ (which thankfully neither
compiler advises the use of yet), as it's original C++98-friendly
implementation has been replaced with a gnu++0x implementation.
<boost/detail/iomanip.hpp> is a portable implementation of <iomanip>, providing
boost::detail::setfill, boost::detail::setbase, boost::detail::setw,
boost::detail::setprecision, boost::detail::setiosflags and
boost::detail::resetiosflags. 



[SVN r68140]
2011-01-14 02:35:58 +00:00
Joaquín M López Muñoz 7b1bcc810d completed fix in [64312] and [64317]
[SVN r64322]
2010-07-25 10:12:38 +00:00
Joaquín M López Muñoz 78a83060f7 completed fix in [64312]
[SVN r64317]
2010-07-24 19:31:45 +00:00
Joaquín M López Muñoz bf08ab429c synced with silent yet backwards-compatibility-breaking change of serialization::version<T>:value type from unsigned int to int in [62358]
[SVN r64312]
2010-07-24 09:17:01 +00:00
Joaquín M López Muñoz a739892808 fixed #4130
[SVN r61482]
2010-04-22 11:36:27 +00:00
Joaquín M López Muñoz 80517e00d7 eliminated dubious use of preprocessor
[SVN r59582]
2010-02-08 15:56:06 +00:00
Joaquín M López Muñoz 4223235333 completed fix in [58485] with proper handling of value_type serialization class versioning
[SVN r59443]
2010-02-03 14:29:55 +00:00
Joaquín M López Muñoz 9dfc424d7a handled serialization of non default constructible values
[SVN r58485]
2009-12-22 07:20:41 +00:00
Joaquín M López Muñoz 270d048f12 fixed #3778
[SVN r58472]
2009-12-21 09:54:44 +00:00
Joaquín M López Muñoz 604128d17a suppressed MSVC /W4 C4512 warning
[SVN r57541]
2009-11-10 10:18:55 +00:00
Troy D. Straszheim 4c3b315b0b rm cmake from trunk. I'm not entirely sure this is necessary to satisfy the inspect script, but I'm not taking any chances, and it is easy to put back
[SVN r56942]
2009-10-17 02:07:38 +00:00
Joaquín M López Muñoz 6b58056716 updated according to latest regression tests results
[SVN r56829]
2009-10-14 15:04:13 +00:00
Joaquín M López Muñoz 7d1417fe8c fixed #3462
[SVN r56354]
2009-09-22 13:29:08 +00:00
Joaquín M López Muñoz 12ba0771e8 documented [55994]
[SVN r55995]
2009-09-03 12:29:42 +00:00
Joaquín M López Muñoz fd2b4ede68 fixed #3365
[SVN r55994]
2009-09-03 12:11:59 +00:00
Troy D. Straszheim 5e50c69465 Copyrights on CMakeLists.txt to keep them from clogging up the inspect
reports.  This is essentially the same commit as r55095 on the release
branch.



[SVN r55159]
2009-07-26 00:49:56 +00:00
Joaquín M López Muñoz 86059ad43f updated according to latest regression tests results
[SVN r55058]
2009-07-21 11:41:18 +00:00
Joaquín M López Muñoz b14efa6fbf documented tag_list
[SVN r55055]
2009-07-21 09:59:35 +00:00
Joaquín M López Muñoz 9c8c001d5d added workaround for IBM XL C/C++
[SVN r53676]
2009-06-06 10:46:10 +00:00
Joaquín M López Muñoz 06b509b35c provided erase() reentrancy even in invariant checking mode
[SVN r53633]
2009-06-04 13:05:10 +00:00
Joaquín M López Muñoz 45adb9c08a added qualifier to solve ambiguity with std::make_tuple
[SVN r53301]
2009-05-27 12:26:43 +00:00
Joaquín M López Muñoz 436ea292c6 handcrafted the element type of the bimap example for the same reasons as explained in [53273]
[SVN r53275]
2009-05-26 08:59:47 +00:00
Joaquín M López Muñoz a5210bff85 handcrafted pair_of_ints to guarantee that first and second belong to pair_of_ints proper and not to some implementation-specific base class, which happens with std::pair in MSVC 10 thus precluding the use of boost::multi_index::member as per 14.3.2/5 (no conversions applied to pointer to member functions template arguments).
[SVN r53273]
2009-05-26 06:34:33 +00:00
Joaquín M López Muñoz 1eebcfcf5f fixed #3076
[SVN r53246]
2009-05-25 12:20:07 +00:00
Joaquín M López Muñoz 8290474391 updated according to latest regression tests results
[SVN r52078]
2009-03-31 16:12:23 +00:00
Joaquín M López Muñoz c80e451d22 updated according to latest regression tests results
[SVN r50321]
2008-12-19 07:53:46 +00:00
Joaquín M López Muñoz 90bc0b7662 suppressed MSVC warning in composite_key, deprecated nth_index_iterator and family, some stylistic changes in the tutorial.
[SVN r49674]
2008-11-10 14:49:57 +00:00
Michael A. Jackson 5d016b4003 Updating dependency information for modularized libraries.
[SVN r49628]
2008-11-07 17:05:27 +00:00
Michael A. Jackson 11f09a3558 Updating CMake files to latest trunk. Added dependency information for regression tests and a few new macros for internal use.
[SVN r49627]
2008-11-07 17:02:56 +00:00
Michael A. Jackson 03ebcdd0f4 Continuing merge of CMake build system files into trunk with the encouragement of Doug Gregor
[SVN r49510]
2008-11-01 13:15:41 +00:00
Joaquín M López Muñoz 62911d5198 updated according to latest regression tests results
[SVN r49142]
2008-10-06 13:10:32 +00:00
Joaquín M López Muñoz 05e70771fd fixed #2313
[SVN r48728]
2008-09-11 07:13:11 +00:00
Joaquín M López Muñoz 6b5f74732b fixed #2257
[SVN r48444]
2008-08-29 12:36:56 +00:00
Joaquín M López Muñoz a404be8a6b stylistic change as per Boris Gubenko's advice
[SVN r47225]
2008-07-08 15:08:11 +00:00
Joaquín M López Muñoz 47b98dd304 updated according to latest regression tests results
[SVN r47071]
2008-07-04 08:02:32 +00:00
Joaquín M López Muñoz d881480b52 updated according to latest regression tests results
[SVN r47041]
2008-07-03 14:40:14 +00:00
Joaquín M López Muñoz 15accb2836 Boost 1.36 version of Boost.MultiIndex
passim: supressed non-ASCII chars in C++ code
bidir_node_iterator.hpp: deleted unused template parameter
bucket_array.hpp: avoided allocator<void> instantiations
hash_index_iterator.hpp: avoided allocator<void> instantiations
hash_index_node.hpp: avoided allocator<void> instantiations, renamed var
ord_index_node.hpp: avoided allocator<void> instantiations
rnd_index_loader.hpp: avoided allocator<void> instantiations
rnd_index_node.hpp: avoided allocator<void> instantiations
rnd_index_ptr_array.hpp: avoided allocator<void> instantiations
rnd_node_iterator.hpp: deleted unused template parameter
seq_index_node.hpp: avoided allocator<void> instantiations
hashed_index.hpp: rewritten modify_ so that elements with unmodified key do not change position
multi_index_container.hpp: added allocator ctor
acknowledgements.html: added acknowledgements for Boost 1.36
compiler_specifics.html: typo
hash_indices.html: documented updating functions behavior wrt unmodified keys, formatting typos
key_extraction.html: formatting typos
multi_index_container.html: added allocator ctor, formatting typos
ord_indices.html: documented updating functions behavior wrt unmodified keys, formatting typos
rnd_indices.html: formatting typos
seq_indices.html: formatting typos
release_notes.html: added release notes for Boost 1.36
hashed.cpp: blocked Boost inspect tool check for ASCII only chars
non_std_allocator.hpp: removed void specialization to verify that no allocator<void> instantiations are generated
test_copy_assignment.cpp: added test for multi_index_container allocator ctor
test_update.cpp: added test for stability of update functions wrt to unmodified keys

[SVN r46770]
2008-06-27 13:32:24 +00:00
Joaquín M López Muñoz 78f6bf5446 updated according to latest regression tests results, fixed a broken link, typo
[SVN r43157]
2008-02-07 16:29:27 +00:00
Joaquín M López Muñoz aebc21ee44 ADL-based swap call moved to an utility function (after mistaken attempt at rev 41220 to solve name-hiding issues)
[SVN r41397]
2007-11-26 13:48:36 +00:00
Joaquín M López Muñoz ff403f0a62 added .exe suffix missing at rev 41297
[SVN r41315]
2007-11-23 07:57:15 +00:00
Joaquín M López Muñoz efd8ea14ef included an exe filename modifying rule to avoid interference problems with Vista UAC (fixes #1429)
[SVN r41297]
2007-11-22 07:59:28 +00:00
Joaquín M López Muñoz 58fd64b622 moved some ADL stuff out of a potentially name-hiding scope
[SVN r41220]
2007-11-19 11:08:11 +00:00
Joaquín M López Muñoz f83aa3c780 updated according to latest regression tests results
[SVN r40838]
2007-11-06 14:33:59 +00:00
Joaquín M López Muñoz 26ce890ff8 fixed some struct/class discordances between decls and defs
[SVN r40542]
2007-10-29 08:16:56 +00:00
Joaquín M López Muñoz c4a9b8f8e6 updated according to latest regression tests results
[SVN r40541]
2007-10-29 08:12:58 +00:00
Joaquín M López Muñoz 3a4ac5c0a4 guarded some static asserts in project() funs from Sun C++ 5.7
[SVN r40292]
2007-10-22 17:22:46 +00:00
Joaquín M López Muñoz ae87c1d454 added missing #include
[SVN r40056]
2007-10-15 16:10:39 +00:00
Joaquín M López Muñoz 40634a5f23 typo
[SVN r40040]
2007-10-15 06:54:34 +00:00
Joaquín M López Muñoz 16778f3ff3 def_ctor_tuple_cons.hpp: no longer used
memfun_key.cpp: is now fun_key.cpp

[SVN r39923]
2007-10-11 11:23:47 +00:00
Joaquín M López Muñoz 47b172ab68 Boost 1.35 version of Boost.MultiIndex
allocator_utilities.hpp: added partial_std_allocator_wrapper::value_type
composite_key.hpp: used hash_fwd.hpp
auto_space.hpp: added support for non-standard allocators
bidir_node_iterator.hpp: moved friend-injected operators out of class
copy_map.hpp: added support for non-standard allocators
hash_index_args.hpp: removed deprecated use of <boost/functional/hash/hash.hpp>
hash_index_iterator.hpp: moved friend-injected operators our of class
hash_index_node.hpp: added support for non-standard allocators
header_holder.hpp:added support for non-standard allocators
index_base.hpp: added support for non-standard allocators, added modify_rollback, added small improvement to modify
index_loader.hpp: added support for non-standard allocators
index_matcher.hpp: added support for non-standard allocators
index_node_base.hpp: added support for non-standard allocators
iter_adaptor.hpp: added some out-of-class operators to alleviate a MSVC++ 6.0 problem
modify_key_adaptor.hpp: renamed some vars to accomudate broader usage scope
node_type.hpp: added support for non-standard allocators
ord_index_node.hpp: added support for non-standard allocators
ord_index_ops.hpp: implemented a more efficient equal_range
rnd_index_loader.hpp: added support for non-standard allocators
rnd_index_node.hpp: added support for non-standard allocators
rnd_index_ops.hpp: added support for non-standard allocators
rnd_index_ptr_array.hpp: added support for non-standard allocators
rnd_node_iterator.hpp: moved friend-injected operators out of class
seq_index_node.hpp: added support for non-standard allocators
seq_index_ops.hpp: added support for non-standard allocators
uintptr_type.hpp: added support for __int64
unbounded.hpp: fixed ODR problem
value_compare.hpp: fixed a small unefficiency
global_fun: initial commit
hashed_index.hpp: added support for non-standard allocators, added c[r]{begin|end}, [local_]iterator_to, rollback modify
identity_fwd.hpp: fixed wrong include guard name
key_extractors.hpp: added global_fun
mem_fun.hpp: removed superfluous =0's
ordered_index.hpp: added support for non-standard allocators, added c[r]{begin|end}, iterator_to, rollback modify, improved equal_range and range, added conformance to DR 233
random_access_index.hpp: added support for non-standard allocators, added c[r]{begin|end}, iterator_to, rollback modify, added conformance to 23.1.1/9
sequenced_index.hpp: added support for non-standard allocators, added c[r]{begin|end}, iterator_to, rollback modify, added conformance to 23.1.1/9, improved resize
multi_index_container.hpp: added support for non-standard allocators, improved ctor_args_list, rollback modify
acknowledgements.html: added entry for Boost 1.35
examples.html: renamed example 2, added B.IP example/composite_keys.cpp
future_work.html: removed entry on bimap
hash_indices.html: added c[r]{begin|end}, [local_]iterator_to, rollback modify
reference/index.html: added global_fun
reference/key_extraction.html: added global_fun, added technical correction
multi_index_container.html: added support for non-standard allocators
ord_indices.html: added c[r]{begin|end}, iterator_to, rollback modify
rnd_indices.html: added c[r]{begin|end}, iterator_to, rollback modify
seq_indices.html: added c[r]{begin|end}, iterator_to, rollback modify
release_notes.html: added entry for Boost 1.35
tests.html: added new serialization test file
basics.html: added rollback modify
creation.html: added support for non-standard allocators
tutorial/indices.html: added iterator_to
tutorial/key_extraction.html: added global_fun
composite_keys.cpp: fixed technicality
fun_key.cpp: was memfun_key.cpp, added global_fun
ip_allocator.cpp: initial commit
example/Jamfile.v2: renamed memfun_key, added ip_allocator
test_perf.cpp: fixed technicality
employee.hpp: used a non-standard allocator
test/Jamfile.v2: added new test file
non_std_allocator.hpp: initial commit
pair_of_ints.hpp: added decrement facilities
test_capacity.cpp: added extra check on resize
test_copy_assignment.cpp: added test for 23.1.1/9
test_iterators.cpp: added tests for c[r]{begin|end} and [local_]iterator_to, fixed technicality
test_key_extractors.cpp: added tests for global_fun
test_modifiers.cpp: added tests dor DR 233, fixed technicality
test_range.cpp: added extra checks to secure range refactoring
test_rearrange.cpp: fixed technicality
test_serialization.cpp: added new test file
test_serialization1.cpp: corrected include, used a non-standard allocator
test_serialization2.cpp: corrected include, used a non-standard allocator, split some stuff ro test_serialization3.cpp
test_serialization3.cpp: initial commit
test_serialization3.hpp: initial commit
test_serialization_template.hpp: removed some reliance on ADL
test_update.cpp: addes tests for rollback modify, fixed technicality

[SVN r39922]
2007-10-11 10:57:30 +00:00
Joaquín M. López Muñoz d6932847ec fixed grammar
[SVN r37104]
2007-02-27 07:47:43 +00:00
Joaquín M. López Muñoz 88a418d563 supressed GCC -W warnings about implicit initialization in copy ctors
[SVN r37078]
2007-02-26 09:13:50 +00:00
Joaquín M. López Muñoz 16325e6039 supressed MSVC++ spurious C4312/C4311 warnings described at http://lists.boost.org/boost-users/2006/03/18075.php, with help from John Maddock
[SVN r37049]
2007-02-23 16:14:35 +00:00
Joaquín M. López Muñoz 7be686f18e avoided reliance on template parameter array-to-pointer decay when calling std::equal since it was posing problems for ICC EM64T 9.1 over MSVC++ 8.0
[SVN r36775]
2007-01-24 18:19:32 +00:00
Joaquín M. López Muñoz 8bdf62586f fixed problem reported at http://lists.boost.org/boost-users/2006/12/24215.php
[SVN r36479]
2006-12-21 11:54:19 +00:00
Joaquín M. López Muñoz 6fa0f070b9 updated acknowledgements list
[SVN r36478]
2006-12-21 11:49:36 +00:00
Joaquín M. López Muñoz 1130b76e4b removed obsolete Boost.Build v1 Jamfile
[SVN r35903]
2006-11-07 14:51:19 +00:00
Joaquín M. López Muñoz 2e22bed967 added v2 Jamfile
[SVN r35899]
2006-11-07 14:41:22 +00:00
Joaquín M. López Muñoz 88f3a9ca8b added Sun Studio 11 for Solaris
[SVN r35633]
2006-10-16 17:37:04 +00:00
Joaquín M. López Muñoz 8e573eba2c extended coverage of BOOST_MULTI_INDEX_PRIVATE_IF_USING_DECL_FOR_TEMPL_FUNCTIONS to Sun Studio
[SVN r35632]
2006-10-16 17:34:47 +00:00
Joaquín M. López Muñoz 2e361f8b6a updated acknowledgements list
[SVN r35441]
2006-10-02 15:13:57 +00:00
Joaquín M. López Muñoz 259f87b550 fixed bugs reported at http://lists.boost.org/boost-users/2006/09/22604.php
[SVN r35440]
2006-10-02 15:12:46 +00:00
Joaquín M. López Muñoz bbeb058580 updated according to latest regression tests results
[SVN r34742]
2006-07-26 15:09:41 +00:00
Joaquín M. López Muñoz 5cd33a9a81 updated acknowledgements list
[SVN r34741]
2006-07-26 14:56:57 +00:00
Joaquín M. López Muñoz 252398ac13 added missing include
[SVN r34603]
2006-07-20 06:18:53 +00:00
Joaquín M. López Muñoz 64b5247bea typo
[SVN r34525]
2006-07-13 07:49:46 +00:00
Joaquín M. López Muñoz bcec2c0467 replaced some &'s with &amp;'s
[SVN r34524]
2006-07-13 07:48:49 +00:00
Joaquín M. López Muñoz c6e0231bed typos
[SVN r34523]
2006-07-13 07:46:19 +00:00
Joaquín M. López Muñoz c757629a6d updated dead link
[SVN r34522]
2006-07-13 07:45:28 +00:00
Joaquín M. López Muñoz 14d94f24fa added names of bug reporters
[SVN r34021]
2006-05-19 06:52:29 +00:00
Joaquín M. López Muñoz 18c8724a46 fixed bug reported at http://lists.boost.org/boost-users/2006/05/19362.php
[SVN r34020]
2006-05-19 06:51:20 +00:00
Joaquín M. López Muñoz 5f0ac92335 fixed some compiler version numbers
[SVN r34019]
2006-05-19 06:49:21 +00:00
Joaquín M. López Muñoz c8e707ddd7 avoided ctor arguments with the same name as correspondent members, as some compilers seem to choke on X::X(T t):t(t)
[SVN r34018]
2006-05-19 06:48:22 +00:00
Joaquín M. López Muñoz f7d22b4de3 rewritten erase(key) to avoid implicit iterator increments leading to linear complexity, as reported by Guillaume Lazzara
[SVN r33914]
2006-05-03 09:28:08 +00:00
Joaquín M. López Muñoz c16d49acd0 omitted unused arg names
[SVN r33759]
2006-04-21 13:07:41 +00:00
Joaquín M. López Muñoz 28192c181a bitten by 8.5.3/5
[SVN r33741]
2006-04-19 07:16:21 +00:00
Joaquín M. López Muñoz 444ebbe95b fixed key extraction problems with non-copyable classes reported at http://lists.boost.org/Archives/boost/2006/04/103065.php; added missing '&'
[SVN r33733]
2006-04-18 16:33:51 +00:00
Joaquín M. López Muñoz 5ecebcbc78 fixed key extraction problems with non-copyable classes reported at http://lists.boost.org/Archives/boost/2006/04/103065.php
[SVN r33732]
2006-04-18 16:32:42 +00:00
Joaquín M. López Muñoz 9a782276a4 fixed doppelganger bug of that discovered for STLport at http://lists.boost.org/Archives/boost/2006/04/102740.php
[SVN r33544]
2006-04-05 07:21:58 +00:00
Joaquín M. López Muñoz f86dce9db1 corrected complexity bound
[SVN r33543]
2006-04-05 07:15:54 +00:00
Joaquín M. López Muñoz 2448ba2a95 removed private ctor decls so that nodes are trivially constructible
[SVN r33429]
2006-03-22 07:16:44 +00:00
Joaquín M. López Muñoz 8ecbfdf080 added fix for a bug of CW 8.3 in "ISO C++ Template Parser" mode causing bogus safe mode run-time asserts
[SVN r33314]
2006-03-10 15:23:42 +00:00
Joaquín M. López Muñoz f9c9851ef3 added workaround for CW 8.3
[SVN r33313]
2006-03-10 15:19:52 +00:00
Joaquín M. López Muñoz 708f8bd4ab sync with v1 Jamfile
[SVN r33256]
2006-03-07 13:17:59 +00:00
Joaquín M. López Muñoz c21722cd10 added blanks to prevent buggy preprocessors from parsing two '>'s as a '>>'
[SVN r33225]
2006-03-06 07:27:05 +00:00
Joaquín M. López Muñoz db3889ceff missing word
[SVN r33206]
2006-03-03 07:20:11 +00:00
Joaquín M. López Muñoz 3be7ae350e typo
[SVN r33201]
2006-03-02 16:17:28 +00:00
Joaquín M. López Muñoz 2a6813f2e7 split test_serialization into two files to reduce stress on MSVC 7.0
[SVN r33200]
2006-03-02 16:14:01 +00:00
Joaquín M. López Muñoz 842bc1ba70 split test_serialization into two to reduce stress on MSVC 7.0
[SVN r33199]
2006-03-02 16:14:00 +00:00
Joaquín M. López Muñoz a1944a19a2 extended workaround from MSVC 6.0 to 7.0
[SVN r33142]
2006-02-27 14:06:06 +00:00
Joaquín M. López Muñoz c2d7a65cfd lexical error
[SVN r33050]
2006-02-21 07:18:14 +00:00
Joaquín M. López Muñoz cf84a0dc1c fixed bug reported at http://lists.boost.org/boost-users/2006/02/17230.php
[SVN r32966]
2006-02-16 16:02:25 +00:00
Joaquín M. López Muñoz 5fec019715 fixed seemingly illegal ADL usage as per std 14.6.4.2
[SVN r32746]
2006-02-08 17:37:33 +00:00
Vladimir Prus c7bfd7cf83 Update Jamfile.v2
[SVN r32735]
2006-02-08 13:26:10 +00:00
Joaquín M. López Muñoz 1235106ac0 merged into test_rearrange
[SVN r32674]
2006-02-06 16:27:33 +00:00
Joaquín M. López Muñoz 5e790014c1 restructured into several pages under doc/tutorial/
[SVN r32673]
2006-02-06 16:14:05 +00:00
Joaquín M. López Muñoz a9c89540ac moved to doc/tutorial/multi_index_cont_example.png
[SVN r32672]
2006-02-06 16:12:58 +00:00
Joaquín M. López Muñoz 1fc02c6b1d removed as parts of the old safe mode framework
[SVN r32671]
2006-02-06 16:08:18 +00:00
Joaquín M. López Muñoz f54edbf0d3 added random access indices; out of bounds checking
[SVN r32670]
2006-02-06 15:53:36 +00:00
Joaquín M. López Muñoz 7274eca56c added random access indices
[SVN r32669]
2006-02-06 15:52:21 +00:00
Joaquín M. López Muñoz e953c2b4ff restricted acceptance of chained pointers so as to not mask convertibility to Value
[SVN r32668]
2006-02-06 15:50:58 +00:00
Joaquín M. López Muñoz cf076474d2 overloaded composite_key_compare::operator() to treat non-tuples as tuples of length 1
[SVN r32667]
2006-02-06 15:48:53 +00:00
Joaquín M. López Muñoz 4c7a97e890 removed test_special_list_ops; added test_rearrange
[SVN r32666]
2006-02-06 15:46:21 +00:00
Joaquín M. López Muñoz 10fe2cd1ab added random access indices; used some type hiding
[SVN r32665]
2006-02-06 15:45:42 +00:00
Joaquín M. López Muñoz b81ee48320 extended test period to increase robustness; considered __GLIBCXX__ for node size calculations
[SVN r32664]
2006-02-06 15:43:36 +00:00
Joaquín M. López Muñoz e043cadb7c added random_access and rearrange
[SVN r32663]
2006-02-06 15:41:56 +00:00
Joaquín M. López Muñoz 233fd40984 removed test_special_list_ops; added test_rearrange; added navigational <link>s;
[SVN r32662]
2006-02-06 15:41:00 +00:00
Joaquín M. López Muñoz 67c04d598f updated; added navigational <link>s
[SVN r32661]
2006-02-06 15:39:35 +00:00
Joaquín M. López Muñoz f1dde3d84e added rearrange facilities; added navigational <link>s; typos
[SVN r32660]
2006-02-06 15:38:39 +00:00
Joaquín M. López Muñoz f8eb1b16ce added navigational <link>s
[SVN r32659]
2006-02-06 15:36:55 +00:00
Joaquín M. López Muñoz 119d6d4a1c restricted acceptance of chained pointers so as to not mask convertibility to Value; overloaded composite_key_compare::operator() to treat non-tuples as tuples of length 1; added navigational <link>s
[SVN r32658]
2006-02-06 15:35:31 +00:00
Joaquín M. López Muñoz 8682a33fcb new section on index views; added navigational <link>s
[SVN r32657]
2006-02-06 15:33:56 +00:00
Joaquín M. López Muñoz 34da3c9fd5 added random access indices; added navigational <link>s
[SVN r32656]
2006-02-06 15:32:27 +00:00
Joaquín M. López Muñoz 0bacd6fbed updated performance figures; discussed ordered index nodes compression; added navigational <link>s
[SVN r32655]
2006-02-06 15:30:50 +00:00
Joaquín M. López Muñoz 98d4cea748 updated performance figures
[SVN r32653]
2006-02-06 15:24:25 +00:00
Joaquín M. López Muñoz a872178185 some link adjustment; added navigational <link>s
[SVN r32652]
2006-02-06 15:22:34 +00:00
Joaquín M. López Muñoz 027b5105ac removed the part on random access indices (already implemented); added navigational <link>s
[SVN r32651]
2006-02-06 15:21:34 +00:00
Joaquín M. López Muñoz d18e3fd6a5 new examples for random access indices and rearrange facilities; added navigational <link>s
[SVN r32650]
2006-02-06 15:20:23 +00:00
Joaquín M. López Muñoz ae533e1b16 noted limitations due to lack of SFINAE and function template ordering support; added navigational <link>s
[SVN r32649]
2006-02-06 15:19:25 +00:00
Joaquín M. López Muñoz 4f6d05b115 added acknowledgements for 1.34 release; added navigational <link>s
[SVN r32647]
2006-02-06 15:17:11 +00:00
Joaquín M. López Muñoz 1e39e5f9af added rearrange facilities
[SVN r32645]
2006-02-06 15:15:45 +00:00
Joaquín M. López Muñoz c1f8fc6348 added random access indices
[SVN r32644]
2006-02-06 15:14:51 +00:00
Joaquín M. López Muñoz f1dcc889ec coming from doc/advanced_topics.html
[SVN r32643]
2006-02-06 15:13:18 +00:00
Joaquín M. López Muñoz 1669a1fb2d moved from doc/multi_index_cont_example.png
[SVN r32642]
2006-02-06 15:12:21 +00:00
Joaquín M. López Muñoz 5fd646dc67 coming from doc/advanced_topics.html; new sections on key extraction concepts and predefined key extractors
[SVN r32641]
2006-02-06 15:10:56 +00:00
Joaquín M. López Muñoz ac2a6d72a3 coming from doc/advanced_topics.html; new sections on index classification, random access indices, index rearranging and ordered indices node compression
[SVN r32640]
2006-02-06 15:09:06 +00:00
Joaquín M. López Muñoz 8d3cfd51a8 coming from doc/tutorial.html
[SVN r32639]
2006-02-06 15:07:46 +00:00
Joaquín M. López Muñoz 35a151c9b0 coming from doc/advanced_topics.html
[SVN r32638]
2006-02-06 15:06:06 +00:00
Joaquín M. López Muñoz aa0ef9b10c coming from doc/advanced_topics.html; new section on value semantics
[SVN r32637]
2006-02-06 15:05:19 +00:00
Joaquín M. López Muñoz cc3da5b51c new member in the family
[SVN r32636]
2006-02-06 15:02:04 +00:00
Joaquín M. López Muñoz 83a1b490ea unsigned integral type with the same size as void *
[SVN r32635]
2006-02-06 15:01:26 +00:00
Joaquín M. López Muñoz 12b9ac21c4 helper class to help reduce symbol name lenghts when using safe mode in MSVC 6.0
[SVN r32634]
2006-02-06 15:00:14 +00:00
Joaquín M. López Muñoz 5190a31109 generic iterator for random access indices
[SVN r32633]
2006-02-06 14:58:46 +00:00
Joaquín M. López Muñoz 192d43569b internal version of boost::iterator_adaptor with better compile times
[SVN r32632]
2006-02-06 14:57:31 +00:00
Joaquín M. López Muñoz aa5cfdfb3c added random access indices
[SVN r32631]
2006-02-06 14:56:21 +00:00
Joaquín M. López Muñoz 519d96871f generic iterator for bidirectional indices
[SVN r32630]
2006-02-06 14:52:08 +00:00
Joaquín M. López Muñoz 9c61f94492 MSVC 6.0 workaround for index_type_list; node values are now accessed through a memfun
[SVN r32629]
2006-02-06 14:49:58 +00:00
Joaquín M. López Muñoz dd5a6bd9a4 adapted to new safe mode framework; node values are now accessed through a memfun; new rearrange memfun; tiny optimization
[SVN r32628]
2006-02-06 14:48:22 +00:00
Joaquín M. López Muñoz 37ca90b823 out of bounds checking
[SVN r32627]
2006-02-06 14:46:03 +00:00
Joaquín M. López Muñoz 964d83df51 adapted to new safe mode framework; rewritten insert_ and link memfuns so as to avoid trycatches; new restore algorithm; node values are now accessed through a memfun
[SVN r32626]
2006-02-06 14:45:15 +00:00
Joaquín M. López Muñoz b16c15342a restricted acceptance of chained pointers so as to not mask convertibility to Value
[SVN r32625]
2006-02-06 14:40:49 +00:00
Joaquín M. López Muñoz e636c5ec72 adapted to new safe mode framework; node values are now accessed through a memfun
[SVN r32624]
2006-02-06 14:39:05 +00:00
Joaquín M. López Muñoz 1654aaa24e missing const qualifier
[SVN r32623]
2006-02-06 14:37:39 +00:00
Joaquín M. López Muñoz 4797a93e7b tweaked previous fix for MSVC 6.0
[SVN r32622]
2006-02-06 14:36:33 +00:00
Joaquín M. López Muñoz 41d3f814ba used aligned_storage according to TR1 interface
[SVN r32621]
2006-02-06 14:35:05 +00:00
Joaquín M. López Muñoz 5aa6cc3b03 removed interoperability bits with old safe mode framework; tiny optimization
[SVN r32620]
2006-02-06 14:34:00 +00:00
Joaquín M. López Muñoz 2cdc3c3778 new safe mode framework based on iterator adaption rather than derivation from safe_iterator; out of bounds checking
[SVN r32619]
2006-02-06 14:32:44 +00:00
Joaquín M. López Muñoz f30144473d node values are now accessed through a memfun
[SVN r32618]
2006-02-06 14:28:14 +00:00
Joaquín M. López Muñoz 7a6121fbbf implemented spatial compression technique; adapted to new safe mode framework; new restore algorithm; tiny optimization
[SVN r32617]
2006-02-06 14:27:26 +00:00
Joaquín M. López Muñoz 538977752f used POD and TR1 guarantees to make node* obtainable from value_type*; node values are now accessed through a memfun
[SVN r32616]
2006-02-06 14:23:02 +00:00
Joaquín M. López Muñoz 2d346be3fb node values are now accessed through a memfun
[SVN r32615]
2006-02-06 14:20:39 +00:00
Joaquín M. López Muñoz 405e8b2a53 refactored to not use base_from_member
[SVN r32614]
2006-02-06 14:19:49 +00:00
Joaquín M. López Muñoz 9ca897dae2 removed interoperability bits with old safe mode framework; tiny optimization
[SVN r32613]
2006-02-06 14:18:45 +00:00
Joaquín M. López Muñoz 683ab3be1d removed interoperability bits with old safe mode framework
[SVN r32612]
2006-02-06 14:17:29 +00:00
Joaquín M. López Muñoz aa4edd99cf fixed error in sync() (http://lists.boost.org/boost-users/2006/01/16710.php); fixed some other inconsistencies
[SVN r32611]
2006-02-06 14:14:28 +00:00
Joaquín M. López Muñoz a87b1eea96 node values are now accessed through a memfun
[SVN r32610]
2006-02-06 14:11:52 +00:00
Joaquín M. López Muñoz 3c1395a626 renamed some identifiers according to newest semantics
[SVN r32609]
2006-02-06 14:09:49 +00:00
Joaquín M. López Muñoz 80812e471a added get_allocator
[SVN r32608]
2006-02-06 14:07:29 +00:00
Joaquín M. López Muñoz edd622e5ac used aligned_storage according to TR1 interface
[SVN r32607]
2006-02-06 14:06:20 +00:00
Joaquín M. López Muñoz 4db9b44b75 in composite_key()::operator(), restricted acceptance of chained pointers so as to not mask convertibility to Value; overloaded composite_key_compare::operator() to treat non-tuples as tuples of length 1
[SVN r32606]
2006-02-06 14:03:55 +00:00
Joaquín M. López Muñoz c6a1c3dd92 fixed SF bug #1378025 (https://sourceforge.net/tracker/?func=detail&atid=107586&aid=1378025&group_id=7586), solution ripped from http://mail.python.org/pipermail/c++-sig/2003-October/005986.html
[SVN r32003]
2005-12-12 17:27:12 +00:00
Joaquín M. López Muñoz 7aacfe029e merged from Version_1_33_1
[SVN r31994]
2005-12-12 08:11:55 +00:00
Joaquín M. López Muñoz 1361bfe530 updated; changes meant for 1.34 are included in 1.33.1
[SVN r30812]
2005-09-05 08:40:38 +00:00
Joaquín M. López Muñoz b92f05140b typos and formatting
[SVN r30811]
2005-09-05 08:39:00 +00:00
Joaquín M. López Muñoz 95d44a6109 fixed a call to reset_object_address (previous version did work, though)
[SVN r30810]
2005-09-05 08:37:35 +00:00
Joaquín M. López Muñoz c7f63a348f removed some of the previous locks as they don't apply to the protected use cases
[SVN r30809]
2005-09-05 08:34:29 +00:00
Joaquín M. López Muñoz f1ad358bff fixed an invariant unsafe flow path
[SVN r30767]
2005-09-01 08:00:57 +00:00
Joaquín M. López Muñoz cfa63b8a4c made safe mode iterators mutithread-safe
[SVN r30750]
2005-08-31 13:50:32 +00:00
Joaquín M. López Muñoz 41be013bc6 updated
[SVN r30723]
2005-08-29 11:53:14 +00:00
Joaquín M. López Muñoz 1e00c5139b erase(position) and erase(first,last) now return iterator to following element
[SVN r30722]
2005-08-29 11:51:56 +00:00
Joaquín M. López Muñoz b3de839dee updated link to TR1 doc; erase(position) and erase(first,last) now return iterator to following element
[SVN r30721]
2005-08-29 11:51:18 +00:00
Joaquín M. López Muñoz 18234ebeee updated link to TR1 doc
[SVN r30720]
2005-08-29 11:50:18 +00:00
Joaquín M. López Muñoz 92207dde6a erase(position) and erase(first,last) for ordered and hashed indices now return iterator to following element
[SVN r30719]
2005-08-29 11:48:20 +00:00
Joaquín M. López Muñoz 7343ddf980 added statement about iterator/reference stability
[SVN r30621]
2005-08-22 08:39:25 +00:00
Joaquín M. López Muñoz 434680c817 typo
[SVN r30620]
2005-08-22 08:18:13 +00:00
Douglas Gregor b28164d7f8 Merged from 1.33.0 release
[SVN r30540]
2005-08-12 13:02:37 +00:00
197 changed files with 14654 additions and 5093 deletions
-16
View File
@@ -1,16 +0,0 @@
# Boost.MultiIndex examples and tests Jamfile
#
# Copyright 2003-2004 Joaquín M López Muñoz.
# 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)
#
# See http://www.boost.org/libs/multi_index for library home page.
subproject libs/multi_index ;
# please order by name to ease maintenance
subinclude libs/multi_index/example ;
subinclude libs/multi_index/test ;
subinclude libs/multi_index/perf ;
+57 -3
View File
@@ -5,6 +5,9 @@
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Boost.MultiIndex Documentation - Acknowledgements</title>
<link rel="stylesheet" href="style.css" type="text/css">
<link rel="start" href="index.html">
<link rel="prev" href="release_notes.html">
<link rel="up" href="index.html">
</head>
<body>
@@ -94,7 +97,7 @@ purpose. It is provided &quot;as is&quot; without express or implied warranty.
</blockquote>
<p>
<span style="float:right;"><img src="lopez.jpg" width="160" height="120"></span>
<span style="float:right;margin-left:10px"><img src="lopez.jpg" width="160" height="120"></span>
I would like to dedicate this piece of work to Rosa Bern&aacute;rdez, my very first
C++ teacher, for her unconditional support in many endeavors of which programming is
by no means the most important. In memory of my cat L&oacute;pez (2001-2003): he
@@ -118,6 +121,57 @@ capabilities are built. Toon Knapen helped adjust the library for VisualAge 6.0.
Markus Sch&ouml;pflin provided a Jamfile tweak for GCC under Tru64 UNIX.
</p>
<h2><a name="boost_1_34">Boost 1.34 release</a></h2>
<p>
<span style="float:left;margin-right:10px"><img src="hector.jpg" width="150" height="198"></span>
Thanks go to Pavel Vo&#382;en&iacute;lek for his useful comments and suggestions
during the development of this release, and to Rosa Bern&aacute;rdez for reviewing
the new material in the documentation.
Alo Sarv suggested a notational improvement in the specification of
partial searches with composite keys.
Maxim Yegorushkin proposed a valuable
<a href="tutorial/indices.html#ordered_node_compression">spatial optimization</a>
for ordered indices and provided figures of its impact on performance
for containers with large numbers of elements.
Caleb Epstein performed the tests under MSVC++ 8.0 described in the
performance section. The following people have reported bugs and problems with
previous versions and prereleases of the library: Alexei Alexandrov,
Mat&iacute;as Capeletto, John Eddy, Martin Eigel, Guillaume Lazzara,
Felipe Magno de Almeida, Julien Pervill&eacute;, Hubert Schmid, Toby Smith.
</p>
<p>
New member in the family! Thanks to H&eacute;ctor for his patience during
long development sessions and his occasional contributions to the source
codebase.
<br style="clear:all;">
</p>
<h2><a name="boost_1_35">Boost 1.35 release</a></h2>
<p>
<a href="tutorial/key_extraction.html#global_fun"><code>global_fun</code></a>
was included after a proposal by Markus Werle. Bruno Mart&iacute;nez Aguerre
suggested the inclusion of
<a href="tutorial/indices.html#iterator_to"><code>iterator_to</code></a>. The
rollback versions of <code>modify</code> and <code>modify_key</code> arose
from discussions with Mat&iacute;as Capeletto. Steven Watanabe spotted an
include guard bug present from the first release of the library.
</p>
<h2><a name="boost_1_36">Boost 1.36 release</a></h2>
<p>
Thanks to Amit Jain for reporting a problem with allocator management.
Michael Fawcett proposed the addition of an allocator constructor to
<code>multi_index_container</code>.
A report from Zachary Zhou has led to
<a href="release_notes.html#stable_update">enhancing the behavior of
hashed indices update functions</a> so that they meet some intuitive expectations.
Grzegorz Jakacki spotted some internal dead code.
</p>
<hr>
<div class="prev_link"><a href="release_notes.html"><img src="prev.gif" alt="release notes" border="0"><br>
@@ -131,9 +185,9 @@ Index
<br>
<p>Revised July 11th 2005</p>
<p>Revised June 25th 2008</p>
<p>&copy; Copyright 2003-2005 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
<p>&copy; Copyright 2003-2008 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
File diff suppressed because it is too large Load Diff
+275 -91
View File
@@ -5,6 +5,10 @@
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Boost.MultiIndex Documentation - Compiler specifics</title>
<link rel="stylesheet" href="style.css" type="text/css">
<link rel="start" href="index.html">
<link rel="prev" href="reference/key_extraction.html">
<link rel="up" href="index.html">
<link rel="next" href="performance.html">
</head>
<body>
@@ -32,9 +36,9 @@ along with suitable workarounds when available.
<h2>Contents</h2>
<ul>
<li><a href="#bcb_64">Borland C++ Builder 6.4</a></li>
<li><a href="#comeau_433_win_vc7_71">Comeau C/C++ 4.3.3 for Windows (VC++ 7.0/7.1 backend)</a></li>
<li><a href="#compaq_65">Compaq C++ 6.5-042 for Tru64 UNIX</a></li>
<li><a href="#bcb_64">Borland C++ Builder 6.4 and later</a></li>
<li><a href="#comeau_43101_win_vc7_71">Comeau C/C++ 4.3.10.1 for Windows (VC++ 9.0 backend)</a></li>
<li><a href="#compaq_65">Compaq C++ 6.5-042 and later for Tru64 UNIX</a></li>
<li>
<a href="#gcc_32">GNU GCC 3.2 and later</a>
<ul>
@@ -42,19 +46,31 @@ along with suitable workarounds when available.
<li><a href="#gcc_4_darwin">Darwin GCC 4.0</a></li>
</ul>
</li>
<li><a href="#acc_60">HP aC++ A.06.00 for HP-UX</a></li>
<li><a href="#acc_612_ia64">HP aC++ A.06.12 and later for HP-UX IA64</a></li>
<li><a href="#acc_380_pa_risc">HP aC++ A.03.80 for HP-UX PA-RISC</a></li>
<li><a href="#va_60">IBM VisualAge C++ V6.0 for AIX</a></li>
<li><a href="#intel_71_8x_lin">Intel C++ Compiler for Linux 7.1/8.0/8.1</a></li>
<li><a href="#intel_em64t_81_lin">Intel C++ Compiler Extended Memory 64 Technology 8.1 for Linux</a></li>
<li><a href="#intel_7x_win">Intel C++ Compiler for Windows 32-bit 7.0/7.1</a></li>
<li><a href="#intel_71_win_stlport_453">Intel C++ Compiler for Windows 32-bit 7.1 + STLport 4.5.3</a></li>
<li><a href="#intel_8x_9x_win">Intel C++ Compiler for Windows 32-bit 8.0/8.1/9.0</a></li>
<li><a href="#cw_83_9x">Metrowerks CodeWarrior 8.3 and later</a></li>
<li><a href="#msvc_60">Microsoft Visual C++ 6.0 Service Pack 5</a></li>
<li><a href="#msvc_60_stlport_453">Microsoft Visual C++ 6.0 Service Pack 5 + STLport 4.5.3</a></li>
<li><a href="#msvc_70">Microsoft Visual C++ 7.0</a></li>
<li><a href="#xl_90">IBM XL C/C++ V9.0 for AIX and later</a></li>
<li><a href="#intel_81_lin">Intel C++ Compiler for Linux 8.1 and later</a></li>
<li><a href="#intel_91_mac">Intel C++ Compiler for Mac OS 9.1 and later</a></li>
<li><a href="#intel_80_win">Intel C++ Compiler for Windows 32-bit 8.0 and later</a></li>
<li><a href="#intel_100_win64">Intel C++ Compiler for Windows 64-bit 10.0 and later</a></li>
<li><a href="#cw_83">Metrowerks CodeWarrior 8.3</a></li>
<li><a href="#cw_9x">Metrowerks CodeWarrior 9 and later</a></li>
<li>
<a href="#msvc_60">Microsoft Visual C++ 6.0 Service Pack 5</a>
<ul>
<li><a href="#msvc_60_stlport_453">Microsoft Visual C++ 6.0 Service Pack 5 + STLport 4.5.3 and later</a></li>
</ul>
</li>
<li>
<a href="#msvc_70">Microsoft Visual C++ 7.0</a>
<ul>
<li><a href="#msvc_70_stlport_501">Microsoft Visual C++ 7.0 + STLport 5.0.1</a></li>
</ul>
</li>
<li><a href="#msvc_71">Microsoft Visual C++ 7.1</a></li>
<li><a href="#msvc_80">Microsoft Visual C++ 8.0</a></li>
<li><a href="#msvc_80">Microsoft Visual C++ 8.0 and later</a></li>
<li><a href="#sun_10">Sun Studio 10 and later for Solaris</a></li>
<li><a href="#portability">Portability techniques</a>
<ul>
<li><a href="#member_offset">Use of <code>member_offset</code></a></li>
@@ -72,26 +88,36 @@ along with suitable workarounds when available.
</li>
</ul>
<h2><a name="bcb_64">Borland C++ Builder 6.4</a></h2>
<h2><a name="bcb_64">Borland C++ Builder 6.4 and later</a></h2>
<p>
Currently, Boost.MultiIndex cannot be used with BCB 6.4. The
number of problems encountered during the tests makes it unlikely that
future versions of the library can be made to work under
this compiler.
Currently, Boost.MultiIndex cannot be used with any of BCB 6.4 up to BCB 2006
and CodeGear C++Builder 2010.
The number of problems encountered during the tests makes it unlikely that
future versions of the library can be made to work under these compilers.
</p>
<h2><a name="comeau_433_win_vc7_71">Comeau C/C++ 4.3.3 for Windows (VC++ 7.0/7.1 backend)</a></h2>
<h2><a name="comeau_43101_win_vc7_71">Comeau C/C++ 4.3.10.1 for Windows (VC++ 9.0 backend)</a></h2>
<p>
<b>Note:</b> Last tested in Boost 1.38. The information might be no longer accurate.
</p>
<p>
No problems have been detected with this compiler. The library fails to compile,
however, when Microsoft Visual C++ 6.0 is used as the backend.
however, when Microsoft Visual C++ 6.0 is used as the backend. Last time they were
tested (Boost.1.34.1), VC++ 7.0/7.1 backends worked correctly. The beta 2 version of
the Comeau compiler 4.3.10.1 has been used.
</p>
<h2><a name="compaq_65">Compaq C++ 6.5-042 for Tru64 UNIX</a></h2>
<h2><a name="compaq_65">Compaq C++ 6.5-042 and later for Tru64 UNIX</a></h2>
<p>
No problems have been detected with this compiler.
<b>Note:</b> Last tested in Boost 1.38. The information might be no longer accurate.
</p>
<p>
No problems have been detected with this compiler. Last tested for version 7.1-006.
</p>
<h2><a name="gcc_32">GNU GCC 3.2 and later</a></h2>
@@ -99,22 +125,18 @@ No problems have been detected with this compiler.
<p>
No problems have been detected with several versions of this compiler
starting from 3.2. The following versions have been explicitly tested:
<ul>
<li>GCC 3.2 20020903 under Linux,</li>
<li>GCC 3.2 20020927 (prerelease) under Cygwin 1.5.7,</li>
<li>GCC 3.2.3 under Linux, (mingw special 20030504-1) under Win32,</li>
<li>GCC 3.3 20030304 (Apple builds 1666 and 1671) under Mac OS,</li>
<li>GCC 3.3.3 (cygwin special) under Cygwin 1.5.7,</li>
<li>GCC 3.3.5 under Linux,</li>
<li>GCC 3.3.6 under Linux and Tru64 (see <a href="#gcc_tru64">below</a>),</li>
<li>GCC 3.4.2 (mingw-special) under Win32,</li>
<li>GCC 3.4.3 under Linux, Solaris and Tru64 (see <a href="#gcc_tru64">below</a>),</li>
<li>GCC 3.4.4 (cygming special) under Cygwin, under Linux,
under Tru64 (see <a href="#gcc_tru64">below</a>), (mingw special) under Win32,</li>
<li>GCC 4.0.0 20041026 (Apple build 4061) under Mac OS
(see <a href="#gcc_4_darwin">below</a>),</li>
<li>GCC 4.0.0 under Linux, (Apple build 5026) under Mac OS,</li>
<li>GCC 4.0.1 under Linux.</li>
<ul>
<li>GCC 3.4.3 under Linux x86-64,</li>
<li>GCC 4.0.1 (Apple Computer, Inc. build 5370), (Apple Inc. build 5490), (Apple Inc. build 5493) under Mac OS,</li>
<li>GCC 4.1.2 20080704 (Red Hat 4.1.2-44) under Linux x86-64,</li>
<li>GCC 4.2.1 20070719 [FreeBSD] under FreeBSD,</li>
<li>GCC 4.2.4 under Linux x86-64,</li>
<li>GCC 4.3.2 under Linux x86-64,</li>
<li>GCC 4.3.3 under Linux x86-64,</li>
<li>GCC 4.3.3 gnu++0x under Linux x86-64,</li>
<li>GCC 4.3.4 under Linux x86-64,</li>
<li>GCC 4.4.1 under Linux, Linux x86-64 and MinGW,</li>
<li>GCC 4.4.1 gnu++0x under Linux x86-64 and MinGW.</li>
</ul>
Boost.MultiIndex does not work with versions 3.1 and prior of GCC.
</p>
@@ -140,21 +162,43 @@ prior), corresponds to a prerelease version of GNU GCC 4.0.0 which introduces
a <a href="http://gcc.gnu.org/bugzilla/show_bug.cgi?id=17435">regression bug</a>
related to binding of references to temporary objects. This bug precludes the
usage of Boost.MultiIndex
<a href="advanced_topics.html#invariant_check">invariant-checking mode</a>; other
<a href="tutorial/debug.html#invariant_check">invariant-checking mode</a>; other
than this, Boost.MultiIndex works correctly.
The bug is corrected in GCC 4.0 Apple build 5026, which is in sync with the official
release of GNU GCC 4.0.0, so the invariant-checking mode is available from this
upgrade.
</p>
<h2><a name="acc_60">HP aC++ A.06.00 for HP-UX</a></h2>
<h2><a name="acc_612_ia64">HP aC++ A.06.12 and later for HP-UX IA64</a></h2>
<p>
<b>Note:</b> Last tested in Boost 1.38. The information might be no longer accurate.
</p>
<p>
No problems have been detected with this compiler.
Last tested for version A.06.17.
</p>
<h2><a name="acc_380_pa_risc">HP aC++ A.03.80 for HP-UX PA-RISC</a></h2>
<p>
<b>Note:</b> Last tested in Boost 1.38. The information might be no longer accurate.
</p>
<p>
No problems have been detected with this compiler.
Last tested for version A.03.85.
</p>
<h2><a name="va_60">IBM VisualAge C++ V6.0 for AIX</a></h2>
<p>
<b>Note:</b> Last tested in Boost 1.33.1. The information might be no longer accurate.
</p>
<blockquote><hr></blockquote>
<p>
<a href="reference/key_extraction.html#member"><code>member</code></a> not supported,
refer to the section on
@@ -181,47 +225,44 @@ Serialization capabilities are not available as Boost.Serialization is not
supported on this platform.
</p>
<h2><a name="intel_71_8x_lin">Intel C++ Compiler for Linux 7.1/8.0/8.1</a></h2>
<p>
No problems have been detected with these compilers.
</p>
<h2><a name="intel_em64t_81_lin">Intel C++ Compiler Extended Memory 64 Technology 8.1
for Linux</a></h2>
<p>
No problems have been detected with this compiler.
</p>
<h2><a name="intel_7x_win">Intel C++ Compiler for Windows 32-bit 7.0/7.1</a></h2>
<h2><a name="xl_90">IBM XL C/C++ V9.0 for AIX and later</a></h2>
<p>
<a href="reference/key_extraction.html#member"><code>member</code></a> not supported,
refer to the section on
<a href="#member_offset">use of <code>member_offset</code></a> for workarounds.
<code>member_offset</code> causes the compiler to emit warnings about the
use of <code>offsetof</code> with non-POD types: these warnings can be suppressed
by setting the compiler option <code>-qsuppress=1540-1281</code>, or, alternatively,
by inserting the following preprocessor directive:
</p>
<blockquote><hr></blockquote>
<blockquote><pre>
<span class=preprocessor>#pragma</span> <span class=identifier>info</span><span class=special>(</span><span class=identifier>nolan</span><span class=special>)</span>
</pre></blockquote>
<p>
When used on top of MSVC++ 7.0 or prior, argument dependent lookup is
disabled by default. This will cause problems with many Boost libraries,
and in particular with the serialization part of Boost.MultiIndex.
Argument dependent lookup is enabled by adding
<code>/Qoption,c,--arg_dep_lookup</code> to the project options.
This latter pragma, however, may also eliminate other warnings not related
to the use of <code>offsetof</code>.
Other than this, Boost.MultiIndex works without problems.
Last tested for version V10.1.
</p>
<h2><a name="#intel_71_win_stlport_453">
Intel C++ Compiler for Windows 32-bit 7.1 + STLport 4.5.3</a></h2>
<h2><a name="intel_81_lin">Intel C++ Compiler for Linux 8.1 and later</a></h2>
<p>
Boost.MultiIndex works for this configuration. The same limitations apply as
in Intel C++ 7.1 with its original Dinkumware standard library. STLport 4.6.2 has
also been confirmed to work correctly.
No problems have been detected with this compiler.
Last tested for compiler versions 10.0 to 11.1.
</p>
<h2><a name="intel_8x_9x_win">Intel C++ Compiler for Windows 32-bit 8.0/8.1/9.0</a></h2>
<h2><a name="intel_91_mac">Intel C++ Compiler for Mac OS 9.1 and later</a></h2>
<p>
No problems have been detected with this compiler.
Tested from version 10.1 to 11.0.
</p>
<h2><a name="intel_80_win">Intel C++ Compiler for Windows 32-bit 8.0 and later</a></h2>
<p>
When used on top of MSVC++ 7.0 or prior, argument dependent lookup is
@@ -230,17 +271,70 @@ and in particular with the serialization part of Boost.MultiIndex.
Argument dependent lookup is enabled by adding
<code>/Qoption,c,--arg_dep_lookup</code> to the project options.
Other than this, Boost.MultiIndex works without problems.
Last tested for compiler version 11.1.
</p>
<h2><a name="cw_83_9x">Metrowerks CodeWarrior 8.3 and later</a></h2>
<h2><a name="intel_100_win64">Intel C++ Compiler for Windows 64-bit 10.0 and later</a></h2>
<p>
Boost.MultiIndex works correctly with versions of this compiler from 8.3 to
9.5, under the two operating systems tested: Mac OS and Windows.
No problems have been detected with this compiler.
Last tested for compiler version 11.1.
</p>
<h2><a name="cw_83">Metrowerks CodeWarrior 8.3</a></h2>
<p>
<b>Note:</b> Last tested in Boost 1.36. The information might be no longer accurate.
</p>
<p>
Predefined key extractors instantiated on a given type do not accept
objects of derived types. For instance:
</p>
<blockquote><pre>
<span class=keyword>struct</span> <span class=identifier>base</span><span class=special>{};</span>
<span class=keyword>struct</span> <span class=identifier>derived</span><span class=special>:</span><span class=keyword>public</span> <span class=identifier>base</span><span class=special>{};</span>
<span class=special>...</span>
<span class=identifier>identity</span><span class=special>&lt;</span><span class=identifier>base</span><span class=special>&gt;</span> <span class=identifier>key_extractor</span><span class=special>;</span>
<span class=identifier>derived</span> <span class=identifier>x</span><span class=special>;</span>
<span class=comment>// not accepted by this compiler: an explicit cast to base is required</span>
<span class=identifier>key_extractor</span><span class=special>(</span><span class=identifier>x</span><span class=special>);</span>
</pre></blockquote>
<p>
Other than this, Boost.MultiIndex works without problems under Mac OS and Windows (last
tested under Windows only).
</p>
<h2><a name="cw_9x">Metrowerks CodeWarrior 9 and later</a></h2>
<p>
<b>Note:</b> Last tested in Boost 1.34.1. The information might be no longer accurate.
</p>
<p>
Boost.MultiIndex works correctly with versions of this compiler from 9.0 to
9.5, both under Mac OS and Windows.
</p>
<h2><a name="msvc_60">Microsoft Visual C++ 6.0 Service Pack 5</a></h2>
<p>
<b>Note:</b> Last tested in Boost 1.36. The information might be no longer accurate.
</p>
<blockquote><hr></blockquote>
<p>
Beginning with Boost.1.36, Boost.Serialization is no longer supported in this
compiler, thus the serialization capabilities cannot be used.
</p>
<blockquote><hr></blockquote>
<p>
<a href="reference/key_extraction.html#member"><code>member</code></a> not supported,
refer to the section on
@@ -313,6 +407,37 @@ in compilers without partial template specialization"</a>.
<blockquote><hr></blockquote>
<p>
Due to problems with function template ordering support,
<a href="reference/key_extraction.html#composite_key_compare"><code>composite_key_compare</code></a>
and related classes do not accept the notational variations of
<code>operator()</code> where one of the operands is treated as if
included into a tuple of length 1. As a result, the user cannot ever
omit tuple enclosing when specifying the arguments of lookup operations
involving composite keys.
</p>
<blockquote><hr></blockquote>
<p>
Predefined key extractors instantiated on a given type do not accept
objects of derived types. For instance:
</p>
<blockquote><pre>
<span class=keyword>struct</span> <span class=identifier>base</span><span class=special>{};</span>
<span class=keyword>struct</span> <span class=identifier>derived</span><span class=special>:</span><span class=keyword>public</span> <span class=identifier>base</span><span class=special>{};</span>
<span class=special>...</span>
<span class=identifier>identity</span><span class=special>&lt;</span><span class=identifier>base</span><span class=special>&gt;</span> <span class=identifier>key_extractor</span><span class=special>;</span>
<span class=identifier>derived</span> <span class=identifier>x</span><span class=special>;</span>
<span class=comment>// not accepted by this compiler: an explicit cast to base is required</span>
<span class=identifier>key_extractor</span><span class=special>(</span><span class=identifier>x</span><span class=special>);</span>
</pre></blockquote>
<blockquote><hr></blockquote>
<p>
MSVC++ 6.0 presents serious limitations for the maximum length of
symbol names generated by the compiler, which might result in the
@@ -336,7 +461,7 @@ This problem is a recurrent bug of the compiler, and has been reported in
other unrelated libraries, like the
<a href="../../../libs/graph/doc/table_of_contents.html">Boost Graph Library</a>,
<a href="../../../libs/multi_array/doc/index.html">Boost.MultiArray</a>,
<a href="../../../libs/regex/doc/index.html">Boost.Regex</a>,
<a href="../../../libs/regex/index.html">Boost.Regex</a>,
<a href="http://www.cgal.org/">CGAL</a> and
<a href="http://www.mysql.com/downloads/api-mysql++.html">MySQL++</a>.
The error is triggered, though not in a systematic manner, by the use
@@ -361,7 +486,7 @@ with equivalent operations:
<p>
The second workaround has not been confirmed by the author, but it is given
on the Internet in connection with this error appearing in other libraries.
Replace line 84 of <code>&lt;xlocnum></code>
Replace line 84 of <code>&lt;xlocnum&gt;</code>
<blockquote><pre>
<span class=preprocessor>#define</span> <span class=identifier>_VIRTUAL</span> <span class=keyword>virtual</span>
@@ -405,27 +530,35 @@ The following measures can help alleviate these problems:
</ul>
</p>
<h2>
<h3>
<a name="msvc_60_stlport_453">Microsoft Visual C++ 6.0 Service Pack 5
+ STLport 4.5.3</a>
</h2>
+ STLport 4.5.3 and later</a>
</h3>
<p>
<b>Note:</b> Last tested in Boost 1.36. The information might be no longer accurate.
</p>
<p>
Boost.MultiIndex works for this configuration. The same limitations apply as
in MSVC++ 6.0 with its original Dinkumware standard library. STLport 4.6.2 has
also been confirmed to work correctly.
in MSVC++ 6.0 with its original Dinkumware standard library. STLport 4.6.2 and
5.0.1 has also been confirmed to work correctly.
</p>
<h2><a name="msvc_70">Microsoft Visual C++ 7.0</a></h2>
<p>
<b>Note:</b> Last tested in Boost 1.35. The information might be no longer accurate.
</p>
<blockquote><hr></blockquote>
<p>
It is not possible to use the serialization capabilities of Boost.MultiIndex
along with the dynamic version of STLport, as some linking errors result.
Use instead the static version of STLport. This bug is reportedly fixed in
STLport 5.0 (in beta stage as of this writing.)
Beginning with Boost.1.36, Boost.Serialization is no longer supported in this
compiler, thus the serialization capabilities cannot be used.
</p>
<h2><a name="msvc_70">Microsoft Visual C++ 7.0</a></h2>
<blockquote><hr></blockquote>
<p>
<a href="reference/key_extraction.html#member"><code>member</code></a> not supported,
@@ -489,23 +622,74 @@ can be remedied as explained in
in compilers without partial template specialization"</a>.
</p>
<blockquote><hr></blockquote>
<p>
Due to problems with function template ordering support,
<a href="reference/key_extraction.html#composite_key_compare"><code>composite_key_compare</code></a>
and related classes do not accept the notational variations of
<code>operator()</code> where one of the operands is treated as if
included into a tuple of length 1. As a result, the user cannot ever
omit tuple enclosing when specifying the arguments of lookup operations
involving composite keys.
</p>
<blockquote><hr></blockquote>
<p>
Predefined key extractors instantiated on a given type do not accept
objects of derived types. For instance:
</p>
<blockquote><pre>
<span class=keyword>struct</span> <span class=identifier>base</span><span class=special>{};</span>
<span class=keyword>struct</span> <span class=identifier>derived</span><span class=special>:</span><span class=keyword>public</span> <span class=identifier>base</span><span class=special>{};</span>
<span class=special>...</span>
<span class=identifier>identity</span><span class=special>&lt;</span><span class=identifier>base</span><span class=special>&gt;</span> <span class=identifier>key_extractor</span><span class=special>;</span>
<span class=identifier>derived</span> <span class=identifier>x</span><span class=special>;</span>
<span class=comment>// not accepted by this compiler: an explicit cast to base is required</span>
<span class=identifier>key_extractor</span><span class=special>(</span><span class=identifier>x</span><span class=special>);</span>
</pre></blockquote>
<h3><a name="msvc_70_stlport_501">Microsoft Visual C++ 7.0 + STLport 5.0.1</a></h3>
<p>
<b>Note:</b> Last tested in Boost 1.35. The information might be no longer accurate.
</p>
<p>
Boost.MultiIndex works for this configuration. The same issues apply as in
MSVC++ 7.0 with its original Dinkumware standard library.
</p>
<h2><a name="msvc_71">Microsoft Visual C++ 7.1</a></h2>
<p>
Problems have been reported when compiling the library with the <code>/Gm</code>
option (Enable Minimal Rebuild.) Seemingly, this is due to an
internal defect of the compiler (see for instance
<a href="http://lists.boost.org/MailArchives/boost-users/msg05988.php">
<a href="http://lists.boost.org/boost-users/2004/02/5987.php">
this mention of a similar issue</a> in the Boost Users mailing list.)
If <code>/Gm</code> is turned off, Boost.MultiIndex compiles and runs
without further problems.
</p>
<h2><a name="msvc_80">Microsoft Visual C++ 8.0</a></h2>
<h2><a name="msvc_80">Microsoft Visual C++ 8.0 and later</a></h2>
<p>
No problems have been detected with this compiler. The Beta 2 version of
this product was used for the testing.
No problems have been detected with this compiler, both in 32-bit and 64-bit modes.
Last tested for compiler versions 8.0 to 10.0.
</p>
<h2><a name="sun_10">Sun Studio 10 and later for Solaris</a></h2>
<p>
No problems have been detected with this platform. Last tested for compiler version
Sun C++ 5.10 (Sun Studio 12 Update 1).
The option <code>-library=stlport4</code> was used to replace the default
standard library with STLport.
</p>
<h2><a name="portability">Portability techniques</a></h2>
@@ -523,7 +707,7 @@ to work correctly with <code>member</code>:
<ul>
<li>MSVC++ 6.0/7.0,</li>
<li>Intel C++ 7.0/7.1 for Windows,</li>
<li>VisualAge 6.0 for AIX.</li>
<li>VisualAge 6.0/9.0 for AIX.</li>
</ul>
This program can help determine if your compiler
properly supports pointers to members as non-type template parameters:
@@ -819,7 +1003,7 @@ Consider a typical instantiation of <code>multi_index_container</code>:
</pre></blockquote>
<p>
Then, for instance, the type <code>employee_set::nth_type&lt;0&gt;::type</code>
Then, for instance, the type <code>employee_set::nth_index&lt;0&gt;::type</code>
resolves to the following in GCC:
</p>
@@ -882,7 +1066,7 @@ in the final type by encapsulating it into another, shorter-named construct:
<code>employee_set_indices</code> works as a conventional <code>typedef</code>
in all respects, save for a detail: its name does not explicitly
include the information contained in the <code>indexed_by</code> instantiation.
Applying this technique, <code>employee_set::nth_type&lt;0&gt;::type</code>
Applying this technique, <code>employee_set::nth_index&lt;0&gt;::type</code>
now becomes:
</p>
@@ -928,9 +1112,9 @@ Performance
<br>
<p>Revised July 26th 2005</p>
<p>Revised October 14th 2009</p>
<p>&copy; Copyright 2003-2005 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
<p>&copy; Copyright 2003-2009 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
+121 -18
View File
@@ -5,6 +5,10 @@
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Boost.MultiIndex Documentation - Examples</title>
<link rel="stylesheet" href="style.css" type="text/css">
<link rel="start" href="index.html">
<link rel="prev" href="performance.html">
<link rel="up" href="index.html">
<link rel="next" href="tests.html">
</head>
<body>
@@ -27,7 +31,7 @@ Tests
<ul>
<li><a href="#example1">Example 1: basic usage</a></li>
<li><a href="#example2">Example 2: using member functions as keys</a></li>
<li><a href="#example2">Example 2: using functions as keys</a></li>
<li><a href="#example3">Example 3: constructing <code>multi_index_container</code>s
with <code>ctor_args_list</code></a></li>
<li><a href="#example4">Example 4: bidirectional map</a></li>
@@ -36,6 +40,9 @@ Tests
<li><a href="#example7">Example 7: composite keys</a></li>
<li><a href="#example8">Example 8: hashed indices</a></li>
<li><a href="#example9">Example 9: serialization and MRU lists</a></li>
<li><a href="#example10">Example 10: random access indices</a></li>
<li><a href="#example11">Example 11: index rearrangement</a></li>
<li><a href="#example12">Example 12: using Boost.Interprocess allocators</a></li>
</ul>
<h2><a name="example1">Example 1: basic usage</a></h2>
@@ -49,23 +56,23 @@ Basic program showing the multi-indexing capabilities of Boost.MultiIndex
with an admittedly boring set of <code>employee</code> records.
</p>
<h2><a name="example2">Example 2: using member functions as keys</a></h2>
<h2><a name="example2">Example 2: using functions as keys</a></h2>
<p>
See <a href="../example/memfun_key.cpp">source code</a>.
See <a href="../example/fun_key.cpp">source code</a>.
</p>
<p>
Usually keys assigned to an index are based on a member variable of the
element, but key extractors can be defined which take their value from
a member function. This has some similarity with the concept of
a member function or a global function. This has some similarity with the concept of
<i>calculated keys</i> supported by some relational database engines.
The example shows how to use the predefined <code>const_mem_fun</code>
key extractor to deal with this situation.
and <code>global_fun</code> key extractors to deal with this situation.
</p>
<p>
Keys based on member functions usually will not be actual references,
Keys based on functions usually will not be actual references,
but rather the temporary values resulting from the invocation of the
member function used. This implies that <code>modify_key</code> cannot be
applied to this type of extractors, which is a perfectly logical
@@ -82,7 +89,7 @@ See <a href="../example/non_default_ctor.cpp">source code</a>.
<p>
We show a practical example of usage of <code>multi_index_container::ctor_arg_list</code>,
whose definition and purpose are explained in the
<a href="advanced_topics.html#ctor_args_list">Advanced topics section</a>. The
<a href="tutorial/creation.html#ctor_args_list">tutorial</a>. The
program groups a sorted collection of numbers based on identification through
modulo arithmetics, by which <code>x</code> and <code>y</code> are equivalent
if <code>(x%n)==(y%n)</code>, for some fixed <code>n</code>.
@@ -97,14 +104,20 @@ See <a href="../example/bimap.cpp">source code</a>.
<p>
This example shows how to construct a bidirectional map with
<code>multi_index_container</code>. By a <i>bidirectional map</i> we mean
a container of elements of <code>std::pair&lt;const FromType,const ToType></code>
such that no two elements exists with the same <code>first</code>
<i>or</i> <code>second</code> value (<code>std::map</code> only
guarantees uniqueness of the first member). Fast lookup is provided
a container of <code>(const FromType,const ToType)</code> pairs
such that no two elements exists with the same first
<i>or</i> second component (<code>std::map</code> only
guarantees uniqueness of the first component). Fast lookup is provided
for both keys. The program features a tiny Spanish-English
dictionary with online query of words in both languages.
</p>
<p>
This bidirectional map can be considered as a primitive precursor
to the full-fledged container provided by
<a href="../../bimap/index.html">Boost.Bimap</a>.
</p>
<h2><a name="example5">Example 5: sequenced indices</a></h2>
<p>
@@ -136,7 +149,7 @@ be defined as:
<span class=keyword>struct</span> <span class=identifier>car_model</span>
<span class=special>{</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>model</span><span class=special>;</span>
<span class=identifier>std</span><span class=special>:</span><span class=identifier>string</span> <span class=identifier>manufacturer</span><span class=special>;</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>manufacturer</span><span class=special>;</span>
<span class=keyword>int</span> <span class=identifier>price</span><span class=special>;</span>
<span class=special>};</span>
</pre></blockquote>
@@ -170,8 +183,8 @@ involves having the manufactures stored in a separate
<p>
Although predefined Boost.MultiIndex key extractors can handle many
situations involving pointers (see
<a href="advanced_topics.html#advanced_key_extractors">advanced features
of Boost.MultiIndex key extractors</a> in the Advanced topics section), this case
<a href="tutorial/key_extraction.html#advanced_key_extractors">advanced features
of Boost.MultiIndex key extractors</a> in the tutorial), this case
is complex enough that a suitable key extractor has to be defined. The following
utility cascades two key extractors:
</p>
@@ -251,7 +264,7 @@ See <a href="../example/composite_keys.cpp">source code</a>.
</p>
<p>
Boost.MultiIndex <a href="advanced_topics.html#composite_keys">
Boost.MultiIndex <a href="tutorial/key_extraction.html#composite_keys">
<code>composite_key</code></a> construct provides a flexible tool for
creating indices with non-trivial sorting criteria.
The program features a rudimentary simulation of a file system
@@ -294,7 +307,7 @@ instance:
<ul>
<li>Implement additional commands, like <code>cp</code>.</li>
<li>Add handling of absolute paths.</li>
<li>Use <a href="advanced_topics.html#serialization">serialization</a>
<li>Use <a href="tutorial/creation.html#serialization">serialization</a>
to store and retrieve the filesystem state between program runs.</li>
</ul>
</p>
@@ -333,6 +346,96 @@ data structure is implemented with <code>multi_index_container</code> by
combining a sequenced index and an index of type <code>hashed_unique</code>.
</p>
<h2><a name="example10">Example 10: random access indices</a></h2>
<p>
See <a href="../example/random_access.cpp">source code</a>.
</p>
<p>
The example resumes the text container introduced in
<a href="#example5">example 5</a> and shows how substituting a random
access index for a sequenced index allows for extra capabilities like
efficient access by position and calculation of the offset of a given
element into the container.
</p>
<h2><a name="example11">Example 11: index rearrangement</a></h2>
<p>
See <a href="../example/rearrange.cpp">source code</a>.
</p>
<p>
There is a relatively common piece of urban lore claiming that
a deck of cards must be shuffled seven times in a row to be perfectly
mixed. The statement derives from the works of mathematician Persi
Diaconis on <i>riffle shuffling</i>: this shuffling
technique involves splitting the deck in two packets roughly the same
size and then dropping the cards from both packets so that they become
interleaved. It has been shown that when repeating this procedure
seven times the statistical distribution of cards is reasonably
close to that associated with a truly random permutation. A measure
of "randomness" can be estimated by counting <i>rising sequences</i>:
consider a permutation of the sequence 1,2, ... , <i>n</i>, a rising sequence
is a maximal chain of consecutive elements <i>m</i>, <i>m+1</i>, ... , <i>m+r</i>
such that they are arranged in ascending order. For instance, the permutation
125364789 is composed of the two rising sequences 1234 and 56789,
as becomes obvious by displaying the sequence like this,
<span style="vertical-align:sub">1</span><span style="vertical-align:sub">2</span><span style="vertical-align:super">5</span><span style="vertical-align:sub">3</span><span style="vertical-align:super">6</span><span style="vertical-align:sub">4</span><span style="vertical-align:super">7</span><span style="vertical-align:super">8</span><span style="vertical-align:super">9</span>.
The average number of rising sequences in a random permutation of
<i>n</i> elements is (<i>n</i>+1)/2: by contrast, after a single riffle
shuffle of an initially sorted deck of cards, there cannot be more than
two rising sequences. The average number of rising sequences approximates
to (<i>n</i>+1)/2 as the number of consecutive riffle shuffles increases,
with seven shuffles yielding a close result for a 52-card poker deck.
Brad Mann's paper
<a href="http://www.dartmouth.edu/~chance/teaching_aids/books_articles/Mann.pdf">"How
many times should you shuffle a deck of cards?"</a> provides a
rigorous yet very accessible treatment of this subject.
</p>
<p>
The example program estimates the average number of rising sequences
in a 52-card deck after repeated riffle shuffling as well as applying
a completely random permutation. The deck is modeled by the following
container:
<blockquote><pre>
<span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=keyword>int</span><span class=special>,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span>
<span class=identifier>random_access</span><span class=special>&lt;&gt;,</span>
<span class=identifier>random_access</span><span class=special>&lt;&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span>
</pre></blockquote>
where the first index stores the current arrangement of the deck, while
the second index is used to remember the start position. This representation
allows for an efficient implementation of a rising sequences counting
algorithm in linear time.
<a href="reference/rnd_indices.html#rearrange"><code>rearrange</code></a>
is used to apply to the deck a shuffle performed externally on an
auxiliary data structure.
</p>
<h2><a name="example12">Example 12: using Boost.Interprocess allocators</a></h2>
<p>
See <a href="../example/ip_allocator.cpp">source code</a>.
</p>
<p>
Boost.MultiIndex supports special allocators such as those provided by
<a href="../../interprocess/index.html">Boost.Interprocess</a>,
which allows for <code>multi_index_container</code>s to be placed in shared
memory. The example features a front-end to a small book database
implemented by means of a <code>multi_index_container</code> stored
in a Boost.Interprocess memory mapped file. The reader can verify that several
instances of the program correctly work simultaneously and immediately see
the changes to the database performed by any other instance.
</p>
<hr>
<div class="prev_link"><a href="performance.html"><img src="prev.gif" alt="performance" border="0"><br>
@@ -347,9 +450,9 @@ Tests
<br>
<p>Revised March 8th 2005</p>
<p>Revised May 26th 2009</p>
<p>&copy; Copyright 2003-2005 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
<p>&copy; Copyright 2003-2009 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
+6 -35
View File
@@ -5,6 +5,10 @@
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Boost.MultiIndex Documentation - Future work</title>
<link rel="stylesheet" href="style.css" type="text/css">
<link rel="start" href="index.html">
<link rel="prev" href="tests.html">
<link rel="up" href="index.html">
<link rel="next" href="release_notes.html">
</head>
<body>
@@ -34,11 +38,9 @@ principle driving the current internal design of <code>multi_index_container</co
<ul>
<li><a href="#ranked_indices">Ranked indices</a></li>
<li><a href="#random_access_indices">Random access indices</a></li>
<li><a href="#notifying">Notifying indices</a></li>
<li><a href="#constraints">Constraints</a></li>
<li><a href="#user_defined_indices">User-defined indices</a></li>
<li><a href="#bimap">Bidirectional map</a></li>
<li><a href="#indexed_maps">Indexed maps</a></li>
<li><a href="#move_semantics">Move semantics</a></li>
</ul>
@@ -56,24 +58,6 @@ has been proposed that order-statistics trees be used to devise a new type of
the functionality of ordered indices.
</p>
<h2><a name="random_access_indices">Random access indices</a></h2>
<p>
These indices provide random access iterators and location of elements
by their position ordinal. Although they seem at first glance to model
the semantics of <code>std::vector</code>, random access indices present
important differences:
<ul>
<li>Iterator and reference validity is preserved on insertion and deletion,</li>
<li>memory contiguity is not provided,</li>
<li>standard mutating algorithms (vg. <code>std::sort</code>) will in general
not work with random access indices, as elements of a
<code>multi_index_container</code> cannot be directly moved or swapped;</li>
</ul>
so it might be more accurate to regard this type of indices as a variation of
sequenced indices with random access semantics.
</p>
<h2><a name="notifying">Notifying indices</a></h2>
<p>
@@ -165,19 +149,6 @@ simple enough to make them worth documenting so that the (bold)
user can write implementations for her own indices.
</p>
<h2><a name="bimap">Bidirectional map</a></h2>
<p>
<a href="examples.html#example4">Example 4</a> in the examples section
features a <i>bidirectional map</i>, implemented as a
<code>multi_index_container</code> with two unique ordered indices. This particular
structure is deemed important enough as to provide it as a separate
class template, relying internally in <code>multi_index_container</code>. As
feedback is collected from the users of Boost.MultiIndex, other singular
instantiations of <code>multi_index_container</code> might be encapsulated
to form a component library of ready to use containers.
</p>
<h2><a name="indexed_maps">Indexed maps</a></h2>
<p>
@@ -255,9 +226,9 @@ Release notes
<br>
<p>Revised July 5th 2005</p>
<p>Revised July 5th 2007</p>
<p>&copy; Copyright 2003-2005 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
<p>&copy; Copyright 2003-2007 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

+10 -9
View File
@@ -5,6 +5,8 @@
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Boost.MultiIndex Documentation - Index</title>
<link rel="stylesheet" href="style.css" type="text/css">
<link rel="start" href="index.html">
<link rel="next" href="tutorial/index.html">
</head>
<body>
@@ -13,7 +15,7 @@
<div class="prev_link"></div>
<div class="up_link"></div>
<div class="next_link"><a href="tutorial.html"><img src="next.gif" alt="tutorial" border="0"><br>
<div class="next_link"><a href="tutorial/index.html"><img src="next.gif" alt="tutorial" border="0"><br>
Tutorial
</a></div><br clear="all" style="clear: all;">
@@ -44,16 +46,16 @@ The versatile nature of Boost.MultiIndex allows for the specification of
a wide spectrum of different data structures. The following are possible
examples of use developed in the documentation:
<ul>
<li><a href="tutorial.html#multipe_sort">Sets with several iteration orders
<li><a href="tutorial/basics.html#multiple_sort">Sets with several iteration orders
and search criteria</a>.</li>
<li><a href="tutorial.html#list_fast_lookup">Lists with fast lookup</a>
<li><a href="tutorial/basics.html#list_fast_lookup">Lists with fast lookup</a>
and/or without duplicates.</li>
<li><a href="examples.html#example4">Bidirectional maps</a>, i.e. maps
searchable either for key or value.</li>
<li><a href="examples.html#example9">MRU (most recently used) lists</a>,
structures keeping the <i>n</i> last referenced items, beginning with
the newest ones.</li>
<li><a href="advanced_topics.html#emulate_std_containers">Emulations of
<li><a href="tutorial/techniques.html#emulate_std_containers">Emulations of
standard containers</a> taking advantage of the extra functionalities
provided by Boost.MultiIndex.</li>
</ul>
@@ -62,8 +64,7 @@ examples of use developed in the documentation:
<h2>Contents</h2>
<ul>
<li><a href="tutorial.html">Tutorial</a></li>
<li><a href="advanced_topics.html">Advanced topics</a></li>
<li><a href="tutorial/index.html">Tutorial</a></li>
<li><a href="reference/index.html">Reference</a></li>
<li><a href="compiler_specifics.html">Compiler specifics</a></li>
<li><a href="performance.html">Performance</a></li>
@@ -78,15 +79,15 @@ examples of use developed in the documentation:
<div class="prev_link"></div>
<div class="up_link"></div>
<div class="next_link"><a href="tutorial.html"><img src="next.gif" alt="tutorial" border="0"><br>
<div class="next_link"><a href="tutorial/index.html"><img src="next.gif" alt="tutorial" border="0"><br>
Tutorial
</a></div><br clear="all" style="clear: all;">
<br>
<p>Revised March 15th 2005</p>
<p>Revised February 6th 2006</p>
<p>&copy; Copyright 2003-2005 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
<p>&copy; Copyright 2003-2006 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 9.7 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 10 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 9.5 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 9.7 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 9.5 KiB

+122 -84
View File
@@ -5,6 +5,10 @@
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Boost.MultiIndex Documentation - Performance</title>
<link rel="stylesheet" href="style.css" type="text/css">
<link rel="start" href="index.html">
<link rel="prev" href="compiler_specifics.html">
<link rel="up" href="index.html">
<link rel="next" href="examples.html">
</head>
<body>
@@ -91,7 +95,7 @@ STL containers.
<h2><a name="simulation">Manual simulation of a <code>multi_index_container</code></a></h2>
<p>
The section of <a href="advanced_topics.html#simulate_std_containers">simulation
The section on <a href="tutorial/techniques.html#emulate_std_containers">emulation
of standard containers with <code>multi_index_container</code></a> shows the equivalence
between single-index <code>multi_index_container</code>s and some STL containers. Let us now
concentrate on the problem of simulating a <code>multi_index_container</code> with two
@@ -154,8 +158,8 @@ inefficient, though: while insertion into the data structure is simple enough:
<span class=identifier>manual_t2</span> <span class=identifier>c2</span><span class=special>;</span>
<span class=comment>// insert the element 5</span>
<span class=identifier>manual_t1</span><span class=special>::</span><span class=identifier>iterator</span><span class=special>=</span><span class=identifier>c1</span><span class=special>.</span><span class=identifier>insert</span><span class=special>(</span><span class=number>5</span><span class=special>).</span><span class=identifier>first</span><span class=special>;</span>
<span class=identifier>c2</span><span class=special>.</span><span class=identifier>insert</span><span class=special>(&amp;*</span><span class=identifier>t1</span><span class=special>);</span>
<span class=identifier>manual_t1</span><span class=special>::</span><span class=identifier>iterator</span> <span class=identifier>it1</span><span class=special>=</span><span class=identifier>c1</span><span class=special>.</span><span class=identifier>insert</span><span class=special>(</span><span class=number>5</span><span class=special>).</span><span class=identifier>first</span><span class=special>;</span>
<span class=identifier>c2</span><span class=special>.</span><span class=identifier>insert</span><span class=special>(&amp;*</span><span class=identifier>it1</span><span class=special>);</span>
</pre></blockquote>
deletion, on the other hand, necessitates a logarithmic search, whereas
@@ -164,8 +168,8 @@ deletion, on the other hand, necessitates a logarithmic search, whereas
<blockquote><pre>
<span class=comment>// remove the element pointed to by it2</span>
<span class=identifier>manual_t2</span><span class=special>::</span><span class=identifier>iterator</span> <span class=identifier>it2</span><span class=special>=...;</span>
<span class=identifier>c1</span><span class=special>.</span><span class=identifier>erase</span><span class=special>(*</span><span class=identifier>it2</span><span class=special>);</span> <span class=comment>// watch out! performs in logarithmic time</span>
<span class=identifier>c2</span><span class=special>.</span><span class=identifier>erase</span><span class=special>(</span><span class=identifier>it1</span><span class=special>);</span>
<span class=identifier>c1</span><span class=special>.</span><span class=identifier>erase</span><span class=special>(**</span><span class=identifier>it2</span><span class=special>);</span> <span class=comment>// watch out! performs in logarithmic time</span>
<span class=identifier>c2</span><span class=special>.</span><span class=identifier>erase</span><span class=special>(</span><span class=identifier>it2</span><span class=special>);</span>
</pre></blockquote>
<p>
@@ -174,14 +178,14 @@ raw pointers, but with elements of type <code>manual_t1::iterator</code>:
</p>
<blockquote><pre>
<span class=keyword>typedef</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>set</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;</span> <span class=identifier>manual_t1</span><span class=special>;</span> <span class=comment>// equivalent to indexed_t's index #0</span>
<span class=keyword>typedef</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>set</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;</span> <span class=identifier>manual_t1</span><span class=special>;</span> <span class=comment>// equivalent to indexed_t's index #0</span>
<span class=keyword>typedef</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>multiset</span><span class=special>&lt;</span>
<span class=identifier>manual_t1</span><span class=special>::</span><span class=identifier>iterator</span><span class=special>,</span>
<span class=identifier>it_compare</span><span class=special>&lt;</span>
<span class=identifier>manual_t1</span><span class=special>::</span><span class=identifier>iterator</span><span class=special>,</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>greater</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span> <span class=identifier>manual_t2</span><span class=special>;</span> <span class=comment>// equivalent to indexed_t's index #1</span>
<span class=special>&gt;</span> <span class=identifier>manual_t2</span><span class=special>;</span> <span class=comment>// equivalent to indexed_t's index #1</span>
</pre></blockquote>
<p>
@@ -194,13 +198,13 @@ equivalent to those of <code>indexed_t</code>:
<span class=identifier>manual_t2</span> <span class=identifier>c2</span><span class=special>;</span>
<span class=comment>// insert the element 5</span>
<span class=identifier>manual_t1</span><span class=special>::</span><span class=identifier>iterator</span><span class=special>=</span><span class=identifier>c1</span><span class=special>.</span><span class=identifier>insert</span><span class=special>(</span><span class=number>5</span><span class=special>).</span><span class=identifier>first</span><span class=special>;</span>
<span class=identifier>c2</span><span class=special>.</span><span class=identifier>insert</span><span class=special>(</span><span class=identifier>t1</span><span class=special>);</span>
<span class=identifier>manual_t1</span><span class=special>::</span><span class=identifier>iterator</span> <span class=identifier>it1</span><span class=special>=</span><span class=identifier>c1</span><span class=special>.</span><span class=identifier>insert</span><span class=special>(</span><span class=number>5</span><span class=special>).</span><span class=identifier>first</span><span class=special>;</span>
<span class=identifier>c2</span><span class=special>.</span><span class=identifier>insert</span><span class=special>(</span><span class=identifier>it1</span><span class=special>);</span>
<span class=comment>// remove the element pointed to by it2</span>
<span class=identifier>manual_t2</span><span class=special>::</span><span class=identifier>iterator</span> <span class=identifier>it2</span><span class=special>=...;</span>
<span class=identifier>c1</span><span class=special>.</span><span class=identifier>erase</span><span class=special>(*</span><span class=identifier>it2</span><span class=special>);</span> <span class=comment>// OK: constant time</span>
<span class=identifier>c2</span><span class=special>.</span><span class=identifier>erase</span><span class=special>(</span><span class=identifier>it1</span><span class=special>);</span>
<span class=identifier>c2</span><span class=special>.</span><span class=identifier>erase</span><span class=special>(</span><span class=identifier>it2</span><span class=special>);</span>
</pre></blockquote>
<p>
@@ -237,7 +241,7 @@ On the other hand, the manual simulation allocates <i>N</i> nodes per
element, the first holding the elements themselves and the rest
storing iterators to the "base" container. In practice, an iterator
merely holds a raw pointer to the node it is associated to, so its size
is independent of the type of the elements. Suming all contributions,
is independent of the type of the elements. Summing all contributions,
the space allocated per element in a manual simulation is
</p>
@@ -263,7 +267,25 @@ then as:
<p>
The formula shows that <code>multi_index_container</code> is more efficient
with regard to memory consumption as the number of indices grow.
with regard to memory consumption as the number of indices grow. An implicit
assumption has been made that headers of <code>multi_index_container</code>
index nodes are the same size that their analogues in STL containers; but there
is a particular case in which this is often not the case: ordered indices use a
<a href="tutorial/indices.html#ordered_node_compression">spatial optimization
technique</a> which is not present in many implementations of
<code>std::set</code>, giving an additional advantage to
<code>multi_index_container</code>s of one system word per ordered index.
Taking this fact into account, the former formula can be adjusted to:
</p>
<blockquote>
<i>S<sub>I</sub></i>&nbsp;/&nbsp;<i>S<sub>M</sub></i> =
<i>S<sub>I</sub></i>&nbsp;/&nbsp;(<i>S<sub>I</sub></i> + (<i>N</i>-1)<i>p</i> + <i>Ow</i>),
</blockquote>
<p>
where <i>O</i> is the number of ordered indices of the container, and <i>w</i>
is the system word size (typically 4 bytes on 32-bit architectures.)
</p>
<p>
@@ -289,9 +311,9 @@ will see later, the reduction can be very significative for
</p>
<p>In the special case of <code>multi_index_container</code>s with only one index,
the best we can hope for is equal performance: the tests show that the
performance degradation in this particular situation ranges from negligible
to small, depending on the compiler used.
resulting performance will roughly match that of the STL equivalent containers:
tests show that there is at most a negligible degradation with respect to STL,
and even in some cases a small improvement.
</p>
<h2><a name="tests">Performance tests</a></h2>
@@ -314,15 +336,33 @@ has been measured for different instantiations of <code>multi_index_container</c
at values of <i>n</i> 1,000, 10,000 and 100,000,
and its execution time compared with that of the equivalent algorithm
for the corresponding manual simulation of the data structure based on
STL containers. The following compilers have been used:
<ul>
<li>GNU GCC 3.3.1 for Cygwin 1.5.7,</li>
<li>Intel C++ Compiler for Windows 32-bit 7.1,</li>
<li>Microsoft Visual C++ 6.0 Service Pack 5,</li>
</ul>
with their default release settings. All tests were performed on a Wintel
box equipped with a P4 1.5GHz processor and 256 MB RAM, running
Microsoft Windows 2000 Professional SP2.
STL containers. The table below describes the test environments used.
</p>
<p align="center">
<table cellspacing="0" cellpadding="5">
<caption><b>Tests environments.</b></caption>
<tr>
<th>Compiler</th>
<th>Settings</th>
<th>OS and CPU</th>
</tr>
<tr>
<td>GCC 3.4.5 (mingw special)</td>
<td><code>-O3</code></td>
<td>Windows 2000 Pro on P4 1.5 GHz, 256 MB RAM</td>
</tr>
<tr class="odd_tr">
<td>Intel C++ 7.1</td>
<td>default release settings</td>
<td>Windows 2000 Pro on P4 1.5 GHz, 256 MB RAM</td>
</tr>
<tr>
<td>Microsoft Visual C++ 8.0</td>
<td>default release settings, <code>_SECURE_SCL=0</code></td>
<td>Windows XP on P4 Xeon 3.2 GHz, 1 GB RAM</td>
</tr>
</table>
</p>
<p>
@@ -357,14 +397,14 @@ which is functionally equivalent to <code>std::set&lt;int></code>.
<p align="center">
<table cellspacing="0">
<tr>
<th width="33%">GCC 3.1.1</th>
<th width="33%">GCC 3.4.5</th>
<th width="33%">ICC 7.1</th>
<th width="33%">MSVC 6.5</th>
<th width="33%">MSVC 8.0</th>
</tr>
<tr>
<td align="center">100%</td>
<td align="center">100%</td>
<td align="center">100%</td>
<td align="center">80%</td>
<td align="center">80%</td>
<td align="center">80%</td>
</tr>
</table>
<b>Table 1: Relative memory consumption of <code>multi_index_container</code> with 1
@@ -372,8 +412,8 @@ ordered index.</b>
</p>
<p>
The figures confirm that in this case <code>multi_index_container</code> nodes are the
same size than those of its <code>std::set</code> counterpart.
The reduction in memory usage is accounted for by the optimization technique implemented
in Boost.MultiIndex ordered indices, as <a href="#spatial_efficiency">explained above</a>.
</p>
<h4><a name="time_1r">Execution time</a></h4>
@@ -385,11 +425,12 @@ width="556" height="372"><br>
</p>
<p>
As expected, <code>multi_index_container</code> does perform in this case somewhat
worse than <code>std::set</code>. The degradation is within 10% for ICC and
MSVC compilers, while in GCC peaks to 20%, which can be significative
in certain applications. This latter result is presumably accounted for by
a lower quality of the optimizing stage carried out by GCC.
Somewhat surprisingly, <code>multi_index_container</code> performs slightly
better than <code>std::set</code>. A very likely explanation for this behavior
is that the lower memory consumption of <code>multi_index_container</code>
results in a higher processor cache hit rate.
The improvement is smallest for GCC, presumably because the worse quality of
this compiler's optimizer masks the cache-related benefits.
</p>
<h3><a name="test_1s">Results for 1 sequenced index</a></h3>
@@ -416,9 +457,9 @@ which is functionally equivalent to <code>std::list&lt;int></code>.
<p align="center">
<table cellspacing="0">
<tr>
<th width="33%">GCC 3.1.1</th>
<th width="33%">GCC 3.4.5</th>
<th width="33%">ICC 7.1</th>
<th width="33%">MSVC 6.5</th>
<th width="33%">MSVC 8.0</th>
</tr>
<tr>
<td align="center">100%</td>
@@ -444,9 +485,10 @@ width="556" height="372"><br>
</p>
<p>
As in the former case, <code>multi_index_container</code> does not attain the performance
of its STL counterpart. Again, worst results are those of GCC, with a
degradation of up to 20% , while ICC and MSVC do not exceed a mere 5%.
<code>multi_index_container</code> does not attain the performance
of its STL counterpart, although the figures are close. Again, the worst results
are those of GCC, with a degradation of up to 7%, while ICC and MSVC do not
exceed a mere 5%.
</p>
<h3><a name="test_2r">Results for 2 ordered indices</a></h3>
@@ -470,14 +512,14 @@ The following instantiation of <code>multi_index_container</code> was tested:
<p align="center">
<table cellspacing="0">
<tr>
<th width="33%">GCC 3.1.1</th>
<th width="33%">GCC 3.4.5</th>
<th width="33%">ICC 7.1</th>
<th width="33%">MSVC 6.5</th>
<th width="33%">MSVC 8.0</th>
</tr>
<tr>
<td align="center">90%</td>
<td align="center">90%</td>
<td align="center">90%</td>
<td align="center">70%</td>
<td align="center">70%</td>
<td align="center">70%</td>
</tr>
</table>
<b>Table 3: Relative memory consumption of <code>multi_index_container</code> with 2
@@ -486,7 +528,7 @@ ordered indices.</b>
<p>
These results concinde with the theoretical formula for
<i>S<sub>I</sub></i>=36 and <i>p</i>=4.
<i>S<sub>I</sub></i> = 28, <i>N</i> = <i>O</i> = 2 and <i>p</i> = <i>w</i> = 4.
</p>
<h4><a name="time_2r">Execution time</a></h4>
@@ -500,7 +542,9 @@ width="556" height="372"><br>
<p>
The experimental results confirm our hypothesis that <code>multi_index_container</code>
provides an improvement on execution time by an approximately constant factor,
which in this case ranges from 65% to 75% depending on the compiler.
which in this case lies around 60%. There is no obvious explanation for the
increased advantage of <code>multi_index_container</code> in MSVC for
<i>n</i>=10<sup>5</sup>.
</p>
<h3><a name="test_1r1s">Results for 1 ordered index + 1 sequenced index</a></h3>
@@ -524,14 +568,14 @@ The following instantiation of <code>multi_index_container</code> was tested:
<p align="center">
<table cellspacing="0">
<tr>
<th width="33%">GCC 3.1.1</th>
<th width="33%">GCC 3.4.5</th>
<th width="33%">ICC 7.1</th>
<th width="33%">MSVC 6.5</th>
<th width="33%">MSVC 8.0</th>
</tr>
<tr>
<td align="center">87.5%</td>
<td align="center">87.5%</td>
<td align="center">87.5%</td>
<td align="center">75%</td>
<td align="center">75%</td>
<td align="center">75%</td>
</tr>
</table>
<b>Table 4: Relative memory consumption of <code>multi_index_container</code> with 1
@@ -540,7 +584,7 @@ ordered index + 1 sequenced index.</b>
<p>
These results concinde with the theoretical formula for
<i>S<sub>I</sub></i>=28 and <i>p</i>=4.
<i>S<sub>I</sub></i> = 24, <i>N</i> = 2, <i>O</i> = 1 and <i>p</i> = <i>w</i> = 4.
</p>
<h4><a name="time_1r1s">Execution time</a></h4>
@@ -556,17 +600,13 @@ width="556" height="372"><br>
<p>
For <i>n</i>=10<sup>3</sup> and <i>n</i>=10<sup>4</sup>, the results
are in agreement with our theoretical analysis, showing a constant factor
improvement of 60-75% with respect to the STL-based manual simulation.
improvement of 50-65% with respect to the STL-based manual simulation.
Curiously enough, this speedup gets even higher when
<i>n</i>=10<sup>5</sup> for two of the compilers (35% for ICC,
25% for MSVC.) In order to rule out spurious results, the tests
have been run many times, yielding similar outcoumes. A tentative
explanation of this unexpected behavior may point to a degradation in
the execution time of the manual simulation, attributable to poor
performance of the standard STL allocator in ICC and MSVC when dealing
with many objects of diverse sizes (the manual simulation is comprised of
an <code>std::set</code> and a <code>std::list</code>, which demand
differently sized nodes.)
<i>n</i>=10<sup>5</sup> for two of the compilers, namely GCC and ICC.
In order to rule out spurious results, the tests
have been run many times, yielding similar outcoumes. Both test environments
are deployed on the same machine, which points to some OS-related reason for
this phenomenon.
</p>
<h3><a name="test_3r">Results for 3 ordered indices</a></h3>
@@ -591,14 +631,14 @@ The following instantiation of <code>multi_index_container</code> was tested:
<p align="center">
<table cellspacing="0">
<tr>
<th width="33%">GCC 3.1.1</th>
<th width="33%">GCC 3.4.5</th>
<th width="33%">ICC 7.1</th>
<th width="33%">MSVC 6.5</th>
<th width="33%">MSVC 8.0</th>
</tr>
<tr>
<td align="center">86.7%</td>
<td align="center">86.7%</td>
<td align="center">86.7%</td>
<td align="center">66.7%</td>
<td align="center">66.7%</td>
<td align="center">66.7%</td>
</tr>
</table>
<b>Table 5: Relative memory consumption of <code>multi_index_container</code> with 3
@@ -607,8 +647,7 @@ ordered indices.</b>
<p>
These results concinde with the theoretical formula for
<i>S<sub>I</sub></i>=52 and <i>p</i>=4.
<i>S<sub>I</sub></i> = 40, <i>N</i> = <i>O</i> = 3 and <i>p</i> = <i>w</i> = 4.
</p>
<h4><a name="time_3r">Execution time</a></h4>
@@ -620,7 +659,7 @@ width="556" height="372"><br>
</p>
<p>
Execution time for this case is between 55% and 65% lower than achieved with
Execution time for this case is between 45% and 55% lower than achieved with
an STL-based manual simulation of the same data structure.
</p>
@@ -646,14 +685,14 @@ The following instantiation of <code>multi_index_container</code> was tested:
<p align="center">
<table cellspacing="0">
<tr>
<th width="33%">GCC 3.1.1</th>
<th width="33%">GCC 3.4.5</th>
<th width="33%">ICC 7.1</th>
<th width="33%">MSVC 6.5</th>
<th width="33%">MSVC 8.0</th>
</tr>
<tr>
<td align="center">84.6%</td>
<td align="center">84.6%</td>
<td align="center">84.6%</td>
<td align="center">69.2%</td>
<td align="center">69.2%</td>
<td align="center">69.2%</td>
</tr>
</table>
<b>Table 6: Relative memory consumption of <code>multi_index_container</code> with 2
@@ -662,7 +701,7 @@ ordered indices + 1 sequenced index.</b>
<p>
These results concinde with the theoretical formula for
<i>S<sub>I</sub></i>=44 and <i>p</i>=4.
<i>S<sub>I</sub></i> = 36, <i>N</i> = 3, <i>O</i> = 2 and <i>p</i> = <i>w</i> = 4.
</p>
<h4><a name="time_2r1s">Execution time</a></h4>
@@ -691,10 +730,9 @@ of indices increase.
<p>
In the special case of replacing standard containers with single-indexed
<code>multi_index_container</code>s, the programmer should balance the benefits brought on
by Boost.MultiIndex (subobject searching, in-place updating, etc.) against the
resulting degradation in execution time. Depending on the compiler, this degradation
can reach up to 20% of the original time.
<code>multi_index_container</code>s, the performance of Boost.MultiIndex
is comparable with that of the tested STL implementations, and can even yield
some improvements both in space consumption and execution time.
</p>
<hr>
@@ -711,9 +749,9 @@ Examples
<br>
<p>Revised May 18th 2005</p>
<p>Revised May 9th 2006</p>
<p>&copy; Copyright 2003-2005 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
<p>&copy; Copyright 2003-2006 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
+142 -48
View File
@@ -5,6 +5,10 @@
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Boost.MultiIndex Documentation - Hashed indices reference</title>
<link rel="stylesheet" href="../style.css" type="text/css">
<link rel="start" href="../index.html">
<link rel="prev" href="ord_indices.html">
<link rel="up" href="index.html">
<link rel="next" href="seq_indices.html">
</head>
<body>
@@ -40,9 +44,11 @@ Sequenced indices
<li><a href="#instantiation_types">Instantiation types</a></li>
<li><a href="#types">Nested types</a></li>
<li><a href="#constructors">Constructors, copy and assignment</a></li>
<li><a href="#iterators">Iterators</a></li>
<li><a href="#modifiers">Modifiers</a></li>
<li><a href="#observers">Observers</a></li>
<li><a href="#lookup">Lookup</a></li>
<li><a href="#bucket_interface">Bucket interface</a></li>
<li><a href="#hash_policy">Hash policy</a></li>
<li><a href="#serialization">Serialization</a></li>
</ul>
@@ -154,7 +160,7 @@ two different forms, according to whether a tag list for the index is provided o
<p>
If provided, <code>TagList</code> must be an instantiation of the class template
<a href="#tag"><code>tag</code></a>.
<a href="indices.html#tag"><code>tag</code></a>.
The template arguments are used by the corresponding index implementation,
refer to the <a href="#hash_indices">hashed indices</a> reference section for further
explanations on their acceptable type values.
@@ -166,7 +172,7 @@ explanations on their acceptable type values.
A hashed index provides fast retrieval of elements of a <code>multi_index_container</code>
through hashing tecnhiques. The interface and semantics of hashed indices are modeled according
to the proposal for unordered associative containers given in the C++
<a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1745.pdf">Proposed
<a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1836.pdf">Proposed
Draft Tecnhical Report on Standard Library Extensions</a>, also known as TR1. A hashed
index is particularized according to a given
<a href="key_extraction.html#key_extractors"><code>Key Extractor</code></a>
@@ -214,6 +220,7 @@ do not exactly conform to the requirements for unordered associative containers.
<span class=keyword>typedef</span> <span class=identifier>Pred</span> <span class=identifier>key_equal</span><span class=special>;</span>
<span class=keyword>typedef</span> <span class=identifier>tuple</span><span class=special>&lt;</span>
<span class=identifier>size_type</span><span class=special>,</span><span class=identifier>key_from_value</span><span class=special>,</span><span class=identifier>hasher</span><span class=special>,</span><span class=identifier>key_equal</span><span class=special>&gt;</span> <span class=identifier>ctor_args</span><span class=special>;</span>
<span class=keyword>typedef</span> <span class=identifier>TagList</span> <span class=identifier>tag_list</span><span class=special>;</span>
<span class=keyword>typedef</span> <span class=identifier>Allocator</span> <span class=identifier>allocator_type</span><span class=special>;</span>
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>Allocator</span><span class=special>::</span><span class=identifier>pointer</span> <span class=identifier>pointer</span><span class=special>;</span>
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>Allocator</span><span class=special>::</span><span class=identifier>const_pointer</span> <span class=identifier>const_pointer</span><span class=special>;</span>
@@ -244,7 +251,12 @@ do not exactly conform to the requirements for unordered associative containers.
<span class=identifier>const_iterator</span> <span class=identifier>begin</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>iterator</span> <span class=identifier>end</span><span class=special>();</span>
<span class=identifier>const_iterator</span> <span class=identifier>end</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>const_iterator</span> <span class=identifier>cbegin</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>const_iterator</span> <span class=identifier>cend</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>iterator</span> <span class=identifier>iterator_to</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=identifier>const_iterator</span> <span class=identifier>iterator_to</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=comment>// modifiers:</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>pair</span><span class=special>&lt;</span><span class=identifier>iterator</span><span class=special>,</span><span class=keyword>bool</span><span class=special>&gt;</span> <span class=identifier>insert</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
@@ -252,13 +264,17 @@ do not exactly conform to the requirements for unordered associative containers.
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>InputIterator</span><span class=special>&gt;</span>
<span class=keyword>void</span> <span class=identifier>insert</span><span class=special>(</span><span class=identifier>InputIterator</span> <span class=identifier>first</span><span class=special>,</span><span class=identifier>InputIterator</span> <span class=identifier>last</span><span class=special>);</span>
<span class=keyword>void</span> <span class=identifier>erase</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>);</span>
<span class=identifier>iterator</span> <span class=identifier>erase</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>);</span>
<span class=identifier>size_type</span> <span class=identifier>erase</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>key_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=keyword>void</span> <span class=identifier>erase</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>first</span><span class=special>,</span><span class=identifier>iterator</span> <span class=identifier>last</span><span class=special>);</span>
<span class=identifier>iterator</span> <span class=identifier>erase</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>first</span><span class=special>,</span><span class=identifier>iterator</span> <span class=identifier>last</span><span class=special>);</span>
<span class=keyword>bool</span> <span class=identifier>replace</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>&gt;</span> <span class=keyword>bool</span> <span class=identifier>modify</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>);</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Rollback</span><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=identifier>modify</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>,</span><span class=identifier>Rollback</span> <span class=identifier>back</span><span class=special>);</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>&gt;</span> <span class=keyword>bool</span> <span class=identifier>modify_key</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>);</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Rollback</span><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=identifier>modify_key</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>,</span><span class=identifier>Rollback</span> <span class=identifier>back</span><span class=special>);</span>
<span class=keyword>void</span> <span class=identifier>clear</span><span class=special>();</span>
<span class=keyword>void</span> <span class=identifier>swap</span><span class=special>(</span><b>index class name</b><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
@@ -309,6 +325,11 @@ do not exactly conform to the requirements for unordered associative containers.
<span class=identifier>const_local_iterator</span> <span class=identifier>begin</span><span class=special>(</span><span class=identifier>size_type</span> <span class=identifier>n</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>local_iterator</span> <span class=identifier>end</span><span class=special>(</span><span class=identifier>size_type</span> <span class=identifier>n</span><span class=special>);</span>
<span class=identifier>const_local_iterator</span> <span class=identifier>end</span><span class=special>(</span><span class=identifier>size_type</span> <span class=identifier>n</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>const_local_iterator</span> <span class=identifier>cbegin</span><span class=special>(</span><span class=identifier>size_type</span> <span class=identifier>n</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>const_local_iterator</span> <span class=identifier>cend</span><span class=special>(</span><span class=identifier>size_type</span> <span class=identifier>n</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>local_iterator</span> <span class=identifier>local_iterator_to</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=identifier>const_local_iterator</span> <span class=identifier>local_iterator_to</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=comment>// hash policy:</span>
@@ -366,7 +387,7 @@ following types:
<ul>
<li><code>Value</code> from <code>multi_index_container</code>,</li>
<li><code>Allocator</code> from <code>multi_index_container</code>,</li>
<li><code>TagList</code> from the index specifier (if provided),</li>
<li><code>TagList</code> from the index specifier (if provided, otherwise <code>tag&lt;&gt;</code> is assumed),</li>
<li><code>KeyFromValue</code> from the index specifier,</li>
<li><code>Hash</code> from the index specifier,</li>
<li><code>Pred</code> from the index specifier.</li>
@@ -430,6 +451,18 @@ objects to which <code>*this</code> and <code>x</code> belong, respectively.<br>
<b>Returns:</b> <code>*this</code>.<br>
</blockquote>
<h4><a name="iterators">Iterators</a></h4>
<code>iterator&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iterator_to(const value_type&amp; x);<br>
const_iterator iterator_to(const value_type&amp; x)const;</code>
<blockquote>
<b>Requires:</b> <code>x</code> is a reference to an element of the container.<br>
<b>Returns:</b> An iterator to <code>x</code>.<br>
<b>Complexity:</b> Constant.<br>
<b>Exception safety:</b> <code>nothrow</code>.<br>
</blockquote>
<h4><a name="modifiers">Modifiers</a></h4>
<code>std::pair&lt;iterator,bool> insert(const value_type&amp; x);</code>
@@ -455,7 +488,7 @@ one element can be causing insertion not to be allowed.<br>
<code>iterator insert(iterator position,const value_type&amp; x);</code>
<blockquote>
<b>Requires:</b> <code>position</code> is a valid iterator of the index.</br>
<b>Requires:</b> <code>position</code> is a valid iterator of the index.<br>
<b>Effects:</b> Inserts <code>x</code> into the <code>multi_index_container</code> to which
the index belongs if
<ul>
@@ -484,7 +517,7 @@ void insert(InputIterator first,InputIterator last);</code>
<code>value_type</code> or a type convertible to <code>value_type</code>.
<code>first</code> and <code>last</code> are not iterators into any
index of the <code>multi_index_container</code> to which this index belongs.
<code>last</code> is reachable from <code>first</code>.</br>
<code>last</code> is reachable from <code>first</code>.<br>
<b>Effects:</b>
<blockquote><pre>
<span class=identifier>iterator</span> <span class=identifier>hint</span><span class=special>=</span><span class=identifier>end</span><span class=special>();</span>
@@ -496,12 +529,15 @@ index of the <code>multi_index_container</code> to which this index belongs.
<b>Exception safety:</b> Basic.<br>
</blockquote>
<code>void erase(iterator position);</code>
<code>iterator erase(iterator position);</code>
<blockquote>
<b>Requires:</b> <code>position</code> is a valid dereferenceable iterator
of the index.</br>
of the index.<br>
<b>Effects:</b> Deletes the element pointed to by <code>position</code>.<br>
<b>Returns:</b> An iterator pointing to the element immediately following
the one that was deleted, or <code>end()</code>
if no such element exists.<br>
<b>Complexity:</b> <code>O(D(n))</code>.<br>
<b>Exception safety:</b> <code>nothrow</code>.<br>
</blockquote>
@@ -517,12 +553,13 @@ the number of elements deleted.<br>
<b>Exception safety:</b> Basic.<br>
</blockquote>
<code>void erase(iterator first,iterator last);</code>
<code>iterator erase(iterator first,iterator last);</code>
<blockquote>
<b>Requires:</b> [<code>first</code>,<code>last</code>) is a valid
range of the index.<br>
<b>Effects:</b> Deletes the elements in [<code>first</code>,<code>last</code>).<br>
<b>Returns:</b> <code>last</code>.<br>
<b>Complexity:</b> <code>O(m*D(n))</code>, where <code>m</code> is
the number of elements in [<code>first</code>,<code>last</code>).<br>
<b>Exception safety:</b> <code>nothrow</code>.<br>
@@ -532,7 +569,7 @@ the number of elements in [<code>first</code>,<code>last</code>).<br>
<blockquote>
<b>Requires:</b> <code>position</code> is a valid dereferenceable iterator
of the index.</br>
of the index.<br>
<b>Effects:</b> Assigns the value <code>x</code> to the element pointed
to by <code>position</code> into the <code>multi_index_container</code> to which
the index belongs if, for the value <code>x</code>
@@ -543,7 +580,8 @@ the index belongs if, for the value <code>x</code>
<code>multi_index_container</code>.</li>
</ul>
<b>Postconditions:</b> Validity of <code>position</code> is preserved
in all cases.<br>
in all cases. If the key of the new value is equivalent to that of the replaced value,
the position of the element does not change.<br>
<b>Returns:</b> <code>true</code> if the replacement took place,
<code>false</code> otherwise.<br>
<b>Complexity:</b> <code>O(R(n))</code>.<br>
@@ -560,7 +598,7 @@ belongs remains in its original state.
<a href="http://www.sgi.com/tech/stl/UnaryFunction.html">
<code>Unary Function</code></a> accepting arguments of type
<code>value_type&amp;</code>. <code>position</code> is a valid dereferenceable
iterator of the index.</br>
iterator of the index.<br>
<b>Effects:</b> Calls <code>mod(e)</code> where <code>e</code> is the element
pointed to by <code>position</code> and rearranges <code>*position</code> into
all the indices of the <code>multi_index_container</code>. Rearrangement is successful if
@@ -572,7 +610,8 @@ all the indices of the <code>multi_index_container</code>. Rearrangement is succ
</ul>
If the rearrangement fails, the element is erased.<br>
<b>Postconditions:</b> Validity of <code>position</code> is preserved if the
operation succeeds.<br>
operation succeeds. If the key of the modified value is equivalent to that of the original
value, the position of the element does not change.<br>
<b>Returns:</b> <code>true</code> if the operation succeeded, <code>false</code>
otherwise.<br>
<b>Complexity:</b> <code>O(M(n))</code>.<br>
@@ -581,6 +620,42 @@ user-provided operation (except possibly <code>mod</code>), then
the element pointed to by <code>position</code> is erased.
</blockquote>
<code>template&lt;typename Modifier,typename Rollback><br>
bool modify(iterator position,Modifier mod,Rollback back);</code>
<blockquote>
<b>Requires:</b> <code>Modifier</code> and <code>Rollback</code> are models of
<a href="http://www.sgi.com/tech/stl/UnaryFunction.html">
<code>Unary Function</code></a> accepting arguments of type
<code>value_type&amp;</code>. <code>position</code> is a valid dereferenceable
iterator of the index. The sequence of operations <code>mod(e)</code>,
<code>back(e)</code>, where <code>e</code> is the element
pointed to by <code>position</code>, restores all keys of the element
to their original state.<br>
<b>Effects:</b> Calls <code>mod(e)</code> where <code>e</code> is the element
pointed to by <code>position</code> and tries to rearrange <code>*position</code> into
all the indices of the <code>multi_index_container</code>. Rearrangement is successful if
<ul>
<li>the index is non-unique OR no other element exists
with equivalent key,</li>
<li>AND rearrangement is allowed by all other indices of the
<code>multi_index_container</code>.</li>
</ul>
If the rearrangement fails, <code>back(e)</code> is invoked and the
element is kept at its original position in all indices.<br>
<b>Postconditions:</b> Validity of <code>position</code> is preserved except if
the element is erased under the conditions described below. If the key of the modified value
is equivalent to that of the original value, the position of the element does not change.<br>
<b>Returns:</b> <code>true</code> if the operation succeeded, <code>false</code>
otherwise.<br>
<b>Complexity:</b> <code>O(M(n))</code>.<br>
<b>Exception safety:</b> Strong, except if <code>back</code> throws an
exception, in which case the modified element is erased. If <code>back</code>
throws inside the handling code executing after some other user-provided
operation has thrown, it is the exception generated by <code>back</code> that
is rethrown.
</blockquote>
<a name="modify_key">
<code>template&lt;typename Modifier> bool modify_key(iterator position,Modifier mod);</code></a>
@@ -591,27 +666,32 @@ from <code>value_type</code>. <code>Modifier</code> is a model of
<a href="http://www.sgi.com/tech/stl/UnaryFunction.html">
<code>Unary Function</code></a> accepting arguments of type
<code>key_type&amp;</code>. <code>position</code> is a valid dereferenceable
iterator of the index.</br>
<b>Effects:</b> Calls <code>mod(k)</code> where <code>k</code> is the key
obtained by the internal <code>KeyFromValue</code> object of the index from
the element pointed to by <code>position</code>, and rearranges
<code>*position</code> into all the indices of the <code>multi_index_container</code>.
Rearrangement is successful if
<ul>
<li>the index is non-unique OR no other element exists
with equivalent key,</li>
<li>AND rearrangement is allowed by all other indices of the
<code>multi_index_container</code>.</li>
</ul>
If the rearrangement fails, the element is erased.<br>
<b>Postconditions:</b>Validity of <code>position</code> is preserved if
the operation succeeds.<br>
<b>Returns:</b> <code>true</code> if the operation succeeded, <code>false</code>
otherwise.<br>
<b>Complexity:</b> <code>O(M(n))</code>.<br>
<b>Exception safety:</b> Basic. If an exception is thrown by some
user-provided operation (except possibly <code>mod</code>), then
the element pointed to by <code>position</code> is erased.
iterator of the index.<br>
<b>Effects:</b> Equivalent to <code>modify(position,mod')</code>,
with <code>mod'</code> defined in such a way that
<code>mod'(x)</code> is the same as <code>mod(key(x))</code>, where
<code>key</code> is the internal <code>KeyFromValue</code> object of the index.
</blockquote>
<code>template&lt;typename Modifier,typename Rollback><br>
bool modify_key(iterator position,Modifier mod,Rollback back);</code>
<blockquote>
<b>Requires:</b> <code>key_from_value</code> is a read/write
<a href="key_extraction.html#key_extractors"><code>Key Extractor</code></a>
from <code>value_type</code>. <code>Modifier</code> and <code>Rollback</code>
are models of <a href="http://www.sgi.com/tech/stl/UnaryFunction.html">
<code>Unary Function</code></a> accepting arguments of type
<code>key_type&amp;</code>. <code>position</code> is a valid dereferenceable
iterator of the index.
The sequence of operations <code>mod(k)</code>,
<code>back(k)</code>, where <code>k</code> is the key of the element
pointed to by <code>position</code>, restores k to its original state.<br>
<b>Effects:</b> Equivalent to <code>modify(position,mod',back')</code>,
with <code>mod'</code> and <code>back</code> defined in such a way that
<code>mod'(x)</code> is the same as <code>mod(key(x))</code> and
<code>back'(x)</code> is the same as <code>back(key(x))</code>, where
<code>key</code> is the internal <code>KeyFromValue</code> object of the index.
</blockquote>
<h4><a name="observers">Observers</a></h4>
@@ -647,7 +727,7 @@ Consider a pair (<code>Hash</code>, <code>Pred</code>) where
and <code>Pred</code> is a
<a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">
<code>Binary Predicate</code></a> inducing an equivalence relation
on <code>Key</code>, whit the additional constraint that equivalent
on <code>Key</code>, with the additional constraint that equivalent
keys have the same hash value.
A triplet of types (<code>CompatibleKey</code>, <code>CompatibleHash</code>,
<code>CompatiblePred</code>) is said to be a <i>compatible extension</i>
@@ -698,7 +778,7 @@ In the context of a compatible extension or a compatible key, the expression
<blockquote>
<b>Requires:</b> <code>CompatibleKey</code> is a compatible key of
(<code>hasher</code>, <code>key_equal</code>).</br>
(<code>hasher</code>, <code>key_equal</code>).<br>
<b>Effects:</b> Returns a pointer to an element whose key is equivalent to
<code>x</code>, or <code>end()</code> if such an element does not exist.<br>
<b>Complexity:</b> Average case <code>O(1)</code> (constant), worst case
@@ -716,7 +796,7 @@ iterator find(<br>
<blockquote>
<b>Requires:</b> (<code>CompatibleKey</code>, <code>CompatibleHash</code>,
<code>CompatiblePred</code>) is a compatible extension of
(<code>hasher</code>, <code>key_equal</code>).</br>
(<code>hasher</code>, <code>key_equal</code>).<br>
<b>Effects:</b> Returns a pointer to an element whose key is equivalent to
<code>x</code>, or <code>end()</code> if such an element does not exist.<br>
<b>Complexity:</b> Average case <code>O(1)</code> (constant), worst case
@@ -729,7 +809,7 @@ size_type count(const CompatibleKey&amp; x)const;
<blockquote>
<b>Requires:</b> <code>CompatibleKey</code> is a compatible key of
(<code>hasher</code>, <code>key_equal</code>).</br>
(<code>hasher</code>, <code>key_equal</code>).<br>
<b>Effects:</b> Returns the number of elements with key equivalent to <code>x</code>.<br>
<b>Complexity:</b> Average case <code>O(count(x))</code>, worst case
<code>O(n)</code>.<br>
@@ -746,7 +826,7 @@ size_type count(<br>
<blockquote>
<b>Requires:</b> (<code>CompatibleKey</code>, <code>CompatibleHash</code>,
<code>CompatiblePred</code>) is a compatible extension of
(<code>hasher</code>, <code>key_equal</code>).</br>
(<code>hasher</code>, <code>key_equal</code>).<br>
<b>Effects:</b> Returns the number of elements with key equivalent to <code>x</code>.<br>
<b>Complexity:</b> Average case <code>O(count(x,hash,eq))</code>, worst case
<code>O(n)</code>.<br>
@@ -758,9 +838,10 @@ std::pair&lt;iterator,iterator> equal_range(const CompatibleKey&amp; x)const;
<blockquote>
<b>Requires:</b> <code>CompatibleKey</code> is a compatible key of
(<code>hasher</code>, <code>key_equal</code>).</br>
(<code>hasher</code>, <code>key_equal</code>).<br>
<b>Effects:</b> Returns a range containing all elements with keys equivalent
to <code>x</code> (and only those).<br>
to <code>x</code> (and only those), or (<code>end()</code>,<code>end()</code>)
if no such elements exist.<br>
<b>Complexity:</b> Average case <code>O(count(x))</code>, worst case
<code>O(n)</code>.<br>
</blockquote>
@@ -768,7 +849,7 @@ to <code>x</code> (and only those).<br>
<code>template&lt;<br>
&nbsp;&nbsp;typename CompatibleKey,typename CompatibleHash, typename CompatiblePred<br>
&gt;<br>
std::pair&lt;iterator,iterator> equal_range(</br>
std::pair&lt;iterator,iterator> equal_range(<br>
&nbsp;&nbsp;const CompatibleKey&amp; x,<br>
&nbsp;&nbsp;const CompatibleHash&amp; hash,const CompatiblePred&amp; eq)const;
</code>
@@ -776,13 +857,26 @@ std::pair&lt;iterator,iterator> equal_range(</br>
<blockquote>
<b>Requires:</b> (<code>CompatibleKey</code>, <code>CompatibleHash</code>,
<code>CompatiblePred</code>) is a compatible extension of
(<code>hasher</code>, <code>key_equal</code>).</br>
(<code>hasher</code>, <code>key_equal</code>).<br>
<b>Effects:</b> Returns a range containing all elements with keys equivalent
to <code>x</code> (and only those).<br>
to <code>x</code> (and only those), or (<code>end()</code>,<code>end()</code>)
if no such elements exist.<br>
<b>Complexity:</b> Average case <code>O(count(x,hash,eq))</code>, worst case
<code>O(n)</code>.<br>
</blockquote>
<h4><a name="bucket_interface">Bucket interface</a></h4>
<code>local_iterator&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;local_iterator_to(const value_type&amp; x);<br>
const_local_iterator local_iterator_to(const value_type&amp; x)const;</code>
<blockquote>
<b>Requires:</b> <code>x</code> is a reference to an element of the container.<br>
<b>Returns:</b> An iterator to <code>x</code>.<br>
<b>Complexity:</b> Constant.<br>
<b>Exception safety:</b> <code>nothrow</code>.<br>
</blockquote>
<h4><a name="hash_policy">Hash policy</a></h4>
@@ -796,7 +890,7 @@ load factor, and <code>bucket_count()>=n</code>.<br>
elements contained is preserved.<br>
<b>Complexity:</b> Average case <code>O(size())</code>, worst case
<code>O(size(n)<sup>2</sup>)</code>.<br>
<b>Exeption safety:</b> Strong.
<b>Exception safety:</b> Strong.
</blockquote>
<h4><a name="serialization">Serialization</a></h4>
@@ -887,9 +981,9 @@ Sequenced indices
<br>
<p>Revised June 7th 2005</p>
<p>Revised July 21st 2009</p>
<p>&copy; Copyright 2003-2005 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
<p>&copy; Copyright 2003-2009 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
+21 -7
View File
@@ -5,14 +5,18 @@
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Boost.MultiIndex Documentation - Reference</title>
<link rel="stylesheet" href="../style.css" type="text/css">
<link rel="start" href="../index.html">
<link rel="prev" href="../tutorial/techniques.html">
<link rel="up" href="../index.html">
<link rel="next" href="multi_index_container.html">
</head>
<body>
<h1><img src="../../../../boost.png" alt="boost.png (6897 bytes)" align=
"middle" width="277" height="86">Boost.MultiIndex Reference</h1>
<div class="prev_link"><a href="../advanced_topics.html"><img src="../prev.gif" alt="advanced topics" border="0"><br>
Advanced topics
<div class="prev_link"><a href="../tutorial/techniques.html"><img src="../prev.gif" alt="techniques" border="0"><br>
Tecnhiques
</a></div>
<div class="up_link"><a href="../index.html"><img src="../up.gif" alt="index" border="0"><br>
Index
@@ -32,6 +36,7 @@ Index
<li><a href="ord_indices.html">Ordered indices</a></li>
<li><a href="hash_indices.html">Hashed indices</a></li>
<li><a href="seq_indices.html">Sequenced indices</a></li>
<li><a href="rnd_indices.html">Random access indices</a></li>
<li><a href="key_extraction.html">Key Extraction</a></li>
</ul>
@@ -68,6 +73,13 @@ The following dependencies among headers of Boost.MultiIndex hold:
<code>"boost/multi_index/tag.hpp"</code></a>.</li>
</ul>
</li>
<li><a href="rnd_indices.html#synopsis">
<code>"boost/multi_index/random_access_index.hpp"</code></a> includes
<ul>
<li><a href="indices.html#tag_synopsis">
<code>"boost/multi_index/tag.hpp"</code></a>.</li>
</ul>
</li>
<li><a href="key_extraction.html#synopsis"><code>"boost/multi_index/key_extractors.hpp"</code></a>
includes
<ul>
@@ -76,7 +88,9 @@ The following dependencies among headers of Boost.MultiIndex hold:
<li><a href="key_extraction.html#member_synopsis">
<code>"boost/multi_index/member.hpp"</code></a>,</li>
<li><a href="key_extraction.html#mem_fun_synopsis">
<code>"boost/multi_index/mem_fun.hpp"</code></a> and</li>
<code>"boost/multi_index/mem_fun.hpp"</code></a>,</li>
<li><a href="key_extraction.html#global_fun_synopsis">
<code>"boost/multi_index/global_fun.hpp"</code></a> and</li>
<li><a href="key_extraction.html#composite_key_synopsis">
<code>"boost/multi_index/composite_key.hpp"</code></a>.</li>
</ul>
@@ -101,8 +115,8 @@ object modules.
<hr>
<div class="prev_link"><a href="../advanced_topics.html"><img src="../prev.gif" alt="advanced topics" border="0"><br>
Advanced topics
<div class="prev_link"><a href="../tutorial/techniques.html"><img src="../prev.gif" alt="techniques" border="0"><br>
Tecnhiques
</a></div>
<div class="up_link"><a href="../index.html"><img src="../up.gif" alt="index" border="0"><br>
Index
@@ -113,9 +127,9 @@ Index
<br>
<p>Revised May 30th 2005</p>
<p>Revised June 19th 2007</p>
<p>&copy; Copyright 2003-2005 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
<p>&copy; Copyright 2003-2007 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
+69 -8
View File
@@ -5,6 +5,10 @@
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Boost.MultiIndex Documentation - Index reference</title>
<link rel="stylesheet" href="../style.css" type="text/css">
<link rel="start" href="../index.html">
<link rel="prev" href="multi_index_container.html">
<link rel="up" href="index.html">
<link rel="next" href="ord_indices.html">
</head>
<body>
@@ -48,6 +52,7 @@ Ordered indices
<li><a href="#other_indices">Other types</a></li>
</ul>
</li>
<li><a href="#views">Index views</a></li>
</ul>
<h2><a name="index_concepts">Index concepts</a></h2>
@@ -77,7 +82,7 @@ these operations, however, do have an impact on all other indices as
well: for instance, insertion through a given index may fail because
there exists another index which bans the operation in order to preserve
its invariant (like uniqueness of elements.) This circumstance, rather
than an obstacle, yields much of the power of Boost.MultiIndex:
than being an obstacle, yields much of the power of Boost.MultiIndex:
equivalent constructions based on manual composition of standard
containers would have to add a fair amount of code in order to
globally preserve the invariants of each container while guaranteeing
@@ -113,7 +118,7 @@ by <code>std::list</code>.
These global operations are not directly exposed to the user, but rather
they are wrapped as appropriate by each index (for instance, ordered indices
provide a set-like suite of insertion member functions, whereas sequenced
indices do have <code>push_back</code> and <code>push_front</code>
and random access indices have <code>push_back</code> and <code>push_front</code>
operations.) Boost.MultiIndex poses no particular conditions on
the interface of indices, save that they must model
<a href="http://www.sgi.com/tech/stl/Container.html">
@@ -188,8 +193,10 @@ index specifiers
<li><a href="hash_indices.html#unique_non_unique"><code>hashed_unique</code> and
<code>hashed_non_unique</code></a> for
<a href="hash_indices.html">hashed indices</a>,</li>
<li>and <a href="seq_indices.html#sequenced"><code>sequenced</code></a> for
<a href="seq_indices.html">sequenced indices</a>.</li>
<li><a href="seq_indices.html#sequenced"><code>sequenced</code></a> for
<a href="seq_indices.html">sequenced indices</a></li>
<li>and <a href="rnd_indices.html#random_access"><code>random_access</code></a> for
<a href="rnd_indices.html">random access indices</a>.</li>
</ul>
</p>
@@ -272,7 +279,10 @@ sequence of tags to be assigned to an index in instantiation time.
<blockquote><pre>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>T0</span><span class=special>,...,</span><span class=keyword>typename</span> <span class=identifier>Tn</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>tag</span><span class=special>;</span>
<span class=keyword>struct</span> <span class=identifier>tag</span>
<span class=special>{</span>
<span class=keyword>typedef</span> <b>implementation defined</b> <span class=identifier>type</span><span class=special>;</span>
<span class=special>};</span>
</pre></blockquote>
<p>
@@ -280,6 +290,13 @@ Elements of <code>tag</code> can be any type, though the user is expected
to provide classes with mnemonic names. Duplicate elements are not allowed.
The maximum number of elements of a <code>tag</code> instantiation is
implementation defined.
The nested
<code>type</code> is a model of
<a href="../../../../libs/mpl/doc/refmanual/random-access-sequence.html">
<code>MPL Random Access Sequence</code></a> and
<a href="../../../../libs/mpl/doc/refmanual/extensible-sequence.html">
<code>MPL Extensible Sequence</code></a> containing the types <code>T0</code>, ... ,
<code>Tn</code> in the same order as specified.
</p>
<h2><a name="index_catalog">Indices provided by Boost.MultiIndex</a></h2>
@@ -304,7 +321,51 @@ reference</a>.
<p>
<ul>
<li><a href="seq_indices.html">Sequenced indices</a> allow to arrange
elements as in a bidirectional list. </li>
elements as in a bidirectional list.</li>
<li><a href="rnd_indices.html">Random access indices</a> provide
constant time positional access and free ordering of elements.</li>
</ul>
</p>
<h2><a name="views">Index views</a></h2>
<p>
The following concept is used by the rearrange facilities of non key-based
indices. Given an index <code>i</code> of type <code>Index</code>, a <i>view
of <code>i</code></i> is any range [<code>first</code>,<code>last</code>)
where <code>first</code> and <code>last</code> are objects of a type
<code>Iterator</code> modelling
<a href="http://www.sgi.com/tech/stl/InputIterator.html">
<code>Input Iterator</code></a> such that
<ol>
<li>the associated value type of <code>Iterator</code> is convertible
to <code>const Index::value_type&amp;</code>
</li>
<li>and each of the elements of <code>i</code> appears exactly once in
[<code>first</code>,<code>last</code>).
</li>
</ol>
Note that the view refers to the actual elements of <code>i</code>, not to
copies of them. Additionally, a view is said to be <i>free</i> if its traversal
order is not affected by changes in the traversal order of <code>i</code>.
Examples of free views are:
<ul>
<li>[<code>c.begin()</code>,<code>c.end()</code>), where <code>c</code> is
any container of reference wrappers (from
<a href="../../../../doc/html/ref.html">Boost.Ref</a>) to the elements
of <code>i</code> containing exactly one reference to every element.
</li>
<li>[<code>i'.begin()</code>,<code>i'.end()</code>), where <code>i'</code> is
any index belonging to the same <code>multi_index_container</code>
as <code>i</code>, except <code>i</code> itself.
</li>
<li>
Any range which is a permutation of the ones described above, as for
instance [<code>c.rbegin()</code>,<code>c.rend()</code>), or
ranges obtained from the former with the aid of
<a href="../../../../libs/iterator/doc/permutation_iterator.html">
<code>permutation_iterator</code></a> from Boost.Iterator.
</li>
</ul>
</p>
@@ -322,9 +383,9 @@ Ordered indices
<br>
<p>Revised May 30th 2005</p>
<p>Revised July 21st 2009</p>
<p>&copy; Copyright 2003-2005 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
<p>&copy; Copyright 2003-2009 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
+275 -24
View File
@@ -5,14 +5,18 @@
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Boost.MultiIndex Documentation - Key extraction reference</title>
<link rel="stylesheet" href="../style.css" type="text/css">
<link rel="start" href="../index.html">
<link rel="prev" href="rnd_indices.html">
<link rel="up" href="index.html">
<link rel="next" href="../compiler_specifics.html">
</head>
<body>
<h1><img src="../../../../boost.png" alt="boost.png (6897 bytes)" align=
"middle" width="277" height="86">Boost.MultiIndex Key extraction reference</h1>
<div class="prev_link"><a href="seq_indices.html"><img src="../prev.gif" alt="sequenced indices" border="0"><br>
Sequenced indices
<div class="prev_link"><a href="rnd_indices.html"><img src="../prev.gif" alt="random access indices" border="0"><br>
Random access indices
</a></div>
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.MultiIndex reference" border="0"><br>
Boost.MultiIndex reference
@@ -59,6 +63,12 @@ Compiler specifics
<li><a href="#boost_multi_index_mem_fun">Macro <code>BOOST_MULTI_INDEX_MEM_FUN</code></a></li>
</ul>
</li>
<li><a href="#global_fun_synopsis">Header
<code>"boost/multi_index/global_fun.hpp"</code> synopsis</a>
<ul>
<li><a href="#global_fun">Class template <code>global_fun</code></a></li>
</ul>
</li>
<li><a href="#composite_key_synopsis">Header
<code>"boost/multi_index/composite_key.hpp"</code> synopsis</a>
<ul>
@@ -127,12 +137,13 @@ for every <code>k1</code> of type <code>const KeyFromValue</code> and
</p>
<p>
Boost.MultiIndex provides five general-purpose key extractors:
Boost.MultiIndex provides six general-purpose key extractors:
<ul>
<li><a href="#identity"><code>identity</code></a>,</li>
<li><a href="#member"><code>member</code></a>,</li>
<li><a href="#const_mem_fun"><code>const_mem_fun</code></a>,</li>
<li><a href="#mem_fun"><code>mem_fun</code></a> and</li>
<li><a href="#mem_fun"><code>mem_fun</code></a>,</li>
<li><a href="#global_fun"><code>global_fun</code></a> and</li>
<li><a href="#composite_key"><code>composite_key</code></a>,</li>
</ul>
plus replacements for some of them:
@@ -174,6 +185,7 @@ ultimately dereferencing to values of <code>Type&amp;</code> or
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>identity</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>member</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>mem_fun</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>global_fun</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>composite_key</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
</pre></blockquote>
@@ -211,7 +223,9 @@ that acts as a do-nothing identity functor.
<span class=special>{</span>
<span class=keyword>typedef</span> <span class=identifier>Type</span> <span class=identifier>result_type</span><span class=special>;</span>
<span class=comment>// only provided if const ChainedPtr&amp; is not convertible to const Type&amp;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>ChainedPtr</span><span class=special>&gt;</span> <span class=identifier>Type</span><span class=special>&amp;</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>ChainedPtr</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=keyword>const</span> <span class=identifier>Type</span><span class=special>&amp;</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>Type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>Type</span><span class=special>&amp;</span> <span class=keyword>operator</span><span class=special>()(</span><span class=identifier>Type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span> <span class=comment>// only provided if Type is non-const
@@ -254,13 +268,13 @@ type to <code>Type</code>.<br>
<b>Returns:</b> a reference to the object chained-pointed to by <code>x</code>.
</blockquote>
<code>const Type&amp; operator()(const Type&amp;x)const;</code>
<code>const Type&amp; operator()(const Type&amp; x)const;</code>
<blockquote>
<b>Returns:</b> <code>x</code>.
</blockquote>
<code>Type&amp; operator()(Type &amp;x)const;</code>
<code>Type&amp; operator()(Type&amp; x)const;</code>
<blockquote>
<b>Returns:</b> <code>x</code>.
@@ -318,7 +332,9 @@ aimed at accessing a given member of a class.
<span class=special>{</span>
<span class=keyword>typedef</span> <span class=identifier>Type</span> <span class=identifier>result_type</span><span class=special>;</span>
<span class=comment>// only provided if const ChainedPtr&amp; is not convertible to const Class&amp;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>ChainedPtr</span><span class=special>&gt;</span> <span class=identifier>Type</span><span class=special>&amp;</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>ChainedPtr</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=keyword>const</span> <span class=identifier>Type</span><span class=special>&amp;</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>Class</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>Type</span><span class=special>&amp;</span> <span class=keyword>operator</span><span class=special>()(</span><span class=identifier>Class</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span> <span class=comment>// only provided if Type is non-const</span>
<span class=keyword>const</span> <span class=identifier>Type</span><span class=special>&amp;</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>reference_wrapper</span><span class=special>&lt;</span><span class=keyword>const</span> <span class=identifier>Class</span><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
@@ -356,13 +372,13 @@ type to <code>Type</code>.<br>
<b>Returns:</b> a reference to the object chained-pointed to by <code>x</code>.
</blockquote>
<code>const Type&amp; operator()(const Class&amp;x)const;</code>
<code>const Type&amp; operator()(const Class&amp; x)const;</code>
<blockquote>
<b>Returns:</b> <code>x.*PtrToMember</code>.
</blockquote>
<code>Type&amp; operator()(const Class&amp;x);</code>
<code>Type&amp; operator()(Class&amp; x)const;</code>
<blockquote>
<b>Returns:</b> <code>x.*PtrToMember</code>.
@@ -408,7 +424,9 @@ luckily enough, most compilers accept it nevertheless, so
<span class=special>{</span>
<span class=keyword>typedef</span> <span class=identifier>Type</span> <span class=identifier>result_type</span><span class=special>;</span>
<span class=comment>// only provided if const ChainedPtr&amp; is not convertible to const Class&amp;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>ChainedPtr</span><span class=special>&gt;</span> <span class=identifier>Type</span><span class=special>&amp;</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>ChainedPtr</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=keyword>const</span> <span class=identifier>Type</span><span class=special>&amp;</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>Class</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>Type</span><span class=special>&amp;</span> <span class=keyword>operator</span><span class=special>()(</span><span class=identifier>Class</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span> <span class=comment>// only provided if Type is non-const</span>
<span class=keyword>const</span> <span class=identifier>Type</span><span class=special>&amp;</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>reference_wrapper</span><span class=special>&lt;</span><span class=keyword>const</span> <span class=identifier>Class</span><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
@@ -511,7 +529,9 @@ returning as key the result of invoking a given constant member function of a cl
<span class=special>{</span>
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>remove_reference</span><span class=special>&lt;</span><span class=identifier>Type</span><span class=special>&gt;::</span><span class=identifier>type</span> <span class=identifier>result_type</span><span class=special>;</span>
<span class=comment>// only provided if const ChainedPtr&amp; is not convertible to const Class&amp;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>ChainedPtr</span><span class=special>&gt;</span> <span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>ChainedPtr</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>Class</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>reference_wrapper</span><span class=special>&lt;</span><span class=keyword>const</span> <span class=identifier>Class</span><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>reference_wrapper</span><span class=special>&lt;</span><span class=identifier>Class</span><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
@@ -581,7 +601,9 @@ returning as key the result of invoking a given member function of a class.
<span class=special>{</span>
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>remove_reference</span><span class=special>&lt;</span><span class=identifier>Type</span><span class=special>&gt;::</span><span class=identifier>type</span> <span class=identifier>result_type</span><span class=special>;</span>
<span class=comment>// only provided if ChainedPtr&amp; is not convertible to Class&amp;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>ChainedPtr</span><span class=special>&gt;</span> <span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>ChainedPtr</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=identifier>Class</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>reference_wrapper</span><span class=special>&lt;</span><span class=identifier>Class</span><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=special>};</span>
@@ -642,7 +664,9 @@ these pointers as an additional template parameter.
<span class=special>{</span>
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>remove_reference</span><span class=special>&lt;</span><span class=identifier>Type</span><span class=special>&gt;::</span><span class=identifier>type</span> <span class=identifier>result_type</span><span class=special>;</span>
<span class=comment>// only provided if const ChainedPtr&amp; is not convertible to const Class&amp;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>ChainedPtr</span><span class=special>&gt;</span> <span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>ChainedPtr</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>Class</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>reference_wrapper</span><span class=special>&lt;</span><span class=keyword>const</span> <span class=identifier>Class</span><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>reference_wrapper</span><span class=special>&lt;</span><span class=identifier>Class</span><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
@@ -684,7 +708,9 @@ used for extraction.
<span class=special>{</span>
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>remove_reference</span><span class=special>&lt;</span><span class=identifier>Type</span><span class=special>&gt;::</span><span class=identifier>type</span> <span class=identifier>result_type</span><span class=special>;</span>
<span class=comment>// only provided if ChainedPtr&amp; is not convertible to Class&amp;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>ChainedPtr</span><span class=special>&gt;</span> <span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>ChainedPtr</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=identifier>Class</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>reference_wrapper</span><span class=special>&lt;</span><span class=identifier>Class</span><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=special>};</span>
@@ -751,6 +777,147 @@ but it resolves to
for MSVC++ 6.0 or lower.
</p>
<h2>
<a name="global_fun_synopsis">Header
<a href="../../../../boost/multi_index/global_fun.hpp">
<code>"boost/multi_index/global_fun.hpp"</code></a> synopsis</a></h2>
<blockquote><pre>
<span class=keyword>namespace</span> <span class=identifier>boost</span><span class=special>{</span>
<span class=keyword>namespace</span> <span class=identifier>multi_index</span><span class=special>{</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>class</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Type</span><span class=special>,</span><span class=identifier>Type</span> <span class=special>(*</span><span class=identifier>PtrToFunction</span><span class=special>)(</span><span class=identifier>Value</span><span class=special>)&gt;</span>
<span class=keyword>struct</span> <span class=identifier>global_fun</span><span class=special>;</span>
<span class=special>}</span> <span class=comment>// namespace boost::multi_index</span>
<span class=special>}</span> <span class=comment>// namespace boost</span>
</pre></blockquote>
<h3><a name="global_fun">Class template <code>global_fun</code></a></h3>
<p>
<code>global_fun</code> is a <a href="#key_extractors"><code>Key Extractor</code></a>
based on a given global or static member function accepting the base type as argument
and returning the associated key.
</p>
<blockquote><pre>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>class</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Type</span><span class=special>,</span><span class=identifier>Type</span> <span class=special>(*</span><span class=identifier>PtrToFunction</span><span class=special>)(</span><span class=identifier>Value</span><span class=special>)&gt;</span>
<span class=keyword>struct</span> <span class=identifier>global_fun</span>
<span class=special>{</span>
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>remove_reference</span><span class=special>&lt;</span><span class=identifier>Type</span><span class=special>&gt;::</span><span class=identifier>type</span> <span class=identifier>result_type</span><span class=special>;</span>
<span class=comment>// Only provided under the following circumstances:
// - If Value is a reference to a constant type, only provided
// when const ChainedPtr&amp; is not convertible to Value;
// - if Value is a reference to a non-const type, only provided
// when ChainedPtr&amp; is not convertible to Value;
// - else, only provided when const ChainedPtr&amp; is not
// convertible to const Value&amp;.</span>
<span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>ChainedPtr</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=comment>// only provided if Value is a reference type</span>
<span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=identifier>Value</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=comment>// only provided if Value is not a reference type</span>
<span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>Value</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=comment>// only provided if Value is not a reference type</span>
<span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>reference_wrapper</span><span class=special>&lt;</span><span class=keyword>const</span> <span class=identifier>Value</span><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=comment>// only provided if Value is a reference type</span>
<span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span>
<span class=keyword>const</span> <span class=identifier>reference_wrapper</span><span class=special>&lt;</span>
<span class=identifier>remove_reference</span><span class=special>&lt;</span><span class=identifier>Value</span><span class=special>&gt;::</span><span class=identifier>type</span><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=comment>// only provided if Value is not a reference type or is
// a reference to a constant type</span>
<span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span>
<span class=keyword>const</span> <span class=identifier>reference_wrapper</span><span class=special>&lt;</span>
<span class=keyword>typename</span> <span class=identifier>remove_const</span><span class=special>&lt;</span>
<span class=keyword>typename</span> <span class=identifier>remove_reference</span><span class=special>&lt;</span><span class=identifier>Value</span><span class=special>&gt;::</span><span class=identifier>type</span><span class=special>&gt;::</span><span class=identifier>type</span><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=special>};</span>
</pre></blockquote>
<p>
<code>PtrToFunction</code> specifies the particular function used to extract
the key of type <code>Type</code> from some <code>BaseType</code>.
<code>global_fun</code> supports the following function signatures:
<ul>
<li><code>Type f(BaseType)</code> (<code>Value</code> is <code>BaseType</code>),</li>
<li><code>Type f(const BaseType&amp;)</code> (<code>Value</code> is <code>const BaseType&amp;</code>),</li>
<li><code>Type f(BaseType&amp;)</code> (<code>Value</code> is <code>BaseType&amp;</code>).</li>
</ul>
<code>global_fun&lt;Type,Value,PtrToFunction&gt;</code> is a model of:
<ul>
<li><a href="#key_extractors"><code>Key Extractor</code></a>
from <code>reference_wrapper&lt;BaseType></code>,</li>
<li><a href="#key_extractors"><code>Key Extractor</code></a>
from any <a href="#chained_pointers">chained pointer</a>
to <code>BaseType</code>.</li>
</ul>
When <code>Value</code> is <code>BaseType</code> or
<code>const BaseType&amp;</code>,
<code>global_fun&lt;Type,Value,PtrToFunction&gt;</code> is also a model of:
<ul>
<li><a href="#key_extractors"><code>Key Extractor</code></a>
from <code>BaseType</code>,</li>
<li><a href="#key_extractors"><code>Key Extractor</code></a>
from <code>reference_wrapper&lt;const BaseType></code>,</li>
<li><a href="#key_extractors"><code>Key Extractor</code></a>
from any <a href="#chained_pointers">chained pointer</a>
to <code>const BaseType</code>.</li>
</ul>
</p>
<h4><code>global_fun</code> members</h4>
<code>template&lt;typename ChainedPtr> Type operator()(const ChainedPtr&amp; x)const;</code>
<blockquote>
<b>Requires:</b> <code>ChainedPtr</code> is a <a href="#chained_pointers">chained pointer</a>
type to <code>Value</code>.<br>
<b>Returns:</b> <code>PtrToFunction)(y)</code>, where <code>y</code> is the
object chained-pointed to by <code>x</code>.
</blockquote>
<code>Type operator()(Value x)const;</code>
<blockquote>
<b>Returns:</b> <code>PtrToFunction(x)</code>.
</blockquote>
<code>Type operator()(const Value&amp; x)const;</code>
<blockquote>
<b>Returns:</b> <code>PtrToFunction(x)</code>.
</blockquote>
<code>Type operator()(const reference_wrapper&lt;const Value&gt;&amp; x)const;</code>
<blockquote>
<b>Returns:</b> <code>PtrToFunction(x.get())</code>.
</blockquote>
<code>
Type operator()(<br>
&nbsp;&nbsp;const reference_wrapper&lt;remove_reference&lt;Value&gt;::type&gt;&amp; x)const;</code>
<blockquote>
<b>Returns:</b> <code>PtrToFunction(x.get())</code>.
</blockquote>
<code>Type operator()(<br>
&nbsp;&nbsp;const reference_wrapper&lt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;typename remove_const&lt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename remove_reference&lt;Value&gt;::type&gt;::type&gt;&amp; x)const;</code>
<blockquote>
<b>Returns:</b> <code>PtrToFunction(x.get())</code>.
</blockquote>
<h2>
<a name="composite_key_synopsis">Header
<a href="../../../../boost/multi_index/composite_key.hpp">
@@ -769,7 +936,7 @@ for MSVC++ 6.0 or lower.
<span class=comment>// comparison operators for composite_key_result:</span>
<span class=comment>// <b>OP</b> is any of =,&lt;,!=,&gt;,&gt;=,&lt;=</span>
<span class=comment>// <b>OP</b> is any of ==,&lt;,!=,&gt;,&gt;=,&lt;=</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>CompositeKey1</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>CompositeKey2</span><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=keyword>operator</span> <b><i>OP</i></b><span class=special>(</span>
@@ -868,6 +1035,7 @@ at compile time. The returned object is of type
<span class=keyword>const</span> <span class=identifier>key_extractor_tuple</span><span class=special>&amp;</span> <span class=identifier>key_extractors</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>key_extractor_tuple</span><span class=special>&amp;</span> <span class=identifier>key_extractors</span><span class=special>()</span>
<span class=comment>// only provided if const ChainedPtr&amp; is not convertible to const value_type&amp;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>ChainedPtr</span><span class=special>&gt;</span>
<span class=identifier>result_type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>ChainedPtr</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
@@ -986,7 +1154,7 @@ instantiations as their extracted key.
<span class=comment>// comparison:</span>
<span class=comment>// <b>OP</b> is any of =,&lt;,!=,&gt;,&gt;=,&lt;=</span>
<span class=comment>// <b>OP</b> is any of ==,&lt;,!=,&gt;,&gt;=,&lt;=</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>CompositeKey1</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>CompositeKey2</span><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=keyword>operator</span> <b><i>OP</i></b><span class=special>(</span>
@@ -1013,8 +1181,8 @@ as <i>temporary</i>, i.e. they should not be stored or copied.
<code>Default Constructible</code></a> or
<a href="http://www.sgi.com/tech/stl/Assignable.html"><code>Assignable</code></a>.
Every object of type <code>composite_key_result&lt;CompositeKey></code> is
internally asociated to the <code>CompositeKey</code> from which it is returned
and the object of type <code>CompositeKey::result_type</code> to which the
internally associated to the <code>CompositeKey</code> from which it is returned
and the object of type <code>CompositeKey::value_type</code> to which the
composite key was applied.
</p>
@@ -1060,7 +1228,7 @@ bool operator==(<br>
<blockquote>
<b>Requires:</b> <code>length(x)==length(y)</code>. The expression
<code>x<sub>i</sub>==y<sub>i</sub></code> is valid for all <code>i</code>
in <code>[0,length(x))</code>.</br>
in <code>[0,length(x))</code>.<br>
<b>Returns:</b> <code>true</code> if and only if
<blockquote>
<code>x<sub>i</sub>==y<sub>i</sub></code> for all <code>i</code>
@@ -1090,7 +1258,7 @@ bool operator<(<br>
<b>Requires:</b> The expressions
<code>x<sub>i</sub>&lt;y<sub>i</sub></code> and
<code>y<sub>i</sub>&lt;x<sub>i</sub></code> are valid for all <code>i</code>
in <code>[0,min(length(x),length(y)))</code>.</br>
in <code>[0,min(length(x),length(y)))</code>.<br>
<b>Returns:</b> <code>true</code> if and only if there exists some
<code>j</code> in the range <code>[0,min(length(x),length(y)))</code>
such that
@@ -1126,7 +1294,7 @@ bool operator <b><i>OP</i></b>(<br>
<blockquote>
<b>Requires:</b> The expressions given below are valid (for the particular
<code><b><i>OP</i></b></code> considered.)</br>
<code><b><i>OP</i></b></code> considered.)<br>
<b>Returns:</b> <code>true</code> if and only if
<blockquote>
<code>!(x==y)</code> (<code><b><i>OP</i></b></code> is <code>!=</code>),<br>
@@ -1267,7 +1435,7 @@ bool operator()(<br>
<b>Requires:</b> <code>length(x)==length(y)</code>. The expressions
<code>key_eqs().get&lt;i>()(x<sub>i</sub>,y<sub>i</sub>)</code> and
<code>key_eqs().get&lt;i>()(y<sub>i</sub>,x<sub>i</sub>)</code>
are valid for all <code>i</code> in <code>[0,length(x))</code>.</br>
are valid for all <code>i</code> in <code>[0,length(x))</code>.<br>
<b>Returns:</b> <code>true</code> if and only
<blockquote>
<code>key_eqs().get&lt;i>()(x<sub>i</sub>,y<sub>i</sub>)</code>
@@ -1417,6 +1585,14 @@ collection of elementary comparison predicates.
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>()(</span>
<span class=keyword>const</span> <span class=identifier>tuple</span><span class=special>&lt;</span><span class=identifier>Value0</span><span class=special>,...,</span><span class=identifier>Valuen</span><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>,</span>
<span class=keyword>const</span> <span class=identifier>composite_key_result</span><span class=special>&lt;</span><span class=identifier>CompositeKey</span><span class=special>&gt;&amp;</span> <span class=identifier>y</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>CompositeKey</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>()(</span>
<span class=keyword>const</span> <span class=identifier>composite_key_result</span><span class=special>&lt;</span><span class=identifier>CompositeKey</span><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>Value</span><span class=special>&amp;</span> <span class=identifier>y</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>CompositeKey</span><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>()(</span>
<span class=keyword>const</span> <span class=identifier>Value</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>composite_key_result</span><span class=special>&lt;</span><span class=identifier>CompositeKey</span><span class=special>&gt;&amp;</span> <span class=identifier>y</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=special>};</span>
</pre></blockquote>
@@ -1507,7 +1683,7 @@ bool operator()(<br>
<code>key_comps().get&lt;i>()(x<sub>i</sub>,y<sub>i</sub>)</code> and
<code>key_comps().get&lt;i>()(y<sub>i</sub>,x<sub>i</sub>)</code>
are valid for all <code>i</code>
in <code>[0,min(length(x),length(y)))</code>.</br>
in <code>[0,min(length(x),length(y)))</code>.<br>
<b>Returns:</b> <code>true</code> if and only if there exists some
<code>j</code> in the range <code>[0,min(length(x),length(y)))</code>
such that
@@ -1522,6 +1698,32 @@ starting at <code>i==0</code>. The evaluation is short-circuited as soon as
the result is determined to be <code>false</code>.
</blockquote>
<code>
template&lt;typename CompositeKey,typename Value&gt;<br>
bool operator()(<br>
&nbsp;&nbsp;const composite_key_result&lt;CompositeKey&gt;&amp; x,const Value&amp; y)const;
</code>
<blockquote>
<b>Effects:</b>
<blockquote><pre>
<span class=keyword>return</span> <span class=keyword>operator</span><span class=special>()(</span><span class=identifier>x</span><span class=special>,</span><span class=identifier>make_tuple</span><span class=special>(</span><span class=identifier>cref</span><span class=special>(</span><span class=identifier>y</span><span class=special>)));</span>
</pre></blockquote><br>
</blockquote>
<code>
template&lt;typename Value,typename CompositeKey&gt;<br>
bool operator()(<br>
&nbsp;&nbsp;const Value&amp; x,const composite_key_result&lt;CompositeKey&gt;&amp; y)const;
</code>
<blockquote>
<b>Effects:</b>
<blockquote><pre>
<span class=keyword>return</span> <span class=keyword>operator</span><span class=special>()(</span><span class=identifier>make_tuple</span><span class=special>(</span><span class=identifier>cref</span><span class=special>(</span><span class=identifier>x</span><span class=special>)),</span><span class=identifier>y</span><span class=special>);</span>
</pre></blockquote><br>
</blockquote>
<h4><a name="composite_key_result_less">Class template
<code>composite_key_result_less</code></a></h4>
@@ -1553,6 +1755,14 @@ are instantiations of <code>std::less</code>.
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>()(</span>
<span class=keyword>const</span> <span class=identifier>tuple</span><span class=special>&lt;</span><span class=identifier>Value0</span><span class=special>,...,</span><span class=identifier>Valuen</span><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>,</span>
<span class=keyword>const</span> <span class=identifier>composite_key_result</span><span class=special>&lt;</span><span class=identifier>CompositeKey</span><span class=special>&gt;&amp;</span> <span class=identifier>y</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>CompositeKey</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>()(</span>
<span class=keyword>const</span> <span class=identifier>composite_key_result</span><span class=special>&lt;</span><span class=identifier>CompositeKey</span><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>Value</span><span class=special>&amp;</span> <span class=identifier>y</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>CompositeKey</span><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>()(</span>
<span class=keyword>const</span> <span class=identifier>Value</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>composite_key_result</span><span class=special>&lt;</span><span class=identifier>CompositeKey</span><span class=special>&gt;&amp;</span> <span class=identifier>y</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=special>};</span>
</pre></blockquote>
@@ -1610,6 +1820,14 @@ are instantiations of <code>std::greater</code>.
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>()(</span>
<span class=keyword>const</span> <span class=identifier>tuple</span><span class=special>&lt;</span><span class=identifier>Value0</span><span class=special>,...,</span><span class=identifier>Valuen</span><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>,</span>
<span class=keyword>const</span> <span class=identifier>composite_key_result</span><span class=special>&lt;</span><span class=identifier>CompositeKey</span><span class=special>&gt;&amp;</span> <span class=identifier>y</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>CompositeKey</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>()(</span>
<span class=keyword>const</span> <span class=identifier>composite_key_result</span><span class=special>&lt;</span><span class=identifier>CompositeKey</span><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>Value</span><span class=special>&amp;</span> <span class=identifier>y</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>CompositeKey</span><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>()(</span>
<span class=keyword>const</span> <span class=identifier>Value</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>composite_key_result</span><span class=special>&lt;</span><span class=identifier>CompositeKey</span><span class=special>&gt;&amp;</span> <span class=identifier>y</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=special>};</span>
</pre></blockquote>
@@ -1671,6 +1889,16 @@ and functionality as <code>composite_key_result_less&lt;CompositeKeyResult></cod
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>()(</span>
<span class=keyword>const</span> <span class=identifier>boost</span><span class=special>::</span><span class=identifier>tuple</span><span class=special>&lt;</span><span class=identifier>Value0</span><span class=special>,...,</span><span class=identifier>Valuen</span><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>,</span>
<span class=keyword>const</span> <span class=identifier>boost</span><span class=special>::</span><span class=identifier>multi_index</span><span class=special>::</span><span class=identifier>composite_key_result</span><span class=special>&lt;</span><span class=identifier>CompositeKey</span><span class=special>&gt;&amp;</span> <span class=identifier>y</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>CompositeKey</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>()(</span>
<span class=keyword>const</span> <span class=identifier>boost</span><span class=special>::</span><span class=identifier>multi_index</span><span class=special>::</span><span class=identifier>composite_key_result</span><span class=special>&lt;</span><span class=identifier>CompositeKey</span><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>,</span>
<span class=keyword>const</span> <span class=identifier>Value</span><span class=special>&amp;</span> <span class=identifier>y</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>CompositeKey</span><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>()(</span>
<span class=keyword>const</span> <span class=identifier>Value</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>,</span>
<span class=keyword>const</span> <span class=identifier>boost</span><span class=special>::</span><span class=identifier>multi_index</span><span class=special>::</span><span class=identifier>composite_key_result</span><span class=special>&lt;</span><span class=identifier>CompositeKey</span><span class=special>&gt;&amp;</span> <span class=identifier>y</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=special>};</span>
<span class=special>}</span> <span class=comment>// namespace std</span>
@@ -1711,6 +1939,16 @@ and functionality as <code>composite_key_result_greater&lt;CompositeKeyResult></
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>()(</span>
<span class=keyword>const</span> <span class=identifier>boost</span><span class=special>::</span><span class=identifier>tuple</span><span class=special>&lt;</span><span class=identifier>Value0</span><span class=special>,...,</span><span class=identifier>Valuen</span><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>,</span>
<span class=keyword>const</span> <span class=identifier>boost</span><span class=special>::</span><span class=identifier>multi_index</span><span class=special>::</span><span class=identifier>composite_key_result</span><span class=special>&lt;</span><span class=identifier>CompositeKey</span><span class=special>&gt;&amp;</span> <span class=identifier>y</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>CompositeKey</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>()(</span>
<span class=keyword>const</span> <span class=identifier>boost</span><span class=special>::</span><span class=identifier>multi_index</span><span class=special>::</span><span class=identifier>composite_key_result</span><span class=special>&lt;</span><span class=identifier>CompositeKey</span><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>,</span>
<span class=keyword>const</span> <span class=identifier>Value</span><span class=special>&amp;</span> <span class=identifier>y</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>CompositeKey</span><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>()(</span>
<span class=keyword>const</span> <span class=identifier>Value</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>,</span>
<span class=keyword>const</span> <span class=identifier>boost</span><span class=special>::</span><span class=identifier>multi_index</span><span class=special>::</span><span class=identifier>composite_key_result</span><span class=special>&lt;</span><span class=identifier>CompositeKey</span><span class=special>&gt;&amp;</span> <span class=identifier>y</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=special>};</span>
<span class=special>}</span> <span class=comment>// namespace std</span>
@@ -1983,9 +2221,22 @@ is lexicographical. Also, the following types are
<code>composite_key_result&lt;composite_key&lt;K0,...,Kk> ></code>, with
<code>Ki::result_type = Qi</code> for all <code>i = 0,...,k</code>.
</blockquote>
provided that each <code>Qi</code> is either <code>Ti</code> or a
<a href="ord_indices.html#set_operations"><code>Compatible Key</code></a>
of <code>Comparei</code>. In this case, the comparison is done
provided that
<ul>
<li>for <code>i = 0,...,min(j,k)-1</code>, <code>Qi</code> is either <code>Ti</code>
or <i>not coarser</i> than <code>Ti</code> (<code>Qi</code> is a
<a href="ord_indices.html#set_operations"><code>Compatible Key</code></a>
of <code>Comparei</code> and there are no two distinct elements of
<code>Ti</code> equivalent to one single element of <code>Qi</code>);
</li>
<li>
<code>Qm</code> (with <code>m = min(j,k)</code>) is either <code>Tm</code> or a
<a href="ord_indices.html#set_operations"><code>Compatible Key</code></a>
of <code>Comparem</code>.
</li>
</ul>
In this case, the comparison is done
lexicographically only on the first <code>1+min(j,k)</code> elements.
</p>
@@ -2000,8 +2251,8 @@ subsets of those associated to <code>!(x&lt;y)&amp;&amp;!(y&lt;x)</code>.
<hr>
<div class="prev_link"><a href="seq_indices.html"><img src="../prev.gif" alt="sequenced indices" border="0"><br>
Sequenced indices
<div class="prev_link"><a href="rnd_indices.html"><img src="../prev.gif" alt="random access indices" border="0"><br>
Random access indices
</a></div>
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.MultiIndex reference" border="0"><br>
Boost.MultiIndex reference
@@ -2012,9 +2263,9 @@ Compiler specifics
<br>
<p>Revised May 30th 2005</p>
<p>Revised June 25th 2008</p>
<p>&copy; Copyright 2003-2005 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
<p>&copy; Copyright 2003-2008 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
+121 -69
View File
@@ -5,6 +5,10 @@
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Boost.MultiIndex Documentation - multi_index_container reference</title>
<link rel="stylesheet" href="../style.css" type="text/css">
<link rel="start" href="../index.html">
<link rel="prev" href="index.html">
<link rel="up" href="index.html">
<link rel="next" href="indices.html">
</head>
<body>
@@ -95,10 +99,15 @@ synopsis</a>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>&gt;</span> <span class=keyword>struct</span> <span class=identifier>nth_index</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>&gt;</span> <span class=keyword>struct</span> <span class=identifier>index</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>&gt;</span> <span class=keyword>struct</span> <span class=identifier>nth_index_iterator</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>&gt;</span> <span class=keyword>struct</span> <span class=identifier>nth_index_const_iterator</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>&gt;</span> <span class=keyword>struct</span> <span class=identifier>index_iterator</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>&gt;</span> <span class=keyword>struct</span> <span class=identifier>index_const_iterator</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>nth_index_iterator</span><span class=special>;</span> <span class=comment><b>// deprecated</b></span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>nth_index_const_iterator</span><span class=special>;</span> <span class=comment><b>// deprecated</b></span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>index_iterator</span><span class=special>;</span> <span class=comment><b>// deprecated</b></span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>index_const_iterator</span><span class=special>;</span> <span class=comment><b>// deprecated</b></span>
<span class=comment>// multi_index_container global functions for index retrieval:</span>
@@ -140,9 +149,9 @@ synopsis</a>
<span class=keyword>int</span> <span class=identifier>N</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IteratorType</span><span class=special>,</span>
<span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Allocator</span>
<span class=special>&gt;</span>
<span class=keyword>typename</span> <span class=identifier>nth_index_iterator</span><span class=special>&lt;</span>
<span class=keyword>typename</span> <span class=identifier>nth_index</span><span class=special>&lt;</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>&gt;,</span><span class=identifier>N</span>
<span class=special>&gt;::</span><span class=identifier>type</span>
<span class=special>&gt;::</span><span class=identifier>type</span><span class=special>::</span><span class=identifier>iterator</span>
<span class=identifier>project</span><span class=special>(</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>&gt;&amp;</span> <span class=identifier>m</span><span class=special>,</span>
<span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>);</span>
@@ -151,9 +160,9 @@ synopsis</a>
<span class=keyword>int</span> <span class=identifier>N</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IteratorType</span><span class=special>,</span>
<span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Allocator</span>
<span class=special>&gt;</span>
<span class=keyword>typename</span> <span class=identifier>nth_index_const_iterator</span><span class=special>&lt;</span>
<span class=keyword>typename</span> <span class=identifier>nth_index</span><span class=special>&lt;</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>&gt;,</span><span class=identifier>N</span>
<span class=special>&gt;::</span><span class=identifier>type</span>
<span class=special>&gt;::</span><span class=identifier>type</span><span class=special>::</span><span class=identifier>const_iterator</span>
<span class=identifier>project</span><span class=special>(</span>
<span class=keyword>const</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>&gt;&amp;</span> <span class=identifier>m</span><span class=special>,</span>
<span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>);</span>
@@ -162,9 +171,9 @@ synopsis</a>
<span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IteratorType</span><span class=special>,</span>
<span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Allocator</span>
<span class=special>&gt;</span>
<span class=keyword>typename</span> <span class=identifier>index_iterator</span><span class=special>&lt;</span>
<span class=keyword>typename</span> <span class=identifier>index</span><span class=special>&lt;</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>&gt;,</span><span class=identifier>Tag</span>
<span class=special>&gt;::</span><span class=identifier>type</span>
<span class=special>&gt;::</span><span class=identifier>type</span><span class=special>::</span><span class=identifier>iterator</span>
<span class=identifier>project</span><span class=special>(</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>&gt;&amp;</span> <span class=identifier>m</span><span class=special>,</span>
<span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>);</span>
@@ -173,9 +182,9 @@ synopsis</a>
<span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IteratorType</span><span class=special>,</span>
<span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Allocator</span>
<span class=special>&gt;</span>
<span class=keyword>typename</span> <span class=identifier>index_const_iterator</span><span class=special>&lt;</span>
<span class=keyword>typename</span> <span class=identifier>index</span><span class=special>&lt;</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>&gt;,</span><span class=identifier>Tag</span>
<span class=special>&gt;::</span><span class=identifier>type</span>
<span class=special>&gt;::</span><span class=identifier>type</span><span class=special>::</span><span class=identifier>const_iterator</span>
<span class=identifier>project</span><span class=special>(</span>
<span class=keyword>const</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>&gt;&amp;</span> <span class=identifier>m</span><span class=special>,</span>
<span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>);</span>
@@ -261,19 +270,26 @@ operators and functions associated with the index (vg. comparison and
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>index</span> <span class=special>{</span><span class=keyword>typedef</span> <b>implementation defined</b> <span class=identifier>type</span><span class=special>;};</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>nth_index_iterator</span> <span class=special>{</span><span class=keyword>typedef</span> <b>implementation defined</b> <span class=identifier>type</span><span class=special>;};</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>nth_index_const_iterator</span> <span class=special>{</span><span class=keyword>typedef</span> <b>implementation defined</b> <span class=identifier>type</span><span class=special>;};</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>index_iterator</span> <span class=special>{</span><span class=keyword>typedef</span> <b>implementation defined</b> <span class=identifier>type</span><span class=special>;};</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>index_const_iterator</span> <span class=special>{</span><span class=keyword>typedef</span> <b>implementation defined</b> <span class=identifier>type</span><span class=special>;};</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>nth_index_iterator</span> <span class=comment><b>// deprecated</b></span>
<span class=special>{</span><span class=keyword>typedef</span> <b><span class=identifier>implementation</span> <span class=identifier>defined</span></b> <span class=identifier>type</span><span class=special>;};</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>nth_index_const_iterator</span> <span class=comment><b>// deprecated</b></span>
<span class=special>{</span><span class=keyword>typedef</span> <b><span class=identifier>implementation</span> <span class=identifier>defined</span></b> <span class=identifier>type</span><span class=special>;};</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>index_iterator</span> <span class=comment><b>// deprecated</b></span>
<span class=special>{</span><span class=keyword>typedef</span> <b><span class=identifier>implementation</span> <span class=identifier>defined</span></b> <span class=identifier>type</span><span class=special>;};</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>index_const_iterator</span> <span class=comment><b>// deprecated</b></span>
<span class=special>{</span><span class=keyword>typedef</span> <b><span class=identifier>implementation</span> <span class=identifier>defined</span></b> <span class=identifier>type</span><span class=special>;};</span>
<span class=comment>// construct/copy/destroy:</span>
<span class=keyword>explicit</span> <span class=identifier>multi_index_container</span><span class=special>(
</span><span class=keyword>const</span> <span class=identifier>ctor_args_list</span><span class=special>&amp;</span> <span class=identifier>args_list</span><span class=special>=</span><span class=identifier>ctor_args_list</span><span class=special>(),
</span><span class=keyword>const</span> <span class=identifier>allocator_type</span><span class=special>&amp;</span> <span class=identifier>al</span><span class=special>=</span><span class=identifier>allocator_type</span><span class=special>());</span>
<span class=keyword>explicit</span> <span class=identifier>multi_index_container</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>allocator_type</span><span class=special>&amp;</span> <span class=identifier>al</span><span class=special>);</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>InputIterator</span><span class=special>&gt;</span>
<span class=identifier>multi_index_container</span><span class=special>(</span>
<span class=identifier>InputIterator</span> <span class=identifier>first</span><span class=special>,</span><span class=identifier>InputIterator</span> <span class=identifier>last</span><span class=special>,</span>
@@ -299,13 +315,13 @@ operators and functions associated with the index (vg. comparison and
<span class=comment>// projection of iterators</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IteratorType</span><span class=special>&gt;</span>
<span class=keyword>typename</span> <span class=identifier>nth_index_iterator</span><span class=special>&lt;</span><span class=identifier>N</span><span class=special>&gt;::</span><span class=identifier>type</span> <span class=identifier>project</span><span class=special>(</span><span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>);</span>
<span class=keyword>typename</span> <span class=identifier>nth_index</span><span class=special>&lt;</span><span class=identifier>N</span><span class=special>&gt;::</span><span class=identifier>type</span><span class=special>::</span><span class=identifier>iterator</span> <span class=identifier>project</span><span class=special>(</span><span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>);</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IteratorType</span><span class=special>&gt;</span>
<span class=keyword>typename</span> <span class=identifier>nth_index_const_iterator</span><span class=special>&lt;</span><span class=identifier>N</span><span class=special>&gt;::</span><span class=identifier>type</span> <span class=identifier>project</span><span class=special>(</span><span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=keyword>typename</span> <span class=identifier>nth_index</span><span class=special>&lt;</span><span class=identifier>N</span><span class=special>&gt;::</span><span class=identifier>type</span><span class=special>::</span><span class=identifier>const_iterator</span> <span class=identifier>project</span><span class=special>(</span><span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IteratorType</span><span class=special>&gt;</span>
<span class=keyword>typename</span> <span class=identifier>index_iterator</span><span class=special>&lt;</span><span class=identifier>Tag</span><span class=special>&gt;::</span><span class=identifier>type</span> <span class=identifier>project</span><span class=special>(</span><span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>);</span>
<span class=keyword>typename</span> <span class=identifier>index</span><span class=special>&lt;</span><span class=identifier>Tag</span><span class=special>&gt;::</span><span class=identifier>type</span><span class=special>::</span><span class=identifier>iterator</span> <span class=identifier>project</span><span class=special>(</span><span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>);</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IteratorType</span><span class=special>&gt;</span>
<span class=keyword>typename</span> <span class=identifier>index_const_iterator</span><span class=special>&lt;</span><span class=identifier>Tag</span><span class=special>&gt;::</span><span class=identifier>type</span> <span class=identifier>project</span><span class=special>(</span><span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=keyword>typename</span> <span class=identifier>index</span><span class=special>&lt;</span><span class=identifier>Tag</span><span class=special>&gt;::</span><span class=identifier>type</span><span class=special>::</span><span class=identifier>const_iterator</span> <span class=identifier>project</span><span class=special>(</span><span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=special>};</span>
<span class=comment>// multi_index_container associated global class templates:</span>
@@ -320,22 +336,26 @@ operators and functions associated with the index (vg. comparison and
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>::</span><span class=identifier>index</span><span class=special>&lt;</span><span class=identifier>Tag</span><span class=special>&gt;::</span><span class=identifier>type</span> <span class=identifier>type</span><span class=special>;</span>
<span class=special>};</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>&gt;</span> <span class=keyword>struct</span> <span class=identifier>nth_index_iterator</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>nth_index_iterator</span> <span class=comment><b>// deprecated</b></span>
<span class=special>{</span>
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>::</span><span class=identifier>nth_index_iterator</span><span class=special>&lt;</span><span class=identifier>N</span><span class=special>&gt;::</span><span class=identifier>type</span> <span class=identifier>type</span><span class=special>;</span>
<span class=special>};</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>&gt;</span> <span class=keyword>struct</span> <span class=identifier>nth_index_const_iterator</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>int</span> <span class=identifier>N</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>nth_index_const_iterator</span> <span class=comment><b>// deprecated</b></span>
<span class=special>{</span>
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>::</span><span class=identifier>nth_index_const_iterator</span><span class=special>&lt;</span><span class=identifier>N</span><span class=special>&gt;::</span><span class=identifier>type</span> <span class=identifier>type</span><span class=special>;</span>
<span class=special>};</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>&gt;</span> <span class=keyword>struct</span> <span class=identifier>index_iterator</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>index_iterator</span> <span class=comment><b>// deprecated</b></span>
<span class=special>{</span>
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>::</span><span class=identifier>index_iterator</span><span class=special>&lt;</span><span class=identifier>Tag</span><span class=special>&gt;::</span><span class=identifier>type</span> <span class=identifier>type</span><span class=special>;</span>
<span class=special>};</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>&gt;</span> <span class=keyword>struct</span> <span class=identifier>index_const_iterator</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>index_const_iterator</span> <span class=comment><b>// deprecated</b></span>
<span class=special>{</span>
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>MultiIndexContainer</span><span class=special>::</span><span class=identifier>index_const_iterator</span><span class=special>&lt;</span><span class=identifier>Tag</span><span class=special>&gt;::</span><span class=identifier>type</span> <span class=identifier>type</span><span class=special>;</span>
<span class=special>};</span>
@@ -392,56 +412,56 @@ operators and functions associated with the index (vg. comparison and
<span class=keyword>int</span> <span class=identifier>N</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IteratorType</span><span class=special>,</span>
<span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Allocator</span>
<span class=special>&gt;</span>
<span class=keyword>typename</span> <span class=identifier>nth_index_iterator</span><span class=special>&lt;</span>
<span class=keyword>typename</span> <span class=identifier>nth_index</span><span class=special>&lt;</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>&gt;,</span><span class=identifier>N</span>
<span class=special>&gt;::</span><span class=identifier>type</span>
<span class=special>&gt;::</span><span class=identifier>type</span><span class=special>::</span><span class=identifier>iterator</span>
<span class=identifier>project</span><span class=special>(</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>&gt;&amp;</span> <span class=identifier>m</span><span class=special>,</span>
<span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>)</span>
<span class=special>{</span>
<span class=keyword>return</span> <span class=identifier>m</span><span class=special>.</span><span class=identifier>project</span><span class=special>&lt;</span><span class=identifier>N</span><span class=special>&gt;(</span><span class=identifier>it</span><span class=special>);</span>
<span class=keyword>return</span> <span class=identifier>m</span><span class=special>.</span><span class=keyword>template</span> <span class=identifier>project</span><span class=special>&lt;</span><span class=identifier>N</span><span class=special>&gt;(</span><span class=identifier>it</span><span class=special>);</span>
<span class=special>}</span>
<span class=keyword>template</span><span class=special>&lt;</span>
<span class=keyword>int</span> <span class=identifier>N</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IteratorType</span><span class=special>,</span>
<span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Allocator</span>
<span class=special>&gt;</span>
<span class=keyword>typename</span> <span class=identifier>nth_index_const_iterator</span><span class=special>&lt;</span>
<span class=keyword>typename</span> <span class=identifier>nth_index</span><span class=special>&lt;</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>&gt;,</span><span class=identifier>N</span>
<span class=special>&gt;::</span><span class=identifier>type</span>
<span class=special>&gt;::</span><span class=identifier>type</span><span class=special>::</span><span class=identifier>const_iterator</span>
<span class=identifier>project</span><span class=special>(</span>
<span class=keyword>const</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>&gt;&amp;</span> <span class=identifier>m</span><span class=special>,</span>
<span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>)</span>
<span class=special>{</span>
<span class=keyword>return</span> <span class=identifier>m</span><span class=special>.</span><span class=identifier>project</span><span class=special>&lt;</span><span class=identifier>N</span><span class=special>&gt;(</span><span class=identifier>it</span><span class=special>);</span>
<span class=keyword>return</span> <span class=identifier>m</span><span class=special>.</span><span class=keyword>template</span> <span class=identifier>project</span><span class=special>&lt;</span><span class=identifier>N</span><span class=special>&gt;(</span><span class=identifier>it</span><span class=special>);</span>
<span class=special>}</span>
<span class=keyword>template</span><span class=special>&lt;</span>
<span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IteratorType</span><span class=special>,</span>
<span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Allocator</span>
<span class=special>&gt;</span>
<span class=keyword>typename</span> <span class=identifier>index_iterator</span><span class=special>&lt;</span>
<span class=keyword>typename</span> <span class=identifier>index</span><span class=special>&lt;</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>&gt;,</span><span class=identifier>Tag</span>
<span class=special>&gt;::</span><span class=identifier>type</span>
<span class=special>&gt;::</span><span class=identifier>type</span><span class=special>::</span><span class=identifier>iterator</span>
<span class=identifier>project</span><span class=special>(</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>&gt;&amp;</span> <span class=identifier>m</span><span class=special>,</span>
<span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>)</span>
<span class=special>{</span>
<span class=keyword>return</span> <span class=identifier>m</span><span class=special>.</span><span class=identifier>project</span><span class=special>&lt;</span><span class=identifier>Tag</span><span class=special>&gt;(</span><span class=identifier>it</span><span class=special>);</span>
<span class=keyword>return</span> <span class=identifier>m</span><span class=special>.</span><span class=keyword>template</span> <span class=identifier>project</span><span class=special>&lt;</span><span class=identifier>Tag</span><span class=special>&gt;(</span><span class=identifier>it</span><span class=special>);</span>
<span class=special>}</span>
<span class=keyword>template</span><span class=special>&lt;</span>
<span class=keyword>typename</span> <span class=identifier>Tag</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IteratorType</span><span class=special>,</span>
<span class=keyword>typename</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Allocator</span>
<span class=special>&gt;</span>
<span class=keyword>typename</span> <span class=identifier>index_const_iterator</span><span class=special>&lt;</span>
<span class=keyword>typename</span> <span class=identifier>index</span><span class=special>&lt;</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>&gt;,</span><span class=identifier>Tag</span>
<span class=special>&gt;::</span><span class=identifier>type</span>
<span class=special>&gt;::</span><span class=identifier>type</span><span class=special>::</span><span class=identifier>const_iterator</span>
<span class=identifier>project</span><span class=special>(</span>
<span class=keyword>const</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>&gt;&amp;</span> <span class=identifier>m</span><span class=special>,</span>
<span class=identifier>IteratorType</span> <span class=identifier>it</span><span class=special>)</span>
<span class=special>{</span>
<span class=keyword>return</span> <span class=identifier>m</span><span class=special>.</span><span class=identifier>project</span><span class=special>&lt;</span><span class=identifier>Tag</span><span class=special>&gt;(</span><span class=identifier>it</span><span class=special>);</span>
<span class=keyword>return</span> <span class=identifier>m</span><span class=special>.</span><span class=keyword>template</span> <span class=identifier>project</span><span class=special>&lt;</span><span class=identifier>Tag</span><span class=special>&gt;(</span><span class=identifier>it</span><span class=special>);</span>
<span class=special>}</span>
<span class=comment>// comparison:</span>
@@ -489,7 +509,8 @@ scheme outlined in the
<ol>
<li><code>Value</code> is the
<a href="http://www.sgi.com/tech/stl/Assignable.html"><code>Assignable</code></a>
type of the elements contained.</li>
type of the elements contained.
</li>
<li><code>IndexSpecifierList</code> specifies the indices that the
<code>multi_index_container</code> is composed of. It must be a non-empty
<a href="../../../../libs/mpl/doc/refmanual/forward-sequence.html">
@@ -499,8 +520,27 @@ scheme outlined in the
syntactic convenience, the
<a href="indices.html#indexed_by"><code>indexed_by</code></a>
MPL sequence can be used.
<li><code>Allocator</code> must comply with the C++ requirements for
allocators <b>[lib.allocator.requirements]</b>.
</li>
<li><code>Allocator</code> must be an allocator of <code>Value</code> objects
satisfying the associated C++ requirements at <b>[lib.allocator.requirements]</b>.
The following relaxations to the standard requirements are allowed:
<ul>
<li>Non-equal allocator instances are supported: swapping two non-equal
instances must not throw any exception.
</li>
<li>For every type <code>T</code>,
the type <code>Allocator::rebind&lt;T&gt;::other::pointer</code> can be any
kind of
<a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html"><code>Random
Access Iterator</code></a>, provided that it is explicitly constructible from
the literal <code>0</code> (standing here as the null pointer) or from any
<code>p</code> of type <code>T*</code> pointing into an area allocated by
some instance of <code>Allocator</code> or some other allocator type rebound
from <code>Allocator</code>. A <code>pointer</code> constructed from
<code>p</code> shall dereference to <code>*p</code>.
</li>
</ul>
</li>
</ol>
Indices of a given <code>multi_index_container</code> instantiation cannot have
duplicate <a href="indices.html#tags">tags</a>, either within a single
@@ -585,7 +625,7 @@ the same order as they were specified.<br>
<blockquote>
<code>index&lt;Tag>::type</code> yields the type of the index which
has <code>Tag</code> as an associated <a href="indices.html#tags">tag type</a>.</br>
has <code>Tag</code> as an associated <a href="indices.html#tags">tag type</a>.<br>
<b>Requires:</b> Some index of the <code>multi_index_container</code> has <code>Tag</code>
as an associated tag type.
</blockquote>
@@ -595,6 +635,7 @@ as an associated tag type.
<blockquote>
<code>nth_index_iterator&lt;N>::type</code> is equivalent to
<code>nth_index&lt;N>::type::iterator</code>.<br>
<b>Note:</b> The use of <code>nth_index_iterator</code> is deprecated.
</blockquote>
<code>template&lt;int N> struct nth_index_const_iterator</code>
@@ -602,6 +643,7 @@ as an associated tag type.
<blockquote>
<code>nth_index_const_iterator&lt;N>::type</code> is equivalent to
<code>nth_index&lt;N>::type::const_iterator</code>.<br>
<b>Note:</b> The use of <code>nth_index_const_iterator</code> is deprecated.
</blockquote>
<code>template&lt;typename Tag> struct index_iterator</code>
@@ -609,6 +651,7 @@ as an associated tag type.
<blockquote>
<code>index_iterator&lt;Tag>::type</code> is equivalent to
<code>index&lt;Tag>::type::iterator</code>.<br>
<b>Note:</b> The use of <code>index_iterator</code> is deprecated.
</blockquote>
<code>template&lt;typename Tag> struct index_const_iterator</code>
@@ -616,12 +659,13 @@ as an associated tag type.
<blockquote>
<code>index_const_iterator&lt;Tag>::type</code> is equivalent to
<code>index&lt;Tag>::type::const_iterator</code>.<br>
<b>Note:</b> The use of <code>index_const_iterator</code> is deprecated.
</blockquote>
<h4><a name="constructors">Constructors, copy and assignment</a></h4>
<code>explicit multi_index_container(<br>
&nbsp;&nbsp;const ctor_args_list&amp; comp=ctor_args_list(),<br>
&nbsp;&nbsp;const ctor_args_list&amp; args_list=ctor_args_list(),<br>
&nbsp;&nbsp;const allocator_type&amp; al=allocator_type());</code>
<blockquote>
@@ -630,6 +674,14 @@ specified argument list and allocator.<br>
<b>Complexity:</b> Constant.
</blockquote>
<code>explicit multi_index_container(const allocator_type&amp; al);</code>
<blockquote>
<b>Effects:</b> Constructs an empty <code>multi_index_container</code> using the
specified allocator and the default value of <code>ctor_args_list</code>.<br>
<b>Complexity:</b> Constant.
</blockquote>
<code>template&lt;typename InputIterator><br>
multi_index_container(<br>
&nbsp;&nbsp;InputIterator first,InputIterator last,<br>
@@ -641,7 +693,7 @@ multi_index_container(<br>
<a href="http://www.sgi.com/tech/stl/InputIterator.html">
<code>Input Iterator</code></a> over elements of type
<code>Value</code> or a type convertible to <code>Value</code>.
<code>last</code> is reachable from <code>first</code>.</br>
<code>last</code> is reachable from <code>first</code>.<br>
<b>Effects:</b> Constructs and empty <code>multi_index_container</code> using the
specified argument list and allocator and fills it with
the elements in the range [<code>first</code>,<code>last</code>).
@@ -754,21 +806,21 @@ are <i>equivalent</i> if:
</p>
<code>template&lt;int N,typename IteratorType><br>
typename nth_index_iterator&lt;N>::type project(IteratorType it);</code>
typename nth_index&lt;N>::type::iterator project(IteratorType it);</code>
<blockquote>
<b>Requires:</b> <code>0 &lt;= N &lt; I</code>. <code>IteratorType</code>
belongs to <code>iterator_type_list</code>. <code>it</code> is a valid
iterator of some index of <code>*this</code> (i.e. does not refer to some
other <code>multi_index_container</code>.)<br>
<b>Effects:</b> Returns an <code>nth_index_iterator&lt;N>::type</code> iterator
<b>Effects:</b> Returns an <code>nth_index&lt;N>::type::iterator</code>
equivalent to <code>it</code>.<br>
<b>Complexity:</b> Constant.<br>
<b>Exception safety:</b> <code>nothrow</code>.
</blockquote>
<code>template&lt;int N,typename IteratorType><br>
typename nth_index_const_iterator&lt;N>::type project(IteratorType it)const;</code>
typename nth_index&lt;N>::type::const_iterator project(IteratorType it)const;</code>
<blockquote>
<b>Requires:</b> <code>0 &lt;= N &lt; I</code>. <code>IteratorType</code>
@@ -776,38 +828,38 @@ belongs to <code>const_iterator_type_list</code> or
<code>iterator_type_list</code>. <code>it</code> is a
valid (constant or non-constant) iterator of some index of <code>*this</code>
(i.e. does not refer to some other <code>multi_index_container</code>.)<br>
<b>Effects:</b> Returns an <code>nth_index_const_iterator&lt;N>::type</code>
iterator equivalent to <code>it</code>.<br>
<b>Complexity:</b> Constant.<br>
<b>Exception safety:</b> <code>nothrow</code>.
</blockquote>
<code>template&lt;typename Tag,typename IteratorType><br>
typename index_iterator&lt;Tag>::type project(IteratorType it);</code>
<blockquote>
<b>Requires:</b> <code>Tag</code> is such that
<code>index_iterator&lt;Tag>::type</code> is valid. <code>IteratorType</code>
belongs to <code>iterator_type_list</code>. <code>it</code> is a valid
iterator of some index of <code>*this</code> (i.e. does not refer to some
other <code>multi_index_container</code>.)<br>
<b>Effects:</b> Returns an <code>index_iterator&lt;Tag>::type</code> iterator
<b>Effects:</b> Returns an <code>nth_index&lt;N>::type::const_iterator</code>
equivalent to <code>it</code>.<br>
<b>Complexity:</b> Constant.<br>
<b>Exception safety:</b> <code>nothrow</code>.
</blockquote>
<code>template&lt;typename Tag,typename IteratorType><br>
typename index_const_iterator&lt;Tag>::type project(IteratorType it)const;</code>
typename index&lt;Tag>::type::iterator project(IteratorType it);</code>
<blockquote>
<b>Requires:</b> <code>Tag</code> is such that
<code>index_const_iterator&lt;Tag>::type</code> is valid. <code>IteratorType</code>
<code>index&lt;Tag>::type</code> is valid. <code>IteratorType</code>
belongs to <code>iterator_type_list</code>. <code>it</code> is a valid
iterator of some index of <code>*this</code> (i.e. does not refer to some
other <code>multi_index_container</code>.)<br>
<b>Effects:</b> Returns an <code>index&lt;Tag>::type::iterator</code>
equivalent to <code>it</code>.<br>
<b>Complexity:</b> Constant.<br>
<b>Exception safety:</b> <code>nothrow</code>.
</blockquote>
<code>template&lt;typename Tag,typename IteratorType><br>
typename index&lt;Tag>::type::const_iterator project(IteratorType it)const;</code>
<blockquote>
<b>Requires:</b> <code>Tag</code> is such that
<code>index&lt;Tag>::type</code> is valid. <code>IteratorType</code>
belongs to <code>const_iterator_type_list</code> or
<code>iterator_type_list</code>. <code>it</code> is a valid
(constant or non-constant) iterator of some index of <code>*this</code>
(i.e. does not refer to some other <code>multi_index_container</code>.)<br>
<b>Effects:</b> Returns an <code>index_const_iterator&lt;Tag>::type</code>
<b>Effects:</b> Returns an <code>index&lt;Tag>::type::const_iterator</code>
iterator equivalent to <code>it</code>.<br>
<b>Complexity:</b> Constant.<br>
<b>Exception safety:</b> <code>nothrow</code>.
@@ -878,9 +930,9 @@ Index reference
<br>
<p>Revised May 30th 2005</p>
<p>Revised November 6th 2008</p>
<p>&copy; Copyright 2003-2005 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
<p>&copy; Copyright 2003-2008 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
+130 -52
View File
@@ -5,6 +5,10 @@
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Boost.MultiIndex Documentation - Ordered indices reference</title>
<link rel="stylesheet" href="../style.css" type="text/css">
<link rel="start" href="../index.html">
<link rel="prev" href="indices.html">
<link rel="up" href="index.html">
<link rel="next" href="hash_indices.html">
</head>
<body>
@@ -39,6 +43,7 @@ Hashed indices
<li><a href="#complexity_signature">Complexity signature</a></li>
<li><a href="#instantiation_types">Instantiation types</a></li>
<li><a href="#constructors">Constructors, copy and assignment</a></li>
<li><a href="#iterators">Iterators</a></li>
<li><a href="#modifiers">Modifiers</a></li>
<li><a href="#observers">Observers</a></li>
<li><a href="#set_operations">Set operations</a></li>
@@ -159,7 +164,7 @@ two different forms, according to whether a tag list for the index is provided o
<p>
If provided, <code>TagList</code> must be an instantiation of the class template
<a href="#tag"><code>tag</code></a>.
<a href="indices.html#tag"><code>tag</code></a>.
The template arguments are used by the corresponding index implementation,
refer to the <a href="#ord_indices">ordered indices</a> reference section for further
explanations on their acceptable type values.
@@ -201,7 +206,7 @@ requirements for these types of containers.
<span class=keyword>namespace</span> <span class=identifier>multi_index</span><span class=special>{</span>
<span class=keyword>namespace</span><span class=special>{</span> <b>implementation defined </b><span class=identifier>unbounded</span><span class=special>;</span> <span class=special>}</span> <span class=comment>// see range()</span>
<b>implementation defined </b><span class=identifier>unbounded</span><span class=special>;</span> <span class=comment>// see range()</span>
<span class=keyword>namespace</span> <span class=identifier>detail</span><span class=special>{</span>
@@ -218,6 +223,7 @@ requirements for these types of containers.
<span class=keyword>typedef</span> <span class=identifier>Compare</span> <span class=identifier>key_compare</span><span class=special>;</span>
<span class=keyword>typedef</span> <b>implementation defined </b><span class=identifier>value_compare</span><span class=special>;</span>
<span class=keyword>typedef</span> <span class=identifier>tuple</span><span class=special>&lt;</span><span class=identifier>key_from_value</span><span class=special>,</span><span class=identifier>key_compare</span><span class=special>&gt;</span> <span class=identifier>ctor_args</span><span class=special>;</span>
<span class=keyword>typedef</span> <span class=identifier>TagList</span> <span class=identifier>tag_list</span><span class=special>;</span>
<span class=keyword>typedef</span> <span class=identifier>Allocator</span> <span class=identifier>allocator_type</span><span class=special>;</span>
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>Allocator</span><span class=special>::</span><span class=identifier>reference</span> <span class=identifier>reference</span><span class=special>;</span>
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>Allocator</span><span class=special>::</span><span class=identifier>const_reference</span> <span class=identifier>const_reference</span><span class=special>;</span>
@@ -248,7 +254,14 @@ requirements for these types of containers.
<span class=identifier>const_reverse_iterator</span> <span class=identifier>rbegin</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>reverse_iterator</span> <span class=identifier>rend</span><span class=special>();</span>
<span class=identifier>const_reverse_iterator</span> <span class=identifier>rend</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>const_iterator</span> <span class=identifier>cbegin</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>const_iterator</span> <span class=identifier>cend</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>const_reverse_iterator</span> <span class=identifier>crbegin</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>const_reverse_iterator</span> <span class=identifier>crend</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>iterator</span> <span class=identifier>iterator_to</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=identifier>const_iterator</span> <span class=identifier>iterator_to</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=comment>// capacity:</span>
<span class=keyword>bool</span> <span class=identifier>empty</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
@@ -262,13 +275,17 @@ requirements for these types of containers.
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>InputIterator</span><span class=special>&gt;</span>
<span class=keyword>void</span> <span class=identifier>insert</span><span class=special>(</span><span class=identifier>InputIterator</span> <span class=identifier>first</span><span class=special>,</span><span class=identifier>InputIterator</span> <span class=identifier>last</span><span class=special>);</span>
<span class=keyword>void</span> <span class=identifier>erase</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>);</span>
<span class=identifier>iterator</span> <span class=identifier>erase</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>);</span>
<span class=identifier>size_type</span> <span class=identifier>erase</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>key_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=keyword>void</span> <span class=identifier>erase</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>first</span><span class=special>,</span><span class=identifier>iterator</span> <span class=identifier>last</span><span class=special>);</span>
<span class=identifier>iterator</span> <span class=identifier>erase</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>first</span><span class=special>,</span><span class=identifier>iterator</span> <span class=identifier>last</span><span class=special>);</span>
<span class=keyword>bool</span> <span class=identifier>replace</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>&gt;</span> <span class=keyword>bool</span> <span class=identifier>modify</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>);</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Rollback</span><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=identifier>modify</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>,</span><span class=identifier>Rollback</span> <span class=identifier>back</span><span class=special>);</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>&gt;</span> <span class=keyword>bool</span> <span class=identifier>modify_key</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>);</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Rollback</span><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=identifier>modify_key</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>,</span><span class=identifier>Rollback</span> <span class=identifier>back</span><span class=special>);</span>
<span class=keyword>void</span> <span class=identifier>swap</span><span class=special>(</span><b>index class name</b><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=keyword>void</span> <span class=identifier>clear</span><span class=special>();</span>
@@ -391,8 +408,8 @@ section</a>. The complexity signature of ordered indices is:
<li>copying: <code>c(n)=n*log(n)</code>,</li>
<li>insertion: <code>i(n)=log(n)</code>,</li>
<li>hinted insertion: <code>h(n)=1</code> (constant) if the hint element
precedes the point of insertion, <code>h(n)=log(n)</code> otherwise,</li>
<li>deletion: <code>d(n)=1</code> (constant),</li>
is immediately after the point of insertion, <code>h(n)=log(n)</code> otherwise,</li>
<li>deletion: <code>d(n)=1</code> (amortized constant),</li>
<li>replacement: <code>r(n)=1</code> (constant) if the element position does not
change, <code>r(n)=log(n)</code> otherwise,</li>
<li>modifying: <code>m(n)=1</code> (constant) if the element position does not
@@ -410,7 +427,7 @@ following types:
<ul>
<li><code>Value</code> from <code>multi_index_container</code>,</li>
<li><code>Allocator</code> from <code>multi_index_container</code>,</li>
<li><code>TagList</code> from the index specifier (if provided),</li>
<li><code>TagList</code> from the index specifier (if provided, otherwise <code>tag&lt;&gt;</code> is assumed),</li>
<li><code>KeyFromValue</code> from the index specifier,</li>
<li><code>Compare</code> from the index specifier.</li>
</ul>
@@ -444,6 +461,18 @@ objects to which <code>*this</code> and <code>x</code> belong, respectively.<br>
<b>Returns:</b> <code>*this</code>.<br>
</blockquote>
<h4><a name="iterators">Iterators</a></h4>
<code>iterator&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iterator_to(const value_type&amp; x);<br>
const_iterator iterator_to(const value_type&amp; x)const;</code>
<blockquote>
<b>Requires:</b> <code>x</code> is a reference to an element of the container.<br>
<b>Returns:</b> An iterator to <code>x</code>.<br>
<b>Complexity:</b> Constant.<br>
<b>Exception safety:</b> <code>nothrow</code>.<br>
</blockquote>
<h4><a name="modifiers">Modifiers</a></h4>
<code>std::pair&lt;iterator,bool> insert(const value_type&amp; x);</code>
@@ -469,7 +498,7 @@ one element can be causing insertion not to be allowed.<br>
<code>iterator insert(iterator position,const value_type&amp; x);</code>
<blockquote>
<b>Requires:</b> <code>position</code> is a valid iterator of the index.</br>
<b>Requires:</b> <code>position</code> is a valid iterator of the index.<br>
<b>Effects:</b> Inserts <code>x</code> into the <code>multi_index_container</code> to which
the index belongs if
<ul>
@@ -479,7 +508,8 @@ the index belongs if
<code>multi_index_container</code>.</li>
</ul>
<code>position</code> is used as a hint to improve the efficiency of the
operation.<br>
operation. If succesful, insertion happens as close as possible to the
location just prior to <code>position</code>.<br>
<b>Returns:</b> 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
@@ -498,7 +528,7 @@ void insert(InputIterator first,InputIterator last);</code>
<code>value_type</code> or a type convertible to <code>value_type</code>.
<code>first</code> and <code>last</code> are not iterators into any
index of the <code>multi_index_container</code> to which this index belongs.
<code>last</code> is reachable from <code>first</code>.</br>
<code>last</code> is reachable from <code>first</code>.<br>
<b>Effects:</b>
<blockquote><pre>
<span class=identifier>iterator</span> <span class=identifier>hint</span><span class=special>=</span><span class=identifier>end</span><span class=special>();</span>
@@ -510,12 +540,15 @@ index of the <code>multi_index_container</code> to which this index belongs.
<b>Exception safety:</b> Basic.<br>
</blockquote>
<code>void erase(iterator position);</code>
<code>iterator erase(iterator position);</code>
<blockquote>
<b>Requires:</b> <code>position</code> is a valid dereferenceable iterator
of the index.</br>
of the index.<br>
<b>Effects:</b> Deletes the element pointed to by <code>position</code>.<br>
<b>Returns:</b> An iterator pointing to the element immediately following
the one that was deleted, or <code>end()</code>
if no such element exists.<br>
<b>Complexity:</b> <code>O(D(n))</code>.<br>
<b>Exception safety:</b> <code>nothrow</code>.<br>
</blockquote>
@@ -530,12 +563,13 @@ the number of elements deleted.<br>
<b>Exception safety:</b> Basic.<br>
</blockquote>
<code>void erase(iterator first,iterator last);</code>
<code>iterator erase(iterator first,iterator last);</code>
<blockquote>
<b>Requires:</b> [<code>first</code>,<code>last</code>) is a valid
range of the index.<br>
<b>Effects:</b> Deletes the elements in [<code>first</code>,<code>last</code>).<br>
<b>Returns:</b> <code>last</code>.<br>
<b>Complexity:</b> <code>O(log(n) + m*D(n))</code>, where <code>m</code> is
the number of elements in [<code>first</code>,<code>last</code>).<br>
<b>Exception safety:</b> <code>nothrow</code>.<br>
@@ -545,7 +579,7 @@ the number of elements in [<code>first</code>,<code>last</code>).<br>
<blockquote>
<b>Requires:</b> <code>position</code> is a valid dereferenceable iterator
of the index.</br>
of the index.<br>
<b>Effects:</b> Assigns the value <code>x</code> to the element pointed
to by <code>position</code> into the <code>multi_index_container</code> to which
the index belongs if, for the value <code>x</code>
@@ -556,7 +590,8 @@ the index belongs if, for the value <code>x</code>
<code>multi_index_container</code>.</li>
</ul>
<b>Postconditions:</b> Validity of <code>position</code> is preserved
in all cases.<br>
in all cases. If the key of the new value is equivalent to that of the
replaced value, the position of the element does not change.<br>
<b>Returns:</b> <code>true</code> if the replacement took place,
<code>false</code> otherwise.<br>
<b>Complexity:</b> <code>O(R(n))</code>.<br>
@@ -573,7 +608,7 @@ belongs remains in its original state.
<a href="http://www.sgi.com/tech/stl/UnaryFunction.html">
<code>Unary Function</code></a> accepting arguments of type
<code>value_type&amp;</code>. <code>position</code> is a valid dereferenceable
iterator of the index.</br>
iterator of the index.<br>
<b>Effects:</b> Calls <code>mod(e)</code> where <code>e</code> is the element
pointed to by <code>position</code> and rearranges <code>*position</code> into
all the indices of the <code>multi_index_container</code>. Rearrangement is successful if
@@ -585,7 +620,8 @@ all the indices of the <code>multi_index_container</code>. Rearrangement is succ
</ul>
If the rearrangement fails, the element is erased.<br>
<b>Postconditions:</b> Validity of <code>position</code> is preserved if the
operation succeeds.<br>
operation succeeds. If the key of the modified value is equivalent to that of the
original value, the position of the element does not change.<br>
<b>Returns:</b> <code>true</code> if the operation succeeded, <code>false</code>
otherwise.<br>
<b>Complexity:</b> <code>O(M(n))</code>.<br>
@@ -594,6 +630,43 @@ user-provided operation (except possibly <code>mod</code>), then
the element pointed to by <code>position</code> is erased.
</blockquote>
<code>template&lt;typename Modifier,typename Rollback><br>
bool modify(iterator position,Modifier mod,Rollback back);</code>
<blockquote>
<b>Requires:</b> <code>Modifier</code> and <code>Rollback</code> are models of
<a href="http://www.sgi.com/tech/stl/UnaryFunction.html">
<code>Unary Function</code></a> accepting arguments of type
<code>value_type&amp;</code>. <code>position</code> is a valid dereferenceable
iterator of the index. The sequence of operations <code>mod(e)</code>,
<code>back(e)</code>, where <code>e</code> is the element
pointed to by <code>position</code>, restores all keys of the element
to their original state.<br>
<b>Effects:</b> Calls <code>mod(e)</code> where <code>e</code> is the element
pointed to by <code>position</code> and tries to rearrange <code>*position</code> into
all the indices of the <code>multi_index_container</code>. Rearrangement is successful if
<ul>
<li>the index is non-unique OR no other element exists
with equivalent key,</li>
<li>AND rearrangement is allowed by all other indices of the
<code>multi_index_container</code>.</li>
</ul>
If the rearrangement fails, <code>back(e)</code> is invoked and the
element is kept at its original position in all indices.<br>
<b>Postconditions:</b> Validity of <code>position</code> is preserved except if
the element is erased under the conditions described below.
If the key of the modified value is equivalent to that of the
original value, the position of the element does not change.<br>
<b>Returns:</b> <code>true</code> if the operation succeeded, <code>false</code>
otherwise.<br>
<b>Complexity:</b> <code>O(M(n))</code>.<br>
<b>Exception safety:</b> Strong, except if <code>back</code> throws an
exception, in which case the modified element is erased. If <code>back</code>
throws inside the handling code executing after some other user-provided
operation has thrown, it is the exception generated by <code>back</code> that
is rethrown.
</blockquote>
<a name="modify_key">
<code>template&lt;typename Modifier> bool modify_key(iterator position,Modifier mod);</code></a>
@@ -604,27 +677,32 @@ from <code>value_type</code>. <code>Modifier</code> is a model of
<a href="http://www.sgi.com/tech/stl/UnaryFunction.html">
<code>Unary Function</code></a> accepting arguments of type
<code>key_type&amp;</code>. <code>position</code> is a valid dereferenceable
iterator of the index.</br>
<b>Effects:</b> Calls <code>mod(k)</code> where <code>k</code> is the key
obtained by the internal <code>KeyFromValue</code> object of the index from
the element pointed to by <code>position</code>, and rearranges
<code>*position</code> into all the indices of the <code>multi_index_container</code>.
Rearrangement is successful if
<ul>
<li>the index is non-unique OR no other element exists
with equivalent key,</li>
<li>AND rearrangement is allowed by all other indices of the
<code>multi_index_container</code>.</li>
</ul>
If the rearrangement fails, the element is erased.<br>
<b>Postconditions:</b>Validity of <code>position</code> is preserved if
the operation succeeds.<br>
<b>Returns:</b> <code>true</code> if the operation succeeded, <code>false</code>
otherwise.<br>
<b>Complexity:</b> <code>O(M(n))</code>.<br>
<b>Exception safety:</b> Basic. If an exception is thrown by some
user-provided operation (except possibly <code>mod</code>), then
the element pointed to by <code>position</code> is erased.
iterator of the index.<br>
<b>Effects:</b> Equivalent to <code>modify(position,mod')</code>,
with <code>mod'</code> defined in such a way that
<code>mod'(x)</code> is the same as <code>mod(key(x))</code>, where
<code>key</code> is the internal <code>KeyFromValue</code> object of the index.
</blockquote>
<code>template&lt;typename Modifier,typename Rollback><br>
bool modify_key(iterator position,Modifier mod,Rollback back);</code>
<blockquote>
<b>Requires:</b> <code>key_from_value</code> is a read/write
<a href="key_extraction.html#key_extractors"><code>Key Extractor</code></a>
from <code>value_type</code>. <code>Modifier</code> and <code>Rollback</code>
are models of <a href="http://www.sgi.com/tech/stl/UnaryFunction.html">
<code>Unary Function</code></a> accepting arguments of type
<code>key_type&amp;</code>. <code>position</code> is a valid dereferenceable
iterator of the index.
The sequence of operations <code>mod(k)</code>,
<code>back(k)</code>, where <code>k</code> is the key of the element
pointed to by <code>position</code>, restores k to its original state.<br>
<b>Effects:</b> Equivalent to <code>modify(position,mod',back')</code>,
with <code>mod'</code> and <code>back</code> defined in such a way that
<code>mod'(x)</code> is the same as <code>mod(key(x))</code> and
<code>back'(x)</code> is the same as <code>back(key(x))</code>, where
<code>key</code> is the internal <code>KeyFromValue</code> object of the index.
</blockquote>
<h4><a name="observers">Observers</a></h4>
@@ -707,7 +785,7 @@ interpretations.
<blockquote>
<b>Requires:</b> <code>CompatibleKey</code> is a compatible key of
<code>key_compare</code>.</br>
<code>key_compare</code>.<br>
<b>Effects:</b> Returns a pointer to an element whose key is equivalent to
<code>x</code>, or <code>end()</code> if such an element does not exist.<br>
<b>Complexity:</b> <code>O(log(n))</code>.<br>
@@ -719,7 +797,7 @@ iterator find(const CompatibleKey&amp; x,const CompatibleCompare&amp; comp)const
<blockquote>
<b>Requires:</b> (<code>CompatibleKey</code>, <code>CompatibleCompare</code>)
is a compatible extension of <code>key_compare</code>.</br>
is a compatible extension of <code>key_compare</code>.<br>
<b>Effects:</b> Returns a pointer to an element whose key is equivalent to
<code>x</code>, or <code>end()</code> if such an element does not exist.<br>
<b>Complexity:</b> <code>O(log(n))</code>.<br>
@@ -731,7 +809,7 @@ count(const CompatibleKey&amp; x)const;
<blockquote>
<b>Requires:</b> <code>CompatibleKey</code> is a compatible key of
<code>key_compare</code>.</br>
<code>key_compare</code>.<br>
<b>Effects:</b> Returns the number of elements with key equivalent to <code>x</code>.<br>
<b>Complexity:</b> <code>O(log(n) + count(x))</code>.<br>
</blockquote>
@@ -742,7 +820,7 @@ size_type count(const CompatibleKey&amp; x,const CompatibleCompare&amp; comp)con
<blockquote>
<b>Requires:</b> (<code>CompatibleKey</code>, <code>CompatibleCompare</code>)
is a compatible extension of <code>key_compare</code>.</br>
is a compatible extension of <code>key_compare</code>.<br>
<b>Effects:</b> Returns the number of elements with key equivalent to <code>x</code>.<br>
<b>Complexity:</b> <code>O(log(n) + count(x,comp))</code>.<br>
</blockquote>
@@ -753,7 +831,7 @@ iterator lower_bound(const CompatibleKey&amp; x)const;
<blockquote>
<b>Requires:</b> <code>CompatibleKey</code> is a compatible key of
<code>key_compare</code>.</br>
<code>key_compare</code>.<br>
<b>Effects:</b> Returns an iterator pointing to the first element with
key not less than <code>x</code>, or <code>end()</code> if such an element does
not exist.<br>
@@ -766,7 +844,7 @@ iterator lower_bound(const CompatibleKey&amp; x,const CompatibleCompare&amp; com
<blockquote>
<b>Requires:</b> (<code>CompatibleKey</code>, <code>CompatibleCompare</code>)
is a compatible extension of <code>key_compare</code>.</br>
is a compatible extension of <code>key_compare</code>.<br>
<b>Effects:</b> Returns an iterator pointing to the first element with
key not less than <code>x</code>, or <code>end()</code> if such an element does
not exist.<br>
@@ -779,7 +857,7 @@ iterator upper_bound(const CompatibleKey&amp; x)const;
<blockquote>
<b>Requires:</b> <code>CompatibleKey</code> is a compatible key of
<code>key_compare</code>.</br>
<code>key_compare</code>.<br>
<b>Effects:</b> Returns an iterator pointing to the first element with
key greater than <code>x</code>, or <code>end()</code> if such an element does
not exist.<br>
@@ -792,7 +870,7 @@ iterator upper_bound(const CompatibleKey&amp; x,const CompatibleCompare&amp; com
<blockquote>
<b>Requires:</b> (<code>CompatibleKey</code>, <code>CompatibleCompare</code>)
is a compatible extension of <code>key_compare</code>.</br>
is a compatible extension of <code>key_compare</code>.<br>
<b>Effects:</b> Returns an iterator pointing to the first element with
key greater than <code>x</code>, or <code>end()</code> if such an element does
not exist.<br>
@@ -806,19 +884,19 @@ std::pair&lt;iterator,iterator> equal_range(<br>
<blockquote>
<b>Requires:</b> <code>CompatibleKey</code> is a compatible key of
<code>key_compare</code>.</br>
<code>key_compare</code>.<br>
<b>Effects:</b> Equivalent to <code>make_pair(lower_bound(x),upper_bound(x))</code>.<br>
<b>Complexity:</b> <code>O(log(n))</code>.<br>
</blockquote>
<code>template&lt;typename CompatibleKey,typename CompatibleCompare><br>
std::pair&lt;iterator,iterator> equal_range(</br>
std::pair&lt;iterator,iterator> equal_range(<br>
&nbsp;&nbsp;const CompatibleKey&amp; x,const CompatibleCompare&amp; comp)const;
</code>
<blockquote>
<b>Requires:</b> (<code>CompatibleKey</code>, <code>CompatibleCompare</code>)
is a compatible extension of <code>key_compare</code>.</br>
is a compatible extension of <code>key_compare</code>.<br>
<b>Effects:</b> Equivalent to
<code>make_pair(lower_bound(x,comp),upper_bound(x,comp))</code>.<br>
<b>Complexity:</b> <code>O(log(n))</code>.<br>
@@ -870,7 +948,7 @@ std::pair&lt;iterator,iterator> range(<br>
<blockquote>
<b>Requires:</b> <code>LowerBounder</code> and <code>UpperBounder</code> are
a lower and upper bounder of <code>key_compare</code>, respectively.</br>
a lower and upper bounder of <code>key_compare</code>, respectively.<br>
<b>Effects:</b> Returns a pair of iterators pointing to the beginning and one
past the end of the subsequence of elements satisfying <code>lower</code> and
<code>upper</code> simultaneously. If no such elements exist, the iterators
@@ -946,9 +1024,9 @@ Hashed indices
<br>
<p>Revised February 7th 2005</p>
<p>Revised December 21st 2009</p>
<p>&copy; Copyright 2003-2005 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
<p>&copy; Copyright 2003-2009 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
File diff suppressed because it is too large Load Diff
+107 -30
View File
@@ -5,6 +5,10 @@
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Boost.MultiIndex Documentation - Sequenced indices reference</title>
<link rel="stylesheet" href="../style.css" type="text/css">
<link rel="start" href="../index.html">
<link rel="prev" href="hash_indices.html">
<link rel="up" href="index.html">
<link rel="next" href="rnd_indices.html">
</head>
<body>
@@ -17,8 +21,8 @@ Hashed indices
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.MultiIndex reference" border="0"><br>
Boost.MultiIndex reference
</a></div>
<div class="next_link"><a href="key_extraction.html"><img src="../next.gif" alt="key extraction" border="0"><br>
Key extraction
<div class="next_link"><a href="rnd_indices.html"><img src="../next.gif" alt="random access indices" border="0"><br>
Random access indices
</a></div><br clear="all" style="clear: all;">
<hr>
@@ -37,10 +41,11 @@ Key extraction
<li><a href="#complexity_signature">Complexity signature</a></li>
<li><a href="#instantiation_types">Instantiation types</a></li>
<li><a href="#constructors">Constructors, copy and assignment</a></li>
<li><a href="#iterators">Iterators</a></li>
<li><a href="#capacity">Capacity operations</a></li>
<li><a href="#modifiers">Modifiers</a></li>
<li><a href="#list_operations">List operations</a></li>
<li><a href="#special_list_operations">Special list operations</a></li>
<li><a href="#rearrange_operations">Rearrange operations</a></li>
<li><a href="#serialization">Serialization</a></li>
</ul>
</li>
@@ -145,7 +150,8 @@ like <code>std::list</code>. Elements in a sequenced index are by default
sorted according to their order of insertion: this means that new elements
inserted through a different index of the <code>multi_index_container</code> are appended
to the end of the sequenced index. Additionally, the index allows for free
reordering of elements in the same vein as <code>std::list</code> does.
reordering of elements in the same vein as <code>std::list</code> does. Validity
of iterators and references to elements is preserved in all operations.
</p>
<p>
@@ -170,7 +176,7 @@ of <a href="http://www.sgi.com/tech/stl/ReversibleContainer.html">
<code>Front Insertion Sequence</code></a> and
<a href="http://www.sgi.com/tech/stl/BackInsertionSequence.html">
<code>Back Insertion Sequence</code></a>. We only provide descriptions
of those types and operations that are that are either not present in the
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.
</p>
@@ -190,7 +196,8 @@ types of containers.
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>node_type</span><span class=special>::</span><span class=identifier>value_type</span> <span class=identifier>value_type</span><span class=special>;</span>
<span class=keyword>typedef</span> <span class=identifier>tuples</span><span class=special>::</span><span class=identifier>null_type</span> <span class=identifier>ctor_args</span><span class=special>;</span>
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>Allocator</span> <span class=identifier>allocator_type</span><span class=special>;</span>
<span class=keyword>typedef</span> <span class=identifier>TagList</span> <span class=identifier>tag_list</span><span class=special>;</span>
<span class=keyword>typedef</span> <span class=identifier>Allocator</span> <span class=identifier>allocator_type</span><span class=special>;</span>
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>allocator_type</span><span class=special>::</span><span class=identifier>reference</span> <span class=identifier>reference</span><span class=special>;</span>
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>allocator_type</span><span class=special>::</span><span class=identifier>const_reference</span> <span class=identifier>const_reference</span><span class=special>;</span>
<span class=keyword>typedef</span> <b>implementation defined</b> <span class=identifier>iterator</span><span class=special>;</span>
@@ -224,6 +231,13 @@ types of containers.
<span class=identifier>const_reverse_iterator</span> <span class=identifier>rbegin</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>reverse_iterator</span> <span class=identifier>rend</span><span class=special>();</span>
<span class=identifier>const_reverse_iterator</span> <span class=identifier>rend</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>const_iterator</span> <span class=identifier>cbegin</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>const_iterator</span> <span class=identifier>cend</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>const_reverse_iterator</span> <span class=identifier>crbegin</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>const_reverse_iterator</span> <span class=identifier>crend</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>iterator</span> <span class=identifier>iterator_to</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=identifier>const_iterator</span> <span class=identifier>iterator_to</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=comment>// capacity:</span>
@@ -255,6 +269,8 @@ types of containers.
<span class=keyword>bool</span> <span class=identifier>replace</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>&gt;</span> <span class=keyword>bool</span> <span class=identifier>modify</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>);</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Rollback</span><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=identifier>modify</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>,</span><span class=identifier>Rollback</span> <span class=identifier>back</span><span class=special>);</span>
<span class=keyword>void</span> <span class=identifier>swap</span><span class=special>(</span><b>index class name</b><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
@@ -282,10 +298,11 @@ types of containers.
<span class=keyword>void</span> <span class=identifier>reverse</span><span class=special>();</span>
<span class=comment>// relocate operations:</span>
<span class=comment>// rearrange operations:</span>
<span class=keyword>void</span> <span class=identifier>relocate</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>iterator</span> <span class=identifier>i</span><span class=special>);</span>
<span class=keyword>void</span> <span class=identifier>relocate</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>iterator</span> <span class=identifier>first</span><span class=special>,</span><span class=identifier>iterator</span> <span class=identifier>last</span><span class=special>);</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>InputIterator</span><span class=special>&gt;</span> <span class=keyword>void</span> <span class=identifier>rearrange</span><span class=special>(</span><span class=identifier>InputIterator</span> <span class=identifier>first</span><span class=special>);</span>
<span class=special>}</span>
<span class=comment>// index comparison:</span>
@@ -376,7 +393,7 @@ index specifier. Instantiations are dependent on the following types:
<ul>
<li><code>Value</code> from <code>multi_index_container</code>,</li>
<li><code>Allocator</code> from <code>multi_index_container</code>,</li>
<li><code>TagList</code> from the index specifier (if provided).</li>
<li><code>TagList</code> from the index specifier (if provided, otherwise <code>tag&lt;&gt;</code> is assumed).</li>
</ul>
<code>TagList</code> must be an instantiation of
<a href="indices.html#tag"><code>tag</code></a>.
@@ -412,7 +429,7 @@ void assign(InputIterator first,InputIterator last);</code>
<code>value_type</code> or a type convertible to <code>value_type</code>.
<code>first</code> and <code>last</code> are not iterators into any
index of the <code>multi_index_container</code> to which this index belongs.
<code>last</code> is reachable from <code>first</code>.</br>
<code>last</code> is reachable from <code>first</code>.<br>
<b>Effects:</b>
<blockquote><pre>
<span class=identifier>clear</span><span class=special>();</span>
@@ -430,6 +447,18 @@ index of the <code>multi_index_container</code> to which this index belongs.
</pre></blockquote>
</blockquote>
<h4><a name="iterators">Iterators</a></h4>
<code>iterator&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iterator_to(const value_type&amp; x);<br>
const_iterator iterator_to(const value_type&amp; x)const;</code>
<blockquote>
<b>Requires:</b> <code>x</code> is a reference to an element of the container.<br>
<b>Returns:</b> An iterator to <code>x</code>.<br>
<b>Complexity:</b> Constant.<br>
<b>Exception safety:</b> <code>nothrow</code>.<br>
</blockquote>
<h4><a name="capacity">Capacity operations</a></h4>
<code>void resize(size_type n,const value_type&amp; x=value_type());</code>
@@ -438,7 +467,11 @@ index of the <code>multi_index_container</code> to which this index belongs.
<b>Effects:</b>
<blockquote><pre>
<span class=keyword>if</span><span class=special>(</span><span class=identifier>n</span><span class=special>&gt;</span><span class=identifier>size</span><span class=special>())</span><span class=identifier>insert</span><span class=special>(</span><span class=identifier>end</span><span class=special>(),</span><span class=identifier>n</span><span class=special>-</span><span class=identifier>size</span><span class=special>(),</span><span class=identifier>x</span><span class=special>);</span>
<span class=keyword>else</span> <span class=keyword>if</span><span class=special>(</span><span class=identifier>n</span><span class=special>&lt;</span><span class=identifier>size</span><span class=special>())</span><span class=identifier>erase</span><span class=special>(</span><span class=identifier>begin</span><span class=special>()+</span><span class=identifier>n</span><span class=special>,</span><span class=identifier>end</span><span class=special>());</span>
<span class=keyword>else</span> <span class=keyword>if</span><span class=special>(</span><span class=identifier>n</span><span class=special>&lt;</span><span class=identifier>size</span><span class=special>()){</span>
<span class=identifier>iterator</span> <span class=identifier>it</span><span class=special>=</span><span class=identifier>begin</span><span class=special>();</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>advance</span><span class=special>(</span><span class=identifier>it</span><span class=special>,</span><span class=identifier>n</span><span class=special>);</span>
<span class=identifier>erase</span><span class=special>(</span><span class=identifier>it</span><span class=special>,</span><span class=identifier>end</span><span class=special>());</span>
<span class=special>}</span>
</pre></blockquote>
<b>Note:</b> If an expansion is requested, the size of the index is not guaranteed
to be <code>n</code> after this operation (other indices may ban insertions.)
@@ -477,7 +510,7 @@ Note that more than one element can be causing insertion not to be allowed.<br>
<code>std::pair&lt;iterator,bool> insert(iterator position,const value_type&amp; x);</code>
<blockquote>
<b>Requires:</b> <code>position</code> is a valid iterator of the index.</br>
<b>Requires:</b> <code>position</code> is a valid iterator of the index.<br>
<b>Effects:</b> Inserts <code>x</code> before <code>position</code> if insertion
is allowed by all other indices of the <code>multi_index_container</code>.<br>
<b>Returns:</b> The return value is a pair <code>p</code>. <code>p.second</code>
@@ -492,7 +525,7 @@ Note that more than one element can be causing insertion not to be allowed.<br>
<code>void insert(iterator position,size_type n,const value_type&amp; x);</code>
<blockquote>
<b>Requires:</b> <code>position</code> is a valid iterator of the index.</br>
<b>Requires:</b> <code>position</code> is a valid iterator of the index.<br>
<b>Effects:</b>
<blockquote><pre>
<span class=keyword>for</span><span class=special>(</span><span class=identifier>size_type</span> <span class=identifier>i</span><span class=special>=</span><span class=number>0</span><span class=special>;</span><span class=identifier>i</span><span class=special>&lt;</span><span class=identifier>n</span><span class=special>;++</span><span class=identifier>i</span><span class=special>)</span><span class=identifier>insert</span><span class=special>(</span><span class=identifier>position</span><span class=special>,</span><span class=identifier>x</span><span class=special>);</span>
@@ -510,7 +543,7 @@ void insert(iterator position,InputIterator first,InputIterator last);</code>
<code>value_type</code> or a type convertible to <code>value_type</code>.
<code>first</code> and <code>last</code> are not iterators into any
index of the <code>multi_index_container</code> to which this index belongs.
<code>last</code> is reachable from <code>first</code>.</br>
<code>last</code> is reachable from <code>first</code>.<br>
<b>Effects:</b>
<blockquote><pre>
<span class=keyword>while</span><span class=special>(</span><span class=identifier>first</span><span class=special>!=</span><span class=identifier>last</span><span class=special>)</span><span class=identifier>insert</span><span class=special>(</span><span class=identifier>position</span><span class=special>,*</span><span class=identifier>first</span><span class=special>++);</span>
@@ -524,7 +557,7 @@ number of elements in [<code>first</code>,<code>last</code>).<br>
<blockquote>
<b>Requires:</b> <code>position</code> is a valid dereferenceable iterator
of the index.</br>
of the index.<br>
<b>Effects:</b> Deletes the element pointed to by <code>position</code>.<br>
<b>Returns:</b> An iterator pointing to the element immediately following
the one that was deleted, or <code>end()</code>
@@ -549,7 +582,7 @@ the number of elements in [<code>first</code>,<code>last</code>).<br>
<blockquote>
<b>Requires:</b> <code>position</code> is a valid dereferenceable iterator
of the index.</br>
of the index.<br>
<b>Effects:</b> Assigns the value <code>x</code> to the element pointed
to by <code>position</code> into the <code>multi_index_container</code> to which
the index belongs if replacing is allowed by all other indices of the
@@ -572,12 +605,12 @@ belongs remains in its original state.
<a href="http://www.sgi.com/tech/stl/UnaryFunction.html">
<code>Unary Function</code></a> accepting arguments of type
<code>value_type&amp;</code>. <code>position</code> is a valid dereferenceable
iterator of the index.</br>
iterator of the index.<br>
<b>Effects:</b> Calls <code>mod(e)</code> where <code>e</code> is the element
pointed to by <code>position</code> and rearranges <code>*position</code> into
all the indices of the <code>multi_index_container</code>. Rearrangement on sequenced
indices does not change the position of the element with respect to the index;
rearrangement on other indices may or might not suceed. If the rearrangement
rearrangement on other indices may or might not succeed. If the rearrangement
fails, the element is erased.<br>
<b>Postconditions:</b> Validity of <code>position</code> is preserved if the
operation succeeds.<br>
@@ -589,10 +622,41 @@ user-provided operation (except possibly <code>mod</code>), then
the element pointed to by <code>position</code> is erased.
</blockquote>
<code>template&lt;typename Modifier,typename Rollback><br>
bool modify(iterator position,Modifier mod,Rollback back);</code>
<blockquote>
<b>Requires:</b> <code>Modifier</code> and <code>Rollback</code> are models of
<a href="http://www.sgi.com/tech/stl/UnaryFunction.html">
<code>Unary Function</code></a> accepting arguments of type
<code>value_type&amp;</code>. <code>position</code> is a valid dereferenceable
iterator of the index. The sequence of operations <code>mod(e)</code>,
<code>back(e)</code>, where <code>e</code> is the element
pointed to by <code>position</code>, restores all keys of the element
to their original state.<br>
<b>Effects:</b> Calls <code>mod(e)</code> where <code>e</code> is the element
pointed to by <code>position</code> and tries to rearrange <code>*position</code> into
all the indices of the <code>multi_index_container</code>. Rearrangement on sequenced
indices does not change the position of the element with respect to the index;
rearrangement on other indices may or might not succeed. If the rearrangement
fails, <code>back(e)</code> is invoked and the
element is kept at its original position in all indices.<br>
<b>Postconditions:</b> Validity of <code>position</code> is preserved except if
the element is erased under the conditions described below.<br>
<b>Returns:</b> <code>true</code> if the operation succeeded, <code>false</code>
otherwise.<br>
<b>Complexity:</b> <code>O(M(n))</code>.<br>
<b>Exception safety:</b> Strong, except if <code>back</code> throws an
exception, in which case the modified element is erased. If <code>back</code>
throws inside the handling code executing after some other user-provided
operation has thrown, it is the exception generated by <code>back</code> that
is rethrown.
</blockquote>
<h4><a name="list_operations">List operations</a></h4>
<p>
Sequenced indices provides the full set of list operations provided by
Sequenced indices provide the full set of list operations found in
<code>std::list</code>; the semantics of these member functions, however,
differ from that of <code>std::list</code> in some cases as insertions
might not succeed due to banning by other indices. Similarly, the complexity
@@ -604,7 +668,7 @@ same <code>multi_index_container</code>.
<blockquote>
<b>Requires:</b> <code>position</code> is a valid iterator of the index.
<code>&amp;x!=this</code>.</br>
<code>&amp;x!=this</code>.<br>
<b>Effects:</b> Inserts the contents of <code>x</code> before <code>position</code>,
in the same order as they were in <code>x</code>. Those elements succesfully
inserted are erased from <code>x</code>.<br>
@@ -665,7 +729,7 @@ is the number of elements erased.<br>
<blockquote>
<b>Effects:</b> Erases all elements <code>x</code> of the index for which
<code>pred(x)</code> holds..<br>
<code>pred(x)</code> holds.<br>
<b>Complexity:</b> <code>O(n + m*D(n))</code>, where <code>m</code>
is the number of elements erased.<br>
<b>Exception safety:</b> Basic.
@@ -779,14 +843,13 @@ not throw; otherwise, basic.
<b>Exception safety:</b> <code>nothrow</code>.
</blockquote>
<h4><a name="special_list_operations">Special list operations</a></h4>
<h4><a name="rearrange_operations">Rearrange operations</a></h4>
<p>
Sequenced indices provide some convenience member functions without
counterparts in <code>std::list</code>. These operations are aimed at
improving the usability of sequenced indices in points where
the support offered by standard list operations is insufficient or
difficult to use.
These operations, without counterpart in <code>std::list</code>
(although <code>splice</code> provides partially overlapping
functionality), perform individual and global repositioning of elements
inside the index.
</p>
<code>void relocate(iterator position,iterator i);</code>
@@ -816,6 +879,20 @@ is repositioned just before <code>position</code>.<br>
<b>Exception safety:</b> <code>nothrow</code>.<br>
</blockquote>
<a name="rearrange"><code>template&lt;typename InputIterator> void rearrange(InputIterator first);</code></a>
<blockquote>
<b>Requires:</b> The range [<code>first</code>,
<code>std::advance(first,n)</code>),
where <code>n</code> is the size of the index, is a
<a href="indices.html#views">free view</a> of the index.<br>
<b>Effects:</b> The elements are rearranged so as to match the
order of the previously described view.<br>
<b>Postconditions:</b> No iterator or reference is invalidated.<br>
<b>Complexity:</b> <code>O(n)</code>.<br>
<b>Exception safety:</b> Basic.<br>
</blockquote>
<h4><a name="serialization">Serialization</a></h4>
<p>
@@ -872,15 +949,15 @@ Hashed indices
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.MultiIndex reference" border="0"><br>
Boost.MultiIndex reference
</a></div>
<div class="next_link"><a href="key_extraction.html"><img src="../next.gif" alt="key extraction" border="0"><br>
Key extraction
<div class="next_link"><a href="rnd_indices.html"><img src="../next.gif" alt="random access indices" border="0"><br>
Random access indices
</a></div><br clear="all" style="clear: all;">
<br>
<p>Revised February 7th 2005</p>
<p>Revised July 21st 2009</p>
<p>&copy; Copyright 2003-2005 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
<p>&copy; Copyright 2003-2009 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
+293 -4
View File
@@ -5,6 +5,10 @@
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Boost.MultiIndex Documentation - Release notes</title>
<link rel="stylesheet" href="style.css" type="text/css">
<link rel="start" href="index.html">
<link rel="prev" href="future_work.html">
<link rel="up" href="index.html">
<link rel="next" href="acknowledgements.html">
</head>
<body>
@@ -27,17 +31,302 @@ Acknowledgements
<h2>Contents</h2>
<ul>
<li><a href="#boost_1_49">Boost 1.49 release</a></li>
<li><a href="#boost_1_48">Boost 1.48 release</a></li>
<li><a href="#boost_1_47">Boost 1.47 release</a></li>
<li><a href="#boost_1_44">Boost 1.44 release</a></li>
<li><a href="#boost_1_43">Boost 1.43 release</a></li>
<li><a href="#boost_1_42">Boost 1.42 release</a></li>
<li><a href="#boost_1_41">Boost 1.41 release</a></li>
<li><a href="#boost_1_38">Boost 1.38 release</a></li>
<li><a href="#boost_1_37">Boost 1.37 release</a></li>
<li><a href="#boost_1_36">Boost 1.36 release</a></li>
<li><a href="#boost_1_35">Boost 1.35 release</a></li>
<li><a href="#boost_1_34">Boost 1.34 release</a></li>
<li><a href="#boost_1_33_1">Boost 1.33.1 release</a></li>
<li><a href="#boost_1_33">Boost 1.33 release</a></li>
</ul>
<h2><a name="boost_1_49">Boost 1.49 release</a></h2>
<p>
<ul>
<li>Suppressed a potential narrow conversion warning described in
ticket <a href="https://svn.boost.org/trac/boost/ticket/3365">#3365</a>.
</li>
</ul>
</p>
<h2><a name="boost_1_48">Boost 1.48 release</a></h2>
<p>
<ul>
<li>Fixed a compatibility problem with
<a href="../../../doc/html/foreach.html">Boost.Foreach</a>
(ticket <a href="https://svn.boost.org/trac/boost/ticket/5741">#5741</a>).
</li>
</ul>
</p>
<h2><a name="boost_1_47">Boost 1.47 release</a></h2>
<p>
<ul>
<li>Fixed an ADL problem in
<a href="reference/key_extraction.html#composite_key_compare"><code>composite_key_compare</code></a>
related with <a href="../../../doc/html/ref.html">Boost.Ref</a>.
</li>
<li>Maintenance fixes.</li>
</ul>
</p>
<h2><a name="boost_1_44">Boost 1.44 release</a></h2>
<p>
<ul>
<li>
Fixed a bug preventing the use of <code>modify_key</code> with
rollback in <a href="reference/ord_indices.html#modify_key">ordered</a> and
<a href="reference/hash_indices.html#modify_key">hashed</a> indices when
<code>Modifier</code> and <code>Rollback</code> are different types
(ticket <a href="https://svn.boost.org/trac/boost/ticket/4130">#4130</a>).
</li>
</ul>
</p>
<h2><a name="boost_1_43">Boost 1.43 release</a></h2>
<p>
<ul>
<li>
<a href="../../serialization/doc/serialization.html#constructors">Serialization
of non default constructible values</a> is now properly supported
through user-provided facilities <code>save_construct_data</code> and
<code>load_construct_data</code>.
<code>multi_index_container</code> serialization
<a href="../../serialization/doc/tutorial.html#versioning">class version</a> has been
bumped from 1 to 2.
</li>
</ul>
</p>
<h2><a name="boost_1_42">Boost 1.42 release</a></h2>
<p>
<ul>
<li>Maintenance fixes.</li>
</ul>
</p>
<h2><a name="boost_1_41">Boost 1.41 release</a></h2>
<p>
<ul>
<li>Serialization now uses the portable
<a href="../../serialization/doc/wrappers.html#collection_size_type"><code>collection_size_type</code></a>
type instead of the original <code>std::size_t</code> (ticket
<a href="https://svn.boost.org/trac/boost/ticket/3365">#3365</a>).
<code>multi_index_container</code> serialization
<a href="../../serialization/doc/tutorial.html#versioning">class version</a> has been
bumped from 0 to 1.
</li>
<li>Fixed a concurrency bug in the implementation of
<a href="tutorial/debug.html#safe_mode">safe mode</a>
(ticket <a href="https://svn.boost.org/trac/boost/ticket/3462">#3462</a>).
</li>
</ul>
</p>
<h2><a name="boost_1_38">Boost 1.38 release</a></h2>
<p>
<ul>
<li>These constructs are deprecated:
<ul>
<li><code>nth_index_iterator&lt;MultiIndexContainer,N&gt;::type</code>,</li>
<li><code>multi_index_container&lt;...&gt;::nth_index_iterator&lt;N&gt;::type</code>,</li>
<li><code>nth_index_const_iterator&lt;MultiIndexContainer,N&gt;::type</code>,</li>
<li><code>multi_index_container&lt;...&gt;::nth_index_const_iterator&lt;N&gt;::type</code>,</li>
<li><code>index_iterator&lt;MultiIndexContainer,Tag&gt;::type</code>,</li>
<li><code>multi_index_container&lt;...&gt;::index_iterator&lt;Tag&gt;::type</code>,</li>
<li><code>index_const_iterator&lt;MultiIndexContainer,Tag&gt;::type</code>,</li>
<li><code>multi_index_container&lt;...&gt;::index_const_iterator&lt;Tag&gt;::type</code>.</li>
</ul>
Use the following instead:
<ul>
<li><code>nth_index&lt;MultiIndexContainer,N&gt;::type::iterator</code>,</li>
<li><code>multi_index_container&lt;...&gt;::nth_index&lt;N&gt;::type::iterator</code>,</li>
<li><code>nth_index&lt;MultiIndexContainer,N&gt;::type::const_iterator</code>,</li>
<li><code>multi_index_container&lt;...&gt;::nth_index&lt;N&gt;::type::const_iterator</code>,</li>
<li><code>index&lt;MultiIndexContainer,Tag&gt;::type::iterator</code>,</li>
<li><code>multi_index_container&lt;...&gt;::index&lt;Tag&gt;::type::iterator</code>,</li>
<li><code>index&lt;MultiIndexContainer,Tag&gt;::type::const_iterator</code>,</li>
<li><code>multi_index_container&lt;...&gt;::index&lt;Tag&gt;::type::const_iterator</code>.</li>
</ul>
</li>
<li>Maintenance fixes.</li>
</ul>
</p>
<h2><a name="boost_1_37">Boost 1.37 release</a></h2>
<p>
<ul>
<li>Maintenance fixes.</li>
</ul>
</p>
<h2><a name="boost_1_36">Boost 1.36 release</a></h2>
<p>
<ul>
<li><a name="stable_update">On prior versions of the library, the <a href="tutorial/indices.html#hash_updating">update
member functions</a> of hashed indices could alter the position of an element even if the
associated key did not change with the update. This is legal but probably unexpected behavior.
The functions have been rewritten to provide the additional guarantee that elements with
unmodified key will not change position in hashed indices, just as always was the case with
ordered indices. These guarantees are now documented in the reference.</a></li>
<li>Added the constructor <code>multi_index_container::multi_index_container(const allocator_type&amp;)</code>
to mimic the equivalent interface in STL sequence containers.
<li>Maintenance fixes.</li>
</ul>
</p>
<h2><a name="boost_1_35">Boost 1.35 release</a></h2>
<p>
<ul>
<li>New <a href="tutorial/key_extraction.html#global_fun"><code>global_fun</code></a>
predefined key extractor.
</li>
<li>Added <a href="tutorial/indices.html#iterator_to"><code>iterator_to</code></a>
facility.
</li>
<li>Included <a href="tutorial/creation.html#special_allocator">support for
non-standard allocators</a> such as those of
<a href="../../interprocess/index.html">Boost.Interprocess</a>, which makes
<code>multi_index_container</code>s placeable in shared memory.
</li>
<li>New versions of <code>modify</code> and <code>modify_key</code> with
rollback, as described in the
<a href="tutorial/basics.html#ord_updating">tutorial</a>.
</li>
<li>Indices provide the new <code>cbegin</code>, <code>cend</code> and,
when applicable, <code>crbegin</code> and <code>crend</code>
member functions, in accordance with the latest drafts of the next
revision of the C++ standard.
</li>
<li>Hinted insertion in ordered indices fully conforms to the resolutions of
C++ Standard Library
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#233">Defect
Report 233</a>. The new requirement that the point of insertion
be always as close as possible to the hint induces a different behavior than
exhibited in former releases of Boost.MultiIndex, which can potentially cause
backwards compatibility problems; in any case, the likelihood of these
compatibility issues arising in a real scenario is very low.
</li>
<li>Sequenced and random access indices now follow the requirements of the
C++ standard for sequence containers with respect to the operations
<code>assign(f,l)</code> and <code>insert(p,f,l)</code> (23.1.1/9): if
<code>f</code> and <code>l</code> are of the same integral type, the
iterator-based overloads of these member functions are avoided:
<blockquote><pre>
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=keyword>int</span><span class=special>,</span><span class=identifier>indexed_by</span><span class=special>&lt;</span><span class=identifier>sequenced</span><span class=special>&lt;&gt;</span> <span class=special>&gt;</span>
<span class=special>&gt;</span> <span class=identifier>sequenced_container</span><span class=special>;</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>list</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;</span> <span class=identifier>l</span><span class=special>(...);</span>
<span class=identifier>sequenced_container</span> <span class=identifier>c</span><span class=special>;</span>
<span class=comment>// iterator-based overload of assign</span>
<span class=identifier>c</span><span class=special>.</span><span class=identifier>assign</span><span class=special>(</span><span class=identifier>l</span><span class=special>.</span><span class=identifier>begin</span><span class=special>(),</span><span class=identifier>l</span><span class=special>.</span><span class=identifier>end</span><span class=special>());</span>
<span class=comment>// The following is equivalent to
// c.assign(
// static_cast&lt;sequenced_container::size_type&gt;(10),100);
// that is, &quot;10&quot; and &quot;100&quot; are not taken to be iterators as
// in the previous expression.</span>
<span class=identifier>c</span><span class=special>.</span><span class=identifier>assign</span><span class=special>(</span><span class=number>10</span><span class=special>,</span><span class=number>100</span><span class=special>);</span>
</pre></blockquote>
</li>
<li>The performance of ordered indices <code>range</code> and
<code>equal_range</code> has been improved.
</li>
<li>Maintenance fixes.</li>
</ul>
</p>
<h2><a name="boost_1_34">Boost 1.34 release</a></h2>
<p>
<ul>
<li>Added <a href="tutorial/indices.html#rnd_indices">random access
indices</a>.
</li>
<li>Non key-based indices provide new
<a href="tutorial/indices.html#rearrange">rearrange facilities</a>
allowing for interaction with external mutating algorithms.
</li>
<li>All predefined Boost.MultiIndex key extractors
instantiated for a given type <code>T</code> can handle objects of types
derived from or convertible to <code>T</code> (and
<a href="reference/key_extraction.html#chained_pointers">chained pointers</a>
to those). Previously, only objects of the exact type specified (along with
<code>reference_wrapper</code>s and chained pointers to them) were accepted.
</li>
<li><a href="reference/key_extraction.html#composite_key_compare"><code>composite_key_compare</code></a>
and related classes accept operands not included in tuples as if they were passed
in a tuple of length 1; this allows the user to omit tuple enclosing in
lookup operations involving composite keys when only the first key is provided.
</li>
<li>The core algorithms of ordered indices have been optimized, yielding
an estimated reduction of about 5% in insertion times.
</li>
<li>Size of ordered indices node headers have been reduced by 25% on
most platforms, using a well known
<a href="tutorial/indices.html#ordered_node_compression">optimization
technique</a>.
</li>
<li>The tutorial has been restructured, new examples added.</li>
<li>Maintenance fixes.</li>
</ul>
</p>
<h2><a name="boost_1_33_1">Boost 1.33.1 release</a></h2>
<p>
<ul>
<li>For ordered and hashed indices, <code>erase(it)</code> and
<code>erase(first,last)</code> now return an iterator to the element
following those being deleted (previously nothing was returned), in
accordance with the C++ Standard Library
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#130">Defect
Report 130</a> and issue 6.19 of TR1
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1837.pdf">Issues
List</a>.
</li>
<li>Boost.MultiIndex offers the usual guarantees with respect to
multithreading code provided by most STL implementations:
<ol>
<li>Concurrent access to different containers is safe.</li>
<li>Concurrent read-only access to the same container is safe.</li>
</ol>
In previous versions of the library, the latter guarantee was not properly
maintained if the <a href="tutorial/debug.html#safe_mode">safe
mode</a> was set. This problem has been fixed now.
</li>
<li>Maintenance fixes.</li>
</ul>
</p>
<h2><a name="boost_1_33">Boost 1.33 release</a></h2>
<p>
<ul>
<li>Added <a href="advanced_topics.html#hashed_indices">hashed indices</a>,
<li>Added <a href="tutorial/indices.html#hashed_indices">hashed indices</a>,
whose interface is based on the specification for unordered associative
containers by the C++ Standard Library Technical Report (TR1).
<li>Added <a href="advanced_topics.html#serialization">serialization support</a>
</li>
<li>Added <a href="tutorial/creation.html#serialization">serialization support</a>
for <a href="../../serialization/index.html">Boost.Serialization</a>.
</li>
<li>Destruction of <code>multi_index_container</code>s and <code>clear</code>
@@ -70,9 +359,9 @@ Acknowledgements
<br>
<p>Revised March 3rd 2005</p>
<p>Revised November 24th 2011</p>
<p>&copy; Copyright 2003-2005 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
<p>&copy; Copyright 2003-2011 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
+20 -14
View File
@@ -5,6 +5,10 @@
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Boost.MultiIndex Documentation - Tests</title>
<link rel="stylesheet" href="style.css" type="text/css">
<link rel="start" href="index.html">
<link rel="prev" href="examples.html">
<link rel="up" href="index.html">
<link rel="next" href="future_work.html">
</head>
<body>
@@ -45,8 +49,9 @@ with some of the least common features offered by Boost.MultiIndex.
</tr>
<tr class="odd_tr">
<td><a href="../test/test_capacity.cpp"><code>test_capacity.cpp</code></a></td>
<td><code>empty</code>, <code>size</code> and (sequenced indices only)
<code>resize</code>.</td>
<td><code>empty</code>, <code>size</code>, <code>resize</code>
(non key-based indices) and <code>reserve</code>/<code>capacity</code>
(random access indices only).</td>
</tr>
<tr>
<td><a href="../test/test_comparison.cpp"><code>test_comparison.cpp</code></a></td>
@@ -63,7 +68,7 @@ with some of the least common features offered by Boost.MultiIndex.
<tr class="odd_tr">
<td><a href="../test/test_copy_assignment.cpp"><code>test_copy_assignment.cpp</code></a></td>
<td>Various forms of assignment: copy, <code>operator =</code>, insertion,
(sequenced indices only) <code>assign</code> .
(non key-based indices only) <code>assign</code> .
</tr>
<tr>
<td><a href="../test/test_hash_ops.cpp"><code>test_hash_ops.cpp</code></a></td>
@@ -79,7 +84,7 @@ with some of the least common features offered by Boost.MultiIndex.
</tr>
<tr class="odd_tr">
<td><a href="../test/test_list_ops.cpp"><code>test_list_ops.cpp</code></a></td>
<td>List-like operations particular to sequenced indices.</td>
<td>List-like operations particular to sequenced and random access indices.</td>
</tr>
<tr>
<td><a href="../test/test_modifiers.cpp"><code>test_modifiers.cpp</code></a></td>
@@ -102,22 +107,23 @@ with some of the least common features offered by Boost.MultiIndex.
<td>Exercises the <code>range</code> facility (ordered indices only).</td>
</tr>
<tr class="odd_tr">
<td><a href="../test/test_rearrange.cpp"><code>test_rearrange.cpp</code></a></td>
<td>Rearrange functions of sequenced and random access indices.</td>
</tr>
<tr>
<td><a href="../test/test_safe_mode.cpp"><code>test_safe_mode.cpp</code></a></td>
<td>Comprehensive coverage of all conditions checked in safe mode.</td>
</tr>
<tr>
<td><a href="../test/test_serialization.cpp"><code>test_serialization.cpp</code></a></td>
<tr class="odd_tr">
<td><a href="../test/test_serialization1.cpp"><code>test_serialization1.cpp</code></a><br>
<a href="../test/test_serialization2.cpp"><code>test_serialization2.cpp</code></a><br>
<a href="../test/test_serialization3.cpp"><code>test_serialization3.cpp</code></a></td>
<td>Serialization support.</td>
</tr>
<tr class="odd_tr">
<tr>
<td><a href="../test/test_set_ops.cpp"><code>test_set_ops.cpp</code></a></td>
<td>Set-like operations particular to ordered indices.</td>
</tr>
<tr>
<td><a href="../test/test_special_list_ops.cpp"><code>test_special_list_ops.cpp</code></a></td>
<td>Convenience functions of sequenced indices not present in
<code>std::list</code>.</td>
</tr>
<tr class="odd_tr">
<td><a href="../test/test_special_set_ops.cpp"><code>test_special_set_ops.cpp</code></a></td>
<td>Checks special lookup operations using compatible sorting criteria.</td>
@@ -144,9 +150,9 @@ Future work
<br>
<p>Revised July 27th 2005</p>
<p>Revised July 11th 2007</p>
<p>&copy; Copyright 2003-2005 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
<p>&copy; Copyright 2003-2007 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
+171 -210
View File
@@ -3,22 +3,26 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Boost.MultiIndex Documentation - Tutorial</title>
<link rel="stylesheet" href="style.css" type="text/css">
<title>Boost.MultiIndex Documentation - Tutorial - Basics</title>
<link rel="stylesheet" href="../style.css" type="text/css">
<link rel="start" href="../index.html">
<link rel="prev" href="index.html">
<link rel="up" href="index.html">
<link rel="next" href="indices.html">
</head>
<body>
<h1><img src="../../../boost.png" alt="boost.png (6897 bytes)" align=
"middle" width="277" height="86">Boost.MultiIndex Tutorial</h1>
<h1><img src="../../../../boost.png" alt="boost.png (6897 bytes)" align=
"middle" width="277" height="86">Boost.MultiIndex Tutorial: Basics</h1>
<div class="prev_link"><a href="index.html"><img src="prev.gif" alt="index" border="0"><br>
Index
<div class="prev_link"><a href="index.html"><img src="../prev.gif" alt="Boost.MultiIndex tutorial" border="0"><br>
Boost.MultiIndex tutorial
</a></div>
<div class="up_link"><a href="index.html"><img src="up.gif" alt="index" border="0"><br>
Index
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.MultiIndex tutorial" border="0"><br>
Boost.MultiIndex tutorial
</a></div>
<div class="next_link"><a href="advanced_topics.html"><img src="next.gif" alt="advanced topics" border="0"><br>
Advanced topics
<div class="next_link"><a href="indices.html"><img src="../next.gif" alt="index types" border="0"><br>
Index types
</a></div><br clear="all" style="clear: all;">
<hr>
@@ -26,16 +30,15 @@ Advanced topics
<h2>Contents</h2>
<ul>
<li><a href="#rationale">Rationale</a></li>
<li><a href="#namespace">Namespace</a></li>
<li><a href="#intro">Introduction</a>
<ul>
<li><a href="#multipe_sort">Multiple sorts on a single set</a></li>
<li><a href="#multiple_sort">Multiple sorts on a single set</a></li>
<li><a href="#list_fast_lookup">A bidirectional list with fast lookup</a></li>
</ul>
</li>
<li><a href="#index_spec">Index specification</a></li>
<li><a href="#tagging">Tagging</a></li>
<li><a href="#iterator_access">Iterator access</a></li>
<li><a href="#index_types">Index types</a>
<ul>
<li><a href="#ord_indices">Ordered indices</a>
@@ -62,78 +65,6 @@ Advanced topics
<li><a href="#complexity">Complexity and exception safety</a></li>
</ul>
<h2><a name="rationale">Rationale</a></h2>
<p>
STL containers are designed around the concept that each container controls its
own collection of elements, giving access to them in a manner specified by the
container's type: so, an <code>std::set</code> maintains the elements ordered
by a specified sorting criterium, <code>std::list</code> allows for free
positioning of elements along a linear sequence, and so on.
</p>
<p>
Sometimes, the necessity arises of having different access interfaces
to the same underlying collection: for instance, some data might need to be
sorted according to more than one comparison predicate, or a bidirectional list
might benefit from a supplemental logarithmic lookup interface. In these
situations, programmers typically resort to manual compositions of different
containers, a solution that generally involves a fair amount of code
devoted to preserve the synchronization of the different parts of
the composition. Boost.MultiIndex allows for the specification of
<code>multi_index_container</code>s comprised of one or more <i>indices</i> with
different interfaces to the same collection of elements. The resulting constructs
are conceptually cleaner than manual compositions, and often perform much better.
An important design decision has been taken that the indices of a given
<code>multi_index_container</code> instantiation be specified at compile time: this
gives ample room for static type checking and code optimization.
</p>
<p>
Boost.MultiIndex takes inspiration from basic concepts of indexing arising in the
theory of relational databases, though it is not intended to provide a full-fledged
relational database framework. <code>multi_index_container</code> integrates seamlessly
into the STL container/algorithm design, and features some extra capabilities regarding
lookup operations and element updating which are useful extensions even for
single-indexed containers.
</p>
<p align="center">
<img src="multi_index_cont_example.png"
alt="diagram of a multi_index_container with three indices"
width="600" height="304"><br>
<b>Fig. 1: Diagram of a <code>multi_index_container</code> with three indices.</b>
</p>
<p>
The figure above depicts a <code>multi_index_container</code> composed of three indices:
the first two present a set-like interface to the elements sorted by
shape and id, respectively, while the latter index provides the functionality
of a bidirectional list in the spirit of <code>std::list</code>. These
indices act as "views" to the internal collection of elements, but they do not only
provide read access to the set: insertion/deletion methods are also implemented much
as those of <code>std::set</code>s or <code>std::list</code>s. Insertion of an
element through one given index will only succeed if the uniqueness constraints of all
indices are met.
</p>
<h2>
<a name="namespace">Namespace</a>
</h2>
<p>
All the types of Boost.MultiIndex reside in namespace <code>::boost::multi_index</code>.
Additionaly, the main class template <code>multi_index_container</code> and global functions
<code>get</code> and <code>project</code> are lifted to namespace <code>::boost</code>
by means of <code>using</code> declarations. For brevity of exposition, the fragments
of code in the documentation are written as if the following declarations were in effect:
</p>
<blockquote><pre>
<span class=keyword>using</span> <span class=keyword>namespace</span> <span class=special>::</span><span class=identifier>boost</span><span class=special>;</span>
<span class=keyword>using</span> <span class=keyword>namespace</span> <span class=special>::</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>multi_index</span><span class=special>;</span>
</pre></blockquote>
<h2><a name="intro">Introduction</a></h2>
<p>
@@ -141,13 +72,13 @@ We introduce the main concepts of Boost.MultiIndex through the study of
two typical use cases.
</p>
<h3><a name="multipe_sort">Multiple sorts on a single set</a></h3>
<h3><a name="multiple_sort">Multiple sorts on a single set</a></h3>
<p>
STL sets and multisets are varying-length containers where elements are efficiently
sorted according to a given comparison predicate. These container classes fall short
of functionality when the programmer wishes to efficiently sort and look up the elements
following a different sorting criterium. Consider for instance:
following a different sorting criterion. Consider for instance:
</p>
<blockquote><pre>
@@ -192,6 +123,11 @@ thus can be solved with Boost.MultiIndex as follows:
</p>
<blockquote><pre>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index_container</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>ordered_index</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>identity</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>member</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=comment>// define a multiply indexed set with indices by id and name</span>
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=identifier>employee</span><span class=special>,</span>
@@ -217,12 +153,13 @@ thus can be solved with Boost.MultiIndex as follows:
<p>
Instead of a single comparison predicate type, as it happens for STL associative
containers, <code>multi_index_container</code> is passed a <i>typelist</i> of index
containers, <code>multi_index_container</code> is passed a
<a href="../reference/multi_index_container.html#multi_index_container">list</a> of index
specifications (<code>indexed_by</code>), each one inducing the corresponding index.
Indices are accessed via
<a href="reference/multi_index_container.html#index_retrieval"><code>get</code></a><code>&lt;N>()</code>
<a href="../reference/multi_index_container.html#index_retrieval"><code>get</code></a><code>&lt;N>()</code>
where <i>N</i> ranges between 0 and the number of comparison
predicates minus one. The functionality of index #0 can be accessed directly from an
predicates minus one. The functionality of index #0 can be accessed directly from a
<code>multi_index_container</code> object without using <code>get&lt;0>()</code>: for instance,
<code>es.begin()</code> is equivalent to <code>es.get&lt;0>().begin()</code>.
</p>
@@ -302,6 +239,11 @@ does precisely this through the combination of sequenced and ordered indices:
</p>
<blockquote><pre>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index_container</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>sequenced_index</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>ordered_index</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>identity</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=comment>// define a multi_index_container with a list-like index and an ordered index</span>
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,</span>
@@ -363,7 +305,7 @@ complexity. The programmer can use index #0 for accessing the text as with
<p>
The indices of a <code>multi_index_container</code> instantiation are specified by
means of the <a href="reference/indices.html#indexed_by">
means of the <a href="../reference/indices.html#indexed_by">
<code>indexed_by</code></a> construct. For instance, the instantiation
</p>
@@ -397,7 +339,7 @@ we specifiy two indices, the first of <a href="#seq_indices">sequenced type</a>,
the second a non-unique <a href="#ord_indices">ordered index</a>. In general, we
can specify an arbitrary number of indices: each of the arguments of
<code>indexed_by</code> is called an
<a href="reference/indices.html#index_specification"><i>index specifier</i></a>.
<a href="../reference/indices.html#index_specification"><i>index specifier</i></a>.
Depending on the type of index being specified, the corresponding specifier
will need additional information: for instance, the specifiers <code>ordered_unique</code>
and <code>ordered_non_unique</code> are provided with a
@@ -455,9 +397,9 @@ first parameter of the corresponding index specifier. The following is a revised
</pre></blockquote>
<p>
Tags have to be passed inside the <code>tag</code> construct. Any type can be
used as a tag for an index, although in general one will choose names that are
descriptive of the index they are associated with. The tagging mechanism allows
Tags have to be passed inside the <a href="../reference/indices.html#tag"><code>tag</code></a>
construct. Any type can be used as a tag for an index, although in general one will choose
names that are descriptive of the index they are associated with. The tagging mechanism allows
us to write expressions like</p>
<blockquote><pre>
@@ -507,6 +449,31 @@ in the previous example can be rewritten to hold two different tags
<span class=special>&gt;</span> <span class=identifier>employee_set</span><span class=special>;</span>
</pre></blockquote>
<h2><a name="iterator_access">Iterator access</a></h2>
<p>
Each index of a <code>multi_index_container</code> uses its own
iterator types, which are different from those of another indices. As is
the rule with STL containers, these iterators are defined as nested
types of the index:
</p>
<blockquote><pre>
<span class=identifier>employee_set</span><span class=special>::</span><span class=identifier>nth_index</span><span class=special>&lt;</span><span class=number>1</span><span class=special>&gt;::</span><span class=identifier>type</span><span class=special>::</span><span class=identifier>iterator</span> <span class=identifier>it</span><span class=special>=</span>
<span class=identifier>es</span><span class=special>.</span><span class=identifier>get</span><span class=special>&lt;</span><span class=number>1</span><span class=special>&gt;().</span><span class=identifier>find</span><span class=special>(</span><span class=string>&quot;Judy Smith&quot;</span><span class=special>);</span>
</pre></blockquote>
<p>
This kind of expressions can be rendered more readable by
means of user-defined <code>typedef</code>s:
</p>
<blockquote><pre>
<span class=keyword>typedef</span> <span class=identifier>employee_set</span><span class=special>::</span><span class=identifier>nth_index</span><span class=special>&lt;</span><span class=number>1</span><span class=special>&gt;::</span><span class=identifier>type</span> <span class=identifier>employee_set_by_name</span><span class=special>;</span>
<span class=identifier>employee_set_by_name</span><span class=special>::</span><span class=identifier>iterator</span> <span class=identifier>it</span><span class=special>=</span>
<span class=identifier>es</span><span class=special>.</span><span class=identifier>get</span><span class=special>&lt;</span><span class=number>1</span><span class=special>&gt;().</span><span class=identifier>find</span><span class=special>(</span><span class=string>&quot;Judy Smith&quot;</span><span class=special>);</span>
</pre></blockquote>
<h2>
<a name="index_types">Index types</a>
</h2>
@@ -518,19 +485,22 @@ Currently, Boost.MultiIndex provides the following index types:
provide a similar interface. There are <i>unique</i> and <i>non-unique</i>
variants: the former do not allow for duplicates, while the latter permit
them (like <code>std::multiset</code>.)</li>
<li>Sequenced indices are modeled after the semantics and interface of
<code>std::list</code>: they arrange the elements as if in a bidirectional
list.</li>
<li>Hashed indices provide fast access to the elements through hashing
tecnhiques, in a similar way as non-standard <code>hash_set</code>s provided
by some vendors. Recently, <i>unordered associative containers</i> have been
proposed as part of an extension of the C++ standard library known
in the standardization commitee as TR1. Hashed indices closely model this
proposal.</li>
<li>Sequenced indices are modeled after the semantics and interface of
<code>std::list</code>: they arrange the elements as if in a bidirectional
list.</li>
<li>Random access indices provide an interface similar to that of
sequenced indices, and additionally feature random access iterators
and positional access to the elements.</li>
</ul>
The examples in the <a href="#intro">introduction</a> exercise ordered and sequenced
indices, which are the most commonly used; hashed indices are presented in the
<a href="advanced_topics.html#hashed_indices">advanced topics</a> section.
indices, which are the most commonly used; the other kinds of indices are presented
in the <a href="indices.html">index types</a> section of the tutorial.
</p>
<h3>
@@ -654,13 +624,13 @@ the sorting is performed. In most cases, one of the following two situations ari
<ul>
<li>The whole element serves as the key, as is the case of the first index
in <code>employee_set</code>. The predefined
<a href="reference/key_extraction.html#identity"><code>identity</code></a> predicate
<a href="key_extraction.html#identity"><code>identity</code></a> predicate
can be used here as a key extractor; <code>identity</code> returns as the key the
same object passed as argument.</li>
<li>The comparison is performed on a particular data member of the element; this
closely follows the specification of indices on a column of a table in relational
databases. Boost.MultiIndex provides
<a href="reference/key_extraction.html#member"><code>member</code></a>, which returns
<a href="key_extraction.html#member"><code>member</code></a>, which returns
as the key a member of the element specified by a given pointer.</li>
</ul>
As an example, consider again the definition of <code>employee_set</code>. The
@@ -688,78 +658,11 @@ we use <code>member</code> to extract the <code>name</code> part of the
</p>
<p>
Another common situation arises when the sorting is performed on the result
of a particular member function. This resembles the notion of
<i>calculated indices</i> supported by some relational databases.
In these cases, the key is not a data member of the element, but rather it is
a value returned by a particular member function. Boost.MultiIndex supports this
kind of key extraction through
<a href="reference/key_extraction.html#const_mem_fun"><code>const_mem_fun</code></a>.
Consider the following extension of our example where sorting on the third index
is based upon the length of the name field:
</p>
<blockquote><pre>
<span class=keyword>struct</span> <span class=identifier>employee</span>
<span class=special>{</span>
<span class=keyword>int</span> <span class=identifier>id</span><span class=special>;</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>name</span><span class=special>;</span>
<span class=identifier>employee</span><span class=special>(</span><span class=keyword>int</span> <span class=identifier>id</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&amp;</span> <span class=identifier>name</span><span class=special>):</span><span class=identifier>id</span><span class=special>(</span><span class=identifier>id</span><span class=special>),</span><span class=identifier>name</span><span class=special>(</span><span class=identifier>name</span><span class=special>){}</span>
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>&lt;(</span><span class=keyword>const</span> <span class=identifier>employee</span><span class=special>&amp;</span> <span class=identifier>e</span><span class=special>)</span><span class=keyword>const</span><span class=special>{</span><span class=keyword>return</span> <span class=identifier>id</span><span class=special>&lt;</span><span class=identifier>e</span><span class=special>.</span><span class=identifier>id</span><span class=special>;}</span>
<span class=comment>// returns the length of the name field</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>size_t</span> <span class=identifier>name_length</span><span class=special>()</span><span class=keyword>const</span><span class=special>{</span><span class=keyword>return</span> <span class=identifier>name</span><span class=special>.</span><span class=identifier>size</span><span class=special>();}</span>
<span class=special>};</span>
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=identifier>employee</span><span class=special>,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span>
<span class=comment>// sort by employee::operator&lt;</span>
<span class=identifier>ordered_unique</span><span class=special>&lt;</span><span class=identifier>identity</span><span class=special>&lt;</span><span class=identifier>employee</span><span class=special>&gt;</span> <span class=special>&gt;,</span>
<span class=comment>// sort by less&lt;string&gt; on name</span>
<span class=identifier>ordered_non_unique</span><span class=special>&lt;</span><span class=identifier>member</span><span class=special>&lt;</span><span class=identifier>employee</span><span class=special>,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,&amp;</span><span class=identifier>employee</span><span class=special>::</span><span class=identifier>name</span><span class=special>&gt;</span> <span class=special>&gt;,</span>
<span class=comment>// sort by less&lt;int&gt; on name_length()</span>
<span class=identifier>ordered_non_unique</span><span class=special>&lt;</span>
<span class=identifier>const_mem_fun</span><span class=special>&lt;</span><span class=identifier>employee</span><span class=special>,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>size_t</span><span class=special>,&amp;</span><span class=identifier>employee</span><span class=special>::</span><span class=identifier>name_length</span><span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span> <span class=identifier>employee_set</span><span class=special>;</span>
</pre></blockquote>
<p><a href="examples.html#example2">Example 2</a> in the examples section
provides a complete program showing how to use <code>const_mem_fun</code>.
Almost always you will want to use a <code>const</code> member function,
since elements in a <code>multi_index_container</code> are treated as constant, much
as elements of an <code>std::set</code>. However, a
<a href="reference/key_extraction.html#mem_fun"><code>mem_fun</code></a>
counterpart is provided for use with non-constant member functions, whose
applicability is discussed on the paragraph on
<a href="advanced_topics.html#advanced_key_extractors">advanced features
of Boost.MultiIndex key extractors</a> in the advanced topics section.
<p>
<p>
More complex scenarios may require the use of
<i>composite keys</i> combining the results of several key extractors.
Composite keys are supported by Boost.MultiIndex through the
<a href="advanced_topics.html#composite_keys"><code>composite_key</code></a>
construct.
</p>
<p>
<code>identity</code>, <code>member</code> and <code>const_mem_fun</code>
(occasionally combined with <code>composite_key</code>) serve
most common situations in the design of a <code>multi_index_container</code>. However, the
user is free to provide her own key extractors in more exotic situations, as long as
these conform to the <a href="reference/key_extraction.html#key_extractors"><code>Key
Extractor</code></a> concept. For instance,
<a href="examples.html#example6">example 6</a> implements several key
extraction techniques called for when elements and/or keys are accessed via
pointers.
Apart from <code>identity</code> and <code>member</code>, Boost.MultiIndex provides
several other predefined key extractors and powerful ways to combine them.
Key extractors can also be defined by the user.
Consult the <a href="key_extraction.html">key extraction section</a> of
the tutorial for a more detailed exposition of this topic.
</p>
<h4><a name="comparison_predicates">Comparison predicates</a></h4>
@@ -848,7 +751,7 @@ comparison predicate
Here we are not only passing IDs instead of <code>employee</code> objects:
an alternative comparison predicate is passed as well. In general, lookup operations
of ordered indices are overloaded to accept
<a href="reference/ord_indices.html#set_operations"><i>compatible sorting
<a href="../reference/ord_indices.html#set_operations"><i>compatible sorting
criteria</i></a>. The somewhat cumbersone definition of compatibility in this context
is given in the reference, but roughly speaking we say that a comparison predicate
<code>C1</code> is compatible with <code>C2</code> if any sequence sorted by
@@ -923,9 +826,9 @@ and error prone task.
</p>
<p>
The <a href="reference/ord_indices.html#range_operations"><code>range</code></a>
The <a href="../reference/ord_indices.html#range_operations"><code>range</code></a>
member function, often in combination with
<a href="../../../libs/lambda/index.html">Boost.Lambda</a> expressions, can
<a href="../../../../libs/lambda/index.html">Boost.Lambda</a> expressions, can
greatly help alleviate this situation:
</p>
@@ -961,7 +864,7 @@ One or both bounds can be omitted with the special <code>unbounded</code> marker
<h4><a name="ord_updating">Updating</a></h4>
<p>
The <a href="reference/ord_indices.html#replace"><code>replace</code></a> member function
The <a href="../reference/ord_indices.html#replace"><code>replace</code></a> member function
performs in-place replacement of a given element as the following example shows:
</p>
@@ -997,7 +900,7 @@ the updating (when retrieving it and inside <code>replace</code>). 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.MultiIndex
provides an alternative updating mechanism called
<a href="reference/ord_indices.html#modify"><code>modify</code></a>:
<a href="../reference/ord_indices.html#modify"><code>modify</code></a>:
</p>
<blockquote><pre>
@@ -1034,18 +937,69 @@ original value is kept and the method returns without altering the container, bu
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 <code>modify</code>, the element is erased and the method returns
<code>false</code>. This difference in behavior between <code>replace</code> and
<code>modify</code> has to be considered by the programmer on a case-by-case basis.
<code>false</code>. There is a further version of <code>modify</code> which
accepts a <i>rollback</i> functor to undo the changes in case of collision:
</p>
<blockquote><pre>
<span class=keyword>struct</span> <span class=identifier>change_id</span>
<span class=special>{</span>
<span class=identifier>change_id</span><span class=special>(</span><span class=keyword>int</span> <span class=identifier>new_id</span><span class=special>):</span><span class=identifier>new_id</span><span class=special>(</span><span class=identifier>new_id</span><span class=special>){}</span>
<span class=keyword>void</span> <span class=keyword>operator</span><span class=special>()(</span><span class=identifier>employee</span><span class=special>&amp;</span> <span class=identifier>e</span><span class=special>)</span>
<span class=special>{</span>
<span class=identifier>e</span><span class=special>.</span><span class=identifier>id</span><span class=special>=</span><span class=identifier>new_id</span><span class=special>;</span>
<span class=special>}</span>
<span class=keyword>private</span><span class=special>:</span>
<span class=keyword>int</span> <span class=identifier>new_id</span><span class=special>;</span>
<span class=special>};</span>
<span class=special>...</span>
<span class=identifier>employee_set</span><span class=special>::</span><span class=identifier>iterator</span> <span class=identifier>it</span><span class=special>=...</span>
<span class=keyword>int</span> <span class=identifier>old_id</span><span class=special>=</span><span class=identifier>it</span><span class=special>-&gt;</span><span class=identifier>id</span><span class=special>;</span> <span class=comment>// keep the original id
// try to modify the id, restore it in case of collisions</span>
<span class=identifier>es</span><span class=special>.</span><span class=identifier>modify</span><span class=special>(</span><span class=identifier>it</span><span class=special>,</span><span class=identifier>change_id</span><span class=special>(</span><span class=number>321</span><span class=special>),</span><span class=identifier>change_id</span><span class=special>(</span><span class=identifier>old_id</span><span class=special>));</span>
</pre></blockquote>
<p>In the example, <code>change_id(old_id)</code> is invoked to restore the original
conditions when the modification results in collisions with some other element.
The differences in behavior between <code>replace</code>, <code>modify</code> and
<code>modify</code> with rollback have to be considered by the programmer on a
case-by-case basis to determine the best updating mechanism.
</p>
<p align="center">
<table cellspacing="0">
<caption><b>Behavior of the different updating mechanisms.</b></caption>
<tr>
<th align="center">updating function</th>
<th>If there is a collision...</th>
</tr>
<tr>
<td align="center"><code>replace(it,x)</code></td>
<td>replacement does not take place.</td>
</tr>
<tr class="odd_tr">
<td align="center"><code>modify(it,mod)</code></td>
<td>the element is erased.</td>
</tr>
<tr>
<td align="center"><code>modify(it,mod,back)</code></td>
<td><code>back</code> is used to restore the original conditions.
(If <code>back</code> throws, the element is erased.)
</td>
</tr>
</table>
</p>
<p>
A key-based version of <code>modify</code>, named
<a href="reference/ord_indices.html#modify_key"><code>modify_key</code></a>, is
provided as well. In this case, the modifying functor is passed a reference to
the <code>key_value</code> part of the element instead of the whole object. Note
that <code>modify_key</code> cannot be used for key extractors which return calculated
values instead of references to data members of the elements, such
as <code>const_mem_fun</code>.
Key-based versions of <code>modify</code>, named
<a href="../reference/ord_indices.html#modify_key"><code>modify_key</code></a>, are
provided as well. In this case, the modifying functors are passed a reference to
the <code>key_type</code> part of the element instead of the whole object.
</p>
<blockquote><pre>
@@ -1071,10 +1025,10 @@ as <code>const_mem_fun</code>.
</pre></blockquote>
<p>
Just as <code>modify</code> does, <code>modify_key</code> erases the element if
the modification results in collisions in some index. <code>modify</code> and
Like <code>modify</code>, there are versions of <code>modify_key</code> with and
without rollback. <code>modify</code> and
<code>modify_key</code> are particularly well suited to use in conjunction to
<a href="../../../libs/lambda/index.html">Boost.Lambda</a>
<a href="../../../../libs/lambda/index.html">Boost.Lambda</a>
for defining the modifying functors:
</p>
@@ -1088,6 +1042,13 @@ for defining the modifying functors:
<span class=identifier>name_index</span><span class=special>.</span><span class=identifier>modify_key</span><span class=special>(</span><span class=identifier>it</span><span class=special>,</span><span class=identifier>_1</span><span class=special>=</span><span class=string>&quot;Anna Smith&quot;</span><span class=special>);</span>
</pre></blockquote>
<p>
<code>modify_key</code> requires that the key extractor be of
a special type called
<a href="key_extraction.html#read_write_key_extractors">read/write</a>:
this is usually, but not always, the case.
</p>
<h3>
<a name="seq_indices">Sequenced indices</a>
</h3>
@@ -1108,10 +1069,10 @@ indices with respect to <code>std::list</code>s, namely that elements of an
<span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=keyword>int</span><span class=special>,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span><span class=identifier>sequenced</span><span class=special>&lt;&gt;</span> <span class=special>&gt;</span>
<span class=special>&gt;</span> <span class=identifier>s</span><span class=special>;</span> <span class=comment>// list-like container</span>
<span class=special>&gt;</span> <span class=identifier>s</span><span class=special>;</span> <span class=comment>// list-like container</span>
<span class=identifier>s</span><span class=special>.</span><span class=identifier>push_front</span><span class=special>(</span><span class=number>0</span><span class=special>);</span>
<span class=special>*(</span><span class=identifier>s</span><span class=special>.</span><span class=identifier>begin</span><span class=special>())==</span><span class=number>1</span><span class=special>;</span> <span class=comment>// ERROR: the element cannot be changed</span>
<span class=special>*(</span><span class=identifier>s</span><span class=special>.</span><span class=identifier>begin</span><span class=special>())=</span><span class=number>1</span><span class=special>;</span> <span class=comment>// ERROR: the element cannot be changed</span>
</pre></blockquote>
<p>
@@ -1178,15 +1139,15 @@ do not always coincide with those of the standard container. Differences
result mainly from the fact that insertions into a sequenced index are not
guaranteed to succeed, due to the possible banning by other indices
of the <code>multi_index_container</code>. Consult the
<a href="reference/seq_indices.html">reference</a> for further details.
<a href="../reference/seq_indices.html">reference</a> for further details.
</p>
<h4><a name="seq_updating">Updating</a></h4>
<p>
Like ordered indices, sequenced indices provide
<a href="reference/seq_indices.html#replace"><code>replace</code></a> and
<a href="reference/seq_indices.html#modify"><code>modify</code></a>
<a href="../reference/seq_indices.html#replace"><code>replace</code></a> and
<a href="../reference/seq_indices.html#modify"><code>modify</code></a>
operations, with identical functionality. There is however no analogous
<code>modify_key</code>, since sequenced indices are not key-based.
</p>
@@ -1195,7 +1156,7 @@ operations, with identical functionality. There is however no analogous
<p>
Given indices <code>i1</code> and <code>i2</code> on the same <code>multi_index_container</code>,
<a href="reference/multi_index_container.html#projection"><code>project</code></a> can be used to
<a href="../reference/multi_index_container.html#projection"><code>project</code></a> can be used to
retrieve an <code>i2</code>-iterator from an <code>i1</code>-iterator, both of them
pointing to the same element of the container. This functionality allows the programmer to
move between different indices of the same <code>multi_index_container</code> when performing
@@ -1228,7 +1189,7 @@ A slightly more interesting example:
<span class=comment>// prepend &quot;older&quot; to all occurrences of &quot;sister&quot;</span>
<span class=identifier>text_container</span><span class=special>::</span><span class=identifier>nth_index_iterator</span><span class=special>&lt;</span><span class=number>1</span><span class=special>&gt;::</span><span class=identifier>type</span> <span class=identifier>it1</span><span class=special>=</span>
<span class=identifier>text_container</span><span class=special>::</span><span class=identifier>nth_index</span><span class=special>&lt;</span><span class=number>1</span><span class=special>&gt;::</span><span class=identifier>type</span><span class=special>::</span><span class=identifier>iterator</span> <span class=identifier>it1</span><span class=special>=</span>
<span class=identifier>sorted_index</span><span class=special>.</span><span class=identifier>lower_bound</span><span class=special>(</span><span class=string>&quot;sister&quot;</span><span class=special>);</span>
<span class=keyword>while</span><span class=special>(</span><span class=identifier>it1</span><span class=special>!=</span><span class=identifier>sorted_index</span><span class=special>.</span><span class=identifier>end</span><span class=special>()&amp;&amp;*</span><span class=identifier>it1</span><span class=special>==</span><span class=string>&quot;sister&quot;</span><span class=special>){</span>
@@ -1257,33 +1218,33 @@ is preserved in the face of insertions, even for replace and modify operations.
Appropriate instantiations of <code>multi_index_container</code> can in fact simulate
<code>std::set</code>, <code>std::multiset</code> and (with more limitations)
<code>std::list</code>, as shown in the
<a href="advanced_topics.html#simulate_std_containers">advanced topics</a>
<a href="techniques.html#emulate_std_containers">techniques</a>
section. These simulations are as nearly as efficient as the original STL
containers; consult the <a href="reference/index.html">reference</a> for further
containers; consult the <a href="../reference/index.html">reference</a> for further
information on complexity guarantees and the
<a href="performance.html">performance section</a> for practical measurements of
<a href="../performance.html">performance section</a> for practical measurements of
efficiency.
</p>
<hr>
<div class="prev_link"><a href="index.html"><img src="prev.gif" alt="index" border="0"><br>
Index
<div class="prev_link"><a href="index.html"><img src="../prev.gif" alt="tutorial" border="0"><br>
Boost.MultiIndex Tutorial
</a></div>
<div class="up_link"><a href="index.html"><img src="up.gif" alt="index" border="0"><br>
Index
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.MultiIndex tutorial" border="0"><br>
Boost.MultiIndex tutorial
</a></div>
<div class="next_link"><a href="advanced_topics.html"><img src="next.gif" alt="advanced topics" border="0"><br>
Advanced topics
<div class="next_link"><a href="indices.html"><img src="../next.gif" alt="index types" border="0"><br>
Index types
</a></div><br clear="all" style="clear: all;">
<br>
<p>Revised March 31st 2005</p>
<p>Revised November 7th 2008</p>
<p>&copy; Copyright 2003-2005 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
<p>&copy; Copyright 2003-2008 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
http://www.boost.org/LICENSE_1_0.txt</a>)
</p>
+353
View File
@@ -0,0 +1,353 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Boost.MultiIndex Documentation - Tutorial - Container creation</title>
<link rel="stylesheet" href="../style.css" type="text/css">
<link rel="start" href="../index.html">
<link rel="prev" href="key_extraction.html">
<link rel="up" href="index.html">
<link rel="next" href="debug.html">
</head>
<body>
<h1><img src="../../../../boost.png" alt="boost.png (6897 bytes)" align=
"middle" width="277" height="86">Boost.MultiIndex Tutorial: Container creation</h1>
<div class="prev_link"><a href="key_extraction.html"><img src="../prev.gif" alt="key extraction" border="0"><br>
Key extraction
</a></div>
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.MultiIndex tutorial" border="0"><br>
Boost.MultiIndex tutorial
</a></div>
<div class="next_link"><a href="debug.html"><img src="../next.gif" alt="debugging support" border="0"><br>
Debugging support
</a></div><br clear="all" style="clear: all;">
<hr>
<h2>Contents</h2>
<ul>
<li><a href="#value_semantics">Value semantics</a></li>
<li><a href="#ctor_args_list">Use of <code>ctor_args_list</code></a></li>
<li><a href="#special_allocator">Special allocator support</a></li>
<li><a href="#serialization">Serialization</a></li>
</ul>
<h2><a name="value_semantics">Value semantics</a></h2>
<p>
<code>multi_index_container</code>s have the usual value semantics associated
to copy construction and assignment, i.e. copies of the elements from the source
container are created and inserted into the destination container.
More interestingly, copying also recreates the original order in which
elements are arranged for <i>every index</i> of the container.
This implies that equality of all indices is preserved under copying
or assignment, for those index types where equality is defined. This behavior
can be regarded as a natural extension to the general rule on copy semantics
stating that if <code>y</code> is a copy of <code>x</code>, then
<code>y==x</code>.
</p>
<h2><a name="ctor_args_list">Use of <code>ctor_args_list</code></a></h2>
<p>
Although in most cases <code>multi_index_container</code>s will be default constructed
(or copied from a preexisting <code>multi_index_container</code>), sometimes it is
necessary to specify particular values for the internal objects used (key extractors,
comparison predicates, allocator), for instance if some of these objects do not have
a default constructor. The same situation can arise with standard STL containers,
which allow for the optional specification of such objects:
</p>
<blockquote><pre>
<span class=comment>// example of non-default constructed std::set</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>IntegralType</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>modulo_less</span>
<span class=special>{</span>
<span class=identifier>modulo_less</span><span class=special>(</span><span class=identifier>IntegralType</span> <span class=identifier>m</span><span class=special>):</span><span class=identifier>modulo</span><span class=special>(</span><span class=identifier>m</span><span class=special>){}</span>
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>()(</span><span class=identifier>IntegralType</span> <span class=identifier>x</span><span class=special>,</span><span class=identifier>IntegralType</span> <span class=identifier>y</span><span class=special>)</span><span class=keyword>const</span>
<span class=special>{</span>
<span class=keyword>return</span> <span class=special>(</span><span class=identifier>x</span><span class=special>%</span><span class=identifier>modulo</span><span class=special>)&lt;(</span><span class=identifier>y</span><span class=special>%</span><span class=identifier>modulo</span><span class=special>);</span>
<span class=special>}</span>
<span class=keyword>private</span><span class=special>:</span>
<span class=identifier>IntegralType</span> <span class=identifier>modulo</span><span class=special>;</span>
<span class=special>};</span>
<span class=keyword>typedef</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>set</span><span class=special>&lt;</span><span class=keyword>unsigned</span> <span class=keyword>int</span><span class=special>,</span><span class=identifier>modulo_less</span><span class=special>&lt;</span><span class=keyword>unsigned</span> <span class=keyword>int</span><span class=special>&gt;</span> <span class=special>&gt;</span> <span class=identifier>modulo_set</span><span class=special>;</span>
<span class=identifier>modulo_set</span> <span class=identifier>m</span><span class=special>(</span><span class=identifier>modulo_less</span><span class=special>&lt;</span><span class=keyword>unsigned</span> <span class=keyword>int</span><span class=special>&gt;(</span><span class=number>10</span><span class=special>));</span>
</pre></blockquote>
<p>
<code>multi_index_container</code> does also provide this functionality, though in a
considerably more complex fashion, due to the fact that the constructor
of a <code>multi_index_container</code> has to accept values for all the internal
objects of its indices. The full form of <code>multi_index_container</code> constructor
is
</p>
<blockquote><pre>
<span class=keyword>explicit</span> <span class=identifier>multi_index_container</span><span class=special>(</span>
<span class=keyword>const</span> <span class=identifier>ctor_args_list</span><span class=special>&amp;</span> <span class=identifier>args_list</span><span class=special>=</span><span class=identifier>ctor_args_list</span><span class=special>(),</span>
<span class=keyword>const</span> <span class=identifier>allocator_type</span><span class=special>&amp;</span> <span class=identifier>al</span><span class=special>=</span><span class=identifier>allocator_type</span><span class=special>());</span>
</pre></blockquote>
<p>
The specification of the allocator object poses no particular problems;
as for the <code>ctor_args_list</code>, this object is designed so as to hold
the necessary construction values for every index in the <code>multi_index_container</code>.
From the point of view of the user, <code>ctor_args_list</code> is equivalent
to the type
</p>
<blockquote><pre>
<span class=identifier>boost</span><span class=special>::</span><span class=identifier>tuple</span><span class=special>&lt;</span><span class=identifier>C<sub>0</sub></span><span class=special>,...,</span><span class=identifier>C<sub>I-1</sub></span><span class=special>&gt;</span>
</pre></blockquote>
<p>
where <code>I</code> is the number of indices, and <code>C<sub>i</sub></code> is
</p>
<blockquote><pre>
<span class=identifier>nth_index</span><span class=special>&lt;</span><span class=identifier>i</span><span class=special>&gt;::</span><span class=identifier>type</span><span class=special>::</span><span class=identifier>ctor_args</span>
</pre></blockquote>
<p>
that is, the nested type <code>ctor_args</code> of the <code>i</code>-th index. Each
<code>ctor_args</code> type is in turn a tuple holding values for constructor
arguments of the associated index: so, ordered indices demand a key extractor object
and a comparison predicate, hashed indices take an initial number of buckets,
a key extractor, a hash function and an equality predicate; while sequenced
and random access indices do not need any construction argument. For instance,
given the definition
</p>
<blockquote><pre>
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=keyword>unsigned</span> <span class=keyword>int</span><span class=special>,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span>
<span class=identifier>hashed_unique</span><span class=special>&lt;</span><span class=identifier>identity</span><span class=special>&lt;</span><span class=keyword>unsigned</span> <span class=keyword>int</span><span class=special>&gt;</span> <span class=special>&gt;,</span>
<span class=identifier>ordered_non_unique</span><span class=special>&lt;</span><span class=identifier>identity</span><span class=special>&lt;</span><span class=keyword>unsigned</span> <span class=keyword>int</span><span class=special>&gt;,</span> <span class=identifier>modulo_less</span><span class=special>&lt;</span><span class=keyword>unsigned</span> <span class=keyword>int</span><span class=special>&gt;</span> <span class=special>&gt;,</span>
<span class=identifier>sequenced</span><span class=special>&lt;&gt;,</span>
<span class=identifier>random_access</span><span class=special>&lt;&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span> <span class=identifier>modulo_indexed_set</span><span class=special>;</span>
</pre></blockquote>
<p>
the corresponding <code>ctor_args_list</code> type is equivalent to
</p>
<blockquote><pre>
<span class=identifier>boost</span><span class=special>::</span><span class=identifier>tuple</span><span class=special>&lt;</span>
<span class=comment>// ctr_args of index #0</span>
<span class=identifier>boost</span><span class=special>::</span><span class=identifier>tuple</span><span class=special>&lt;</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>size_t</span><span class=special>,</span> <span class=comment>// initial number of buckets; 0 if unspecified</span>
<span class=identifier>identity</span><span class=special>&lt;</span><span class=keyword>unsigned</span> <span class=keyword>int</span><span class=special>&gt;,</span>
<span class=identifier>boost</span><span class=special>::</span><span class=identifier>hash</span><span class=special>&lt;</span><span class=keyword>unsigned</span> <span class=keyword>int</span><span class=special>&gt;,</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>equal_to</span><span class=special>&lt;</span><span class=keyword>unsigned</span> <span class=keyword>int</span><span class=special>&gt;</span> <span class=special>&gt;,</span>
<span class=comment>// ctr_args of index #1</span>
<span class=identifier>boost</span><span class=special>::</span><span class=identifier>tuple</span><span class=special>&lt;</span>
<span class=identifier>identity</span><span class=special>&lt;</span><span class=keyword>unsigned</span> <span class=keyword>int</span><span class=special>&gt;,</span>
<span class=identifier>modulo_less</span><span class=special>&lt;</span><span class=keyword>unsigned</span> <span class=keyword>int</span><span class=special>&gt;</span> <span class=special>&gt;,</span>
<span class=comment>// sequenced indices do not have any construction argument</span>
<span class=identifier>boost</span><span class=special>::</span><span class=identifier>tuple</span><span class=special>&lt;&gt;,</span>
<span class=comment>// neither do random access indices</span>
<span class=identifier>boost</span><span class=special>::</span><span class=identifier>tuple</span><span class=special>&lt;&gt;</span>
<span class=special>&gt;</span>
</pre></blockquote>
<p>
Such a <code>modulo_indexed_set</code> cannot be default constructed, because
<code>modulo_less</code> does not provide a default constructor. The following shows
how the construction can be done:
</p>
<blockquote><pre>
<span class=identifier>modulo_indexed_set</span><span class=special>::</span><span class=identifier>ctor_args_list</span> <span class=identifier>args_list</span><span class=special>=</span>
<span class=identifier>boost</span><span class=special>::</span><span class=identifier>make_tuple</span><span class=special>(</span>
<span class=comment>// ctor_args for index #0 is default constructible</span>
<span class=identifier>modulo_indexed_set</span><span class=special>::</span><span class=identifier>nth_index</span><span class=special>&lt;</span><span class=number>0</span><span class=special>&gt;::</span><span class=identifier>type</span><span class=special>::</span><span class=identifier>ctor_args</span><span class=special>(),</span>
<span class=identifier>boost</span><span class=special>::</span><span class=identifier>make_tuple</span><span class=special>(</span><span class=identifier>identity</span><span class=special>&lt;</span><span class=keyword>unsigned</span> <span class=keyword>int</span><span class=special>&gt;(),</span><span class=identifier>modulo_less</span><span class=special>&lt;</span><span class=keyword>unsigned</span> <span class=keyword>int</span><span class=special>&gt;(</span><span class=number>10</span><span class=special>)),</span>
<span class=comment>// these are also default constructible (actually, empty tuples)</span>
<span class=identifier>modulo_indexed_set</span><span class=special>::</span><span class=identifier>nth_index</span><span class=special>&lt;</span><span class=number>2</span><span class=special>&gt;::</span><span class=identifier>type</span><span class=special>::</span><span class=identifier>ctor_args</span><span class=special>(),</span>
<span class=identifier>modulo_indexed_set</span><span class=special>::</span><span class=identifier>nth_index</span><span class=special>&lt;</span><span class=number>3</span><span class=special>&gt;::</span><span class=identifier>type</span><span class=special>::</span><span class=identifier>ctor_args</span><span class=special>()</span>
<span class=special>);</span>
<span class=identifier>modulo_indexed_set</span> <span class=identifier>m</span><span class=special>(</span><span class=identifier>args_list</span><span class=special>);</span>
</pre></blockquote>
<p>
A program is provided in the <a href="../examples.html#example3">examples section</a> that
puts in practise these concepts.
</p>
<h2><a name="special_allocator">Special allocator support</a></h2>
<p>
Boost.MultiIndex allows for a slightly more general class of allocators
than strictly required by the C++ standard, as explained in detail in the
<a href="../reference/multi_index_container.html#instantiation_types">reference</a>.
An important type of non-standard allocators supported are those provided by the
<a href="../../../interprocess/index.html">Boost Interprocess Library</a>;
this opens up the possibility of placing <code>multi_index_container</code>s
in shared memory.
</p>
<blockquote><pre>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>interprocess</span><span class=special>/</span><span class=identifier>allocators</span><span class=special>/</span><span class=identifier>allocator</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>interprocess</span><span class=special>/</span><span class=identifier>managed_shared_memory</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=keyword>namespace</span> <span class=identifier>bip</span><span class=special>=</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>interprocess</span><span class=special>;</span>
<span class=comment>// a shared memory compatible allocator of ints</span>
<span class=keyword>typedef</span> <span class=identifier>bip</span><span class=special>::</span><span class=identifier>allocator</span><span class=special>&lt;</span>
<span class=keyword>int</span><span class=special>,</span><span class=identifier>bip</span><span class=special>::</span><span class=identifier>managed_shared_memory</span><span class=special>::</span><span class=identifier>segment_manager</span>
<span class=special>&gt;</span> <span class=identifier>shared_int_allocator</span><span class=special>;</span>
<span class=comment>// define a shared memory compatible multi_index_container
// using shared_int_allocator</span>
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=keyword>int</span><span class=special>,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span>
<span class=identifier>sequenced</span><span class=special>&lt;&gt;,</span>
<span class=identifier>ordered_unique</span><span class=special>&lt;</span><span class=identifier>identity</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;</span> <span class=special>&gt;</span>
<span class=special>&gt;,</span>
<span class=identifier>shared_int_allocator</span>
<span class=special>&gt;</span> <span class=identifier>unique_int_list</span><span class=special>;</span>
<span class=special>...</span>
<span class=comment>// create a managed memory segment</span>
<span class=identifier>bip</span><span class=special>::</span><span class=identifier>managed_shared_memory</span> <span class=identifier>seg</span><span class=special>(</span>
<span class=identifier>bip</span><span class=special>::</span><span class=identifier>create_only</span><span class=special>,</span><span class=string>&quot;SharedMemoryID&quot;</span><span class=special>,</span><span class=number>65536</span><span class=special>);</span>
<span class=comment>// construct a unique_int_list into the segment</span>
<span class=identifier>unique_int_list</span><span class=special>*</span> <span class=identifier>puil</span><span class=special>=</span><span class=identifier>seg</span><span class=special>.</span><span class=identifier>construct</span><span class=special>&lt;</span><span class=identifier>unique_int_list</span><span class=special>&gt;</span>
<span class=special>(</span><span class=string>&quot;UniqueIntListID&quot;</span><span class=special>)</span> <span class=comment>// object identifier within the segment
// Construction args: first a ctor arg list, then a
// shared memory allocator obtained from the segment object.</span>
<span class=special>(</span><span class=identifier>unique_int_list</span><span class=special>::</span><span class=identifier>ctor_args_list</span><span class=special>(),</span>
<span class=identifier>unique_int_list</span><span class=special>::</span><span class=identifier>allocator_type</span><span class=special>(</span><span class=identifier>seg</span><span class=special>.</span><span class=identifier>get_segment_manager</span><span class=special>()));</span>
</pre></blockquote>
<p>
The examples section includes a <a href="../examples.html#example12">program</a>
that further explores this capability.
</p>
<h2><a name="serialization">Serialization</a></h2>
<p>
<code>multi_index_container</code>s can be archived and retrieved by means of the
<a href="../../../serialization/index.html">Boost Serialization Library</a>. Both regular
and XML archives are supported. The usage is straightforward and does not
differ from that of any other serializable type. For instance:
</p>
<blockquote><pre>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>archive</span><span class=special>/</span><span class=identifier>text_oarchive</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>archive</span><span class=special>/</span><span class=identifier>text_iarchive</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>fstream</span><span class=special>&gt;</span>
<span class=special>...</span>
<span class=keyword>void</span> <span class=identifier>save</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>employee_set</span><span class=special>&amp;</span> <span class=identifier>es</span><span class=special>)</span>
<span class=special>{</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>ofstream</span> <span class=identifier>ofs</span><span class=special>(</span><span class=string>&quot;data&quot;</span><span class=special>);</span>
<span class=identifier>boost</span><span class=special>::</span><span class=identifier>archive</span><span class=special>::</span><span class=identifier>text_oarchive</span> <span class=identifier>oa</span><span class=special>(</span><span class=identifier>ofs</span><span class=special>);</span>
<span class=identifier>oa</span><span class=special>&lt;&lt;</span><span class=identifier>es</span><span class=special>;</span>
<span class=special>}</span>
<span class=keyword>void</span> <span class=identifier>load</span><span class=special>(</span><span class=identifier>employee_set</span><span class=special>&amp;</span> <span class=identifier>es</span><span class=special>)</span>
<span class=special>{</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>ifstream</span> <span class=identifier>ifs</span><span class=special>(</span><span class=string>&quot;data&quot;</span><span class=special>);</span>
<span class=identifier>boost</span><span class=special>::</span><span class=identifier>archive</span><span class=special>::</span><span class=identifier>text_iarchive</span> <span class=identifier>ia</span><span class=special>(</span><span class=identifier>ifs</span><span class=special>);</span>
<span class=identifier>ia</span><span class=special>&gt;&gt;</span><span class=identifier>es</span><span class=special>;</span>
<span class=special>}</span>
<span class=special>...</span>
<span class=identifier>employee_set</span> <span class=identifier>es</span><span class=special>;</span>
<span class=special>...</span> <span class=comment>// fill it with data</span>
<span class=identifier>save</span><span class=special>(</span><span class=identifier>es</span><span class=special>);</span>
<span class=special>...</span>
<span class=identifier>employee_set</span> <span class=identifier>restored_es</span><span class=special>;</span>
<span class=identifier>load</span><span class=special>(</span><span class=identifier>restored_es</span><span class=special>);</span>
</pre></blockquote>
<p>
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
<code>BOOST_MULTI_INDEX_DISABLE_SERIALIZATION</code>. 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.
</p>
<p>
In accordance with Boost.MultiIndex
<a href="#value_semantics">value semantics</a>, retrieving an
archived <code>multi_index_container</code> restores not only
the elements, but also the order they were arranged into for
every index of the container. There is an exception to this rule,
though: for <a href="indices.html#hashed_indices">hashed
indices</a>, 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 index, 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.
</p>
<p>
Iterators to indices of a <code>multi_index_container</code> can also be
serialized. Serialization of iterators must be done only after serializing
their corresponding container.
</p>
<p>
<a href="../examples.html#example9">Example 9</a> in the examples section shows
the serialization capabilities of Boost.MultiIndex.
</p>
<hr>
<div class="prev_link"><a href="key_extraction.html"><img src="../prev.gif" alt="key extraction" border="0"><br>
Key extraction
</a></div>
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.MultiIndex tutorial" border="0"><br>
Boost.MultiIndex tutorial
</a></div>
<div class="next_link"><a href="debug.html"><img src="../next.gif" alt="debugging support" border="0"><br>
Debugging support
</a></div><br clear="all" style="clear: all;">
<br>
<p>Revised July 17th 2007</p>
<p>&copy; Copyright 2003-2007 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
http://www.boost.org/LICENSE_1_0.txt</a>)
</p>
</body>
</html>
+252
View File
@@ -0,0 +1,252 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Boost.MultiIndex Documentation - Tutorial -Debugging support</title>
<link rel="stylesheet" href="../style.css" type="text/css">
<link rel="start" href="../index.html">
<link rel="prev" href="creation.html">
<link rel="up" href="index.html">
<link rel="next" href="techniques.html">
</head>
<body>
<h1><img src="../../../../boost.png" alt="boost.png (6897 bytes)" align=
"middle" width="277" height="86">Boost.MultiIndex Tutorial: Debugging support</h1>
<div class="prev_link"><a href="creation.html"><img src="../prev.gif" alt="container creation" border="0"><br>
Container creation
</a></div>
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.MultiIndex tutorial" border="0"><br>
Boost.MultiIndex tutorial
</a></div>
<div class="next_link"><a href="techniques.html"><img src="../next.gif" alt="techniques" border="0"><br>
Techniques
</a></div><br clear="all" style="clear: all;">
<hr>
<h2>Contents</h2>
<ul>
<li><a href="#debugging_support">Debugging support</a></li>
<li><a href="#safe_mode">Safe mode</a>
<ul>
<li><a href="#serialization_and_safe_mode">Serialization and safe mode</a></li>
</ul>
</li>
<li><a href="#invariant_check">Invariant-checking mode</a></li>
</ul>
<h2><a name="debugging_support">Debugging support</a></h2>
<p>
The concept of <i>Design by Contract</i>, originally developed as part
of Bertrand Meyer's <a href="http://www.eiffel.com">Eiffel</a> language,
revolves around the formulation of a <i>contract</i> between the user
of a library and the implementor, by which the first is required to
respect some <i>preconditions</i> on the values passed when invoking
methods of the library, and the implementor guarantees in return
that certain constraints on the results are met (<i>postconditions</i>),
as well as the honoring of specified internal consistency rules, called
<i>invariants</i>. Eiffel natively supports the three parts of the
contract just described by means of constructs <code>require</code>,
<code>ensure</code> and <code>invariant</code>, respectively.
</p>
<p>
C++ does not enjoy direct support for Design by Contract techniques: these
are customarily implemented as assertion code, often turned off in
release mode for performance reasons. Following this approach,
Boost.MultiIndex provides two distinct debugging modes:
<ul>
<li><i>Safe mode</i> checks preconditions on the invocations to the
facilities of the library,</li>
<li><i>invariant-checking mode</i> performs post-execution checks aimed
at ensuring that the internal consistency of the library is preserved.</li>
</ul>
These two modes are independent of each other and can be set on or off
individually. It is important to note that errors detected by safe mode are
due in principle to faulty code in the user's program, while
invariant-checking mode detects potential <i>internal</i> bugs in the
implementation of Boost.MultiIndex.
</p>
<h2><a name="safe_mode">Safe mode</a></h2>
<p>
The idea of adding precondition checking facilities to STL as a debugging aid
was first introduced by Cay S. Horstmann in his
<a href="http://www.horstmann.com/safestl.html">Safe STL</a> library and later
adopted by <a href="http://www.stlport.com/doc/debug_mode.html">STLport Debug
Mode</a>. Similarly, Boost.MultiIndex features the so-called <i>safe mode</i>
in which all sorts of preconditions are checked when dealing with iterators
and functions of the library.
</p>
<p>
Boost.MultiIndex safe mode is set by globally defining the macro
<code>BOOST_MULTI_INDEX_ENABLE_SAFE_MODE</code>. Error conditions
are checked via the macro <code>BOOST_MULTI_INDEX_SAFE_MODE_ASSERT</code>, which
by default resolves to a call to <a href="../../../../libs/utility/assert.html">
<code>BOOST_ASSERT</code></a>.
</p>
<p>
If the user decides to define her own version of
<code>BOOST_MULTI_INDEX_SAFE_MODE_ASSERT</code>, it has to take the form
</p>
<blockquote><pre>
<span class=identifier>BOOST_MULTI_INDEX_SAFE_MODE_ASSERT</span><span class=special>(</span><span class=identifier>expr</span><span class=special>,</span><span class=identifier>error_code</span><span class=special>)</span>
</pre></blockquote>
<p>
where <code>expr</code> is the condition checked and <code>error_code</code>
is one value of the <code>safe_mode::error_code</code> enumeration:
</p>
<blockquote><pre>
<span class=keyword>namespace</span> <span class=identifier>boost</span><span class=special>{</span>
<span class=keyword>namespace</span> <span class=identifier>multi_index</span><span class=special>{</span>
<span class=keyword>namespace</span> <span class=identifier>safe_mode</span><span class=special>{</span>
<span class=keyword>enum</span> <span class=identifier>error_code</span>
<span class=special>{</span>
<span class=identifier>invalid_iterator</span><span class=special>,</span> <span class=comment>// vg. default cted or pointing to erased element</span>
<span class=identifier>not_dereferenceable_iterator</span><span class=special>,</span> <span class=comment>// iterator is not dereferenceable</span>
<span class=identifier>not_incrementable_iterator</span><span class=special>,</span> <span class=comment>// iterator points to end of sequence</span>
<span class=identifier>not_decrementable_iterator</span><span class=special>,</span> <span class=comment>// iterator points to beginning of sequence</span>
<span class=identifier>not_owner</span><span class=special>,</span> <span class=comment>// iterator does not belong to the container</span>
<span class=identifier>not_same_owner</span><span class=special>,</span> <span class=comment>// iterators belong to different containers</span>
<span class=identifier>invalid_range</span><span class=special>,</span> <span class=comment>// last not reachable from first</span>
<span class=identifier>inside_range</span><span class=special>,</span> <span class=comment>// iterator lies within a range (and it mustn't)</span>
<span class=identifier>out_of_bounds</span><span class=special>,</span> <span class=comment>// move attempted beyond container limits</span>
<span class=identifier>same_container</span> <span class=comment>// containers ought to be different</span>
<span class=special>};</span>
<span class=special>}</span> <span class=comment>// namespace multi_index::safe_mode</span>
<span class=special>}</span> <span class=comment>// namespace multi_index</span>
<span class=special>}</span> <span class=comment>// namespace boost</span>
</pre></blockquote>
<p>
For instance, the following replacement of
<code>BOOST_MULTI_INDEX_SAFE_MODE_ASSERT</code> throws an exception instead of
asserting:
</p>
<blockquote><pre>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index_container</span><span class=special>/</span><span class=identifier>safe_mode_errors</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>safe_mode_exception</span>
<span class=special>{</span>
<span class=identifier>safe_mode_exception</span><span class=special>(</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>multi_index</span><span class=special>::</span><span class=identifier>safe_mode</span><span class=special>::</span><span class=identifier>error_code</span> <span class=identifier>error_code</span><span class=special>):</span>
<span class=identifier>error_code</span><span class=special>(</span><span class=identifier>error_code</span><span class=special>)</span>
<span class=special>{}</span>
<span class=identifier>boost</span><span class=special>::</span><span class=identifier>multi_index</span><span class=special>::</span><span class=identifier>safe_mode</span><span class=special>::</span><span class=identifier>error_code</span> <span class=identifier>error_code</span><span class=special>;</span>
<span class=special>};</span>
<span class=preprocessor>#define</span> <span class=identifier>BOOST_MULTI_INDEX_SAFE_MODE_ASSERT</span><span class=special>(</span><span class=identifier>expr</span><span class=special>,</span><span class=identifier>error_code</span><span class=special>)</span> <span class=special>\</span>
<span class=keyword>if</span><span class=special>(!(</span><span class=identifier>expr</span><span class=special>)){</span><span class=keyword>throw</span> <span class=identifier>safe_mode_exception</span><span class=special>(</span><span class=identifier>error_code</span><span class=special>);}</span>
<span class=comment>// This has to go before the inclusion of any header from Boost.MultiIndex,
// except possibly safe_error_codes.hpp.</span>
</pre></blockquote>
<p>
Other possibilites, like outputting to a log or firing some kind of alert, are
also implementable.
</p>
<p>
<b>Warning:</b> Safe mode adds a very important overhead to the program
both in terms of space and time used, so in general it should not be set for
<code>NDEBUG</code> builds. Also, this mode is intended solely as a debugging aid,
and programs must not rely on it as part of their normal execution flow: in
particular, no guarantee is made that all possible precondition errors are diagnosed,
or that the checks remain stable across different versions of the library.
</p>
<h3><a name="serialization_and_safe_mode">Serialization and safe mode</a></h3>
<p>
Iterators restored from an archive are not subject to safe mode checks. This is
so because it is not possible to automatically know the associated
<code>multi_index_container</code> of an iterator from the serialization
information alone. However, if desired, a restored iterator can be converted to a
checked value by using the following workaround:
</p>
<blockquote><pre>
<span class=identifier>employee_set</span> <span class=identifier>es</span><span class=special>;</span>
<span class=identifier>employee_set</span><span class=special>::</span><span class=identifier>nth_index</span><span class=special>&lt;</span><span class=number>1</span><span class=special>&gt;::</span><span class=identifier>iterator</span> <span class=identifier>it</span><span class=special>;</span>
<span class=comment>// restore es and it from an archive ar</span>
<span class=identifier>ar</span><span class=special>&gt;&gt;</span><span class=identifier>es</span><span class=special>;</span>
<span class=identifier>ar</span><span class=special>&gt;&gt;</span><span class=identifier>it</span><span class=special>;</span> <span class=comment>// it won't benefit from safe mode checks
// Turn it into a checked value by providing Boost.MultiIndex
// with info about the associated container.
// This statement has virtually zero cost if safe mode is turned off.</span>
<span class=identifier>it</span><span class=special>=</span><span class=identifier>es</span><span class=special>.</span><span class=identifier>project</span><span class=special>&lt;</span><span class=number>1</span><span class=special>&gt;(</span><span class=identifier>it</span><span class=special>);</span>
</pre></blockquote>
<h2><a name="invariant_check">Invariant-checking mode</a></h2>
<p>
The so called <i>invariant-checking mode</i> of Boost.MultiIndex can be
set by globally defining the macro
<code>BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING</code>.
When this mode is in effect, all public functions of Boost.MultiIndex
will perform post-execution tests aimed at ensuring that the basic
internal invariants of the data structures managed are preserved.
</p>
<p>
If an invariant test fails, Boost.MultiIndex will indicate the failure
by means of the unary macro <code>BOOST_MULTI_INDEX_INVARIANT_ASSERT</code>.
Unless the user provides a definition for this macro, it defaults to
<a href="../../../../libs/utility/assert.html">
<code>BOOST_ASSERT</code></a>. Any assertion of this kind should
be regarded in principle as a bug in the library. Please report such
problems, along with as much contextual information as possible, to the
maintainer of the library.
</p>
<p>
It is recommended that users of Boost.MultiIndex always set the
invariant-checking mode in debug builds.
</p>
<hr>
<div class="prev_link"><a href="creation.html"><img src="../prev.gif" alt="container creation" border="0"><br>
Container creation
</a></div>
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.MultiIndex tutorial" border="0"><br>
Boost.MultiIndex tutorial
</a></div>
<div class="next_link"><a href="techniques.html"><img src="../next.gif" alt="techniques" border="0"><br>
Techniques
</a></div><br clear="all" style="clear: all;">
<br>
<p>Revised February 6th 2006</p>
<p>&copy; Copyright 2003-2006 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
http://www.boost.org/LICENSE_1_0.txt</a>)
</p>
</body>
</html>
+139
View File
@@ -0,0 +1,139 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Boost.MultiIndex Documentation - Tutorial</title>
<link rel="stylesheet" href="../style.css" type="text/css">
<link rel="start" href="../index.html">
<link rel="prev" href="../index.html">
<link rel="up" href="../index.html">
<link rel="next" href="basics.html">
</head>
<body>
<h1><img src="../../../../boost.png" alt="boost.png (6897 bytes)" align=
"middle" width="277" height="86">Boost.MultiIndex Tutorial</h1>
<div class="prev_link"><a href="../index.html"><img src="../prev.gif" alt="index" border="0"><br>
Index
</a></div>
<div class="up_link"><a href="../index.html"><img src="../up.gif" alt="index" border="0"><br>
Index
</a></div>
<div class="next_link"><a href="basics.html"><img src="../next.gif" alt="basics" border="0"><br>
Basics
</a></div><br clear="all" style="clear: all;">
<hr>
<h2>Contents</h2>
<ul>
<li><a href="#rationale">Rationale</a></li>
<li><a href="#namespace">Namespace</a></li>
<li><a href="basics.html">Basics</a></li>
<li><a href="indices.html">Index types</a></li>
<li><a href="key_extraction.html">Key extraction</a></li>
<li><a href="creation.html">Container creation</a></li>
<li><a href="debug.html">Debugging support</a></li>
<li><a href="techniques.html">Techniques</a></li>
</ul>
<h2><a name="rationale">Rationale</a></h2>
<p>
STL containers are designed around the concept that each container controls its
own collection of elements, giving access to them in a manner specified by the
container's type: so, an <code>std::set</code> maintains the elements ordered
by a specified sorting criterion, <code>std::list</code> allows for free
positioning of elements along a linear sequence, and so on.
</p>
<p>
Sometimes, the necessity arises of having different access interfaces
to the same underlying collection: for instance, some data might need to be
sorted according to more than one comparison predicate, or a bidirectional list
might benefit from a supplemental logarithmic lookup interface. In these
situations, programmers typically resort to manual compositions of different
containers, a solution that generally involves a fair amount of code
devoted to preserve the synchronization of the different parts of
the composition. Boost.MultiIndex allows for the specification of
<code>multi_index_container</code>s comprised of one or more <i>indices</i> with
different interfaces to the same collection of elements. The resulting constructs
are conceptually cleaner than manual compositions, and often perform much better.
An important design decision has been taken that the indices of a given
<code>multi_index_container</code> instantiation be specified at compile time: this
gives ample room for static type checking and code optimization.
</p>
<p>
Boost.MultiIndex takes inspiration from basic concepts of indexing arising in the
theory of relational databases, though it is not intended to provide a full-fledged
relational database framework. <code>multi_index_container</code> integrates seamlessly
into the STL container/algorithm design, and features some extra capabilities regarding
lookup operations and element updating which are useful extensions even for
single-indexed containers.
</p>
<p align="center">
<img src="multi_index_cont_example.png"
alt="diagram of a multi_index_container with three indices"
width="600" height="304"><br>
<b>Fig. 1: Diagram of a <code>multi_index_container</code> with three indices.</b>
</p>
<p>
The figure above depicts a <code>multi_index_container</code> composed of three indices:
the first two present a set-like interface to the elements sorted by
shape and id, respectively, while the latter index provides the functionality
of a bidirectional list in the spirit of <code>std::list</code>. These
indices act as "views" to the internal collection of elements, but they do not only
provide read access to the set: insertion/deletion methods are also implemented much
as those of <code>std::set</code>s or <code>std::list</code>s. Insertion of an
element through one given index will only succeed if the uniqueness constraints of all
indices are met.
</p>
<h2>
<a name="namespace">Namespace</a>
</h2>
<p>
All the public types of Boost.MultiIndex reside in namespace <code>::boost::multi_index</code>.
Additionaly, the main class template <code>multi_index_container</code> and global functions
<code>get</code> and <code>project</code> are lifted to namespace <code>::boost</code>
by means of <code>using</code> declarations. For brevity of exposition, the fragments
of code in the documentation are written as if the following declarations were in effect:
</p>
<blockquote><pre>
<span class=keyword>using</span> <span class=keyword>namespace</span> <span class=special>::</span><span class=identifier>boost</span><span class=special>;</span>
<span class=keyword>using</span> <span class=keyword>namespace</span> <span class=special>::</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>multi_index</span><span class=special>;</span>
</pre></blockquote>
<hr>
<div class="prev_link"><a href="../index.html"><img src="../prev.gif" alt="index" border="0"><br>
Index
</a></div>
<div class="up_link"><a href="../index.html"><img src="../up.gif" alt="index" border="0"><br>
Index
</a></div>
<div class="next_link"><a href="basics.html"><img src="../next.gif" alt="basics" border="0"><br>
Basics
</a></div><br clear="all" style="clear: all;">
<br>
<p>Revised February 21st 2006</p>
<p>&copy; Copyright 2003-2006 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
http://www.boost.org/LICENSE_1_0.txt</a>)
</p>
</body>
</html>
+731
View File
@@ -0,0 +1,731 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Boost.MultiIndex Documentation - Tutorial - Index types</title>
<link rel="stylesheet" href="../style.css" type="text/css">
<link rel="start" href="../index.html">
<link rel="prev" href="basics.html">
<link rel="up" href="index.html">
<link rel="next" href="key_extraction.html">
</head>
<body>
<h1><img src="../../../../boost.png" alt="boost.png (6897 bytes)" align=
"middle" width="277" height="86">Boost.MultiIndex Tutorial: Index types</h1>
<div class="prev_link"><a href="basics.html"><img src="../prev.gif" alt="basics" border="0"><br>
Basics
</a></div>
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.MultiIndex tutorial" border="0"><br>
Boost.MultiIndex tutorial
</a></div>
<div class="next_link"><a href="key_extraction.html"><img src="../next.gif" alt="key estraction" border="0"><br>
Key extraction
</a></div><br clear="all" style="clear: all;">
<hr>
<h2>Contents</h2>
<ul>
<li><a href="#classification">Classification</a>
<li><a href="#hashed_indices">Hashed indices</a>
<ul>
<li><a href="#hash_unique_non_unique">Unique and non-unique variants</a></li>
<li><a href="#hash_spec">Specification</a></li>
<li><a href="#hash_lookup">Lookup</a></li>
<li><a href="#hash_updating">Updating</a></li>
<li><a href="#guarantees">Guarantees on iterator validity and exception safety</a></li>
</ul>
</li>
<li><a href="#rnd_indices">Random access indices</a>
<ul>
<li><a href="#rnd_spec">Specification</a></li>
<li><a href="#rnd_interface">Interface</a></li>
<li><a href="#rnd_vs_vector">Comparison with <code>std::vector</code></a></li>
</ul>
</li>
<li><a href="#rearrange">Index rearranging</a></li>
<li><a href="#iterator_to"><code>iterator_to</code></a></li>
<li><a href="#ordered_node_compression">Ordered indices node compression</a></li>
</ul>
<h2><a name="classification">Classification</a></h2>
<p>
Boost.MultiIndex provides six different index types, which can be classified as
shown in the table below. <a href="basics.html#ord_indices">Ordered</a> and
<a href="basics.html#seq_indices">sequenced</a> indices,
which are the most commonly used, have been explained in the basics section;
the rest of index types can be regarded as variations of the former providing
some added benefits, functionally or in the area of performance.
</p>
<p align="center">
<table cellspacing="0">
<caption><b>Boost.MultiIndex indices.</b></caption>
<tr>
<th align="center"colspan="2">type</th>
<th align="center">specifier</th>
</tr>
<tr>
<td align="center" rowspan="4">&nbsp;&nbsp;key-based&nbsp;&nbsp;</td>
<td align="center" rowspan="2">&nbsp;&nbsp;ordered&nbsp;&nbsp;</td>
<td align="center">&nbsp;&nbsp;<code>ordered_unique</code>&nbsp;&nbsp;</td>
</tr>
<tr class="odd_tr">
<td align="center">&nbsp;&nbsp;<code>ordered_non_unique</code>&nbsp;&nbsp;</td>
</tr>
<tr>
<td align="center" rowspan="2">&nbsp;&nbsp;hashed&nbsp;&nbsp;</td>
<td align="center">&nbsp;&nbsp;<code>hashed_unique</code>&nbsp;&nbsp;</td>
</tr>
<tr class="odd_tr">
<td align="center">&nbsp;&nbsp;<code>hashed_non_unique</code>&nbsp;&nbsp;</td>
</tr>
<tr>
<td align="center" rowspan="2" colspan="2">&nbsp;&nbsp;non key-based&nbsp;&nbsp;</td>
<td align="center"><code>&nbsp;&nbsp;sequenced&nbsp;&nbsp;</code></td>
</tr>
<tr class="odd_tr">
<td align="center"><code>&nbsp;&nbsp;random_access&nbsp;&nbsp;</code></td>
</tr>
</table>
</p>
<p>
Key-based indices, of which ordered indices are the usual example, provide
efficient lookup of elements based on some piece of information called the
<i>element key</i>: there is an extensive suite of
<a href="key_extraction.html">key extraction</a>
utility classes allowing for the specification of such keys. Fast lookup
imposes an internally managed order on these indices that the user is not
allowed to modify; non key-based indices, on the other hand, can be freely
rearranged at the expense of lacking lookup facilities. Sequenced indices,
modeled after the interface of <code>std::list</code>, are the customary
example of a non key-based index.
</p>
<h2><a name="hashed_indices">Hashed indices</a></h2>
<p>
Hashed indices constitute a trade-off with respect to ordered indices: if correctly used,
they provide much faster lookup of elements, at the expense of losing sorting
information.
Let us revisit our <code>employee_set</code> example: suppose a field for storing
the Social Security number is added, with the requisite that lookup by this
number should be as fast as possible. Instead of the usual ordered index, a
hashed index can be resorted to:
</p>
<blockquote><pre>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index_container</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>hashed_index</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>ordered_index</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>identity</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>member</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>employee</span>
<span class=special>{</span>
<span class=keyword>int</span> <span class=identifier>id</span><span class=special>;</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>name</span><span class=special>;</span>
<span class=keyword>int</span> <span class=identifier>ssnumber</span><span class=special>;</span>
<span class=identifier>employee</span><span class=special>(</span><span class=keyword>int</span> <span class=identifier>id</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&amp;</span> <span class=identifier>name</span><span class=special>,</span><span class=keyword>int</span> <span class=identifier>ssnumber</span><span class=special>):</span>
<span class=identifier>id</span><span class=special>(</span><span class=identifier>id</span><span class=special>),</span><span class=identifier>name</span><span class=special>(</span><span class=identifier>name</span><span class=special>),</span><span class=identifier>ssnumber</span><span class=special>(</span><span class=identifier>ssnumber</span><span class=special>){}</span>
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>&lt;(</span><span class=keyword>const</span> <span class=identifier>employee</span><span class=special>&amp;</span> <span class=identifier>e</span><span class=special>)</span><span class=keyword>const</span><span class=special>{</span><span class=keyword>return</span> <span class=identifier>id</span><span class=special>&lt;</span><span class=identifier>e</span><span class=special>.</span><span class=identifier>id</span><span class=special>;}</span>
<span class=special>};</span>
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=identifier>employee</span><span class=special>,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span>
<span class=comment>// sort by employee::operator&lt;</span>
<span class=identifier>ordered_unique</span><span class=special>&lt;</span><span class=identifier>identity</span><span class=special>&lt;</span><span class=identifier>employee</span><span class=special>&gt;</span> <span class=special>&gt;,</span>
<span class=comment>// sort by less&lt;string&gt; on name</span>
<span class=identifier>ordered_non_unique</span><span class=special>&lt;</span><span class=identifier>member</span><span class=special>&lt;</span><span class=identifier>employee</span><span class=special>,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,&amp;</span><span class=identifier>employee</span><span class=special>::</span><span class=identifier>name</span><span class=special>&gt;</span> <span class=special>&gt;,</span>
<span class=comment>// hashed on ssnumber</span>
<span class=identifier>hashed_unique</span><span class=special>&lt;</span><span class=identifier>member</span><span class=special>&lt;</span><span class=identifier>employee</span><span class=special>,</span><span class=keyword>int</span><span class=special>,&amp;</span><span class=identifier>employee</span><span class=special>::</span><span class=identifier>ssnumber</span><span class=special>&gt;</span> <span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span> <span class=identifier>employee_set</span>
</pre></blockquote>
<p>
Note that the hashed index does not guarantee any particular ordering of the
elements: so, for instance, we cannot efficiently query the employees whose SSN is
greater than a given number. Usually, you must consider these restrictions when
determining whether a hashed index is preferred over an ordered one.
</p>
<p>
If you are familiar with non-standard <code>hash_set</code>s provided
by some compiler vendors, then learning to use hashed indices should be straightforward.
However, the interface of hashed indices is modeled after the specification
for unordered associative containers by the
<a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1836.pdf">C++ Standard
Library Technical Report</a> (TR1),
which differs in some significant aspects from existing pre-standard
implementations:
<ul>
<li>As there is no notion of ordering between keys, the <a href="#hash_lookup">lookup
interface</a> does not offer <code>lower_bound</code> or <code>upper_bound</code>
member functions (unlike Dinkumware's solution.)</li>
<li>A set of member functions is provided for handling the internal
bucket structure on which hashed indices rely. This includes facilities
for <a href="../reference/hash_indices.html#hash_policy">rehashing</a>,
control of the load factor (number of elements divided by number of buckets),
and inspection of the buckets contents. Pre-standard implementations
do not have such an extensive functionality.</li>
</ul>
Check the <a href="../reference/hash_indices.html">reference</a> for a
complete specification of the interface of hashed indices,
and <a href="../examples.html#example8">example 8</a> and
<a href="../examples.html#example9">example 9</a> for practical applications.
</p>
</p>
<h3><a name="hash_unique_non_unique">Unique and non-unique variants</a></h3>
<p>
Just like ordered indices, hashed indices have unique and non-unique variants, selected
with the specifiers <code>hashed_unique</code> and <code>hashed_non_unique</code>,
respectively. In the latter case, elements with equivalent keys are kept together and can
be jointly retrieved by means of the <code>equal_range</code> member function.
</p>
<h3><a name="hash_spec">Specification</a></h3>
<p>
Hashed indices specifiers have two alternative syntaxes, depending on whether
<a href="basics.html#tagging">tags</a> are provided or not:
</p>
<blockquote><pre>
<span class=special>(</span><span class=identifier>hashed_unique</span> <span class=special>|</span> <span class=identifier>hashed_non_unique</span><span class=special>)
</span><span class=special>&lt;[</span><i>(tag)</i><span class=special>[,</span><i>(key extractor)</i><span class=special>[,</span><i>(hash function)</i><span class=special>[,</span><i>(equality predicate)</i><span class=special>]]]]&gt;</span>
<span class=special>(</span><span class=identifier>hashed_unique</span> <span class=special>|</span> <span class=identifier>hashed_non_unique</span><span class=special>)</span>
<span class=special>&lt;[</span><i>(key extractor)</i><span class=special>[,</span><i>(hash function)</i><span class=special>[,</span><i>(equality predicate)</i><span class=special>]]]&gt;</span>
</pre></blockquote>
<p>
The key extractor parameter works in exactly the same way as for
<a href="basics.html#key_extraction">ordered indices</a>; lookup, insertion,
etc., are based on the key returned by the extractor rather than the whole
element.
</p>
<p>
The hash function is the very core of the fast lookup capabilities of this type of
indices: a hasher
is just a <a href="http://www.sgi.com/tech/stl/UnaryFunction.html"><code>Unary
Function</code></a> returning an <code>std::size_t</code> 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 <i>every</i> possible scenario; the default value for this parameter uses
<a href="../../../functional/hash/index.html">Boost.Hash</a>, which often provides good
enough results.
</p>
<p>
The equality predicate is used to determine whether two keys are to be treated
as the same. The default
value <code>std::equal_to&lt;KeyFromValue::result_type&gt;</code> is in most
cases exactly what is needed, so very rarely will you have to provide
your own predicate. Note that hashed indices require that two
equivalent keys have the same hash value, which
in practice greatly reduces the freedom in choosing an equality predicate.
</p>
<h3><a name="hash_lookup">Lookup</a></h3>
<p>
The lookup interface of hashed indices consists in member functions
<code>find</code>, <code>count</code> and <code>equal_range</code>.
Note that <code>lower_bound</code> and <code>upper_bound</code> are not
provided, as there is no intrinsic ordering of keys in this type of indices.
</p>
<p>
Just as with ordered indices, these member functions take keys
as their search arguments, rather than entire objects. Remember that
ordered indices lookup operations are further augmented to accept
<i>compatible keys</i>, which can roughly be regarded as "subkeys".
For hashed indices, a concept of
<a href="../reference/hash_indices.html#lookup">compatible key</a> is also
supported, though its usefulness is much more limited: basically,
a compatible key is an object which is entirely equivalent to
a native object of <code>key_type</code> value, though maybe with
a different internal representation:
</p>
<blockquote><pre>
<span class=comment>// US SSN numbering scheme</span>
<span class=keyword>struct</span> <span class=identifier>ssn</span>
<span class=special>{</span>
<span class=identifier>ssn</span><span class=special>(</span><span class=keyword>int</span> <span class=identifier>area_no</span><span class=special>,</span><span class=keyword>int</span> <span class=identifier>group_no</span><span class=special>,</span><span class=keyword>int</span> <span class=identifier>serial_no</span><span class=special>):</span>
<span class=identifier>area_no</span><span class=special>(</span><span class=identifier>area_no</span><span class=special>),</span><span class=identifier>group_no</span><span class=special>(</span><span class=identifier>group_no</span><span class=special>),</span><span class=identifier>serial_no</span><span class=special>(</span><span class=identifier>serial_no</span><span class=special>)</span>
<span class=special>{}</span>
<span class=keyword>int</span> <span class=identifier>to_int</span><span class=special>()</span><span class=keyword>const</span>
<span class=special>{</span>
<span class=keyword>return</span> <span class=identifier>serial_no</span><span class=special>+</span><span class=number>10000</span><span class=special>*</span><span class=identifier>group_no</span><span class=special>+</span><span class=number>1000000</span><span class=special>*</span><span class=identifier>area_no</span><span class=special>;</span>
<span class=special>}</span>
<span class=keyword>private</span><span class=special>:</span>
<span class=keyword>int</span> <span class=identifier>area_no</span><span class=special>;</span>
<span class=keyword>int</span> <span class=identifier>group_no</span><span class=special>;</span>
<span class=keyword>int</span> <span class=identifier>serial_no</span><span class=special>;</span>
<span class=special>};</span>
<span class=comment>// interoperability with SSNs in raw int form</span>
<span class=keyword>struct</span> <span class=identifier>ssn_equal</span>
<span class=special>{</span>
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>ssn</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>int</span> <span class=identifier>y</span><span class=special>)</span><span class=keyword>const</span>
<span class=special>{</span>
<span class=keyword>return</span> <span class=identifier>x</span><span class=special>.</span><span class=identifier>to_int</span><span class=special>()==</span><span class=identifier>y</span><span class=special>;</span>
<span class=special>}</span>
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>int</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>ssn</span><span class=special>&amp;</span> <span class=identifier>y</span><span class=special>)</span><span class=keyword>const</span>
<span class=special>{</span>
<span class=keyword>return</span> <span class=identifier>x</span><span class=special>==</span><span class=identifier>y</span><span class=special>.</span><span class=identifier>to_int</span><span class=special>();</span>
<span class=special>}</span>
<span class=special>};</span>
<span class=keyword>struct</span> <span class=identifier>ssn_hash</span>
<span class=special>{</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>size_t</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>ssn</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span>
<span class=special>{</span>
<span class=keyword>return</span> <span class=identifier>boost</span><span class=special>::</span><span class=identifier>hash</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;()(</span><span class=identifier>x</span><span class=special>.</span><span class=identifier>to_int</span><span class=special>());</span>
<span class=special>}</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>size_t</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>int</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span>
<span class=special>{</span>
<span class=keyword>return</span> <span class=identifier>boost</span><span class=special>::</span><span class=identifier>hash</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;()(</span><span class=identifier>x</span><span class=special>);</span>
<span class=special>}</span>
<span class=special>};</span>
<span class=keyword>typedef</span> <span class=identifier>employee_set</span><span class=special>::</span><span class=identifier>nth_index</span><span class=special>&lt;</span><span class=number>2</span><span class=special>&gt;::</span><span class=identifier>type</span> <span class=identifier>employee_set_by_ssn</span><span class=special>;</span>
<span class=identifier>employee_set</span> <span class=identifier>es</span><span class=special>;</span>
<span class=identifier>employee_set_by_ssn</span><span class=special>&amp;</span> <span class=identifier>ssn_index</span><span class=special>=</span><span class=identifier>es</span><span class=special>.</span><span class=identifier>get</span><span class=special>&lt;</span><span class=number>2</span><span class=special>&gt;();</span>
<span class=special>...</span>
<span class=comment>// find an employee by ssn</span>
<span class=identifier>employee</span> <span class=identifier>e</span><span class=special>=*(</span><span class=identifier>ssn_index</span><span class=special>.</span><span class=identifier>find</span><span class=special>(</span><span class=identifier>ssn</span><span class=special>(</span><span class=number>12</span><span class=special>,</span><span class=number>1005</span><span class=special>,</span><span class=number>20678</span><span class=special>),</span><span class=identifier>ssn_hash</span><span class=special>(),</span><span class=identifier>ssn_equal</span><span class=special>()));</span>
</pre></blockquote>
<p>
In the example, we provided a hash functor <code>ssn_hash</code> and an
equality predicate <code>ssn_equal</code> allowing for interoperability
between <code>ssn</code> objects and the raw <code>int</code>s stored as
<code>SSN</code>s in <code>employee_set</code>.
</p>
<p>
By far, the most useful application of compatible keys in the context
of hashed indices lies in the fact that they allow for seamless usage of
<a href="key_extraction.html#composite_keys">composite keys</a>.
</p>
<h3><a name="hash_updating">Updating</a></h3>
<p>
Hashed indices have
<a href="../reference/hash_indices.html#replace"><code>replace</code></a>,
<a href="../reference/hash_indices.html#modify"><code>modify</code></a> and
<a href="../reference/hash_indices.html#modify_key"><code>modify_key</code></a>
member functions, with the same functionality as in ordered indices.
</p>
<h3><a name="guarantees">Guarantees on iterator validity and exception safety</a></h3>
<p>
Due to the internal constraints imposed by the Boost.MultiIndex framework,
hashed indices provide guarantees on iterator validity and
exception safety that are actually stronger than required by the
C++ Standard Library Technical Report (TR1) with respect
to unordered associative containers:
<ul>
<li>Iterator validity is preserved in any case during insertion or rehashing:
TR1 allows for iterator invalidation when a rehash (implicit or explicit)
is performed.</li>
<li>Erasing an element or range of elements via iterators does not throw ever,
as the internal hash function and equality predicate objects are not actually
invoked.</li>
<li><code>rehash</code> provides the strong exception safety guarantee
unconditionally. TR1 only warrants it if the internal hash function and
equality predicate objects do not throw. The somewhat surprising consequence
is that a TR1-compliant unordered associative container might erase
elements if an exception is thrown during rehashing!</li>
</ul>
In general, these stronger guarantees play in favor of the user's convenience,
specially that which refers to iterator stability. A (hopefully minimal)
degradation in performance might result in exchange for these commodities,
though.
</p>
<h2><a name="rnd_indices">Random access indices</a></h2>
<p>
Random access indices offer the same kind of functionality as
<a href="basics.html#seq_indices">sequenced indices</a>, with the extra advantages
that their iterators are random access, and <code>operator[]</code>
and <code>at()</code> are provided for accessing
elements based on their position in the index. Let us rewrite a
container used in a previous <a href="basics.html#list_fast_lookup">example</a>,
using random access instead of sequenced indices:
</p>
<blockquote><pre>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index_container</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>random_access_index</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>ordered_index</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>identity</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=comment>// text container with fast lookup based on a random access index</span>
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span>
<span class=identifier>random_access</span><span class=special>&lt;&gt;,</span>
<span class=identifier>ordered_non_unique</span><span class=special>&lt;</span><span class=identifier>identity</span><span class=special>&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&gt;</span> <span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span> <span class=identifier>text_container</span><span class=special>;</span>
<span class=comment>// global text container object</span>
<span class=identifier>text_container</span> <span class=identifier>tc</span><span class=special>;</span>
</pre></blockquote>
<p>
Random access capabilities allow us to efficiently write code
like the following:
</p>
<blockquote><pre>
<span class=keyword>void</span> <span class=identifier>print_page</span><span class=special>(</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>size_t</span> <span class=identifier>page_num</span><span class=special>)</span>
<span class=special>{</span>
<span class=keyword>static</span> <span class=keyword>const</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>size_t</span> <span class=identifier>words_per_page</span><span class=special>=</span><span class=number>50</span><span class=special>;</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>size_t</span> <span class=identifier>pos0</span><span class=special>=</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>min</span><span class=special>(</span><span class=identifier>tc</span><span class=special>.</span><span class=identifier>size</span><span class=special>(),</span><span class=identifier>page_num</span><span class=special>*</span><span class=identifier>words_per_page</span><span class=special>);</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>size_t</span> <span class=identifier>pos1</span><span class=special>=</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>min</span><span class=special>(</span><span class=identifier>tc</span><span class=special>.</span><span class=identifier>size</span><span class=special>(),</span><span class=identifier>pos0</span><span class=special>+</span><span class=identifier>words_per_page</span><span class=special>);</span>
<span class=comment>// note random access iterators can be added offsets</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>copy</span><span class=special>(</span>
<span class=identifier>tc</span><span class=special>.</span><span class=identifier>begin</span><span class=special>()+</span><span class=identifier>pos0</span><span class=special>,</span><span class=identifier>tc</span><span class=special>.</span><span class=identifier>begin</span><span class=special>()+</span><span class=identifier>pos1</span><span class=special>,</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>ostream_iterator</span><span class=special>&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&gt;(</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>cout</span><span class=special>));</span>
<span class=special>}</span>
<span class=keyword>void</span> <span class=identifier>print_random_word</span><span class=special>()</span>
<span class=special>{</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>cout</span><span class=special>&lt;&lt;</span><span class=identifier>tc</span><span class=special>[</span><span class=identifier>rand</span><span class=special>()%</span><span class=identifier>tc</span><span class=special>.</span><span class=identifier>size</span><span class=special>()];</span>
<span class=special>}</span>
</pre></blockquote>
<p>
This added flexibility comes at a price: insertions and deletions at positions
other than the end of the index have linear complexity, whereas these operations
are constant time for sequenced indices. This situation is reminiscent of the
differences in complexity behavior between <code>std::list</code> and
<code>std::vector</code>: in the case of random access indices, however,
insertions and deletions never incur any element copying, so the actual
performance of these operations can be acceptable, despite the theoretical
disadvantage with respect to sequenced indices.
</p>
<p>
<a href="../examples.html#example10">Example 10</a> and
<a href="../examples.html#example11">example 11</a> in the examples section put
random access indices in practice.
</p>
<h3><a name="rnd_spec">Specification</a></h3>
<p>
Random access indices are specified with the <code>random_access</code> construct,
where the <a href="basics.html#tagging">tag</a> parameter is, as usual, optional:
</p>
<blockquote><pre>
<span class=identifier>random_access</span><span class=special>&lt;[</span><i>(tag)</i><span class=special>]&gt;</span>
</pre></blockquote>
<h3><a name="rnd_interface">Interface</a></h3>
<p>
All public functions offered by sequenced indices are also provided
by random access indices, so that the latter can act as a drop-in replacement
of the former (save with respect to their complexity bounds, as explained above).
Besides, random access
indices have <code>operator[]</code> and <code>at()</code> for positional
access to the elements, and member functions
<a href="../reference/rnd_indices.html#capacity_memfun"><code>capacity</code></a> and
<a href="../reference/rnd_indices.html#reserve"><code>reserve</code></a>
that control internal reallocation in a similar manner as the homonym
facilities in <code>std::vector</code>. Check the
<a href="../reference/rnd_indices.html">reference</a> for details.
</p>
<h3><a name="rnd_vs_vector">Comparison with <code>std::vector</code></a></h3>
<p>
It is tempting to see random access indices as an analogue of <code>std::vector</code>
for use in Boost.MultiIndex, but this metaphor can be misleading, as both constructs,
though similar in many respects, show important semantic differences. An
advantage of random access indices is that their iterators, as well as references
to their elements, are <i>stable</i>, that is, they remain valid after any insertions
or deletions. On the other hand, random access indices have several disadvantages with
respect to <code>std::vector</code>s:
<ul>
<li>They do not provide <i>memory contiguity</i>, a property
of <code>std::vector</code>s by which elements are stored adjacent to one
another in a single block of memory.
</li>
<li>As usual in Boost.MultiIndex, elements of random access indices are immutable
and can only be modified through member functions
<a href="../reference/rnd_indices.html#replace"><code>replace</code></a> and
<a href="../reference/rnd_indices.html#modify"><code>modify</code></a>.
This precludes the usage of many mutating
algorithms that are nonetheless applicable to <code>std::vector</code>s.
</li>
</ul>
The latter shortcoming can be partially remedied by means of the
<a href="#rearrange">rearranging interface</a> these indices provide.
</p>
<p>
In general, it is more instructive to regard random access indices as
a variation of sequenced indices providing random access semantics, instead
of insisting on the <code>std::vector</code> analogy.
</p>
<h2><a name="rearrange">Index rearranging</a></h2>
<p>
By design, index elements are immutable, i.e. iterators only grant
<code>const</code> access to them, and only through the provided
updating interface (<code>replace</code>, <code>modify</code> and
<code>modify_key</code>) can the elements be modified. This restriction
is set up so that the internal invariants of key-based indices are
not broken (for instance, ascending order traversal in ordered
indices), but induces important limitations in non key-based indices:
</p>
<blockquote><pre>
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=keyword>int</span><span class=special>,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span>
<span class=identifier>random_access</span><span class=special>&lt;&gt;,</span>
<span class=identifier>ordered_unique</span><span class=special>&lt;</span><span class=identifier>identity</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;</span> <span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span> <span class=identifier>container</span><span class=special>;</span>
<span class=identifier>container</span> <span class=identifier>c</span><span class=special>;</span>
<span class=special>...</span>
<span class=comment>// compiler error: assignment to read-only objects</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>random_shuffle</span><span class=special>(</span><span class=identifier>c</span><span class=special>.</span><span class=identifier>begin</span><span class=special>(),</span><span class=identifier>c</span><span class=special>.</span><span class=identifier>end</span><span class=special>());</span>
</pre></blockquote>
<p>
What is unfortunate about the previous example is that the operation
performed by <code>std::random_shuffle</code> is potentially compatible
with <code>multi_index_container</code> invariants, as its result can be
described by a permutation of the elements in the random access index
with no actual modifications to the elements themselves. There are many
more examples of such compatible algorithms in the C++ standard library,
like for instance all sorting and partition functions.
</p>
<p>
Sequenced and random access indices provide a means to take advantage
of such external algorithms. In order to introduce this facility we need
a preliminary concept: a <i>view</i> of an index is defined as
some iterator range [<code>first</code>,<code>last</code>) over the
elements of the index such that all its elements are contained in the
range exactly once. Continuing with our example, we can apply
<code>std::random_suffle</code> on an ad hoc view obtained from the
container:
</p>
<blockquote><pre>
<span class=comment>// note that the elements of the view are not copies of the elements
// in c, but references to them</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>vector</span><span class=special>&lt;</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>reference_wrapper</span><span class=special>&lt;</span><span class=keyword>const</span> <span class=keyword>int</span><span class=special>&gt;</span> <span class=special>&gt;</span> <span class=identifier>v</span><span class=special>;</span>
<span class=identifier>BOOST_FOREACH</span><span class=special>(</span><span class=keyword>const</span> <span class=keyword>int</span><span class=special>&amp;</span> <span class=identifier>i</span><span class=special>,</span><span class=identifier>c</span><span class=special>)</span><span class=identifier>v</span><span class=special>.</span><span class=identifier>push_back</span><span class=special>(</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>cref</span><span class=special>(</span><span class=identifier>i</span><span class=special>));</span>
<span class=comment>// this compiles OK, as reference_wrappers are assignable</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>random_shuffle</span><span class=special>(</span><span class=identifier>v</span><span class=special>.</span><span class=identifier>begin</span><span class=special>(),</span><span class=identifier>v</span><span class=special>.</span><span class=identifier>end</span><span class=special>());</span>
</pre></blockquote>
<p>
Elements of <code>v</code> are <code>reference_wrapper</code>s (from
<a href="../../../../doc/html/ref.html">Boost.Ref</a>) to the actual elements
in the multi-index container. These objects still do not allow modification
of the referenced entities, but they are
<a href="http://www.sgi.com/tech/stl/Assignable.html"><code>Assignable</code></a>,
which is the only requirement <code>std::random_suffle</code> imposes. Once
we have our desired rearrange stored in the view, we can transfer it to
the container with
</p>
<blockquote><pre>
<span class=identifier>c</span><span class=special>.</span><span class=identifier>rearrange</span><span class=special>(</span><span class=identifier>v</span><span class=special>.</span><span class=identifier>begin</span><span class=special>());</span>
</pre></blockquote>
<p>
<code>rearrange</code> accepts an input iterator signaling the beginning
of the external view (and end iterator is not needed since the length of
the view is the same as that of the index) and internally relocates the
elements of the index so that their traversal order matches the view.
Albeit with some circumventions, <code>rearrange</code> allows for the
application of a varied range of algorithms to non key-based indices.
Please note that the view concept is very general, and in no way tied
to the particular implementation example shown above. For instance, indices
of a <code>multi_index_container</code> are indeed views with respect to
its non key-based indices:
</p>
<blockquote><pre>
<span class=comment>// rearrange as index #1 (ascending order)</span>
<span class=identifier>c</span><span class=special>.</span><span class=identifier>rearrange</span><span class=special>(</span><span class=identifier>c</span><span class=special>.</span><span class=identifier>get</span><span class=special>&lt;</span><span class=number>1</span><span class=special>&gt;().</span><span class=identifier>begin</span><span class=special>());</span>
<span class=comment>// rearrange in descending order</span>
<span class=identifier>c</span><span class=special>.</span><span class=identifier>rearrange</span><span class=special>(</span><span class=identifier>c</span><span class=special>.</span><span class=identifier>get</span><span class=special>&lt;</span><span class=number>1</span><span class=special>&gt;().</span><span class=identifier>rbegin</span><span class=special>());</span>
</pre></blockquote>
<p>
The only important requirement imposed on views is that they must be
<i>free</i>, i.e. they are not affected by relocations on the base index:
thus, <code>rearrange</code> does not accept the following:
</p>
<blockquote><pre>
<span class=comment>// undefined behavior: [rbegin(),rend()) is not free with respect
// to the base index</span>
<span class=identifier>c</span><span class=special>.</span><span class=identifier>rearrange</span><span class=special>(</span><span class=identifier>c</span><span class=special>.</span><span class=identifier>rbegin</span><span class=special>());</span>
</pre></blockquote>
<p>
The view concept is defined in detail in the
<a href="../reference/indices.html#views">reference</a>.
See <a href="../examples.html#example11">example 11</a> in the examples section
for a demonstration of use of <code>rearrange</code>.
</p>
<h2><a name="iterator_to"><code>iterator_to</code></a></h2>
<p>
All indices of Boost.MultiIndex provide a member function called <code>iterator_to</code>
which returns an iterator to a given element of the container:
</p>
<blockquote><pre>
<span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=keyword>int</span><span class=special>,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span><span class=identifier>sequenced</span><span class=special>&lt;&gt;</span> <span class=special>&gt;</span>
<span class=special>&gt;</span> <span class=identifier>c</span><span class=special>;</span>
<span class=special>...</span>
<span class=comment>// convoluted way to do c.pop_back()</span>
<span class=identifier>c</span><span class=special>.</span><span class=identifier>erase</span><span class=special>(</span><span class=identifier>c</span><span class=special>.</span><span class=identifier>iterator_to</span><span class=special>(</span><span class=identifier>c</span><span class=special>.</span><span class=identifier>back</span><span class=special>()));</span>
<span class=comment>// The following, though similar to the previous code,
// does not work: iterator_to accepts a reference to
// the element in the container, not a copy.</span>
<span class=keyword>int</span> <span class=identifier>x</span><span class=special>=</span><span class=identifier>c</span><span class=special>.</span><span class=identifier>back</span><span class=special>();</span>
<span class=identifier>c</span><span class=special>.</span><span class=identifier>erase</span><span class=special>(</span><span class=identifier>c</span><span class=special>.</span><span class=identifier>iterator_to</span><span class=special>(</span><span class=identifier>x</span><span class=special>));</span> <span class=comment>// run-time failure ensues</span>
</pre></blockquote>
<p>
<code>iterator_to</code> provides a way to retrieve an iterator to an element
from a pointer to the element, thus making iterators and pointers interchangeable
for the purposes of element pointing (not so for traversal) in many situations.
This notwithstanding, it is not the aim of <code>iterator_to</code> to
promote the usage of pointers as substitutes for real iterators: the latter are
specifically designed for handling the elements of a container,
and not only benefit from the iterator orientation of container interfaces,
but are also capable of exposing many more programming bugs than raw pointers, both
at compile and run time. <code>iterator_to</code> is thus meant to be used
in scenarios where access via iterators is not suitable or desireable:
<ul>
<li>Interoperability with preexisting APIs based on pointers or references.</li>
<li>Publication of pointer-based interfaces (for instance, when
designing a C-compatible library).
</li>
<li>The exposure of pointers in place of iterators can act as a <i>type
erasure</i> barrier effectively decoupling the user of the code
from the implementation detail of which particular container is being
used. Similar techniques, like the famous Pimpl idiom, are used
in large projects to reduce dependencies and build times.
</li>
<li>Self-referencing contexts where an element acts upon its owner
container and no iterator to itself is available.
</li>
</ul>
</p>
<h2><a name="ordered_node_compression">Ordered indices node compression</a></h2>
<p>
Ordered indices are implemented by means of a data structure
known as a <i>red-black tree</i>. Nodes of a red-back tree contain pointers
to the parent and the two children nodes, plus a 1-bit field referred to as
the <i>node color</i> (hence the name of the structure). Due to alignment
issues, on most architectures the color field occupies one entire word, that is,
4 bytes in 32-bit systems and 8 bytes in 64-bit environments. This waste
of space can be avoided by embedding the color bit inside one of the
node pointers, provided not all the bits of the pointer representation contain
useful information: this is precisely the case in many architectures where
such nodes are aligned to even addresses, which implies that the least
significant bit of the address must always be zero.
</p>
<p>
Boost.MultiIndex ordered indices implement this type of node compression
whenever applicable. As compared with common implementations of the STL
container <code>std::set</code>, node compression can
result in a reduction of header overload by 25% (from 16 to 12 bytes on
typical 32-bit architectures, and from 32 to 24 bytes on 64-bit systems).
The impact on performance of this optimization has been checked to be negligible
for moderately sized containers, whereas containers with many elements (hundreds
of thousands or more) perform faster with this optimization, most likely due to
L1 and L2 cache effects.
</p>
<p>
Node compression can be disabled by globally setting the macro
<code>BOOST_MULTI_INDEX_DISABLE_COMPRESSED_ORDERED_INDEX_NODES</code>.
</p>
<hr>
<div class="prev_link"><a href="basics.html"><img src="../prev.gif" alt="basics" border="0"><br>
Basics
</a></div>
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.MultiIndex tutorial" border="0"><br>
Boost.MultiIndex tutorial
</a></div>
<div class="next_link"><a href="key_extraction.html"><img src="../next.gif" alt="key estraction" border="0"><br>
Key extraction
</a></div><br clear="all" style="clear: all;">
<br>
<p>Revised October 15th 2007</p>
<p>&copy; Copyright 2003-2007 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
http://www.boost.org/LICENSE_1_0.txt</a>)
</p>
</body>
</html>
+968
View File
@@ -0,0 +1,968 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Boost.MultiIndex Documentation - Tutorial - Key extraction</title>
<link rel="stylesheet" href="../style.css" type="text/css">
<link rel="start" href="../index.html">
<link rel="prev" href="indices.html">
<link rel="up" href="index.html">
<link rel="next" href="creation.html">
</head>
<body>
<h1><img src="../../../../boost.png" alt="boost.png (6897 bytes)" align=
"middle" width="277" height="86">Boost.MultiIndex Tutorial: Key extraction</h1>
<div class="prev_link"><a href="indices.html"><img src="../prev.gif" alt="index types" border="0"><br>
Index types
</a></div>
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.MultiIndex tutorial" border="0"><br>
Boost.MultiIndex tutorial
</a></div>
<div class="next_link"><a href="creation.html"><img src="../next.gif" alt="container creation" border="0"><br>
Container creation
</a></div><br clear="all" style="clear: all;">
<hr>
<h2>Contents</h2>
<ul>
<li><a href="#intro">Introduction</a>
<ul>
<li><a href="#read_write_key_extractors">Read/write key extractors</a></li>
</ul>
</li>
<li><a href="#predefined_key_extractors">Predefined key extractors</a>
<ul>
<li><a href="#identity"><code>identity</code></a></li>
<li><a href="#member"><code>member</code></a></li>
<li><a href="#const_mem_fun"><code>const_mem_fun</code>
and <code>mem_fun</code></a></li>
<li><a href="#global_fun"><code>global_fun</code></a></li>
</ul>
</li>
<li><a href="#user_defined_key_extractors">User-defined key extractors</a></li>
<li><a href="#composite_keys">Composite keys</a>
<ul>
<li><a href="#composite_keys_hash">Composite keys and hashed indices</a></li>
</ul>
</li>
<li><a href="#advanced_key_extractors">Advanced features of Boost.MultiIndex key
extractors</a></li>
</ul>
<h2><a name="intro">Introduction</a></h2>
<p>
STL associative containers have a notion of key, albeit in a somewhat incipient
form. So, the keys of such containers are identified by a nested type
<code>key_type</code>; for <code>std::set</code>s and <code>std::multiset</code>s,
<code>key_type</code> coincides with <code>value_type</code>, i.e. the key is the
element itself. <code>std::map</code> and <code>std::multimap</code> manage
elements of type <code>std::pair&lt;const Key,T&gt;</code>, where the first
member is the key. In either case, the process of obtaining the key from a
given element is implicitly fixed and cannot be customized by the user.
</p>
<p>
Fixed key extraction mechanisms like those performed by STL associative
containers do not scale well in the context of Boost.MultiIndex, where
several indices share their <code>value_type</code> definition but
might feature completely different lookup semantics. For this reason,
Boost.MultiIndex formalizes the concept of a
<a href="../reference/key_extraction.html#key_extractors"><code>Key
Extractor</code></a> in order to make it explicit and controllable
in the definition of key-based indices.
</p>
<p>
Intuitively speaking, a key extractor is a function object that accepts
a reference to an element and returns its associated key. The formal
concept also imposes some reasonable constraints about the stability
of the process, in the sense that extractors are assumed to
return the same key when passed the same element: this is in consonance
with the informal understanding that keys are actually some "part"
of the element and do not depend on external data.
</p>
<h3><a name="read_write_key_extractors">Read/write key extractors</a></h3>
<p>
A key extractor is called <i>read/write</i> if it returns a non-constant reference
to the key when passed a non-constant element, and it is called <i>read-only</i>
otherwise. Boost.MultiIndex requires that the key extractor be read/write
when using the <code>modify_key</code> member function of ordered and hashed
indices. In all other situations, read-only extractors suffice.
The section on <a href="#advanced_key_extractors">advanced features
of Boost.MultiIndex key extractors</a> details which of the predefined
key extractors are read/write.
</p>
<h2><a name="predefined_key_extractors">Predefined key extractors</a></h2>
<h3><a name="identity"><code>identity</code></a></h3>
<p>
The <a href="../reference/key_extraction.html#identity"><code>identity</code></a>
key extractor returns the entire base object as the associated key:
</p>
<blockquote><pre>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index_container</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>ordered_index</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>identity</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=keyword>int</span><span class=special>,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span>
<span class=identifier>ordered_unique</span><span class=special>&lt;</span>
<span class=identifier>identity</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;</span> <span class=comment>// the key is the entire element</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span> <span class=identifier>cont</span><span class=special>;</span>
</pre></blockquote>
<h3><a name="member"><code>member</code></a></h3>
<p>
<a href="../reference/key_extraction.html#member"><code>member</code></a>
key extractors return a reference to a specified
data field of the base object. For instance, in the following version of our
familiar employee container:
</p>
<blockquote><pre>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index_container</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>ordered_index</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>identity</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>member</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=identifier>employee</span><span class=special>,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span>
<span class=identifier>ordered_unique</span><span class=special>&lt;</span><span class=identifier>identity</span><span class=special>&lt;</span><span class=identifier>employee</span><span class=special>&gt;</span> <span class=special>&gt;,</span>
<span class=identifier>ordered_non_unique</span><span class=special>&lt;</span><span class=identifier>member</span><span class=special>&lt;</span><span class=identifier>employee</span><span class=special>,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,&amp;</span><span class=identifier>employee</span><span class=special>::</span><span class=identifier>name</span><span class=special>&gt;</span> <span class=special>&gt;,</span>
<span class=identifier>ordered_unique</span><span class=special>&lt;</span><span class=identifier>member</span><span class=special>&lt;</span><span class=identifier>employee</span><span class=special>,</span><span class=keyword>int</span><span class=special>,&amp;</span><span class=identifier>employee</span><span class=special>::</span><span class=identifier>ssnumber</span><span class=special>&gt;</span> <span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span> <span class=identifier>employee_set</span><span class=special>;</span>
</pre></blockquote>
<p>
the second and third indices use <code>member</code> extractors on
<code>employee::name</code> and <code>employee::ssnumber</code>, respectively.
The specification of an instantiation of <code>member</code> is simple
yet a little contrived:
</p>
<blockquote><pre>
<span class=identifier>member</span><span class=special>&lt;</span><span class=identifier><i>(base type)</i></span><span class=special>,</span><span class=identifier><i>(key type)</i></span><span class=special>,</span><span class=identifier><i>(pointer to member)</i></span><span class=special>&gt;</span>
</pre></blockquote>
<p>
It might seem that the first and second parameters are superfluous,
since the type of the base object and of the associated data field are
already implicit in the pointer to member argument: unfortunately, it is
not possible to extract this information with current C++ mechanisms,
which makes the syntax of <code>member</code> a little too verbose.
</p>
<h3><a name="const_mem_fun"><code>const_mem_fun</code> and <code>mem_fun</code></a></h3>
<p>
Sometimes, the key of an index is not a concrete data member of the element,
but rather it is a value returned by a particular member function.
This resembles the notion of <i>calculated indices</i> supported by some
relational databases. Boost.MultiIndex supports this
kind of key extraction through
<a href="../reference/key_extraction.html#const_mem_fun"><code>const_mem_fun</code></a>.
Consider the following container where sorting on the third index
is based upon the length of the name field:
</p>
<blockquote><pre>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index_container</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>ordered_index</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>identity</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>member</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>mem_fun</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>employee</span>
<span class=special>{</span>
<span class=keyword>int</span> <span class=identifier>id</span><span class=special>;</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>name</span><span class=special>;</span>
<span class=identifier>employee</span><span class=special>(</span><span class=keyword>int</span> <span class=identifier>id</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&amp;</span> <span class=identifier>name</span><span class=special>):</span><span class=identifier>id</span><span class=special>(</span><span class=identifier>id</span><span class=special>),</span><span class=identifier>name</span><span class=special>(</span><span class=identifier>name</span><span class=special>){}</span>
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>&lt;(</span><span class=keyword>const</span> <span class=identifier>employee</span><span class=special>&amp;</span> <span class=identifier>e</span><span class=special>)</span><span class=keyword>const</span><span class=special>{</span><span class=keyword>return</span> <span class=identifier>id</span><span class=special>&lt;</span><span class=identifier>e</span><span class=special>.</span><span class=identifier>id</span><span class=special>;}</span>
<span class=comment>// returns the length of the name field</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>size_t</span> <span class=identifier>name_length</span><span class=special>()</span><span class=keyword>const</span><span class=special>{</span><span class=keyword>return</span> <span class=identifier>name</span><span class=special>.</span><span class=identifier>size</span><span class=special>();}</span>
<span class=special>};</span>
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=identifier>employee</span><span class=special>,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span>
<span class=comment>// sort by employee::operator&lt;</span>
<span class=identifier>ordered_unique</span><span class=special>&lt;</span><span class=identifier>identity</span><span class=special>&lt;</span><span class=identifier>employee</span><span class=special>&gt;</span> <span class=special>&gt;,</span>
<span class=comment>// sort by less&lt;string&gt; on name</span>
<span class=identifier>ordered_non_unique</span><span class=special>&lt;</span><span class=identifier>member</span><span class=special>&lt;</span><span class=identifier>employee</span><span class=special>,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,&amp;</span><span class=identifier>employee</span><span class=special>::</span><span class=identifier>name</span><span class=special>&gt;</span> <span class=special>&gt;,</span>
<span class=comment>// sort by less&lt;int&gt; on name_length()</span>
<span class=identifier>ordered_non_unique</span><span class=special>&lt;</span>
<span class=identifier>const_mem_fun</span><span class=special>&lt;</span><span class=identifier>employee</span><span class=special>,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>size_t</span><span class=special>,&amp;</span><span class=identifier>employee</span><span class=special>::</span><span class=identifier>name_length</span><span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span> <span class=identifier>employee_set</span><span class=special>;</span>
</pre></blockquote>
<p>
<code>const_mem_fun</code> usage syntax is similar to that of
<a href="#member"><code>member</code></a>:
</p>
<blockquote><pre>
<span class=identifier>const_mem_fun</span><span class=special>&lt;</span><span class=identifier><i>(base type)</i></span><span class=special>,</span><span class=identifier><i>(key type)</i></span><span class=special>,</span><span class=identifier><i>(pointer to member function)</i></span><span class=special>&gt;</span>
</pre></blockquote>
<p>
The member function referred to must be <code>const</code>, take no arguments and return
a value of the specified key type.
Almost always you will want to use a <code>const</code> member function,
since elements in a <code>multi_index_container</code> are treated as constant, much
as elements of an <code>std::set</code>. However, a
<a href="../reference/key_extraction.html#mem_fun"><code>mem_fun</code></a>
counterpart is provided for use with non-constant member functions, whose
applicability is discussed on the paragraph on
<a href="#advanced_key_extractors">advanced features
of Boost.MultiIndex key extractors</a>.
</p>
<p><a href="../examples.html#example2">Example 2</a> in the examples section
provides a complete program showing how to use <code>const_mem_fun</code>.
<p>
<h3><a name="global_fun"><code>global_fun</code></a></h3>
<p>
Whereas <code>const_mem_fun</code> and <code>mem_fun</code> are based on a
given member function of the base type from where the key is extracted,
<a href="../reference/key_extraction.html#global_fun"><code>global_fun</code></a>
takes a global function (or static member function) accepting the base
type as its parameter and returning the key:
</p>
<blockquote><pre>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index_container</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>ordered_index</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>global_fun</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>rectangle</span>
<span class=special>{</span>
<span class=keyword>int</span> <span class=identifier>x0</span><span class=special>,</span><span class=identifier>y0</span><span class=special>;</span>
<span class=keyword>int</span> <span class=identifier>x1</span><span class=special>,</span><span class=identifier>y1</span><span class=special>;</span>
<span class=special>};</span>
<span class=keyword>unsigned</span> <span class=keyword>long</span> <span class=identifier>area</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>rectangle</span><span class=special>&amp;</span> <span class=identifier>r</span><span class=special>)</span>
<span class=special>{</span>
<span class=keyword>return</span> <span class=special>(</span><span class=keyword>unsigned</span> <span class=keyword>long</span><span class=special>)(</span><span class=identifier>r</span><span class=special>.</span><span class=identifier>x1</span><span class=special>-</span><span class=identifier>r</span><span class=special>.</span><span class=identifier>x0</span><span class=special>)*(</span><span class=identifier>r</span><span class=special>.</span><span class=identifier>x1</span><span class=special>-</span><span class=identifier>r</span><span class=special>.</span><span class=identifier>x0</span><span class=special>)+</span>
<span class=special>(</span><span class=keyword>unsigned</span> <span class=keyword>long</span><span class=special>)(</span><span class=identifier>r</span><span class=special>.</span><span class=identifier>y1</span><span class=special>-</span><span class=identifier>r</span><span class=special>.</span><span class=identifier>y0</span><span class=special>)*(</span><span class=identifier>r</span><span class=special>.</span><span class=identifier>y1</span><span class=special>-</span><span class=identifier>r</span><span class=special>.</span><span class=identifier>y0</span><span class=special>);</span>
<span class=special>}</span>
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=identifier>rectangle</span><span class=special>,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span>
<span class=comment>// sort by increasing area</span>
<span class=identifier>ordered_non_unique</span><span class=special>&lt;</span><span class=identifier>global_fun</span><span class=special>&lt;</span><span class=keyword>const</span> <span class=identifier>rectangle</span><span class=special>&amp;,</span><span class=keyword>unsigned</span> <span class=keyword>long</span><span class=special>,&amp;</span><span class=identifier>area</span><span class=special>&gt;</span> <span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span> <span class=identifier>rectangle_container</span><span class=special>;</span>
</pre></blockquote>
<p>
The specification of <code>global_fun</code> obeys the following syntax:
</p>
<blockquote><pre>
<span class=identifier>global_fun</span><span class=special>&lt;</span><span class=identifier><i>(argument type)</i></span><span class=special>,</span><span class=identifier><i>(key type)</i></span><span class=special>,</span><span class=identifier><i>(pointer to function)</i></span><span class=special>&gt;</span>
</pre></blockquote>
<p>
where the argument type and key type must match <i>exactly</i> those in the
signature of the function used; for instance, in the example above the argument
type is <code>const rectangle&amp;</code>, without omitting the "<code>const</code>"
and "<code>&amp;</code>" parts. So, although most of the time the base type will be
accepted by constant reference, <code>global_fun</code> is also prepared to take
functions accepting their argument by value or by non-constant reference: this
latter case cannot generally be used directly in the specification of
<code>multi_index_container</code>s as their elements are treated as constant,
but the section on <a href="#advanced_key_extractors">advanced features
of Boost.MultiIndex key extractors</a> describes valid use cases of
key extraction based on such functions with a non-constant reference argument.
</p>
<p><a href="../examples.html#example2">Example 2</a> in the examples section
uses <code>gobal_fun</code>.
<p>
<h2><a name="user_defined_key_extractors">User-defined key extractors</a></h2>
<p>
Although the <a href="#predefined_key_extractors">predefined key extractors</a>
provided by Boost.MultiIndex are intended to serve most cases,
the user can also provide her own key extractors in more exotic situations,
as long as these conform to the
<a href="../reference/key_extraction.html#key_extractors"><code>Key
Extractor</code></a> concept.
</p>
<blockquote><pre>
<span class=comment>// some record class</span>
<span class=keyword>struct</span> <span class=identifier>record</span>
<span class=special>{</span>
<span class=identifier>boost</span><span class=special>::</span><span class=identifier>gregorian</span><span class=special>::</span><span class=identifier>date</span> <span class=identifier>d</span><span class=special>;</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>str</span><span class=special>;</span>
<span class=special>};</span>
<span class=comment>// extracts a record's year</span>
<span class=keyword>struct</span> <span class=identifier>record_year</span>
<span class=special>{</span>
<span class=comment>// result_type typedef required by Key Extractor concept</span>
<span class=keyword>typedef</span> <span class=identifier>boost</span><span class=special>::</span><span class=identifier>gregorian</span><span class=special>::</span><span class=identifier>greg_year</span> <span class=identifier>result_type</span><span class=special>;</span>
<span class=identifier>result_type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>record</span><span class=special>&amp;</span> <span class=identifier>r</span><span class=special>)</span><span class=keyword>const</span> <span class=comment>// operator() must be const</span>
<span class=special>{</span>
<span class=keyword>return</span> <span class=identifier>r</span><span class=special>.</span><span class=identifier>d</span><span class=special>.</span><span class=identifier>year</span><span class=special>();</span>
<span class=special>}</span>
<span class=special>};</span>
<span class=comment>// example of use of the previous key extractor</span>
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=identifier>record</span><span class=special>,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span>
<span class=identifier>ordered_non_unique</span><span class=special>&lt;</span><span class=identifier>record_year</span><span class=special>&gt;</span> <span class=comment>// sorted by record's year</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span> <span class=identifier>record_log</span><span class=special>;</span>
</pre></blockquote>
<p>
<a href="../examples.html#example6">Example 6</a> in the examples section
applies some user-defined key extractors in a complex scenario where
keys are accessed via pointers.
</p>
<h2><a name="composite_keys">Composite keys</a></h2>
<p>
In relational databases, composite keys depend on two or more fields of a given table.
The analogous concept in Boost.MultiIndex is modeled by means of
<a href="../reference/key_extraction.html#composite_key">
<code>composite_key</code></a>, as shown in the example:
</p>
<blockquote><pre>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index_container</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>ordered_index</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>member</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>composite_key</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>phonebook_entry</span>
<span class=special>{</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>family_name</span><span class=special>;</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>given_name</span><span class=special>;</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>phone_number</span><span class=special>;</span>
<span class=identifier>phonebook_entry</span><span class=special>(</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>family_name</span><span class=special>,</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>given_name</span><span class=special>,</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>phone_number</span><span class=special>):</span>
<span class=identifier>family_name</span><span class=special>(</span><span class=identifier>family_name</span><span class=special>),</span><span class=identifier>given_name</span><span class=special>(</span><span class=identifier>given_name</span><span class=special>),</span><span class=identifier>phone_number</span><span class=special>(</span><span class=identifier>phone_number</span><span class=special>)</span>
<span class=special>{}</span>
<span class=special>};</span>
<span class=comment>// define a multi_index_container with a composite key on
// (family_name,given_name)</span>
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=identifier>phonebook_entry</span><span class=special>,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span>
<span class=comment>//non-unique as some subscribers might have more than one number</span>
<span class=identifier>ordered_non_unique</span><span class=special>&lt;</span>
<span class=identifier>composite_key</span><span class=special>&lt;</span>
<span class=identifier>phonebook_entry</span><span class=special>,</span>
<span class=identifier>member</span><span class=special>&lt;</span><span class=identifier>phonebook_entry</span><span class=special>,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,&amp;</span><span class=identifier>phonebook_entry</span><span class=special>::</span><span class=identifier>family_name</span><span class=special>&gt;,</span>
<span class=identifier>member</span><span class=special>&lt;</span><span class=identifier>phonebook_entry</span><span class=special>,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,&amp;</span><span class=identifier>phonebook_entry</span><span class=special>::</span><span class=identifier>given_name</span><span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;,</span>
<span class=identifier>ordered_unique</span><span class=special>&lt;</span> <span class=comment>// unique as numbers belong to only one subscriber</span>
<span class=identifier>member</span><span class=special>&lt;</span><span class=identifier>phonebook_entry</span><span class=special>,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,&amp;</span><span class=identifier>phonebook_entry</span><span class=special>::</span><span class=identifier>phone_number</span><span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span> <span class=identifier>phonebook</span><span class=special>;</span>
</pre></blockquote>
<p>
<code>composite_key</code> accepts two or more key extractors on the same
value (here, <code>phonebook_entry</code>). Lookup operations on a composite
key are accomplished by passing tuples with the values searched:
</p>
<blockquote><pre>
<span class=identifier>phonebook</span> <span class=identifier>pb</span><span class=special>;</span>
<span class=special>...</span>
<span class=comment>// search for Dorothea White's number</span>
<span class=identifier>phonebook</span><span class=special>::</span><span class=identifier>iterator</span> <span class=identifier>it</span><span class=special>=</span><span class=identifier>pb</span><span class=special>.</span><span class=identifier>find</span><span class=special>(</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>make_tuple</span><span class=special>(</span><span class=string>&quot;White&quot;</span><span class=special>,</span><span class=string>&quot;Dorothea&quot;</span><span class=special>));</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>number</span><span class=special>=</span><span class=identifier>it</span><span class=special>-&gt;</span><span class=identifier>phone_number</span><span class=special>;</span>
</pre></blockquote>
<p>
Composite keys are sorted by lexicographical order, i.e. sorting is performed
by the first key, then the second key if the first one is equal, etc. This
order allows for partial searches where only the first keys are specified:
</p>
<blockquote><pre>
<span class=identifier>phonebook</span> <span class=identifier>pb</span><span class=special>;</span>
<span class=special>...</span>
<span class=comment>// look for all Whites</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>pair</span><span class=special>&lt;</span><span class=identifier>phonebook</span><span class=special>::</span><span class=identifier>iterator</span><span class=special>,</span><span class=identifier>phonebook</span><span class=special>::</span><span class=identifier>iterator</span><span class=special>&gt;</span> <span class=identifier>p</span><span class=special>=</span>
<span class=identifier>pb</span><span class=special>.</span><span class=identifier>equal_range</span><span class=special>(</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>make_tuple</span><span class=special>(</span><span class=string>&quot;White&quot;</span><span class=special>));</span>
</pre></blockquote>
<p>
As a notational convenience, when only the first key is specified it is possible
to pass the argument directly without including it into a tuple:
</p>
<blockquote><pre>
<span class=identifier>phonebook</span> <span class=identifier>pb</span><span class=special>;</span>
<span class=special>...</span>
<span class=comment>// look for all Whites</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>pair</span><span class=special>&lt;</span><span class=identifier>phonebook</span><span class=special>::</span><span class=identifier>iterator</span><span class=special>,</span><span class=identifier>phonebook</span><span class=special>::</span><span class=identifier>iterator</span><span class=special>&gt;</span> <span class=identifier>p</span><span class=special>=</span><span class=identifier>pb</span><span class=special>.</span><span class=identifier>equal_range</span><span class=special>(</span><span class=string>&quot;White&quot;</span><span class=special>);</span>
</pre></blockquote>
<p>
On the other hand, partial searches without specifying the first keys are not
allowed.
</p>
<p>
By default, the corresponding <code>std::less</code> predicate is used
for each subkey of a composite key. Alternate comparison predicates can
be specified with <a href="../reference/key_extraction.html#composite_key_compare">
<code>composite_key_compare</code></a>:
</p>
<blockquote><pre>
<span class=comment>// phonebook with given names in reverse order</span>
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=identifier>phonebook_entry</span><span class=special>,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span>
<span class=identifier>ordered_non_unique</span><span class=special>&lt;</span>
<span class=identifier>composite_key</span><span class=special>&lt;</span>
<span class=identifier>phonebook_entry</span><span class=special>,</span>
<span class=identifier>member</span><span class=special>&lt;</span><span class=identifier>phonebook_entry</span><span class=special>,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,&amp;</span><span class=identifier>phonebook_entry</span><span class=special>::</span><span class=identifier>family_name</span><span class=special>&gt;,</span>
<span class=identifier>member</span><span class=special>&lt;</span><span class=identifier>phonebook_entry</span><span class=special>,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,&amp;</span><span class=identifier>phonebook_entry</span><span class=special>::</span><span class=identifier>given_name</span><span class=special>&gt;</span>
<span class=special>&gt;,</span>
<span class=identifier>composite_key_compare</span><span class=special>&lt;</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>less</span><span class=special>&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&gt;,</span> <span class=comment>// family names sorted as by default</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>greater</span><span class=special>&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&gt;</span> <span class=comment>// given names reversed</span>
<span class=special>&gt;</span>
<span class=special>&gt;,</span>
<span class=identifier>ordered_unique</span><span class=special>&lt;</span>
<span class=identifier>member</span><span class=special>&lt;</span><span class=identifier>phonebook_entry</span><span class=special>,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,&amp;</span><span class=identifier>phonebook_entry</span><span class=special>::</span><span class=identifier>phone_number</span><span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span> <span class=identifier>phonebook</span><span class=special>;</span>
</pre></blockquote>
<p>
See <a href="../examples.html#example7">example 7</a> in the examples section
for an application of <code>composite_key</code>.
</p>
<h3><a name="composite_keys_hash">Composite keys and hashed indices</a></h3>
<p>
Composite keys can also be used with hashed indices in a straightforward manner:
</p>
<blockquote><pre>
<span class=keyword>struct</span> <span class=identifier>street_entry</span>
<span class=special>{</span>
<span class=comment>// quadrant coordinates</span>
<span class=keyword>int</span> <span class=identifier>x</span><span class=special>;</span>
<span class=keyword>int</span> <span class=identifier>y</span><span class=special>;</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>name</span><span class=special>;</span>
<span class=identifier>street_entry</span><span class=special>(</span><span class=keyword>int</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>int</span> <span class=identifier>y</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&amp;</span> <span class=identifier>name</span><span class=special>):</span><span class=identifier>x</span><span class=special>(</span><span class=identifier>x</span><span class=special>),</span><span class=identifier>y</span><span class=special>(</span><span class=identifier>y</span><span class=special>),</span><span class=identifier>name</span><span class=special>(</span><span class=identifier>name</span><span class=special>){}</span>
<span class=special>};</span>
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=identifier>street_entry</span><span class=special>,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span>
<span class=identifier>hashed_non_unique</span><span class=special>&lt;</span> <span class=comment>// indexed by quadrant coordinates</span>
<span class=identifier>composite_key</span><span class=special>&lt;</span>
<span class=identifier>street_entry</span><span class=special>,</span>
<span class=identifier>member</span><span class=special>&lt;</span><span class=identifier>street_entry</span><span class=special>,</span><span class=keyword>int</span><span class=special>,&amp;</span><span class=identifier>street_entry</span><span class=special>::</span><span class=identifier>x</span><span class=special>&gt;,</span>
<span class=identifier>member</span><span class=special>&lt;</span><span class=identifier>street_entry</span><span class=special>,</span><span class=keyword>int</span><span class=special>,&amp;</span><span class=identifier>street_entry</span><span class=special>::</span><span class=identifier>y</span><span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;,</span>
<span class=identifier>hashed_non_unique</span><span class=special>&lt;</span> <span class=comment>// indexed by street name</span>
<span class=identifier>member</span><span class=special>&lt;</span><span class=identifier>street_entry</span><span class=special>,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,&amp;</span><span class=identifier>street_entry</span><span class=special>::</span><span class=identifier>name</span><span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span> <span class=identifier>street_locator</span><span class=special>;</span>
<span class=identifier>street_locator</span> <span class=identifier>sl</span><span class=special>;</span>
<span class=special>...</span>
<span class=keyword>void</span> <span class=identifier>streets_in_quadrant</span><span class=special>(</span><span class=keyword>int</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>int</span> <span class=identifier>y</span><span class=special>)</span>
<span class=special>{</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>pair</span><span class=special>&lt;</span><span class=identifier>street_locator</span><span class=special>::</span><span class=identifier>iterator</span><span class=special>,</span><span class=identifier>street_locator</span><span class=special>::</span><span class=identifier>iterator</span><span class=special>&gt;</span> <span class=identifier>p</span><span class=special>=</span>
<span class=identifier>sl</span><span class=special>.</span><span class=identifier>equal_range</span><span class=special>(</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>make_tuple</span><span class=special>(</span><span class=identifier>x</span><span class=special>,</span><span class=identifier>y</span><span class=special>));</span>
<span class=keyword>while</span><span class=special>(</span><span class=identifier>p</span><span class=special>.</span><span class=identifier>first</span><span class=special>!=</span><span class=identifier>p</span><span class=special>.</span><span class=identifier>second</span><span class=special>){</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>cout</span><span class=special>&lt;&lt;</span><span class=identifier>p</span><span class=special>.</span><span class=identifier>first</span><span class=special>-&gt;</span><span class=identifier>name</span><span class=special>&lt;&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>endl</span><span class=special>;</span>
<span class=special>++</span><span class=identifier>p</span><span class=special>.</span><span class=identifier>first</span><span class=special>;</span>
<span class=special>}</span>
<span class=special>}</span>
</pre></blockquote>
<p>
Note that hashing is automatically taken care of: <code>boost::hash</code> is
specialized to hash a composite key as a function of the <code>boost::hash</code>
values of its elements. Should we need to specify different hash functions for the
elements of a composite key, we can explicitly do so by using the
<a href="../reference/key_extraction.html#composite_key_hash"><code>composite_key_hash</code></a>
utility:
</p>
<blockquote><pre>
<span class=keyword>struct</span> <span class=identifier>tuned_int_hash</span>
<span class=special>{</span>
<span class=keyword>int</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>int</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span>
<span class=special>{</span>
<span class=comment>// specially tuned hash for this application</span>
<span class=special>}</span>
<span class=special>};</span>
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=identifier>street_entry</span><span class=special>,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span>
<span class=identifier>hashed_non_unique</span><span class=special>&lt;</span> <span class=comment>// indexed by quadrant coordinates</span>
<span class=identifier>composite_key</span><span class=special>&lt;</span>
<span class=identifier>street_entry</span><span class=special>,</span>
<span class=identifier>member</span><span class=special>&lt;</span><span class=identifier>street_entry</span><span class=special>,</span><span class=keyword>int</span><span class=special>,&amp;</span><span class=identifier>street_entry</span><span class=special>::</span><span class=identifier>x</span><span class=special>&gt;,</span>
<span class=identifier>member</span><span class=special>&lt;</span><span class=identifier>street_entry</span><span class=special>,</span><span class=keyword>int</span><span class=special>,&amp;</span><span class=identifier>street_entry</span><span class=special>::</span><span class=identifier>y</span><span class=special>&gt;</span>
<span class=special>&gt;,</span>
<span class=identifier>composite_key_hash</span><span class=special>&lt;</span>
<span class=identifier>tuned_int_hash</span><span class=special>,</span>
<span class=identifier>tuned_int_hash</span>
<span class=special>&gt;</span>
<span class=special>&gt;,</span>
<span class=identifier>hashed_non_unique</span><span class=special>&lt;</span> <span class=comment>// indexed by street name</span>
<span class=identifier>member</span><span class=special>&lt;</span><span class=identifier>street_entry</span><span class=special>,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,&amp;</span><span class=identifier>street_entry</span><span class=special>::</span><span class=identifier>name</span><span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span> <span class=identifier>street_locator</span><span class=special>;</span>
</pre></blockquote>
<p>
Also, equality of composite keys can be tuned with
<a href="../reference/key_extraction.html#composite_key_equal_to"><code>composite_key_equal_to</code></a>,
though in most cases the default equality predicate (relying on
the <code>std::equal_to</code> instantiations for the element types)
will be the right choice.
</p>
<p>
Unlike with ordered indices, we cannot perform partial searches specifying
only the first elements of a composite key:
</p>
<blockquote><pre>
<span class=comment>// try to locate streets in quadrants with x==0
// compile-time error: hashed indices do not allow such operations</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>pair</span><span class=special>&lt;</span><span class=identifier>street_locator</span><span class=special>::</span><span class=identifier>iterator</span><span class=special>,</span><span class=identifier>street_locator</span><span class=special>::</span><span class=identifier>iterator</span><span class=special>&gt;</span> <span class=identifier>p</span><span class=special>=</span>
<span class=identifier>sl</span><span class=special>.</span><span class=identifier>equal_range</span><span class=special>(</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>make_tuple</span><span class=special>(</span><span class=number>0</span><span class=special>));</span>
</pre></blockquote>
<p>
The reason for this limitation is quite logical: as the hash value of a composite
key depends on all of its elements, it is impossible to calculate it from
partial information.
</p>
<h2><a name="advanced_key_extractors">Advanced features of Boost.MultiIndex key
extractors</a></h2>
<p>
The <a href="../reference/key_extraction.html#key_extractors"><code>Key Extractor</code></a>
concept allows the same object to extract keys from several different types,
possibly through suitably defined overloads of <code>operator()</code>:
</p>
<blockquote><pre>
<span class=comment>// example of a name extractor from employee and employee *</span>
<span class=keyword>struct</span> <span class=identifier>name_extractor</span>
<span class=special>{</span>
<span class=keyword>typedef</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span> <span class=identifier>result_type</span><span class=special>;</span>
<span class=keyword>const</span> <span class=identifier>result_type</span><span class=special>&amp;</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>employee</span><span class=special>&amp;</span> <span class=identifier>e</span><span class=special>)</span><span class=keyword>const</span><span class=special>{</span><span class=keyword>return</span> <span class=identifier>e</span><span class=special>.</span><span class=identifier>name</span><span class=special>;}</span>
<span class=identifier>result_type</span><span class=special>&amp;</span> <span class=keyword>operator</span><span class=special>()(</span><span class=identifier>employee</span><span class=special>*</span> <span class=identifier>e</span><span class=special>)</span><span class=keyword>const</span><span class=special>{</span><span class=keyword>return</span> <span class=identifier>e</span><span class=special>-&gt;</span><span class=identifier>name</span><span class=special>;}</span>
<span class=special>};</span>
<span class=comment>// name_extractor can handle elements of type employee...</span>
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=identifier>employee</span><span class=special>,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span>
<span class=identifier>ordered_unique</span><span class=special>&lt;</span><span class=identifier>name_extractor</span><span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span> <span class=identifier>employee_set</span><span class=special>;</span>
<span class=comment>// ...as well as elements of type employee *</span>
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=identifier>employee</span><span class=special>*,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span>
<span class=identifier>ordered_unique</span><span class=special>&lt;</span><span class=identifier>name_extractor</span><span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span> <span class=identifier>employee_ptr_set</span><span class=special>;</span>
</pre></blockquote>
<p>
This possibility is fully exploited by predefined key extractors provided
by Boost.MultiIndex, making it simpler to define <code>multi_index_container</code>s
where elements are pointers or references to the actual objects. The following
specifies a <code>multi_index_container</code> of pointers to employees sorted by their
names.
</p>
<blockquote><pre>
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=identifier>employee</span> <span class=special>*,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span>
<span class=identifier>ordered_non_unique</span><span class=special>&lt;</span><span class=identifier>member</span><span class=special>&lt;</span><span class=identifier>employee</span><span class=special>,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,&amp;</span><span class=identifier>employee</span><span class=special>::</span><span class=identifier>name</span><span class=special>&gt;</span> <span class=special>&gt;</span> <span class=special>&gt;</span>
<span class=special>&gt;</span> <span class=identifier>employee_set</span><span class=special>;</span>
</pre></blockquote>
<p>
Note that this is specified in exactly the same manner as a <code>multi_index_container</code>
of actual <code>employee</code> objects: <code>member</code> takes care of the
extra dereferencing needed to gain access to <code>employee::name</code>. A similar
functionality is provided for interoperability with reference wrappers from
<a href="../../../../doc/html/ref.html">Boost.Ref</a>:
</p>
<blockquote><pre>
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=identifier>boost</span><span class=special>::</span><span class=identifier>reference_wrapper</span><span class=special>&lt;</span><span class=keyword>const</span> <span class=identifier>employee</span><span class=special>&gt;,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span>
<span class=identifier>ordered_non_unique</span><span class=special>&lt;</span><span class=identifier>member</span><span class=special>&lt;</span><span class=identifier>employee</span><span class=special>,</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>,&amp;</span><span class=identifier>employee</span><span class=special>::</span><span class=identifier>name</span><span class=special>&gt;</span> <span class=special>&gt;</span> <span class=special>&gt;</span>
<span class=special>&gt;</span> <span class=identifier>employee_set</span><span class=special>;</span>
</pre></blockquote>
<p>
In fact, support for pointers is further extended to accept what we call
<i>chained pointers</i>. Such a chained pointer is defined by induction as a raw or
smart pointer or iterator to the actual element, to a reference wrapper of the
element or <i>to another chained pointer</i>; that is, chained pointers are arbitrary
compositions of pointer-like types ultimately dereferencing
to the element from where the key is to be extracted. Examples of chained
pointers to <code>employee</code> are:
<ul>
<li><code>employee *</code>,</li>
<li><code>const employee *</code>,</li>
<li><code>std::auto_ptr&lt;employee></code>,</li>
<li><code>std::list&lt;boost::reference_wrapper&lt;employee> >::iterator</code>,</li>
<li><code>employee **</code>,</li>
<li><code>boost::shared_ptr&lt;const employee *></code>.</li>
</ul>
In general, chained pointers with dereferencing distance greater than 1 are not
likely to be used in a normal program, but they can arise in frameworks
which construct "views" as <code>multi_index_container</code>s from preexisting
<code>multi_index_container</code>s.
</p>
<p>
In order to present a short summary of the different usages of Boost.MultiIndex
key extractors in the presence of reference wrappers and pointers, consider the
following final type:
</p>
<blockquote><pre>
<span class=keyword>struct</span> <span class=identifier>T</span>
<span class=special>{</span>
<span class=keyword>int</span> <span class=identifier>i</span><span class=special>;</span>
<span class=keyword>const</span> <span class=keyword>int</span> <span class=identifier>j</span><span class=special>;</span>
<span class=keyword>int</span> <span class=identifier>f</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=keyword>int</span> <span class=identifier>g</span><span class=special>();</span>
<span class=keyword>static</span> <span class=keyword>int</span> <span class=identifier>gf</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>T</span><span class=special>&amp;);</span>
<span class=keyword>static</span> <span class=keyword>int</span> <span class=identifier>gg</span><span class=special>(</span><span class=identifier>T</span><span class=special>&amp;);</span>
<span class=special>};</span>
</pre></blockquote>
<p>
The table below lists the appropriate key extractors to be used for
different pointer and reference wrapper types based on <code>T</code>, for
each of its members.
</p>
<p align="center">
<table cellspacing="0">
<caption><b>Use cases for Boost.MultiIndex key extractors.</b></caption>
<tr>
<th>element type</th>
<th>&nbsp;key&nbsp;</th>
<th>key extractor</th>
<th>applicable to<br><code>const</code> elements?</th>
<th>read/write?</th>
</tr>
<tr>
<td align="center" rowspan="6"><code>T</code></td>
<td><code>i</code></td>
<td><code>member&lt;T,int,&amp;T::i></code></td>
<td align="center">yes</td>
<td align="center">yes</td>
</tr>
<tr>
<td><code>j</code></td>
<td><code>member&lt;T,const int,&amp;T::j></code></td>
<td align="center">yes</td>
<td align="center">no</td>
</tr>
<tr>
<td><code>f()</code></td>
<td><code>const_mem_fun&lt;T,int,&amp;T::f></code></td>
<td align="center">yes</td>
<td align="center">no</td>
</tr>
<tr>
<td><code>g()</code></td>
<td><code>mem_fun&lt;T,int,&amp;T::g></code></td>
<td align="center">no</td>
<td align="center">no</td>
</tr>
<tr>
<td><code>gf()</code></td>
<td><code>global_fun&lt;const T&amp;,int,&amp;T::gf></code></td>
<td align="center">yes</td>
<td align="center">no</td>
</tr>
<tr>
<td><code>gg()</code></td>
<td><code>global_fun&lt;T&amp;,int,&amp;T::gg></code></td>
<td align="center">no</td>
<td align="center">no</td>
</tr>
<tr class="odd_tr">
<td align="center" rowspan="6"><code>reference_wrapper&lt;T></code></td>
<td><code>i</code></td>
<td><code>member&lt;T,int,&amp;T::i></code></td>
<td align="center">yes</td>
<td align="center">yes</td>
</tr>
<tr class="odd_tr">
<td><code>j</code></td>
<td><code>member&lt;T,const int,&amp;T::j></code></td>
<td align="center">yes</td>
<td align="center">no</td>
</tr>
<tr class="odd_tr">
<td><code>f()</code></td>
<td><code>const_mem_fun&lt;T,int,&amp;T::f></code></td>
<td align="center">yes</td>
<td align="center">no</td>
</tr>
<tr class="odd_tr">
<td><code>g()</code></td>
<td><code>mem_fun&lt;T,int,&amp;T::g></code></td>
<td align="center">yes</td>
<td align="center">no</td>
</tr>
<tr class="odd_tr">
<td><code>gf()</code></td>
<td><code>global_fun&lt;const T&amp;,int,&amp;T::gf></code></td>
<td align="center">yes</td>
<td align="center">no</td>
</tr>
<tr class="odd_tr">
<td><code>gg()</code></td>
<td><code>global_fun&lt;T&amp;,int,&amp;T::gg></code></td>
<td align="center">yes</td>
<td align="center">no</td>
</tr>
<tr>
<td align="center" rowspan="6"><code>reference_wrapper&lt;const T></code></td>
<td><code>i</code></td>
<td><code>member&lt;T,const int,&amp;T::i></code></td>
<td align="center">yes</td>
<td align="center">no</td>
</tr>
<tr>
<td><code>j</code></td>
<td><code>member&lt;T,const int,&amp;T::j></code></td>
<td align="center">yes</td>
<td align="center">no</td>
</tr>
<tr>
<td><code>f()</code></td>
<td><code>const_mem_fun&lt;T,int,&amp;T::f></code></td>
<td align="center">yes</td>
<td align="center">no</td>
</tr>
<tr>
<td><code>g()</code></td>
<td colspan="3">&nbsp;</td>
</tr>
<tr>
<td><code>gf()</code></td>
<td><code>global_fun&lt;const T&amp;,int,&amp;T::gf></code></td>
<td align="center">yes</td>
<td align="center">no</td>
</tr>
<tr>
<td><code>gg()</code></td>
<td colspan="3">&nbsp;</td>
</tr>
<tr class="odd_tr">
<td align="center" rowspan="6">chained pointer to <code>T</code><br>
or to <code>reference_wrapper&lt;T></code></td>
<td><code>i</code></td>
<td><code>member&lt;T,int,&amp;T::i></code></td>
<td align="center">yes</td>
<td align="center">yes</td>
</tr>
<tr class="odd_tr">
<td><code>j</code></td>
<td><code>member&lt;T,const int,&amp;T::j></code></td>
<td align="center">yes</td>
<td align="center">no</td>
</tr>
<tr class="odd_tr">
<td><code>f()</code></td>
<td><code>const_mem_fun&lt;T,int,&amp;T::f></code></td>
<td align="center">yes</td>
<td align="center">no</td>
</tr>
<tr class="odd_tr">
<td><code>g()</code></td>
<td><code>mem_fun&lt;T,int,&amp;T::g></code></td>
<td align="center">yes</td>
<td align="center">no</td>
</tr>
<tr class="odd_tr">
<td><code>gf()</code></td>
<td><code>global_fun&lt;const T&amp;,int,&amp;T::gf></code></td>
<td align="center">yes</td>
<td align="center">no</td>
</tr>
<tr class="odd_tr">
<td><code>gg()</code></td>
<td><code>global_fun&lt;T&amp;,int,&amp;T::gg></code></td>
<td align="center">yes</td>
<td align="center">no</td>
</tr>
<tr>
<td align="center" rowspan="6">chained pointer to <code>const T</code><br>
or to <code>reference_wrapper&lt;const T></code></td>
<td><code>i</code></td>
<td><code>member&lt;T,const int,&amp;T::i></code></td>
<td align="center">yes</td>
<td align="center">no</td>
</tr>
<tr>
<td><code>j</code></td>
<td><code>member&lt;T,const int,&amp;T::j></code></td>
<td align="center">yes</td>
<td align="center">no</td>
</tr>
<tr>
<td><code>f()</code></td>
<td><code>const_mem_fun&lt;T,int,&amp;T::f></code></td>
<td align="center">yes</td>
<td align="center">no</td>
</tr>
<tr>
<td><code>g()</code></td>
<td colspan="3">&nbsp;</td>
</tr>
<tr>
<td><code>gf()</code></td>
<td><code>global_fun&lt;const T&amp;,int,&amp;T::gf></code></td>
<td align="center">yes</td>
<td align="center">no</td>
</tr>
<tr>
<td><code>gg()</code></td>
<td colspan="3">&nbsp;</td>
</tr>
</table>
</p>
<p>
The column "applicable to <code>const</code> elements?" states whether the
corresponding key extractor can be used when passed constant elements (this
relates to the elements specified in the first column, not the referenced
<code>T</code> objects). The only negative cases are for <code>T::g</code> and
<code>T:gg</code> when the elements are raw <code>T</code> objects, which make sense
as we are dealing with a non-constant member function (<code>T::g</code>)
and a function taking <code>T</code> by
non-constant reference: this also implies that <code>multi_index_container</code>s
of elements of <code>T</code> cannot be sorted by <code>T::g</code> or <code>T::gg</code>, because
elements contained within a <code>multi_index_container</code> are treated as constant.
</p>
<p>
The column "read/write?" shows which combinations yield
<a href="#read_write_key_extractors">read/write key extractors</a>.
</p>
<p>
Some care has to be taken to preserve <code>const</code>-correctness in the
specification of <code>member</code> key extractors: in some sense, the <code>const</code>
qualifier is carried along to the member part, even if that particular
member is not defined as <code>const</code>. For instance, if the elements
are of type <code>const T *</code>, sorting by <code>T::i</code> is <i>not</i>
specified as <code>member&lt;const T,int,&amp;T::i></code>, but rather as
<code>member&lt;T,const int,&amp;T::i></code>.
</p>
<p>
For practical demonstrations of use of these key extractors, refer to
<a href="../examples.html#example2">example 2</a> and
<a href="../examples.html#example6">example 6</a> in the examples section.
</p>
<hr>
<div class="prev_link"><a href="indices.html"><img src="../prev.gif" alt="index types" border="0"><br>
Index types
</a></div>
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.MultiIndex tutorial" border="0"><br>
Boost.MultiIndex tutorial
</a></div>
<div class="next_link"><a href="creation.html"><img src="../next.gif" alt="container creation" border="0"><br>
Container creation
</a></div><br clear="all" style="clear: all;">
<br>
<p>Revised June 11th 2007</p>
<p>&copy; Copyright 2003-2007 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
http://www.boost.org/LICENSE_1_0.txt</a>)
</p>
</body>
</html>

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 85 KiB

+405
View File
@@ -0,0 +1,405 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0.1 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Boost.MultiIndex Documentation - Tutorial - Techniques</title>
<link rel="stylesheet" href="../style.css" type="text/css">
<link rel="start" href="../index.html">
<link rel="prev" href="debug.html">
<link rel="up" href="index.html">
<link rel="next" href="../reference/index.html">
</head>
<body>
<h1><img src="../../../../boost.png" alt="boost.png (6897 bytes)" align=
"middle" width="277" height="86">Boost.MultiIndex Tutorial: Techniques</h1>
<div class="prev_link"><a href="debug.html"><img src="../prev.gif" alt="debugging support" border="0"><br>
Debugging support
</a></div>
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.MultiIndex tutorial" border="0"><br>
Boost.MultiIndex tutorial
</a></div>
<div class="next_link"><a href="../reference/index.html"><img src="../next.gif" alt="Boost.MultiIndex reference" border="0"><br>
Boost.MultiIndex reference
</a></div><br clear="all" style="clear: all;">
<hr>
<h2>Contents</h2>
<ul>
<li><a href="#emulate_std_containers">Emulating standard containers with
<code>multi_index_container</code></a>
<ul>
<li><a href="#emulate_assoc_containers">Emulation of associative
containers</a></li>
<li><a href="#emulate_std_list">Emulation of <code>std::list</code></a></li>
</ul>
</li>
<li><a href="#metaprogrammming">Metaprogramming and <code>multi_index_container</code></a>
<ul>
<li><a href="#mpl_analysis">MPL analysis</a></li>
<li><a href="#mpl_synthesis">MPL synthesis</a></li>
</ul>
</li>
</ul>
<h2><a name="emulate_std_containers">Emulating standard containers with
<code>multi_index_container</code></a></h2>
<h3><a name="emulate_assoc_containers">Emulation of associative
containers</a></h3>
<p>
Academic movitations aside, there is a practical interest in emulating standard
associative containers by means of <code>multi_index_container</code>, namely to take
advantage of extended functionalities provided by <code>multi_index_container</code> for
lookup, range querying and updating.
</p>
<p>
In order to emulate a <code>std::set</code> one can follow the substitution
rule:
</p>
<blockquote><pre>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>set</span><span class=special>&lt;</span><span class=identifier>Key</span><span class=special>,</span><span class=identifier>Compare</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>&gt;</span> <span class=special>-&gt;</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=identifier>Key</span><span class=special>,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span><span class=identifier>ordered_unique</span><span class=special>&lt;</span><span class=identifier>identity</span><span class=special>&lt;</span><span class=identifier>Key</span><span class=special>&gt;,</span><span class=identifier>Compare</span><span class=special>&gt;</span> <span class=special>&gt;,</span>
<span class=identifier>Allocator</span>
<span class=special>&gt;</span>
</pre></blockquote>
<p>
In the default case where <code>Compare=std::less&lt;Key></code> and
<code>Allocator=std::allocator&lt;Key></code>, the substitution rule is
simplified as
</p>
<blockquote><pre>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>set</span><span class=special>&lt;</span><span class=identifier>Key</span><span class=special>&gt;</span> <span class=special>-&gt;</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span><span class=identifier>Key</span><span class=special>&gt;</span>
</pre></blockquote>
<p>
The substitution of <code>multi_index_container</code> for <code>std::set</code> keeps
the whole set of functionality provided by <code>std::set</code>, so in
principle it is a drop-in replacement needing no further adjustments.
</p>
<p>
<code>std::multiset</code> can be emulated in a similar manner, according to the
following rule:
</p>
<blockquote><pre>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>multiset</span><span class=special>&lt;</span><span class=identifier>Key</span><span class=special>,</span><span class=identifier>Compare</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>&gt;</span> <span class=special>-&gt;</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=identifier>Key</span><span class=special>,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span><span class=identifier>ordered_non_unique</span><span class=special>&lt;</span><span class=identifier>identity</span><span class=special>&lt;</span><span class=identifier>Key</span><span class=special>&gt;,</span><span class=identifier>Compare</span><span class=special>&gt;</span> <span class=special>&gt;,</span>
<span class=identifier>Allocator</span>
<span class=special>&gt;</span>
</pre></blockquote>
<p>
When default values are taken into consideration, the rule takes the form
</p>
<blockquote><pre>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>multiset</span><span class=special>&lt;</span><span class=identifier>Key</span><span class=special>&gt;</span> <span class=special>-&gt;</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=identifier>Key</span><span class=special>,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span><span class=identifier>ordered_non_unique</span><span class=special>&lt;</span><span class=identifier>identity</span><span class=special>&lt;</span><span class=identifier>Key</span><span class=special>&gt;</span> <span class=special>&gt;</span> <span class=special>&gt;</span>
<span class=special>&gt;</span>
</pre></blockquote>
<p>
The emulation of <code>std::multiset</code>s with <code>multi_index_container</code>
results in a slight difference with respect to the interface offered: the member
function <code>insert(const value_type&amp;)</code> does not return an
<code>iterator</code> as in <code>std::multiset</code>s, but rather a
<code>std::pair&lt;iterator,bool></code> in the spirit of <code>std::set</code>s.
In this particular case, however, the <code>bool</code> member of the returned
pair is always <code>true</code>.
</p>
<p>
The case of <code>std::map</code>s and <code>std::multimap</code>s does not lend
itself to such a direct emulation by means of <code>multi_index_container</code>. The main
problem lies in the fact that elements of a <code>multi_index_container</code> are treated
as constant, while the <code>std::map</code> and <code>std::multimap</code> handle
objects of type <code>std::pair&lt;const Key,T></code>, thus allowing for free
modification of the value part. To overcome this difficulty we need to create an ad
hoc pair class:
</p>
<blockquote><pre>
<span class=keyword>template</span> <span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>T1</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>T2</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>mutable_pair</span>
<span class=special>{</span>
<span class=keyword>typedef</span> <span class=identifier>T1</span> <span class=identifier>first_type</span><span class=special>;</span>
<span class=keyword>typedef</span> <span class=identifier>T2</span> <span class=identifier>second_type</span><span class=special>;</span>
<span class=identifier>mutable_pair</span><span class=special>():</span><span class=identifier>first</span><span class=special>(</span><span class=identifier>T1</span><span class=special>()),</span><span class=identifier>second</span><span class=special>(</span><span class=identifier>T2</span><span class=special>()){}</span>
<span class=identifier>mutable_pair</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>T1</span><span class=special>&amp;</span> <span class=identifier>f</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>T2</span><span class=special>&amp;</span> <span class=identifier>s</span><span class=special>):</span><span class=identifier>first</span><span class=special>(</span><span class=identifier>f</span><span class=special>),</span><span class=identifier>second</span><span class=special>(</span><span class=identifier>s</span><span class=special>){}</span>
<span class=identifier>mutable_pair</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>pair</span><span class=special>&lt;</span><span class=identifier>T1</span><span class=special>,</span><span class=identifier>T2</span><span class=special>&gt;&amp;</span> <span class=identifier>p</span><span class=special>):</span><span class=identifier>first</span><span class=special>(</span><span class=identifier>p</span><span class=special>.</span><span class=identifier>first</span><span class=special>),</span><span class=identifier>second</span><span class=special>(</span><span class=identifier>p</span><span class=special>.</span><span class=identifier>second</span><span class=special>){}</span>
<span class=identifier>T1</span> <span class=identifier>first</span><span class=special>;</span>
<span class=keyword>mutable</span> <span class=identifier>T2</span> <span class=identifier>second</span><span class=special>;</span>
<span class=special>};</span>
</pre></blockquote>
<p>
and so the substitution rules are:
</p>
<blockquote><pre>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>map</span><span class=special>&lt;</span><span class=identifier>Key</span><span class=special>,</span><span class=identifier>T</span><span class=special>,</span><span class=identifier>Compare</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>&gt;</span> <span class=special>-&gt;</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=identifier>Element</span><span class=special>,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span>
<span class=identifier>ordered_unique</span><span class=special>&lt;</span><span class=identifier>member</span><span class=special>&lt;</span><span class=identifier>Element</span><span class=special>,</span><span class=identifier>Key</span><span class=special>,&amp;</span><span class=identifier>Element</span><span class=special>::</span><span class=identifier>first</span><span class=special>&gt;,</span><span class=identifier>Compare</span><span class=special>&gt;</span>
<span class=special>&gt;,</span>
<span class=keyword>typename</span> <span class=identifier>Allocator</span><span class=special>::</span><span class=keyword>template</span> <span class=identifier>rebind</span><span class=special>&lt;</span><span class=identifier>Element</span><span class=special>&gt;::</span><span class=identifier>other</span>
<span class=special>&gt;</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>multimap</span><span class=special>&lt;</span><span class=identifier>Key</span><span class=special>,</span><span class=identifier>T</span><span class=special>,</span><span class=identifier>Compare</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>&gt;</span> <span class=special>-&gt;</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=identifier>Element</span><span class=special>,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span>
<span class=identifier>ordered_non_unique</span><span class=special>&lt;</span><span class=identifier>member</span><span class=special>&lt;</span><span class=identifier>Element</span><span class=special>,</span><span class=identifier>Key</span><span class=special>,&amp;</span><span class=identifier>Element</span><span class=special>::</span><span class=identifier>first</span><span class=special>&gt;,</span><span class=identifier>Compare</span><span class=special>&gt;</span>
<span class=special>&gt;,</span>
<span class=keyword>typename</span> <span class=identifier>Allocator</span><span class=special>::</span><span class=keyword>template</span> <span class=identifier>rebind</span><span class=special>&lt;</span><span class=identifier>Element</span><span class=special>&gt;::</span><span class=identifier>other</span>
<span class=special>&gt;</span>
(<span class=identifier>with</span> <span class=identifier>Element</span><span class=special>=</span><span class=identifier>mutable_pair</span><span class=special>&lt;</span><span class=identifier>Key</span><span class=special>,</span><span class=identifier>T</span><span class=special>&gt;</span>)
</pre></blockquote>
<p>
If default values are considered, the rules take the form:
</p>
<blockquote><pre>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>map</span><span class=special>&lt;</span><span class=identifier>Key</span><span class=special>,</span><span class=identifier>T</span><span class=special>&gt;</span> <span class=special>-&gt;</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=identifier>Element</span><span class=special>,
</span><span class=identifier>indexed_by</span><span class=special>&lt;</span><span class=identifier>ordered_unique</span><span class=special>&lt;</span><span class=identifier>member</span><span class=special>&lt;</span><span class=identifier>Element</span><span class=special>,</span><span class=identifier>Key</span><span class=special>,&amp;</span><span class=identifier>Element</span><span class=special>::</span><span class=identifier>first</span><span class=special>&gt;</span> <span class=special>&gt;</span> <span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>multimap</span><span class=special>&lt;</span><span class=identifier>Key</span><span class=special>,</span><span class=identifier>T</span><span class=special>&gt;</span> <span class=special>-&gt;</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=identifier>Element</span><span class=special>,
</span><span class=identifier>indexed_by</span><span class=special>&lt;</span><span class=identifier>ordered_non_unique</span><span class=special>&lt;</span><span class=identifier>member</span><span class=special>&lt;</span><span class=identifier>Element</span><span class=special>,</span><span class=identifier>Key</span><span class=special>,&amp;</span><span class=identifier>Element</span><span class=special>::</span><span class=identifier>first</span><span class=special>&gt;</span> <span class=special>&gt;</span> <span class=special>&gt;</span>
<span class=special>&gt;</span>
(<span class=identifier>with</span> <span class=identifier>Element</span><span class=special>=</span><span class=identifier>mutable_pair</span><span class=special>&lt;</span><span class=identifier>Key</span><span class=special>,</span><span class=identifier>T</span><span class=special>&gt;</span>)
</pre></blockquote>
<p>
Unlike as with standard sets, the interface of these <code>multi_index_container</code>-emulated
maps does not exactly conform to that of <code>std::map</code>s and
<code>std::multimap</code>s. The most obvious difference is the lack of
<code>operator []</code>, either in read or write mode; this, however, can be
emulated with appropriate use of <code>find</code> and <code>insert</code>.
</p>
<p>
These emulations of standard associative containers with <code>multi_index_container</code>
are comparable to the original constructs in terms of space and time efficiency.
See the <a href="../performance.html">performance section</a> for further details.
</p>
<h3><a name="emulate_std_list">Emulation of <code>std::list</code></a></h3>
<p>
Unlike the case of associative containers, emulating <code>std::list</code>
in Boost.MultiIndex does not add any significant functionality, so the following
is presented merely for completeness sake.
</p>
<p>
Much as with standard maps, the main difficulty to overcome when emulating
<code>std::list</code> derives from the constant nature of elements of a
<code>multi_index_container</code>. Again, some sort of adaption class is needed, like
for instance the following:
</p>
<blockquote><pre>
<span class=keyword>template</span> <span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>T</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>mutable_value</span>
<span class=special>{</span>
<span class=identifier>mutable_value</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>T</span><span class=special>&amp;</span> <span class=identifier>t</span><span class=special>):</span><span class=identifier>t</span><span class=special>(</span><span class=identifier>t</span><span class=special>){}</span>
<span class=keyword>operator</span> <span class=identifier>T</span><span class=special>&amp;()</span><span class=keyword>const</span><span class=special>{</span><span class=keyword>return</span> <span class=identifier>t</span><span class=special>;}</span>
<span class=keyword>private</span><span class=special>:</span>
<span class=keyword>mutable</span> <span class=identifier>T</span> <span class=identifier>t</span><span class=special>;</span>
<span class=special>};</span>
</pre></blockquote>
<p>
which allows us to use the substitution rule:
</p>
<blockquote><pre>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>list</span><span class=special>&lt;</span><span class=identifier>T</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>&gt;</span> <span class=special>-&gt;</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=identifier>Element</span><span class=special>,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span><span class=identifier>sequenced</span><span class=special>&lt;&gt;</span> <span class=special>&gt;,</span>
<span class=keyword>typename</span> <span class=identifier>Allocator</span><span class=special>::</span><span class=keyword>template</span> <span class=identifier>rebind</span><span class=special>&lt;</span><span class=identifier>Element</span><span class=special>&gt;::</span><span class=identifier>other</span>
<span class=special>&gt;</span>
(<span class=identifier>with</span> <span class=identifier>Element</span><span class=special>=</span><span class=identifier>mutable_value</span><span class=special>&lt;</span><span class=identifier>T</span><span class=special>&gt;</span>)
</pre></blockquote>
<p>
or, if the default value <code>Allocator=std::allocator&lt;T></code> is used:
</p>
<blockquote><pre>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>list</span><span class=special>&lt;</span><span class=identifier>T</span><span class=special>&gt;</span> <span class=special>-&gt;</span>
<span class=identifier>multi_index_container</span><span class=special>&lt;</span><span class=identifier>mutable_value</span><span class=special>&lt;</span><span class=identifier>T</span><span class=special>&gt;,</span><span class=identifier>indexed_by</span><span class=special>&lt;</span><span class=identifier>sequenced</span><span class=special>&lt;&gt;</span> <span class=special>&gt;</span> <span class=special>&gt;</span>
</pre></blockquote>
<h2><a name="metaprogrammming">Metaprogramming and <code>multi_index_container</code></a></h2>
<p>
Boost.MultiIndex provides a number of facilities intended to allow the analysis and
synthesis of <code>multi_index_container</code> instantiations by
<a href="../../../../libs/mpl/doc/index.html">MPL</a> metaprograms.
</p>
<h3><a name="mpl_analysis">MPL analysis</a></h3>
<p>
Given a <code>multi_index_container</code> instantiation, the following nested types are
provided for compile-time inspection of the various types occurring in the
definition of the <code>multi_index_container</code>:
<ul>
<li><code>index_specifier_type_list</code>,</li>
<li><code>index_type_list</code>,</li>
<li><code>iterator_type_list</code>,</li>
<li><code>const_iterator_type_list</code>.</li>
</ul>
Each of these types is an MPL sequence with as many elements as indices
comprise the <code>multi_index_container</code>: for instance, the <code>n</code>-th
element of <code>iterator_type_list</code> is the same as
<code>nth_index&lt;n>::type::iterator</code>.
</p>
<p>
A subtle but important distinction exists between
<code>index_specifier_type_list</code> and <code>index_type_list</code>:
the former typelist holds the index <i>specifiers</i>
with which the <code>multi_index_container</code> instantiation was defined,
while the latter gives access to the actual implementation classes
corresponding to each specifier. An example will help to clarify
this distinction. Given the instantiation:
</p>
<blockquote><pre>
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=keyword>int</span><span class=special>,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span>
<span class=identifier>ordered_unique</span><span class=special>&lt;</span><span class=identifier>identity</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;</span> <span class=special>&gt;,</span>
<span class=identifier>sequenced</span><span class=special>&lt;&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span> <span class=identifier>indexed_t</span><span class=special>;</span>
</pre></blockquote>
<p>
<code>indexed_t::index_specifier_type_list</code> is a type list with
elements
</p>
<blockquote><pre>
<span class=identifier>ordered_unique</span><span class=special>&lt;</span><span class=identifier>identity</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;</span> <span class=special>&gt;</span>
<span class=identifier>sequenced</span><span class=special>&lt;&gt;</span>
</pre></blockquote>
<p>
while <code>indexed_t::index_type_list</code> holds the types
</p>
<blockquote><pre>
<span class=identifier>multi_index_container</span><span class=special>::</span><span class=identifier>nth_type</span><span class=special>&lt;</span><span class=number>0</span><span class=special>&gt;::</span><span class=identifier>type</span>
<span class=identifier>multi_index_container</span><span class=special>::</span><span class=identifier>nth_type</span><span class=special>&lt;</span><span class=number>1</span><span class=special>&gt;::</span><span class=identifier>type</span>
</pre></blockquote>
<p>
so the typelists are radically different. Check the
<a href="../reference/multi_index_container.html#types">reference</a>
for the exact MPL sequence concepts modeled by these type lists.
</p>
<h3><a name="mpl_synthesis">MPL synthesis</a></h3>
<p>
Although typically indices are specified by means of the
<code>indexed_by</code> construct, actually any MPL sequence of
index specifiers can be provided instead:
</p>
<blockquote><pre>
<span class=keyword>typedef</span> <span class=identifier>mpl</span><span class=special>::</span><span class=identifier>vector</span><span class=special>&lt;</span><span class=identifier>ordered_unique</span><span class=special>&lt;</span><span class=identifier>identity</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;</span> <span class=special>&gt;,</span><span class=identifier>sequenced</span><span class=special>&lt;&gt;</span> <span class=special>&gt;</span> <span class=identifier>index_list_t</span><span class=special>;</span>
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=keyword>int</span><span class=special>,</span>
<span class=identifier>index_list_t</span>
<span class=special>&gt;</span> <span class=identifier>indexed_t</span><span class=special>;</span>
</pre></blockquote>
<p>
This possibility enables the synthesis of instantiations of
<code>multi_index_container</code> through MPL metaprograms, as the following
example shows:
</p>
<blockquote><pre>
<span class=comment>// original multi_index_container instantiation</span>
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=keyword>int</span><span class=special>,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span>
<span class=identifier>ordered_unique</span><span class=special>&lt;</span><span class=identifier>identity</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;</span> <span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span> <span class=identifier>indexed_t1</span><span class=special>;</span>
<span class=comment>// we take its index list and add an index</span>
<span class=keyword>typedef</span> <span class=identifier>boost</span><span class=special>::</span><span class=identifier>mpl</span><span class=special>::</span><span class=identifier>push_front</span><span class=special>&lt;</span>
<span class=identifier>indexed_t1</span><span class=special>::</span><span class=identifier>index_specifier_type_list</span><span class=special>,</span>
<span class=identifier>sequenced</span><span class=special>&lt;&gt;</span>
<span class=special>&gt;::</span><span class=identifier>type</span> <span class=identifier>index_list_t</span><span class=special>;</span>
<span class=comment>// augmented multi_index_container</span>
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=keyword>int</span><span class=special>,</span>
<span class=identifier>index_list_t</span>
<span class=special>&gt;</span> <span class=identifier>indexed_t2</span><span class=special>;</span>
</pre></blockquote>
<hr>
<div class="prev_link"><a href="debug.html"><img src="../prev.gif" alt="debugging support" border="0"><br>
Debugging support
</a></div>
<div class="up_link"><a href="index.html"><img src="../up.gif" alt="Boost.MultiIndex tutorial" border="0"><br>
Boost.MultiIndex tutorial
</a></div>
<div class="next_link"><a href="../reference/index.html"><img src="../next.gif" alt="Boost.MultiIndex reference" border="0"><br>
Boost.MultiIndex reference
</a></div><br clear="all" style="clear: all;">
<br>
<p>Revised November 7th 2008</p>
<p>&copy; Copyright 2003-2008 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
http://www.boost.org/LICENSE_1_0.txt</a>)
</p>
</body>
</html>
+20 -8
View File
@@ -1,14 +1,12 @@
# Boost.MultiIndex examples Jamfile
#
# Copyright 2003-2005 Joaquín M López Muñoz.
# Copyright 2003-2007 Joaquín M López Muñoz.
# 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)
#
# See http://www.boost.org/libs/multi_index for library home page.
subproject libs/multi_index/example ;
exe basic
: basic.cpp
: <include>$(BOOST_ROOT)
@@ -29,14 +27,19 @@ exe composite_keys
: <include>$(BOOST_ROOT)
;
exe fun_key
: fun_key.cpp
: <include>$(BOOST_ROOT)
;
exe hashed
: hashed.cpp
: <include>$(BOOST_ROOT)
;
exe memfun_key
: memfun_key.cpp
: <include>$(BOOST_ROOT)
exe ip_allocator
: ip_allocator.cpp
: <include>$(BOOST_ROOT) <threading>multi
;
exe non_default_ctor
@@ -44,6 +47,16 @@ exe non_default_ctor
: <include>$(BOOST_ROOT)
;
exe random_access
: random_access.cpp
: <include>$(BOOST_ROOT)
;
exe rearrange
: rearrange.cpp
: <include>$(BOOST_ROOT)
;
exe sequenced
: sequenced.cpp
: <include>$(BOOST_ROOT)
@@ -51,7 +64,6 @@ exe sequenced
exe serialization
: serialization.cpp
<lib>../../serialization/build/boost_serialization
/boost/serialization//boost_serialization
: <include>$(BOOST_ROOT)
std::locale-support
;
+1 -1
View File
@@ -1,6 +1,6 @@
/* Boost.MultiIndex basic example.
*
* Copyright 2003-2005 Joaqu匤 M Lez Muz.
* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
+12 -5
View File
@@ -1,6 +1,6 @@
/* Boost.MultiIndex example of a bidirectional map.
*
* Copyright 2003-2005 Joaquín M López Muñoz.
* Copyright 2003-2009 Joaquin M Lopez Munoz.
* 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)
@@ -18,7 +18,6 @@
#include <boost/multi_index/ordered_index.hpp>
#include <iostream>
#include <string>
#include <utility>
using boost::multi_index_container;
using namespace boost::multi_index;
@@ -35,7 +34,15 @@ struct to{};
template<typename FromType,typename ToType>
struct bidirectional_map
{
typedef std::pair<FromType,ToType> value_type;
struct value_type
{
value_type(const FromType& first_,const ToType& second_):
first(first_),second(second_)
{}
FromType first;
ToType second;
};
#if defined(BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS) ||\
defined(BOOST_MSVC)&&(BOOST_MSVC<1300) ||\
@@ -108,7 +115,7 @@ int main()
std::cout<<word<<" is said "<<it->second<<" in English"<<std::endl;
}
else{
nth_index_iterator<dictionary,1>::type it2=get<1>(d).find(word);
nth_index<dictionary,1>::type::iterator it2=get<1>(d).find(word);
if(it2!=get<1>(d).end()){
std::cout<<word<<" is said "<<it2->first<<" in Spanish"<<std::endl;
}
@@ -129,7 +136,7 @@ int main()
else{
/* word not found in Spanish, try our luck in English */
dictionary::index_iterator<to>::type it2=d.get<to>().find(word);
dictionary::index<to>::type::iterator it2=d.get<to>().find(word);
if(it2!=d.get<to>().end()){
std::cout<<word<<" is said "<<it2->first<<" in Spanish"<<std::endl;
}
+3 -3
View File
@@ -1,6 +1,6 @@
/* Boost.MultiIndex example: complex searches and foreign keys.
*
* Copyright 2003-2005 Joaquín M López Muñoz.
* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
@@ -245,7 +245,7 @@ int main()
/* find all the cars for the manufacturer given */
index_iterator<car_table,manufacturer>::type ic0,ic1;
boost::multi_index::index<car_table,manufacturer>::type::iterator ic0,ic1;
boost::tuples::tie(ic0,ic1)=get<manufacturer>(ct).equal_range(cm);
/* construct a view (indexed by price) with these */
@@ -280,7 +280,7 @@ int main()
/* find the cars in the range given */
index_iterator<car_table,price>::type ic0,ic1;
boost::multi_index::index<car_table,price>::type::iterator ic0,ic1;
ic0=get<price>(ct).lower_bound(min_price);
ic1=get<price>(ct).upper_bound(max_price);
+3 -2
View File
@@ -1,6 +1,6 @@
/* Boost.MultiIndex example of composite keys.
*
* Copyright 2003-2005 Joaquín M López Muñoz.
* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
@@ -18,6 +18,7 @@
#include <boost/multi_index/composite_key.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/next_prior.hpp>
#include <boost/tokenizer.hpp>
#include <functional>
#include <iostream>
@@ -287,7 +288,7 @@ int main()
continue;
}
it->second->execute(++tok.begin(),tok.end());
it->second->execute(boost::next(tok.begin()),tok.end());
}
return 0;
+26 -5
View File
@@ -1,6 +1,6 @@
/* Boost.MultiIndex example of member functions used as key extractors.
/* Boost.MultiIndex example of functions used as key extractors.
*
* Copyright 2003-2005 Joaquín M López Muñoz.
* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
@@ -14,6 +14,7 @@
#endif
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/global_fun.hpp>
#include <boost/multi_index/mem_fun.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <iostream>
@@ -29,8 +30,8 @@ using namespace boost::multi_index;
struct name_record
{
name_record(std::string given_name,std::string family_name):
given_name(given_name),family_name(family_name)
name_record(std::string given_name_,std::string family_name_):
given_name(given_name_),family_name(family_name_)
{}
std::string name()const
@@ -46,7 +47,13 @@ private:
std::string family_name;
};
/* multi_index_container with only one index based on name_record::name().
std::string::size_type name_record_length(const name_record& r)
{
return r.name().size();
}
/* multi_index_container with indices based on name_record::name()
* and name_record_length().
* See Compiler specifics: Use of const_mem_fun_explicit and
* mem_fun_explicit for info on BOOST_MULTI_INDEX_CONST_MEM_FUN.
*/
@@ -56,6 +63,9 @@ typedef multi_index_container<
indexed_by<
ordered_unique<
BOOST_MULTI_INDEX_CONST_MEM_FUN(name_record,std::string,name)
>,
ordered_non_unique<
global_fun<const name_record&,std::string::size_type,name_record_length>
>
>
> name_record_set;
@@ -71,9 +81,20 @@ int main()
/* list the names in ns in phonebook order */
std::cout<<"Phonenook order\n"
<<"---------------"<<std::endl;
for(name_record_set::iterator it=ns.begin();it!=ns.end();++it){
std::cout<<it->name()<<std::endl;
}
/* list the names in ns according to their length*/
std::cout<<"\nLength order\n"
<< "------------"<<std::endl;
for(nth_index<name_record_set,1>::type::iterator it1=get<1>(ns).begin();
it1!=get<1>(ns).end();++it1){
std::cout<<it1->name()<<std::endl;
}
return 0;
}
+3 -1
View File
@@ -1,6 +1,6 @@
/* Boost.MultiIndex example of use of hashed indices.
*
* Copyright 2003-2005 Joaqu匤 M Lez Muz.
* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
@@ -66,6 +66,8 @@ typedef boost::tokenizer<boost::char_separator<char> > text_tokenizer;
int main()
{
/* boostinspect:noascii */
std::string text=
"En un lugar de la Mancha, de cuyo nombre no quiero acordarme, no ha "
"mucho tiempo que vivía un hidalgo de los de lanza en astillero, adarga "
+293
View File
@@ -0,0 +1,293 @@
/* Boost.MultiIndex example of use of Boost.Interprocess allocators.
*
* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
*
* See http://www.boost.org/libs/multi_index for library home page.
*/
#if !defined(NDEBUG)
#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING
#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <algorithm>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <boost/interprocess/managed_mapped_file.hpp>
#include <boost/interprocess/sync/named_mutex.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/member.hpp>
#include <iostream>
#include <iterator>
#include <sstream>
#include <string>
using boost::multi_index_container;
using namespace boost::multi_index;
namespace bip=boost::interprocess;
/* shared_string is a string type placeable in shared memory,
* courtesy of Boost.Interprocess.
*/
typedef bip::basic_string<
char,std::char_traits<char>,
bip::allocator<char,bip::managed_mapped_file::segment_manager>
> shared_string;
/* Book record. All its members can be placed in shared memory,
* hence the structure itself can too.
*/
struct book
{
shared_string name;
shared_string author;
unsigned pages;
unsigned prize;
book(const shared_string::allocator_type& al):
name(al),author(al),pages(0),prize(0)
{}
friend std::ostream& operator<<(std::ostream& os,const book& b)
{
os<<b.author<<": \""<<b.name<<"\", $"<<b.prize<<", "<<b.pages<<" pages\n";
return os;
}
};
/* partial_str_less allows for partial searches taking into account
* only the first n chars of the strings compared against. See
* Tutorial: Basics: Special lookup operations for more info on this
* type of comparison functors.
*/
/* partial_string is a mere string holder used to differentiate from
* a plain string.
*/
struct partial_string
{
partial_string(const shared_string& str):str(str){}
shared_string str;
};
struct partial_str_less
{
bool operator()(const shared_string& x,const shared_string& y)const
{
return x<y;
}
bool operator()(const shared_string& x,const partial_string& y)const
{
return x.substr(0,y.str.size())<y.str;
}
bool operator()(const partial_string& x,const shared_string& y)const
{
return x.str<y.substr(0,x.str.size());
}
};
/* Define a multi_index_container of book records with indices on
* author, name and prize. The index on names allows for partial
* searches. This container can be placed in shared memory because:
* * book can be placed in shared memory.
* * We are using a Boost.Interprocess specific allocator.
*/
/* see Compiler specifics: Use of member_offset for info on
* BOOST_MULTI_INDEX_MEMBER
*/
typedef multi_index_container<
book,
indexed_by<
ordered_non_unique<
BOOST_MULTI_INDEX_MEMBER(book,shared_string,author)
>,
ordered_non_unique<
BOOST_MULTI_INDEX_MEMBER(book,shared_string,name),
partial_str_less
>,
ordered_non_unique<
BOOST_MULTI_INDEX_MEMBER(book,unsigned,prize)
>
>,
bip::allocator<book,bip::managed_mapped_file::segment_manager>
> book_container;
/* A small utility to get data entered via std::cin */
template<typename T>
void enter(const char* msg,T& t)
{
std::cout<<msg;
std::string str;
std::getline(std::cin,str);
std::istringstream iss(str);
iss>>t;
}
void enter(const char* msg,std::string& str)
{
std::cout<<msg;
std::getline(std::cin,str);
}
void enter(const char* msg,shared_string& str)
{
std::cout<<msg;
std::string stdstr;
std::getline(std::cin,stdstr);
str=stdstr.c_str();
}
int main()
{
/* Create (or open) the memory mapped file where the book container
* is stored, along with a mutex for synchronized access.
*/
bip::managed_mapped_file seg(
bip::open_or_create,"./book_container.db",
65536);
bip::named_mutex mutex(
bip::open_or_create,"7FD6D7E8-320B-11DC-82CF-F0B655D89593");
/* create or open the book container in shared memory */
book_container* pbc=seg.find_or_construct<book_container>("book container")(
book_container::ctor_args_list(),
book_container::allocator_type(seg.get_segment_manager()));
std::string command_info=
"1. list books by author\n"
"2. list all books by prize\n"
"3. insert a book\n"
"4. delete a book\n"
"0. exit\n";
std::cout<<command_info;
/* main loop */
for(bool exit=false;!exit;){
int command=-1;
enter("command: ",command);
switch(command){
case 0:{ /* exit */
exit=true;
break;
}
case 1:{ /* list books by author */
std::string author;
enter("author (empty=all authors): ",author);
/* operations with the container must be mutex protected */
bip::scoped_lock<bip::named_mutex> lock(mutex);
std::pair<book_container::iterator,book_container::iterator> rng;
if(author.empty()){
rng=std::make_pair(pbc->begin(),pbc->end());
}
else{
rng=pbc->equal_range(
shared_string(
author.c_str(),
shared_string::allocator_type(seg.get_segment_manager())));
}
if(rng.first==rng.second){
std::cout<<"no entries\n";
}
else{
std::copy(
rng.first,rng.second,std::ostream_iterator<book>(std::cout));
}
break;
}
case 2:{ /* list all books by prize */
bip::scoped_lock<bip::named_mutex> lock(mutex);
std::copy(
get<2>(*pbc).begin(),get<2>(*pbc).end(),
std::ostream_iterator<book>(std::cout));
break;
}
case 3:{ /* insert a book */
book b(shared_string::allocator_type(seg.get_segment_manager()));
enter("author: ",b.author);
enter("name: " ,b.name);
enter("prize: " ,b.prize);
enter("pages: " ,b.pages);
std::cout<<"insert the following?\n"<<b<<"(y/n): ";
char yn='n';
enter("",yn);
if(yn=='y'||yn=='Y'){
bip::scoped_lock<bip::named_mutex> lock(mutex);
pbc->insert(b);
}
break;
}
case 4:{ /* delete a book */
shared_string name(
shared_string::allocator_type(seg.get_segment_manager()));
enter(
"name of the book (you can enter\nonly the first few characters): ",
name);
typedef nth_index<book_container,1>::type index_by_name;
index_by_name& idx=get<1>(*pbc);
index_by_name::iterator it;
book b(shared_string::allocator_type(seg.get_segment_manager()));
{
/* Look for a book whose title begins with name. Note that we
* are unlocking after doing the search so as to not leave the
* container blocked during user prompting. That is also why a
* local copy of the book is done.
*/
bip::scoped_lock<bip::named_mutex> lock(mutex);
it=idx.find(partial_string(name));
if(it==idx.end()){
std::cout<<"no such book found\n";
break;
}
b=*it;
}
std::cout<<"delete the following?\n"<<b<<"(y/n): ";
char yn='n';
enter("",yn);
if(yn=='y'||yn=='Y'){
bip::scoped_lock<bip::named_mutex> lock(mutex);
idx.erase(it);
}
break;
}
default:{
std::cout<<"select one option:\n"<<command_info;
break;
}
}
}
return 0;
}
+1 -1
View File
@@ -1,6 +1,6 @@
/* Boost.MultiIndex example of use of multi_index_container::ctor_args_list.
*
* Copyright 2003-2004 Joaqu匤 M Lez Muz.
* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
+102
View File
@@ -0,0 +1,102 @@
/* Boost.MultiIndex example of use of random access indices.
*
* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
*
* See http://www.boost.org/libs/multi_index for library home page.
*/
#if !defined(NDEBUG)
#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING
#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE
#endif
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/random_access_index.hpp>
#include <boost/tokenizer.hpp>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
using boost::multi_index_container;
using namespace boost::multi_index;
/* text_container holds words as inserted and also keep them indexed
* by dictionary order.
*/
typedef multi_index_container<
std::string,
indexed_by<
random_access<>,
ordered_non_unique<identity<std::string> >
>
> text_container;
/* ordered index */
typedef nth_index<text_container,1>::type ordered_text;
/* Helper function for obtaining the position of an element in the
* container.
*/
template<typename IndexIterator>
text_container::size_type text_position(
const text_container& tc,IndexIterator it)
{
/* project to the base index and calculate offset from begin() */
return project<0>(tc,it)-tc.begin();
}
typedef boost::tokenizer<boost::char_separator<char> > text_tokenizer;
int main()
{
std::string text=
"'Oh, you wicked little thing!' cried Alice, catching up the kitten, "
"and giving it a little kiss to make it understand that it was in "
"disgrace. 'Really, Dinah ought to have taught you better manners! You "
"ought, Dinah, you know you ought!' she added, looking reproachfully at "
"the old cat, and speaking in as cross a voice as she could manage "
"-- and then she scrambled back into the armchair, taking the kitten and "
"the worsted with her, and began winding up the ball again. But she "
"didn't get on very fast, as she was talking all the time, sometimes to "
"the kitten, and sometimes to herself. Kitty sat very demurely on her "
"knee, pretending to watch the progress of the winding, and now and then "
"putting out one paw and gently touching the ball, as if it would be glad "
"to help, if it might.";
/* feed the text into the container */
text_container tc;
tc.reserve(text.size()); /* makes insertion faster */
text_tokenizer tok(text,boost::char_separator<char>(" \t\n.,;:!?'\"-"));
std::copy(tok.begin(),tok.end(),std::back_inserter(tc));
std::cout<<"enter a position (0-"<<tc.size()-1<<"):";
text_container::size_type pos=tc.size();
std::cin>>pos;
if(pos>=tc.size()){
std::cout<<"out of bounds"<<std::endl;
}
else{
std::cout<<"the word \""<<tc[pos]<<"\" appears at position(s): ";
std::pair<ordered_text::iterator,ordered_text::iterator> p=
get<1>(tc).equal_range(tc[pos]);
while(p.first!=p.second){
std::cout<<text_position(tc,p.first++)<<" ";
}
std::cout<<std::endl;
}
return 0;
}
+245
View File
@@ -0,0 +1,245 @@
/* Boost.MultiIndex example of use of rearrange facilities.
*
* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
*
* See http://www.boost.org/libs/multi_index for library home page.
*/
#if !defined(NDEBUG)
#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING
#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE
#endif
#include <boost/config.hpp>
#include <boost/detail/iterator.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/random_access_index.hpp>
#include <boost/random/binomial_distribution.hpp>
#include <boost/random/uniform_real.hpp>
#include <boost/random/mersenne_twister.hpp>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
using boost::multi_index_container;
using namespace boost::multi_index;
/* We model a card deck with a random access array containing
* card numbers (from 0 to 51), supplemented with an additional
* index which retains the start ordering.
*/
class deck
{
BOOST_STATIC_CONSTANT(std::size_t,num_cards=52);
typedef multi_index_container<
int,
indexed_by<
random_access<>, /* base index */
random_access<> /* "start" index */
>
> container_type;
container_type cont;
public:
deck()
{
cont.reserve(num_cards);
get<1>(cont).reserve(num_cards);
for(std::size_t i=0;i<num_cards;++i)cont.push_back(i);
}
typedef container_type::iterator iterator;
typedef container_type::size_type size_type;
iterator begin()const{return cont.begin();}
iterator end()const{return cont.end();}
size_type size()const{return cont.size();}
template<typename InputIterator>
void rearrange(InputIterator it)
{
cont.rearrange(it);
}
void reset()
{
/* simply rearrange the base index like the start index */
cont.rearrange(get<1>(cont).begin());
}
std::size_t position(int i)const
{
/* The position of a card in the deck is calculated by locating
* the card through the start index (which is ordered), projecting
* to the base index and diffing with the begin position.
* Resulting complexity: constant.
*/
return project<0>(cont,get<1>(cont).begin()+i)-cont.begin();
}
std::size_t rising_sequences()const
{
/* Iterate through all cards and increment the sequence count
* when the current position is left to the previous.
* Resulting complexity: O(n), n=num_cards.
*/
std::size_t s=1;
std::size_t last_pos=0;
for(std::size_t i=0;i<num_cards;++i){
std::size_t pos=position(i);
if(pos<last_pos)++s;
last_pos=pos;
}
return s;
}
};
/* A vector of reference_wrappers to deck elements can be used
* as a view to the deck container.
* We use a special implicit_reference_wrapper having implicit
* ctor from its base type, as this simplifies the use of generic
* techniques on the resulting data structures.
*/
template<typename T>
class implicit_reference_wrapper:public boost::reference_wrapper<T>
{
private:
typedef boost::reference_wrapper<T> super;
public:
implicit_reference_wrapper(T& t):super(t){}
};
typedef std::vector<implicit_reference_wrapper<const int> > deck_view;
/* Riffle shuffle is modeled like this: A cut is selected in the deck
* following a binomial distribution. Then, cards are randomly selected
* from one packet or the other with probability proportional to
* packet size.
*/
template<typename RandomAccessIterator,typename OutputIterator>
void riffle_shuffle(
RandomAccessIterator first,RandomAccessIterator last,
OutputIterator out)
{
static boost::mt19937 rnd_gen;
typedef typename boost::detail::iterator_traits<
RandomAccessIterator>::difference_type difference_type;
typedef boost::binomial_distribution<
difference_type> rnd_cut_select_type;
typedef boost::uniform_real<> rnd_deck_select_type;
rnd_cut_select_type cut_select(last-first);
RandomAccessIterator middle=first+cut_select(rnd_gen);
difference_type s0=middle-first;
difference_type s1=last-middle;
rnd_deck_select_type deck_select;
while(s0!=0&&s1!=0){
if(deck_select(rnd_gen)<(double)s0/(s0+s1)){
*out++=*first++;
--s0;
}
else{
*out++=*middle++;
--s1;
}
}
std::copy(first,first+s0,out);
std::copy(middle,middle+s1,out);
}
struct riffle_shuffler
{
void operator()(deck& d)const
{
dv.clear();
dv.reserve(d.size());
riffle_shuffle(
d.begin(),d.end(),std::back_inserter(dv)); /* do the shuffling */
d.rearrange(dv.begin()); /* apply to the deck */
}
private:
mutable deck_view dv;
};
/* A truly random shuffle (up to stdlib implementation quality) using
* std::random_shuffle.
*/
struct random_shuffler
{
void operator()(deck& d)const
{
dv.clear();
dv.reserve(d.size());
std::copy(d.begin(),d.end(),std::back_inserter(dv));
std::random_shuffle(dv.begin(),dv.end()); /* do the shuffling */
d.rearrange(dv.begin()); /* apply to the deck */
}
private:
mutable deck_view dv;
};
/* Repeat a given shuffling algorithm repeats_num times
* and obtain the resulting rising sequences number. Average
* for tests_num trials.
*/
template<typename Shuffler>
double shuffle_test(
unsigned int repeats_num,unsigned int tests_num
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Shuffler))
{
deck d;
Shuffler sh;
unsigned long total=0;
for(unsigned int n=0;n<tests_num;++n){
for(unsigned m=0;m<repeats_num;++m)sh(d);
total+=d.rising_sequences();
d.reset();
}
return (double)total/tests_num;
}
int main()
{
unsigned rifs_num=0;
unsigned tests_num=0;
std::cout<<"number of riffle shuffles (vg 5):";
std::cin>>rifs_num;
std::cout<<"number of tests (vg 1000):";
std::cin>>tests_num;
std::cout<<"shuffling..."<<std::endl;
std::cout<<"riffle shuffling\n"
" avg number of rising sequences: "
<<shuffle_test<riffle_shuffler>(rifs_num,tests_num)
<<std::endl;
std::cout<<"random shuffling\n"
" avg number of rising sequences: "
<<shuffle_test<random_shuffler>(1,tests_num)
<<std::endl;
return 0;
}
+1 -1
View File
@@ -1,6 +1,6 @@
/* Boost.MultiIndex example of use of sequenced indices.
*
* Copyright 2003-2005 Joaqu匤 M Lez Muz.
* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
+2 -2
View File
@@ -1,6 +1,6 @@
/* Boost.MultiIndex example of serialization of a MRU list.
*
* Copyright 2003-2005 Joaquín M López Muñoz.
* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
@@ -50,7 +50,7 @@ public:
typedef Item item_type;
typedef typename item_list::iterator iterator;
mru_list(std::size_t max_num_items):max_num_items(max_num_items){}
mru_list(std::size_t max_num_items_):max_num_items(max_num_items_){}
void insert(const item_type& item)
{
+49 -3
View File
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
/* Copyright 2003-2011 Joaquin M Lopez Munoz.
* 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)
@@ -14,6 +14,7 @@
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/functional/hash_fwd.hpp>
#include <boost/multi_index/detail/access_specifier.hpp>
#include <boost/multi_index/detail/prevent_eti.hpp>
#include <boost/mpl/eval_if.hpp>
@@ -29,8 +30,17 @@
#include <boost/static_assert.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/utility/enable_if.hpp>
#include <functional>
#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
#include <boost/ref.hpp>
#endif
#if !defined(BOOST_NO_SFINAE)
#include <boost/type_traits/is_convertible.hpp>
#endif
/* A composite key stores n key extractors and "computes" the
* result on a given value as a packed reference to the value and
* the composite key itself. Actual invocations to the component
@@ -97,7 +107,6 @@
namespace boost{
template<class T> class reference_wrapper; /* fwd decl. */
template<class T> struct hash; /* fwd decl. */
namespace multi_index{
@@ -554,6 +563,11 @@ struct hash_cval:
/* composite_key_result */
#if defined(BOOST_MSVC)
#pragma warning(push)
#pragma warning(disable:4512)
#endif
template<typename CompositeKey>
struct composite_key_result
{
@@ -569,6 +583,10 @@ struct composite_key_result
const value_type& value;
};
#if defined(BOOST_MSVC)
#pragma warning(pop)
#endif
/* composite_key */
/* NB. Some overloads of operator() have an extra dummy parameter int=0.
@@ -607,7 +625,15 @@ public:
key_extractor_tuple& key_extractors(){return *this;}
template<typename ChainedPtr>
result_type operator()(const ChainedPtr& x)const
#if !defined(BOOST_NO_SFINAE)
typename disable_if<
is_convertible<const ChainedPtr&,const value_type&>,result_type>::type
#else
result_type
#endif
operator()(const ChainedPtr& x)const
{
return operator()(*x);
}
@@ -966,6 +992,16 @@ public:
key_comps());
}
#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
template<typename CompositeKey,typename Value>
bool operator()(
const composite_key_result<CompositeKey>& x,
const Value& y)const
{
return operator()(x,boost::make_tuple(boost::cref(y)));
}
#endif
template
<
typename CompositeKey,
@@ -991,6 +1027,16 @@ public:
>::compare(x.composite_key.key_extractors(),x.value,y,key_comps());
}
#if !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
template<typename Value,typename CompositeKey>
bool operator()(
const Value& x,
const composite_key_result<CompositeKey>& y)const
{
return operator()(boost::make_tuple(boost::cref(x)),y);
}
#endif
template
<
BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value),
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
@@ -34,12 +34,19 @@
* MSVC 7.1/8.0 seem to have a similar problem, though the conditions in
* which the error happens are not that simple. I have yet to isolate this
* into a snippet suitable for bug reporting.
* Sun Studio also has this problem, which might be related, from the
* information gathered at Sun forums, with a known issue notified at the
* internal bug report 6421933. The bug is present up to Studio Express 2,
* the latest preview version of the future Sun Studio 12. As of this writing
* (October 2006) it is not known whether a fix will finally make it into the
* official Sun Studio 12.
*/
#if BOOST_WORKAROUND(__GNUC__, <3)||\
BOOST_WORKAROUND(__GNUC__,==3)&&(__GNUC_MINOR__<4)||\
BOOST_WORKAROUND(BOOST_MSVC,==1310)||\
BOOST_WORKAROUND(BOOST_MSVC,==1400)
BOOST_WORKAROUND(BOOST_MSVC,==1400)||\
BOOST_WORKAROUND(__SUNPRO_CC,BOOST_TESTED_AT(0x590))
#define BOOST_MULTI_INDEX_PRIVATE_IF_USING_DECL_FOR_TEMPL_FUNCTIONS public
#else
#define BOOST_MULTI_INDEX_PRIVATE_IF_USING_DECL_FOR_TEMPL_FUNCTIONS private
@@ -0,0 +1,44 @@
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
*
* See http://www.boost.org/libs/multi_index for library home page.
*/
#ifndef BOOST_MULTI_INDEX_DETAIL_ADL_SWAP_HPP
#define BOOST_MULTI_INDEX_DETAIL_ADL_SWAP_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <algorithm>
namespace boost{
namespace multi_index{
namespace detail{
template<typename T>
void adl_swap(T& x,T& y)
{
#if !defined(BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL)
using std::swap;
swap(x,y);
#else
std::swap(x,y);
#endif
}
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
@@ -14,10 +14,11 @@
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/aligned_storage.hpp>
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/noncopyable.hpp>
#include <boost/serialization/serialization.hpp>
#include <boost/type_traits/aligned_storage.hpp>
#include <boost/type_traits/alignment_of.hpp>
namespace boost{
@@ -63,10 +64,10 @@ struct archive_constructed:private noncopyable
(&get())->~T();
}
T& get(){return *static_cast<T*>(space.address());}
T& get(){return *static_cast<T*>(static_cast<void*>(&space));}
private:
aligned_storage<sizeof(T)> space;
typename aligned_storage<sizeof(T),alignment_of<T>::value>::type space;
};
} /* namespace multi_index::detail */
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
@@ -16,6 +16,8 @@
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <algorithm>
#include <boost/detail/allocator_utilities.hpp>
#include <boost/multi_index/detail/adl_swap.hpp>
#include <boost/multi_index/detail/prevent_eti.hpp>
#include <boost/noncopyable.hpp>
#include <memory>
@@ -44,8 +46,15 @@ namespace detail{
template<typename T,typename Allocator=std::allocator<T> >
struct auto_space:private noncopyable
{
typedef typename prevent_eti<
Allocator,
typename boost::detail::allocator::rebind_to<
Allocator,T
>::type
>::type::pointer pointer;
explicit auto_space(const Allocator& al=Allocator(),std::size_t n=1):
al_(al),n_(n),data_(n_?al_.allocate(n_):0)
al_(al),n_(n),data_(n_?al_.allocate(n_):pointer(0))
{}
~auto_space()
@@ -53,10 +62,13 @@ struct auto_space:private noncopyable
if(n_)al_.deallocate(data_,n_);
}
T* data()const{return data_;}
Allocator get_allocator()const{return al_;}
pointer data()const{return data_;}
void swap(auto_space& x)
{
if(al_!=x.al_)adl_swap(al_,x.al_);
std::swap(n_,x.n_);
std::swap(data_,x.data_);
}
@@ -65,7 +77,7 @@ private:
typename boost::detail::allocator::rebind_to<
Allocator,T>::type al_;
std::size_t n_;
T* data_;
pointer data_;
};
template<typename T,typename Allocator>
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
@@ -46,12 +46,12 @@ struct index_applier
#else
struct index_applier
{
template<typename IndexSpecifierMeta,typename Super>
template<typename IndexSpecifierMeta,typename SuperMeta>
struct apply
{
typedef typename IndexSpecifierMeta::type index_specifier;
typedef typename IndexSpecifierMeta::type index_specifier;
typedef typename index_specifier::
BOOST_NESTED_TEMPLATE index_class<Super>::type type;
BOOST_NESTED_TEMPLATE index_class<SuperMeta>::type type;
};
};
#endif
@@ -0,0 +1,113 @@
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
*
* See http://www.boost.org/libs/multi_index for library home page.
*/
#ifndef BOOST_MULTI_INDEX_DETAIL_BIDIR_NODE_ITERATOR_HPP
#define BOOST_MULTI_INDEX_DETAIL_BIDIR_NODE_ITERATOR_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/operators.hpp>
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/split_member.hpp>
#endif
namespace boost{
namespace multi_index{
namespace detail{
/* Iterator class for node-based indices with bidirectional
* iterators (ordered and sequenced indices.)
*/
template<typename Node>
class bidir_node_iterator:
public bidirectional_iterator_helper<
bidir_node_iterator<Node>,
typename Node::value_type,
std::ptrdiff_t,
const typename Node::value_type*,
const typename Node::value_type&>
{
public:
bidir_node_iterator(){}
explicit bidir_node_iterator(Node* node_):node(node_){}
const typename Node::value_type& operator*()const
{
return node->value();
}
bidir_node_iterator& operator++()
{
Node::increment(node);
return *this;
}
bidir_node_iterator& operator--()
{
Node::decrement(node);
return *this;
}
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
/* Serialization. As for why the following is public,
* see explanation in safe_mode_iterator notes in safe_mode.hpp.
*/
BOOST_SERIALIZATION_SPLIT_MEMBER()
typedef typename Node::base_type node_base_type;
template<class Archive>
void save(Archive& ar,const unsigned int)const
{
node_base_type* bnode=node;
ar<<serialization::make_nvp("pointer",bnode);
}
template<class Archive>
void load(Archive& ar,const unsigned int)
{
node_base_type* bnode;
ar>>serialization::make_nvp("pointer",bnode);
node=static_cast<Node*>(bnode);
}
#endif
/* get_node is not to be used by the user */
typedef Node node_type;
Node* get_node()const{return node;}
private:
Node* node;
};
template<typename Node>
bool operator==(
const bidir_node_iterator<Node>& x,
const bidir_node_iterator<Node>& y)
{
return x.get_node()==y.get_node();
}
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
@@ -17,6 +17,7 @@
#include <algorithm>
#include <boost/multi_index/detail/auto_space.hpp>
#include <boost/multi_index/detail/hash_index_node.hpp>
#include <boost/multi_index/detail/prevent_eti.hpp>
#include <boost/noncopyable.hpp>
#include <cstddef>
#include <limits.h>
@@ -84,8 +85,20 @@ protected:
template<typename Allocator>
class bucket_array:public bucket_array_base
{
typedef typename prevent_eti<
Allocator,
hashed_index_node_impl<
typename boost::detail::allocator::rebind_to<
Allocator,
char
>::type
>
>::type node_impl_type;
public:
bucket_array(const Allocator& al,hashed_index_node_impl* end_,std::size_t size):
typedef typename node_impl_type::pointer pointer;
bucket_array(const Allocator& al,pointer end_,std::size_t size):
size_(bucket_array_base::next_prime(size)),
spc(al,size_+1)
{
@@ -104,21 +117,21 @@ public:
return hash%size_;
}
hashed_index_node_impl* begin()const{return &buckets()[0];}
hashed_index_node_impl* end()const{return &buckets()[size_];}
hashed_index_node_impl* at(std::size_t n)const{return &buckets()[n];}
pointer begin()const{return buckets();}
pointer end()const{return buckets()+size_;}
pointer at(std::size_t n)const{return buckets()+n;}
std::size_t first_nonempty(std::size_t n)const
{
for(;;++n){
hashed_index_node_impl* x=at(n);
pointer x=at(n);
if(x->next()!=x)return n;
}
}
void clear()
{
for(hashed_index_node_impl* x=begin(),*y=end();x!=y;++x)x->next()=x;
for(pointer x=begin(),y=end();x!=y;++x)x->next()=x;
}
void swap(bucket_array& x)
@@ -128,10 +141,10 @@ public:
}
private:
std::size_t size_;
auto_space<hashed_index_node_impl,Allocator> spc;
std::size_t size_;
auto_space<node_impl_type,Allocator> spc;
hashed_index_node_impl* buckets()const
pointer buckets()const
{
return spc.data();
}
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaqu M Lez Muz.
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
+26 -19
View File
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
@@ -17,6 +17,7 @@
#include <algorithm>
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/multi_index/detail/auto_space.hpp>
#include <boost/multi_index/detail/prevent_eti.hpp>
#include <boost/noncopyable.hpp>
#include <cstddef>
#include <functional>
@@ -69,31 +70,31 @@ public:
{
if(!released){
for(std::size_t i=0;i<n;++i){
boost::detail::allocator::destroy(&spc.data()[i].second->value);
deallocate(spc.data()[i].second);
boost::detail::allocator::destroy(&(spc.data()+i)->second->value());
deallocate((spc.data()+i)->second);
}
}
}
const_iterator begin()const{return spc.data();}
const_iterator end()const{return spc.data()+n;}
const_iterator begin()const{return &*spc.data();}
const_iterator end()const{return &*(spc.data()+n);}
void clone(Node* node)
{
spc.data()[n].first=node;
spc.data()[n].second=al_.allocate(1);
(spc.data()+n)->first=node;
(spc.data()+n)->second=&*al_.allocate(1);
BOOST_TRY{
boost::detail::allocator::construct(
&spc.data()[n].second->value,node->value);
&(spc.data()+n)->second->value(),node->value());
}
BOOST_CATCH(...){
deallocate(spc.data()[n].second);
deallocate((spc.data()+n)->second);
BOOST_RETHROW;
}
BOOST_CATCH_END
++n;
if(n==size_)std::sort(spc.data(),spc.data()+size_);
if(n==size_)std::sort(&*spc.data(),&*spc.data()+size_);
}
Node* find(Node* node)const
@@ -109,18 +110,24 @@ public:
}
private:
typename boost::detail::allocator::rebind_to<
Allocator,Node>::type al_;
std::size_t size_;
auto_space<copy_map_entry<Node>,Allocator> spc;
std::size_t n;
Node* header_org_;
Node* header_cpy_;
bool released;
typedef typename prevent_eti<
Allocator,
typename boost::detail::allocator::rebind_to<
Allocator,Node>::type
>::type allocator_type;
typedef typename allocator_type::pointer allocator_pointer;
allocator_type al_;
std::size_t size_;
auto_space<copy_map_entry<Node>,Allocator> spc;
std::size_t n;
Node* header_org_;
Node* header_cpy_;
bool released;
void deallocate(Node* node)
{
al_.deallocate(node,1);
al_.deallocate(static_cast<allocator_pointer>(node),1);
}
};
@@ -1,59 +0,0 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
* 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)
*
* See http://www.boost.org/libs/multi_index for library home page.
*/
#ifndef BOOST_MULTI_INDEX_DETAIL_DEF_CTOR_TUPLE_CONS_HPP
#define BOOST_MULTI_INDEX_DETAIL_DEF_CTOR_TUPLE_CONS_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/config.hpp>
#if defined(BOOST_MSVC)
/* In MSVC, tuples::cons is not default constructible. We provide a
* tiny wrapper around tuple::cons filling that hole.
*/
#include <boost/tuple/tuple.hpp>
namespace boost{
namespace multi_index{
namespace detail{
template<typename Cons>
struct default_constructible_tuple_cons:Cons
{
default_constructible_tuple_cons():
Cons(
Cons::head_type(),
static_cast<const Cons::tail_type&>(
default_constructible_tuple_cons<Cons::tail_type>()))
{}
default_constructible_tuple_cons(const Cons& cons):Cons(cons){}
};
template<>
struct default_constructible_tuple_cons<tuples::null_type>:tuples::null_type
{
default_constructible_tuple_cons(){}
default_constructible_tuple_cons(const tuples::null_type&){}
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif /* BOOST_MSVC */
#endif
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
@@ -37,25 +37,25 @@ public:
typedef const typename Node::value_type& reference;
typedef std::forward_iterator_tag iterator_category;
duplicates_iterator(Node* node,Node* end,Predicate pred):
node(node),begin_chunk(0),end(end),pred(pred)
duplicates_iterator(Node* node_,Node* end_,Predicate pred_):
node(node_),begin_chunk(0),end(end_),pred(pred_)
{
advance();
}
duplicates_iterator(Node* end,Predicate pred):
node(end),begin_chunk(end),end(end),pred(pred)
duplicates_iterator(Node* end_,Predicate pred_):
node(end_),begin_chunk(end_),end(end_),pred(pred_)
{
}
reference operator*()const
{
return node->value;
return node->value();
}
pointer operator->()const
{
return node->value;
return &node->value();
}
duplicates_iterator& operator++()
@@ -77,15 +77,14 @@ public:
private:
void sync()
{
if(pred(begin_chunk->value,node->value))advance();
if(node!=end&&pred(begin_chunk->value(),node->value()))advance();
}
void advance()
{
for(Node* node2=node;node!=end;node=node2){
Node::increment(node2);
if(node2!=end&&!pred(node->value,node2->value))break;
node=node2;
if(node2!=end&&!pred(node->value(),node2->value()))break;
}
begin_chunk=node;
}
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaqu M Lez Muz.
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
@@ -14,7 +14,7 @@
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/functional/hash/hash.hpp>
#include <boost/functional/hash.hpp>
#include <boost/mpl/aux_/na.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/identity.hpp>
@@ -26,8 +26,6 @@
namespace boost{
template<class T> struct hash; /* fwd decl. */
namespace multi_index{
namespace detail{
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
@@ -14,9 +14,6 @@
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/detail/workaround.hpp>
#include <boost/multi_index/detail/hash_index_proxy.hpp>
#include <boost/multi_index/detail/safe_mode.hpp>
#include <boost/operators.hpp>
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
@@ -30,144 +27,81 @@ namespace multi_index{
namespace detail{
/* An iterator template for nodes of multi_index::detail::hashed_index.
* Built with the aid boost::forward_iterator_helper from
* boost/operators.hpp.
/* Iterator class for hashed indices.
*/
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
template<typename Node,typename BucketArray>
class hashed_index_iterator:
public boost::forward_iterator_helper<
hashed_index_iterator<Node,BucketArray>,
typename Node::value_type,
std::ptrdiff_t,
const typename Node::value_type*,
const typename Node::value_type&>,
public safe_iterator<hashed_index_proxy<Node,BucketArray> >
#else
template<typename Node,typename BucketArray,typename Container>
class hashed_index_iterator:
public boost::forward_iterator_helper<
hashed_index_iterator<Node,BucketArray,Container>,
typename Node::value_type,
std::ptrdiff_t,
const typename Node::value_type*,
const typename Node::value_type&>,
public safe_iterator<Container>
#endif
#else
template<typename Node,typename BucketArray>
class hashed_index_iterator:
public boost::forward_iterator_helper<
public forward_iterator_helper<
hashed_index_iterator<Node,BucketArray>,
typename Node::value_type,
std::ptrdiff_t,
const typename Node::value_type*,
const typename Node::value_type&>
#endif
{
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
public:
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
typedef hashed_index_proxy<Node,BucketArray> container_type;
#else
typedef Container container_type;
#endif
private:
typedef safe_iterator<container_type> safe_super;
public:
hashed_index_iterator():node(0),buckets(0){}
hashed_index_iterator(
Node* node_,BucketArray& buckets_,container_type* cont_):
safe_super(cont_),node(node_),buckets(&buckets_){}
hashed_index_iterator& operator=(const hashed_index_iterator& x)
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(x);
safe_super::operator=(x);
node=x.node;
buckets=x.buckets;
return *this;
}
#else
public:
hashed_index_iterator(){}
hashed_index_iterator(Node* node_,BucketArray& buckets_):
node(node_),buckets(&buckets_){}
#endif
hashed_index_iterator(Node* node_,BucketArray* buckets_):
node(node_),buckets(buckets_)
{}
const typename Node::value_type& operator*()const
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(*this);
BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(*this);
return node->value;
return node->value();
}
hashed_index_iterator& operator++()
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(*this);
BOOST_MULTI_INDEX_CHECK_INCREMENTABLE_ITERATOR(*this);
Node::increment(node,buckets->begin(),buckets->end());
return *this;
}
friend bool operator==(const hashed_index_iterator& x,const hashed_index_iterator& y)
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(x);
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(y);
BOOST_MULTI_INDEX_CHECK_SAME_OWNER(x,y);
return x.node==y.node;
}
/* get_node is not to be used by the user */
Node* get_node()const{return node;}
private:
Node* node;
BucketArray* buckets;
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
/* serialization */
friend class boost::serialization::access;
/* Serialization. As for why the following is public,
* see explanation in safe_mode_iterator notes in safe_mode.hpp.
*/
BOOST_SERIALIZATION_SPLIT_MEMBER()
typedef typename Node::base_type node_base_type;
template<class Archive>
void save(Archive& ar,const unsigned int version)const
void save(Archive& ar,const unsigned int)const
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(*this);
node_base_type* bnode=node;
ar<<serialization::make_nvp("pointer",bnode);
ar<<serialization::make_nvp("pointer",buckets);
}
template<class Archive>
void load(Archive& ar,const unsigned int version)
void load(Archive& ar,const unsigned int)
{
node_base_type* bnode;
ar>>serialization::make_nvp("pointer",bnode);
node=static_cast<Node*>(bnode);
ar>>serialization::make_nvp("pointer",buckets);
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
safe_super::uncheck();
#endif
}
#endif
/* get_node is not to be used by the user */
typedef Node node_type;
Node* get_node()const{return node;}
private:
Node* node;
BucketArray* buckets;
};
template<typename Node,typename BucketArray>
bool operator==(
const hashed_index_iterator<Node,BucketArray>& x,
const hashed_index_iterator<Node,BucketArray>& y)
{
return x.get_node()==y.get_node();
}
} /* namespace multi_index::detail */
} /* namespace multi_index */
@@ -1,44 +0,0 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
* 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)
*
* See http://www.boost.org/libs/multi_index for library home page.
*/
#ifndef BOOST_MULTI_INDEX_DETAIL_HASH_INDEX_ITERATOR_FWD_HPP
#define BOOST_MULTI_INDEX_DETAIL_HASH_INDEX_ITERATOR_FWD_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
namespace boost{
namespace multi_index{
namespace detail{
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
template<typename Node,typename BucketArray>
class hashed_index_iterator;
#else
template<typename Node,typename BucketArray,typename Container>
class hashed_index_iterator;
#endif
#else
template<typename Node,typename BucketArray>
class hashed_index_iterator;
#endif
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
@@ -14,6 +14,8 @@
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/detail/allocator_utilities.hpp>
#include <boost/multi_index/detail/prevent_eti.hpp>
#include <functional>
namespace boost{
@@ -24,28 +26,33 @@ namespace detail{
/* singly-linked node for use by hashed_index */
template<typename Allocator>
struct hashed_index_node_impl
{
hashed_index_node_impl*& next(){return next_;}
hashed_index_node_impl*const & next()const{return next_;}
typedef typename prevent_eti<
Allocator,
typename boost::detail::allocator::rebind_to<
Allocator,hashed_index_node_impl
>::type
>::type::pointer pointer;
typedef typename prevent_eti<
Allocator,
typename boost::detail::allocator::rebind_to<
Allocator,hashed_index_node_impl
>::type
>::type::const_pointer const_pointer;
/* interoperability with hashed_index_proxy */
static hashed_index_node_impl* end(hashed_index_node_impl* header)
{
return header;
}
pointer& next(){return next_;}
pointer next()const{return next_;}
/* algorithmic stuff */
static void increment(
hashed_index_node_impl*& x,
hashed_index_node_impl* bbegin,hashed_index_node_impl* bbend)
static void increment(pointer& x,pointer bbegin,pointer bend)
{
std::less_equal<hashed_index_node_impl*> leq;
std::less_equal<pointer> leq;
x=x->next();
if(leq(bbegin,x)&&leq(x,bbend)){ /* bucket node */
if(leq(bbegin,x)&&leq(x,bend)){ /* bucket node */
do{
++x;
}while(x->next()==x);
@@ -53,76 +60,100 @@ struct hashed_index_node_impl
}
}
static void link(
hashed_index_node_impl* x,hashed_index_node_impl* pos)
static void link(pointer x,pointer pos)
{
x->next()=pos->next();
pos->next()=x;
};
static void unlink(hashed_index_node_impl* x)
static void unlink(pointer x)
{
hashed_index_node_impl* y=x->next();
pointer y=x->next();
while(y->next()!=x){y=y->next();}
y->next()=x->next();
}
static hashed_index_node_impl* prev(hashed_index_node_impl* x)
static pointer prev(pointer x)
{
hashed_index_node_impl* y=x->next();
pointer y=x->next();
while(y->next()!=x){y=y->next();}
return y;
}
static void unlink_next(hashed_index_node_impl* x)
static void unlink_next(pointer x)
{
x->next()=x->next()->next();
}
private:
hashed_index_node_impl();
hashed_index_node_impl* next_;
pointer next_;
};
template<typename Super>
struct hashed_index_node_trampoline:hashed_index_node_impl{};
struct hashed_index_node_trampoline:
prevent_eti<
Super,
hashed_index_node_impl<
typename boost::detail::allocator::rebind_to<
typename Super::allocator_type,
char
>::type
>
>::type
{
typedef typename prevent_eti<
Super,
hashed_index_node_impl<
typename boost::detail::allocator::rebind_to<
typename Super::allocator_type,
char
>::type
>
>::type impl_type;
};
template<typename Super>
struct hashed_index_node:Super,hashed_index_node_trampoline<Super>
{
hashed_index_node_impl* impl()
{return static_cast<impl_type*>(this);}
const hashed_index_node_impl* impl()const
{return static_cast<const impl_type*>(this);}
private:
typedef hashed_index_node_trampoline<Super> trampoline;
static hashed_index_node* from_impl(hashed_index_node_impl *x)
{return static_cast<hashed_index_node*>(static_cast<impl_type*>(x));}
static const hashed_index_node* from_impl(
const hashed_index_node_impl* x)
public:
typedef typename trampoline::impl_type impl_type;
typedef typename trampoline::pointer impl_pointer;
typedef typename trampoline::const_pointer const_impl_pointer;
impl_pointer impl()
{
return static_cast<impl_pointer>(
static_cast<impl_type*>(static_cast<trampoline*>(this)));
}
const_impl_pointer impl()const
{
return static_cast<const_impl_pointer>(
static_cast<const impl_type*>(static_cast<const trampoline*>(this)));
}
static hashed_index_node* from_impl(impl_pointer x)
{
return static_cast<hashed_index_node*>(
static_cast<trampoline*>(&*x));
}
static const hashed_index_node* from_impl(const_impl_pointer x)
{
return static_cast<const hashed_index_node*>(
static_cast<const impl_type*>(x));
static_cast<const trampoline*>(&*x));
}
static void increment(
hashed_index_node*& x,
hashed_index_node_impl* bbegin,hashed_index_node_impl* bend)
hashed_index_node*& x,impl_pointer bbegin,impl_pointer bend)
{
hashed_index_node_impl* xi=x->impl();
impl_type::increment(xi,bbegin,bend);
impl_pointer xi=x->impl();
trampoline::increment(xi,bbegin,bend);
x=from_impl(xi);
}
/* interoperability with hashed_index_proxy */
static hashed_index_node* end(hashed_index_node* header)
{
return from_impl(impl_type::end(header->impl()));
}
private:
typedef hashed_index_node_trampoline<Super> impl_type;
};
} /* namespace multi_index::detail */
@@ -1,75 +0,0 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
* 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)
*
* See http://www.boost.org/libs/multi_index for library home page.
*/
#ifndef BOOST_MULTI_INDEX_DETAIL_HASH_hashed_index_proxy_HPP
#define BOOST_MULTI_INDEX_DETAIL_HASH_hashed_index_proxy_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/detail/workaround.hpp>
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
#include <algorithm>
#include <boost/multi_index/detail/hash_index_iterator_fwd.hpp>
#include <boost/multi_index/detail/safe_mode.hpp>
namespace boost{
namespace multi_index{
namespace detail{
/* Analogous of index_proxy for interoperability with
* hashed_index_iterator.
*/
template<typename Node,typename BucketArray>
class hashed_index_proxy:
public safe_container<hashed_index_proxy<Node,BucketArray> >
{
protected:
hashed_index_proxy(Node* header_,BucketArray& buckets_):
header(header_),buckets(&buckets_){}
void swap(hashed_index_proxy<Node,BucketArray>& x)
{
std::swap(header,x.header);
std::swap(buckets,x.buckets);
safe_container<hashed_index_proxy<Node,BucketArray> >::swap(x);
}
public:
typedef hashed_index_iterator<Node,BucketArray> iterator;
typedef hashed_index_iterator<Node,BucketArray> const_iterator;
hashed_index_iterator<Node,BucketArray> end()const
{
return hashed_index_iterator<Node,BucketArray>(
Node::end(header),*buckets,const_cast<hashed_index_proxy*>(this));
}
private:
Node* header;
BucketArray* buckets;
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif /* workaround */
#endif /* BOOST_MULTI_INDEX_ENABLE_SAFE_MODE */
#endif
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
@@ -14,7 +14,6 @@
#endif
#include <boost/noncopyable.hpp>
#include <boost/utility/base_from_member.hpp>
namespace boost{
@@ -22,23 +21,23 @@ namespace multi_index{
namespace detail{
/* An utility class derived from base_from_member used to hold
* a pointer to the header node. The base from member idiom is used
* because index classes, which are superclasses of multi_index_container,
* need this header in construction time.
* The allocation is made by the allocator of the multi_index_container
/* A utility class used to hold a pointer to the header node.
* The base from member idiom is used because index classes, which are
* superclasses of multi_index_container, need this header in construction
* time. The allocation is made by the allocator of the multi_index_container
* class --hence, this allocator needs also be stored resorting
* to the base from member trick.
*/
template<typename NodeType,typename Final>
struct header_holder:base_from_member<NodeType*>,private noncopyable
template<typename NodeTypePtr,typename Final>
struct header_holder:private noncopyable
{
header_holder():super(final().allocate_node()){}
~header_holder(){final().deallocate_node(super::member);}
header_holder():member(final().allocate_node()){}
~header_holder(){final().deallocate_node(&*member);}
NodeTypePtr member;
private:
typedef base_from_member<NodeType*> super;
Final& final(){return *static_cast<Final*>(this);}
};
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
@@ -46,7 +46,7 @@ template<typename Value,typename IndexSpecifierList,typename Allocator>
class index_base
{
protected:
typedef index_node_base<Value> node_type;
typedef index_node_base<Value,Allocator> node_type;
typedef typename multi_index_node_type<
Value,IndexSpecifierList,Allocator>::type final_node_type;
typedef multi_index_container<
@@ -85,24 +85,24 @@ protected:
node_type* insert_(value_param_type v,node_type* x)
{
boost::detail::allocator::construct(&x->value,v);
boost::detail::allocator::construct(&x->value(),v);
return x;
}
node_type* insert_(value_param_type v,node_type*,node_type* x)
{
boost::detail::allocator::construct(&x->value,v);
boost::detail::allocator::construct(&x->value(),v);
return x;
}
void erase_(node_type* x)
{
boost::detail::allocator::destroy(&x->value);
boost::detail::allocator::destroy(&x->value());
}
void delete_node_(node_type* x)
{
boost::detail::allocator::destroy(&x->value);
boost::detail::allocator::destroy(&x->value());
}
void clear_(){}
@@ -111,12 +111,14 @@ protected:
bool replace_(value_param_type v,node_type* x)
{
x->value=v;
x->value()=v;
return true;
}
bool modify_(node_type*){return true;}
bool modify_rollback_(node_type*){return true;}
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
/* serialization */
@@ -162,9 +164,13 @@ protected:
{return final().replace_(k,x);}
template<typename Modifier>
bool final_modify_(Modifier mod,final_node_type* x)
bool final_modify_(Modifier& mod,final_node_type* x)
{return final().modify_(mod,x);}
template<typename Modifier,typename Rollback>
bool final_modify_(Modifier& mod,Rollback& back,final_node_type* x)
{return final().modify_(mod,back,x);}
#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
void final_check_invariant_()const{final().check_invariant_();}
#endif
@@ -1,180 +0,0 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
* 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)
*
* See http://www.boost.org/libs/multi_index for library home page.
*/
#ifndef BOOST_MULTI_INDEX_DETAIL_INDEX_ITERATOR_HPP
#define BOOST_MULTI_INDEX_DETAIL_INDEX_ITERATOR_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/detail/workaround.hpp>
#include <boost/multi_index/detail/index_iterator_fwd.hpp>
#include <boost/multi_index/detail/index_proxy.hpp>
#include <boost/multi_index/detail/safe_mode.hpp>
#include <boost/operators.hpp>
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/split_member.hpp>
#endif
namespace boost{
namespace multi_index{
namespace detail{
/* An iterator template for nodes of multi_index::detail::index.
* Built with the aid boost::bidirectional_iterator_helper from
* boost/operators.hpp.
*/
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
template<typename Node>
class index_iterator:
public boost::bidirectional_iterator_helper<
index_iterator<Node>,
typename Node::value_type,
std::ptrdiff_t,
const typename Node::value_type*,
const typename Node::value_type&>,
public safe_iterator<index_proxy<Node> >
#else
template<typename Node,typename Container>
class index_iterator:
public boost::bidirectional_iterator_helper<
index_iterator<Node,Container>,
typename Node::value_type,
std::ptrdiff_t,
const typename Node::value_type*,
const typename Node::value_type&>,
public safe_iterator<Container>
#endif
#else
template<typename Node>
class index_iterator:
public boost::bidirectional_iterator_helper<
index_iterator<Node>,
typename Node::value_type,
std::ptrdiff_t,
const typename Node::value_type*,
const typename Node::value_type&>
#endif
{
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
public:
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
typedef index_proxy<Node> container_type;
#else
typedef Container container_type;
#endif
private:
typedef safe_iterator<container_type> safe_super;
public:
index_iterator():node(0){}
index_iterator(Node* node_,container_type* cont_):
safe_super(cont_),node(node_){}
index_iterator& operator=(const index_iterator& x)
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(x);
safe_super::operator=(x);
node=x.node;
return *this;
}
#else
public:
index_iterator(){}
index_iterator(Node* node_):node(node_){}
#endif
const typename Node::value_type& operator*()const
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(*this);
BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(*this);
return node->value;
}
index_iterator& operator++()
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(*this);
BOOST_MULTI_INDEX_CHECK_INCREMENTABLE_ITERATOR(*this);
Node::increment(node);
return *this;
}
index_iterator& operator--()
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(*this);
BOOST_MULTI_INDEX_CHECK_DECREMENTABLE_ITERATOR(*this);
Node::decrement(node);
return *this;
}
friend bool operator==(const index_iterator& x,const index_iterator& y)
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(x);
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(y);
BOOST_MULTI_INDEX_CHECK_SAME_OWNER(x,y);
return x.node==y.node;
}
/* get_node is not to be used by the user */
Node* get_node()const{return node;}
private:
Node* node;
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
/* serialization */
friend class boost::serialization::access;
BOOST_SERIALIZATION_SPLIT_MEMBER()
typedef typename Node::base_type node_base_type;
template<class Archive>
void save(Archive& ar,const unsigned int version)const
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(*this);
node_base_type* bnode=node;
ar<<serialization::make_nvp("pointer",bnode);
}
template<class Archive>
void load(Archive& ar,const unsigned int version)
{
node_base_type* bnode;
ar>>serialization::make_nvp("pointer",bnode);
node=static_cast<Node*>(bnode);
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
safe_super::uncheck();
#endif
}
#endif
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -1,44 +0,0 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
* 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)
*
* See http://www.boost.org/libs/multi_index for library home page.
*/
#ifndef BOOST_MULTI_INDEX_DETAIL_INDEX_ITERATOR_FWD_HPP
#define BOOST_MULTI_INDEX_DETAIL_INDEX_ITERATOR_FWD_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
namespace boost{
namespace multi_index{
namespace detail{
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
template<typename Node>
class index_iterator;
#else
template<typename Node,typename Container>
class index_iterator;
#endif
#else
template<typename Node>
class index_iterator;
#endif
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
@@ -91,7 +91,7 @@ public:
}
private:
Node** entries()const{return spc.data();}
Node** entries()const{return &*spc.data();}
/* We try to delay sorting as much as possible just in case it
* is not necessary, hence this version of load_node.
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
@@ -179,7 +179,7 @@ protected:
}
private:
entry* entries()const{return spc.data();}
entry* entries()const{return &*spc.data();}
auto_space<entry,Allocator> spc;
std::size_t size_;
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
@@ -13,8 +13,11 @@
#pragma once
#endif
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/type_traits/aligned_storage.hpp>
#include <boost/type_traits/alignment_of.hpp>
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
#include <boost/archive/archive_exception.hpp>
#include <boost/serialization/access.hpp>
#include <boost/throw_exception.hpp>
@@ -31,16 +34,41 @@ namespace detail{
*/
template<typename Value>
struct index_node_base
struct pod_value_holder
{
typename aligned_storage<
sizeof(Value),
alignment_of<Value>::value
>::type space;
};
template<typename Value,typename Allocator>
struct index_node_base:private pod_value_holder<Value>
{
typedef index_node_base base_type; /* used for serialization purposes */
typedef Value value_type;
value_type value;
typedef Allocator allocator_type;
value_type& value()
{
return *static_cast<value_type*>(
static_cast<void*>(&this->space));
}
const value_type& value()const
{
return *static_cast<const value_type*>(
static_cast<const void*>(&this->space));
}
static index_node_base* from_value(const value_type* p)
{
return static_cast<index_node_base *>(
reinterpret_cast<pod_value_holder<Value>*>( /* std 9.2.17 */
const_cast<value_type*>(p)));
}
private:
index_node_base();
/* this class is not intended to be cted, merely allocated */
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
friend class boost::serialization::access;
@@ -54,9 +82,18 @@ private:
{
}
#endif
};
template<typename Node,typename Value>
Node* node_from_value(
const Value* p
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Node))
{
typedef typename Node::allocator_type allocator_type;
return static_cast<Node*>(
index_node_base<Value,allocator_type>::from_value(p));
}
} /* namespace multi_index::detail */
} /* namespace multi_index */
@@ -75,9 +112,9 @@ namespace multi_index{
namespace detail{
#endif
template<class Archive,typename Value>
template<class Archive,typename Value,typename Allocator>
inline void load_construct_data(
Archive&,boost::multi_index::detail::index_node_base<Value>*,
Archive&,boost::multi_index::detail::index_node_base<Value,Allocator>*,
const unsigned int)
{
throw_exception(
@@ -1,82 +0,0 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
* 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)
*
* See http://www.boost.org/libs/multi_index for library home page.
*/
#ifndef BOOST_MULTI_INDEX_DETAIL_INDEX_PROXY_HPP
#define BOOST_MULTI_INDEX_DETAIL_INDEX_PROXY_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/detail/workaround.hpp>
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
#include <algorithm>
#include <boost/multi_index/detail/index_iterator_fwd.hpp>
#include <boost/multi_index/detail/safe_mode.hpp>
namespace boost{
namespace multi_index{
namespace detail{
/* In safe mode, index iterators are derived from safe_iterator<Index>,
* where Index is the type of the index where the iterator belongs. Due
* to the long symbol names of indices, MSVC++ 6.0 often issues a
* LNK1179 (duplicate comdat) error. To workaround this problem,
* index_proxy is used instead. index_proxy<Node> acts as an index
* over nodes of type Node in all aspects relevant to safe_iterator, and
* its shorter symbol name makes life easier for MSVC++ 6.0.
*/
template<typename Node>
class index_proxy:public safe_container<index_proxy<Node> >
{
protected:
index_proxy(Node* header_):header(header_){}
void swap(index_proxy<Node>& x)
{
std::swap(header,x.header);
safe_container<index_proxy<Node> >::swap(x);
}
public:
typedef index_iterator<Node> iterator;
typedef index_iterator<Node> const_iterator;
index_iterator<Node> begin()const
{
return index_iterator<Node>(
Node::begin(header),const_cast<index_proxy*>(this));
}
index_iterator<Node> end()const
{
return index_iterator<Node>(
Node::end(header),const_cast<index_proxy*>(this));
}
private:
Node* header;
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif /* workaround */
#endif /* BOOST_MULTI_INDEX_ENABLE_SAFE_MODE */
#endif
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaqu M Lez Muz.
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaqu M Lez Muz.
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaqu M Lez Muz.
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
@@ -0,0 +1,325 @@
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
*
* See http://www.boost.org/libs/multi_index for library home page.
*/
#ifndef BOOST_MULTI_INDEX_DETAIL_ITER_ADAPTOR_HPP
#define BOOST_MULTI_INDEX_DETAIL_ITER_ADAPTOR_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/mpl/apply.hpp>
#include <boost/multi_index/detail/prevent_eti.hpp>
#include <boost/operators.hpp>
namespace boost{
namespace multi_index{
namespace detail{
/* Poor man's version of boost::iterator_adaptor. Used instead of the
* original as compile times for the latter are significantly higher.
* The interface is not replicated exactly, only to the extent necessary
* for internal consumption.
*/
/* NB. The purpose of the (non-inclass) global operators ==, < and - defined
* above is to partially alleviate a problem of MSVC++ 6.0 by * which
* friend-injected operators on T are not visible if T is instantiated only
* in template code where T is a dependent type.
*/
class iter_adaptor_access
{
public:
template<class Class>
static typename Class::reference dereference(const Class& x)
{
return x.dereference();
}
template<class Class>
static bool equal(const Class& x,const Class& y)
{
return x.equal(y);
}
template<class Class>
static void increment(Class& x)
{
x.increment();
}
template<class Class>
static void decrement(Class& x)
{
x.decrement();
}
template<class Class>
static void advance(Class& x,typename Class::difference_type n)
{
x.advance(n);
}
template<class Class>
static typename Class::difference_type distance_to(
const Class& x,const Class& y)
{
return x.distance_to(y);
}
};
template<typename Category>
struct iter_adaptor_selector;
template<class Derived,class Base>
class forward_iter_adaptor_base:
public forward_iterator_helper<
Derived,
typename Base::value_type,
typename Base::difference_type,
typename Base::pointer,
typename Base::reference>
{
public:
typedef typename Base::reference reference;
reference operator*()const
{
return iter_adaptor_access::dereference(final());
}
friend bool operator==(const Derived& x,const Derived& y)
{
return iter_adaptor_access::equal(x,y);
}
Derived& operator++()
{
iter_adaptor_access::increment(final());
return final();
}
private:
Derived& final(){return *static_cast<Derived*>(this);}
const Derived& final()const{return *static_cast<const Derived*>(this);}
};
template<class Derived,class Base>
bool operator==(
const forward_iter_adaptor_base<Derived,Base>& x,
const forward_iter_adaptor_base<Derived,Base>& y)
{
return iter_adaptor_access::equal(
static_cast<const Derived&>(x),static_cast<const Derived&>(y));
}
template<>
struct iter_adaptor_selector<std::forward_iterator_tag>
{
template<class Derived,class Base>
struct apply
{
typedef forward_iter_adaptor_base<Derived,Base> type;
};
};
template<class Derived,class Base>
class bidirectional_iter_adaptor_base:
public bidirectional_iterator_helper<
Derived,
typename Base::value_type,
typename Base::difference_type,
typename Base::pointer,
typename Base::reference>
{
public:
typedef typename Base::reference reference;
reference operator*()const
{
return iter_adaptor_access::dereference(final());
}
friend bool operator==(const Derived& x,const Derived& y)
{
return iter_adaptor_access::equal(x,y);
}
Derived& operator++()
{
iter_adaptor_access::increment(final());
return final();
}
Derived& operator--()
{
iter_adaptor_access::decrement(final());
return final();
}
private:
Derived& final(){return *static_cast<Derived*>(this);}
const Derived& final()const{return *static_cast<const Derived*>(this);}
};
template<class Derived,class Base>
bool operator==(
const bidirectional_iter_adaptor_base<Derived,Base>& x,
const bidirectional_iter_adaptor_base<Derived,Base>& y)
{
return iter_adaptor_access::equal(
static_cast<const Derived&>(x),static_cast<const Derived&>(y));
}
template<>
struct iter_adaptor_selector<std::bidirectional_iterator_tag>
{
template<class Derived,class Base>
struct apply
{
typedef bidirectional_iter_adaptor_base<Derived,Base> type;
};
};
template<class Derived,class Base>
class random_access_iter_adaptor_base:
public random_access_iterator_helper<
Derived,
typename Base::value_type,
typename Base::difference_type,
typename Base::pointer,
typename Base::reference>
{
public:
typedef typename Base::reference reference;
typedef typename Base::difference_type difference_type;
reference operator*()const
{
return iter_adaptor_access::dereference(final());
}
friend bool operator==(const Derived& x,const Derived& y)
{
return iter_adaptor_access::equal(x,y);
}
friend bool operator<(const Derived& x,const Derived& y)
{
return iter_adaptor_access::distance_to(x,y)>0;
}
Derived& operator++()
{
iter_adaptor_access::increment(final());
return final();
}
Derived& operator--()
{
iter_adaptor_access::decrement(final());
return final();
}
Derived& operator+=(difference_type n)
{
iter_adaptor_access::advance(final(),n);
return final();
}
Derived& operator-=(difference_type n)
{
iter_adaptor_access::advance(final(),-n);
return final();
}
friend difference_type operator-(const Derived& x,const Derived& y)
{
return iter_adaptor_access::distance_to(y,x);
}
private:
Derived& final(){return *static_cast<Derived*>(this);}
const Derived& final()const{return *static_cast<const Derived*>(this);}
};
template<class Derived,class Base>
bool operator==(
const random_access_iter_adaptor_base<Derived,Base>& x,
const random_access_iter_adaptor_base<Derived,Base>& y)
{
return iter_adaptor_access::equal(
static_cast<const Derived&>(x),static_cast<const Derived&>(y));
}
template<class Derived,class Base>
bool operator<(
const random_access_iter_adaptor_base<Derived,Base>& x,
const random_access_iter_adaptor_base<Derived,Base>& y)
{
return iter_adaptor_access::distance_to(
static_cast<const Derived&>(x),static_cast<const Derived&>(y))>0;
}
template<class Derived,class Base>
typename random_access_iter_adaptor_base<Derived,Base>::difference_type
operator-(
const random_access_iter_adaptor_base<Derived,Base>& x,
const random_access_iter_adaptor_base<Derived,Base>& y)
{
return iter_adaptor_access::distance_to(
static_cast<const Derived&>(y),static_cast<const Derived&>(x));
}
template<>
struct iter_adaptor_selector<std::random_access_iterator_tag>
{
template<class Derived,class Base>
struct apply
{
typedef random_access_iter_adaptor_base<Derived,Base> type;
};
};
template<class Derived,class Base>
struct iter_adaptor_base
{
typedef iter_adaptor_selector<
typename Base::iterator_category> selector;
typedef typename prevent_eti<
selector,
typename mpl::apply2<
selector,Derived,Base>::type
>::type type;
};
template<class Derived,class Base>
class iter_adaptor:public iter_adaptor_base<Derived,Base>::type
{
protected:
iter_adaptor(){}
explicit iter_adaptor(const Base& b_):b(b_){}
const Base& base_reference()const{return b;}
Base& base_reference(){return b;}
private:
Base b;
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
@@ -24,19 +24,19 @@ namespace detail{
* with references to references, dealing with function pointers, etc.
*/
template<typename Modifier,typename Value,typename KeyFromValue>
template<typename Fun,typename Value,typename KeyFromValue>
struct modify_key_adaptor
{
modify_key_adaptor(Modifier mod_,KeyFromValue kfv_):mod(mod_),kfv(kfv_){}
modify_key_adaptor(Fun f_,KeyFromValue kfv_):f(f_),kfv(kfv_){}
void operator()(Value& x)
{
mod(kfv(x));
f(kfv(x));
}
private:
Modifier mod;
Fun f;
KeyFromValue kfv;
};
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaqu M Lez Muz.
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaqu M Lez Muz.
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
@@ -65,7 +65,7 @@ struct multi_index_node_type
typedef typename mpl::reverse_iter_fold<
IndexSpecifierList,
index_node_base<Value>,
index_node_base<Value,Allocator>,
mpl::bind2<index_node_applier,mpl::_2,mpl::_1>
>::type type;
};
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaqu M Lez Muz.
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
@@ -40,8 +40,18 @@
#pragma once
#endif
#include <algorithm>
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <cstddef>
#include <boost/detail/allocator_utilities.hpp>
#include <boost/multi_index/detail/prevent_eti.hpp>
#if !defined(BOOST_MULTI_INDEX_DISABLE_COMPRESSED_ORDERED_INDEX_NODES)
#include <boost/mpl/and.hpp>
#include <boost/mpl/if.hpp>
#include <boost/multi_index/detail/uintptr_type.hpp>
#include <boost/type_traits/alignment_of.hpp>
#include <boost/type_traits/is_same.hpp>
#endif
namespace boost{
@@ -52,28 +62,199 @@ namespace detail{
/* definition of red-black nodes for ordered_index */
enum ordered_index_color{red=false,black=true};
enum ordered_index_side{to_left=false,to_right=true};
struct ordered_index_node_impl
template<typename Allocator>
struct ordered_index_node_impl; /* fwd decl. */
template<typename Allocator>
struct ordered_index_node_std_base
{
ordered_index_color& color(){return color_;}
const ordered_index_color& color()const{return color_;}
ordered_index_node_impl*& parent(){return parent_;}
ordered_index_node_impl*const & parent()const{return parent_;}
ordered_index_node_impl*& left(){return left_;}
ordered_index_node_impl*const & left()const{return left_;}
ordered_index_node_impl*& right(){return right_;}
ordered_index_node_impl*const & right()const{return right_;}
typedef typename prevent_eti<
Allocator,
typename boost::detail::allocator::rebind_to<
Allocator,
ordered_index_node_impl<Allocator>
>::type
>::type::pointer pointer;
typedef typename prevent_eti<
Allocator,
typename boost::detail::allocator::rebind_to<
Allocator,
ordered_index_node_impl<Allocator>
>::type
>::type::const_pointer const_pointer;
typedef ordered_index_color& color_ref;
typedef pointer& parent_ref;
/* interoperability with index_iterator */
ordered_index_color& color(){return color_;}
ordered_index_color color()const{return color_;}
pointer& parent(){return parent_;}
pointer parent()const{return parent_;}
pointer& left(){return left_;}
pointer left()const{return left_;}
pointer& right(){return right_;}
pointer right()const{return right_;}
static void increment(ordered_index_node_impl*& x)
private:
ordered_index_color color_;
pointer parent_;
pointer left_;
pointer right_;
};
#if !defined(BOOST_MULTI_INDEX_DISABLE_COMPRESSED_ORDERED_INDEX_NODES)
/* If ordered_index_node_impl has even alignment, we can use the least
* significant bit of one of the ordered_index_node_impl pointers to
* store color information. This typically reduces the size of
* ordered_index_node_impl by 25%.
*/
#if defined(BOOST_MSVC)
/* This code casts pointers to an integer type that has been computed
* to be large enough to hold the pointer, however the metaprogramming
* logic is not always spotted by the VC++ code analyser that issues a
* long list of warnings.
*/
#pragma warning(push)
#pragma warning(disable:4312 4311)
#endif
template<typename Allocator>
struct ordered_index_node_compressed_base
{
typedef ordered_index_node_impl<Allocator>* pointer;
typedef const ordered_index_node_impl<Allocator>* const_pointer;
struct color_ref
{
if(x->right()){
color_ref(uintptr_type* r_):r(r_){}
operator ordered_index_color()const
{
return ordered_index_color(*r&uintptr_type(1));
}
color_ref& operator=(ordered_index_color c)
{
*r&=~uintptr_type(1);
*r|=uintptr_type(c);
return *this;
}
color_ref& operator=(const color_ref& x)
{
return operator=(x.operator ordered_index_color());
}
private:
uintptr_type* r;
};
struct parent_ref
{
parent_ref(uintptr_type* r_):r(r_){}
operator pointer()const
{
return (pointer)(void*)(*r&~uintptr_type(1));
}
parent_ref& operator=(pointer p)
{
*r=((uintptr_type)(void*)p)|(*r&uintptr_type(1));
return *this;
}
parent_ref& operator=(const parent_ref& x)
{
return operator=(x.operator pointer());
}
pointer operator->()const
{
return operator pointer();
}
private:
uintptr_type* r;
};
color_ref color(){return color_ref(&parentcolor_);}
ordered_index_color color()const
{
return ordered_index_color(parentcolor_&std::size_t(1ul));
}
parent_ref parent(){return parent_ref(&parentcolor_);}
pointer parent()const
{
return (pointer)(void*)(parentcolor_&~uintptr_type(1));
}
pointer& left(){return left_;}
pointer left()const{return left_;}
pointer& right(){return right_;}
pointer right()const{return right_;}
private:
uintptr_type parentcolor_;
pointer left_;
pointer right_;
};
#if defined(BOOST_MSVC)
#pragma warning(pop)
#endif
#endif
template<typename Allocator>
struct ordered_index_node_impl_base:
#if !defined(BOOST_MULTI_INDEX_DISABLE_COMPRESSED_ORDERED_INDEX_NODES)
mpl::if_c<
!(has_uintptr_type::value)||
(alignment_of<ordered_index_node_compressed_base<Allocator> >::value%2)||
!(is_same<
typename prevent_eti<
Allocator,
typename boost::detail::allocator::rebind_to<
Allocator,
ordered_index_node_impl<Allocator>
>::type
>::type::pointer,
ordered_index_node_impl<Allocator>*>::value),
ordered_index_node_std_base<Allocator>,
ordered_index_node_compressed_base<Allocator>
>::type
#else
ordered_index_node_std_base<Allocator>
#endif
{};
template<typename Allocator>
struct ordered_index_node_impl:ordered_index_node_impl_base<Allocator>
{
private:
typedef ordered_index_node_impl_base<Allocator> super;
public:
typedef typename super::color_ref color_ref;
typedef typename super::parent_ref parent_ref;
typedef typename super::pointer pointer;
typedef typename super::const_pointer const_pointer;
/* interoperability with bidir_node_iterator */
static void increment(pointer& x)
{
if(x->right()!=pointer(0)){
x=x->right();
while(x->left())x=x->left();
while(x->left()!=pointer(0))x=x->left();
}
else{
ordered_index_node_impl* y=x->parent();
pointer y=x->parent();
while(x==y->right()){
x=y;
y=y->parent();
@@ -82,17 +263,17 @@ struct ordered_index_node_impl
}
}
static void decrement(ordered_index_node_impl*& x)
static void decrement(pointer& x)
{
if(x->color()==red&&x->parent()->parent()==x){
x=x->right();
}
else if(x->left()){
ordered_index_node_impl* y=x->left();
while(y->right())y=y->right();
else if(x->left()!=pointer(0)){
pointer y=x->left();
while(y->right()!=pointer(0))y=y->right();
x=y;
}else{
ordered_index_node_impl* y=x->parent();
pointer y=x->parent();
while(x==y->left()){
x=y;
y=y->parent();
@@ -101,26 +282,13 @@ struct ordered_index_node_impl
}
}
/* interoperability with index_proxy */
static ordered_index_node_impl* begin(ordered_index_node_impl* header)
{
return header->left();
}
static ordered_index_node_impl* end(ordered_index_node_impl* header)
{
return header;
}
/* algorithmic stuff */
static void rotate_left(
ordered_index_node_impl* x,ordered_index_node_impl*& root)
static void rotate_left(pointer x,parent_ref root)
{
ordered_index_node_impl* y=x->right();
pointer y=x->right();
x->right()=y->left();
if(y->left())y->left()->parent()=x;
if(y->left()!=pointer(0))y->left()->parent()=x;
y->parent()=x->parent();
if(x==root) root=y;
@@ -130,24 +298,23 @@ struct ordered_index_node_impl
x->parent()=y;
}
static ordered_index_node_impl* minimum(ordered_index_node_impl* x)
static pointer minimum(pointer x)
{
while(x->left())x=x->left();
while(x->left()!=pointer(0))x=x->left();
return x;
}
static ordered_index_node_impl* maximum(ordered_index_node_impl* x)
static pointer maximum(pointer x)
{
while(x->right())x=x->right();
while(x->right()!=pointer(0))x=x->right();
return x;
}
static void rotate_right(
ordered_index_node_impl* x,ordered_index_node_impl*& root)
static void rotate_right(pointer x,parent_ref root)
{
ordered_index_node_impl* y=x->left();
pointer y=x->left();
x->left()=y->right();
if(y->right())y->right()->parent()=x;
if(y->right()!=pointer(0))y->right()->parent()=x;
y->parent()=x->parent();
if(x==root) root=y;
@@ -157,14 +324,13 @@ struct ordered_index_node_impl
x->parent()=y;
}
static void rebalance(
ordered_index_node_impl* x,ordered_index_node_impl*& root)
static void rebalance(pointer x,parent_ref root)
{
x->color()=red;
while(x!=root&&x->parent()->color()==red){
if(x->parent()==x->parent()->parent()->left()){
ordered_index_node_impl* y=x->parent()->parent()->right();
if(y&&y->color()==red){
pointer y=x->parent()->parent()->right();
if(y!=pointer(0)&&y->color()==red){
x->parent()->color()=black;
y->color()=black;
x->parent()->parent()->color()=red;
@@ -181,8 +347,8 @@ struct ordered_index_node_impl
}
}
else{
ordered_index_node_impl* y=x->parent()->parent()->left();
if(y&&y->color()==red){
pointer y=x->parent()->parent()->left();
if(y!=pointer(0)&&y->color()==red){
x->parent()->color()=black;
y->color()=black;
x->parent()->parent()->color()=red;
@@ -202,23 +368,47 @@ struct ordered_index_node_impl
root->color()=black;
}
static ordered_index_node_impl* rebalance_for_erase(
ordered_index_node_impl* z,ordered_index_node_impl*& root,
ordered_index_node_impl*& leftmost,ordered_index_node_impl*& rightmost)
static void link(
pointer x,ordered_index_side side,pointer position,pointer header)
{
ordered_index_node_impl* y=z;
ordered_index_node_impl* x=0;
ordered_index_node_impl* x_parent=0;
if(y->left()==0){ /* z has at most one non-null child. y==z. */
x=y->right(); /* x might be null */
if(side==to_left){
position->left()=x; /* also makes leftmost=x when parent==header */
if(position==header){
header->parent()=x;
header->right()=x;
}
else if(position==header->left()){
header->left()=x; /* maintain leftmost pointing to min node */
}
}
else{
if(y->right()==0) { /* z has exactly one non-null child. y==z. */
x=y->left(); /* x is not null */
position->right()=x;
if(position==header->right()){
header->right()=x; /* maintain rightmost pointing to max node */
}
else{ /* z has two non-null children. Set y to */
y=y->right(); /* z's successor. x might be null. */
while(y->left())y=y->left();
}
x->parent()=position;
x->left()=pointer(0);
x->right()=pointer(0);
ordered_index_node_impl::rebalance(x,header->parent());
}
static pointer rebalance_for_erase(
pointer z,parent_ref root,pointer& leftmost,pointer& rightmost)
{
pointer y=z;
pointer x=pointer(0);
pointer x_parent=pointer(0);
if(y->left()==pointer(0)){ /* z has at most one non-null child. y==z. */
x=y->right(); /* x might be null */
}
else{
if(y->right()==pointer(0)){ /* z has exactly one non-null child. y==z. */
x=y->left(); /* x is not null */
}
else{ /* z has two non-null children. Set y to */
y=y->right(); /* z's successor. x might be null. */
while(y->left()!=pointer(0))y=y->left();
x=y->right();
}
}
@@ -227,7 +417,7 @@ struct ordered_index_node_impl
y->left()=z->left();
if(y!=z->right()){
x_parent=y->parent();
if(x) x->parent()=y->parent();
if(x!=pointer(0))x->parent()=y->parent();
y->parent()->left()=x; /* y must be a child of left */
y->right()=z->right();
z->right()->parent()=y;
@@ -240,12 +430,14 @@ struct ordered_index_node_impl
else if(z->parent()->left()==z)z->parent()->left()=y;
else z->parent()->right()=y;
y->parent()=z->parent();
std::swap(y->color(),z->color());
ordered_index_color c=y->color();
y->color()=z->color();
z->color()=c;
y=z; /* y now points to node to be actually deleted */
}
else{ /* y==z */
x_parent=y->parent();
if(x)x->parent()=y->parent();
if(x!=pointer(0))x->parent()=y->parent();
if(root==z){
root=x;
}
@@ -254,15 +446,15 @@ struct ordered_index_node_impl
else z->parent()->right()=x;
}
if(leftmost==z){
if(z->right()==0){ /* z->left() must be null also */
if(z->right()==pointer(0)){ /* z->left() must be null also */
leftmost=z->parent();
}
else{
leftmost=minimum(x); /* makes leftmost==header if z==root */
leftmost=minimum(x); /* makes leftmost==header if z==root */
}
}
if(rightmost==z){
if(z->left()==0){ /* z->right() must be null also */
if(z->left()==pointer(0)){ /* z->right() must be null also */
rightmost=z->parent();
}
else{ /* x==z->left() */
@@ -271,106 +463,87 @@ struct ordered_index_node_impl
}
}
if(y->color()!=red){
while(x!=root&&(x==0 || x->color()==black)){
while(x!=root&&(x==pointer(0)|| x->color()==black)){
if(x==x_parent->left()){
ordered_index_node_impl* w=x_parent->right();
pointer w=x_parent->right();
if(w->color()==red){
w->color()=black;
x_parent->color()=red;
rotate_left(x_parent,root);
w=x_parent->right();
}
if((w->left()==0||w->left()->color()==black) &&
(w->right()==0||w->right()->color()==black)){
if((w->left()==pointer(0)||w->left()->color()==black) &&
(w->right()==pointer(0)||w->right()->color()==black)){
w->color()=red;
x=x_parent;
x_parent=x_parent->parent();
}
else{
if(w->right()==0
if(w->right()==pointer(0 )
|| w->right()->color()==black){
if(w->left()) w->left()->color()=black;
if(w->left()!=pointer(0)) w->left()->color()=black;
w->color()=red;
rotate_right(w,root);
w=x_parent->right();
}
w->color()=x_parent->color();
x_parent->color()=black;
if(w->right())w->right()->color()=black;
if(w->right()!=pointer(0))w->right()->color()=black;
rotate_left(x_parent,root);
break;
}
}
else{ /* same as above,with right <-> left */
ordered_index_node_impl* w=x_parent->left();
pointer w=x_parent->left();
if(w->color()==red){
w->color()=black;
x_parent->color()=red;
rotate_right(x_parent,root);
w=x_parent->left();
}
if((w->right()==0||w->right()->color()==black) &&
(w->left()==0||w->left()->color()==black)){
if((w->right()==pointer(0)||w->right()->color()==black) &&
(w->left()==pointer(0)||w->left()->color()==black)){
w->color()=red;
x=x_parent;
x_parent=x_parent->parent();
}
else{
if(w->left()==0||w->left()->color()==black){
if(w->right())w->right()->color()=black;
if(w->left()==pointer(0)||w->left()->color()==black){
if(w->right()!=pointer(0))w->right()->color()=black;
w->color()=red;
rotate_left(w,root);
w=x_parent->left();
}
w->color()=x_parent->color();
x_parent->color()=black;
if(w->left())w->left()->color()=black;
if(w->left()!=pointer(0))w->left()->color()=black;
rotate_right(x_parent,root);
break;
}
}
}
if(x)x->color()=black;
if(x!=pointer(0))x->color()=black;
}
return y;
}
static void restore(
ordered_index_node_impl* x,ordered_index_node_impl* prior,
ordered_index_node_impl* next,ordered_index_node_impl* header)
static void restore(pointer x,pointer position,pointer header)
{
if(next->left()==0){
next->left()=x;
x->parent()=next;
if(next==header->left()){
header->left()=x; /* maintain leftmost pointing to min node */
}
}
else if(x!=prior){ /* prior->right() must be null */
prior->right()=x;
x->parent()=prior;
if(prior==header->right()){
header->right()=x; /* maintain rightmost pointing to max node */
}
if(position->left()==pointer(0)||position->left()==header){
link(x,to_left,position,header);
}
else{
header->parent()=x;
header->left()=x;
header->right()=x;
x->parent()=header;
decrement(position);
link(x,to_right,position,header);
}
x->left()=0;
x->right()=0;
rebalance(x,header->parent());
}
#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
/* invariant stuff */
static std::size_t black_count(
ordered_index_node_impl* node,ordered_index_node_impl* root)
static std::size_t black_count(pointer node,pointer root)
{
if(!node)return 0;
if(node==pointer(0))return 0;
std::size_t sum=0;
for(;;){
if(node->color()==black)++sum;
@@ -380,76 +553,92 @@ struct ordered_index_node_impl
return sum;
}
#endif
private:
ordered_index_node_impl();
ordered_index_color color_;
ordered_index_node_impl* parent_;
ordered_index_node_impl* left_;
ordered_index_node_impl* right_;
};
template<typename Super>
struct ordered_index_node_trampoline:ordered_index_node_impl{};
struct ordered_index_node_trampoline:
prevent_eti<
Super,
ordered_index_node_impl<
typename boost::detail::allocator::rebind_to<
typename Super::allocator_type,
char
>::type
>
>::type
{
typedef typename prevent_eti<
Super,
ordered_index_node_impl<
typename boost::detail::allocator::rebind_to<
typename Super::allocator_type,
char
>::type
>
>::type impl_type;
};
template<typename Super>
struct ordered_index_node:Super,ordered_index_node_trampoline<Super>
{
ordered_index_color& color(){return impl_type::color();}
const ordered_index_color& color()const{return impl_type::color();}
ordered_index_node_impl*& parent(){return impl_type::parent();}
ordered_index_node_impl*const & parent()const{return impl_type::parent();}
ordered_index_node_impl*& left(){return impl_type::left();}
ordered_index_node_impl*const & left()const{return impl_type::left();}
ordered_index_node_impl*& right(){return impl_type::right();}
ordered_index_node_impl*const & right()const{return impl_type::right();}
private:
typedef ordered_index_node_trampoline<Super> trampoline;
ordered_index_node_impl* impl(){return static_cast<impl_type*>(this);}
const ordered_index_node_impl* impl()const
{return static_cast<const impl_type*>(this);}
public:
typedef typename trampoline::impl_type impl_type;
typedef typename trampoline::color_ref impl_color_ref;
typedef typename trampoline::parent_ref impl_parent_ref;
typedef typename trampoline::pointer impl_pointer;
typedef typename trampoline::const_pointer const_impl_pointer;
static ordered_index_node* from_impl(ordered_index_node_impl *x)
impl_color_ref color(){return trampoline::color();}
ordered_index_color color()const{return trampoline::color();}
impl_parent_ref parent(){return trampoline::parent();}
impl_pointer parent()const{return trampoline::parent();}
impl_pointer& left(){return trampoline::left();}
impl_pointer left()const{return trampoline::left();}
impl_pointer& right(){return trampoline::right();}
impl_pointer right()const{return trampoline::right();}
impl_pointer impl()
{
return static_cast<ordered_index_node*>(static_cast<impl_type*>(x));
return static_cast<impl_pointer>(
static_cast<impl_type*>(static_cast<trampoline*>(this)));
}
static const ordered_index_node* from_impl(const ordered_index_node_impl* x)
const_impl_pointer impl()const
{
return static_cast<const_impl_pointer>(
static_cast<const impl_type*>(static_cast<const trampoline*>(this)));
}
static ordered_index_node* from_impl(impl_pointer x)
{
return static_cast<ordered_index_node*>(
static_cast<trampoline*>(&*x));
}
static const ordered_index_node* from_impl(const_impl_pointer x)
{
return static_cast<const ordered_index_node*>(
static_cast<const impl_type*>(x));
static_cast<const trampoline*>(&*x));
}
/* interoperability with index_iterator */
/* interoperability with bidir_node_iterator */
static void increment(ordered_index_node*& x)
{
ordered_index_node_impl* xi=x->impl();
impl_type::increment(xi);
impl_pointer xi=x->impl();
trampoline::increment(xi);
x=from_impl(xi);
}
static void decrement(ordered_index_node*& x)
{
ordered_index_node_impl* xi=x->impl();
impl_type::decrement(xi);
impl_pointer xi=x->impl();
trampoline::decrement(xi);
x=from_impl(xi);
}
/* interoperability with index_proxy */
static ordered_index_node* begin(ordered_index_node* header)
{
return from_impl(impl_type::begin(header->impl()));
}
static ordered_index_node* end(ordered_index_node* header)
{
return from_impl(impl_type::end(header->impl()));
}
private:
typedef ordered_index_node_trampoline<Super> impl_type;
};
} /* namespace multi_index::detail */
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
@@ -40,6 +40,9 @@
#pragma once
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <utility>
namespace boost{
namespace multi_index{
@@ -55,21 +58,20 @@ template<
typename CompatibleKey,typename CompatibleCompare
>
inline Node* ordered_index_find(
Node* header,const KeyFromValue& key,const CompatibleKey& x,
Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
const CompatibleCompare& comp)
{
Node* y=header;
Node* z=Node::from_impl(header->parent());
while (z){
if(!comp(key(z->value),x)){
y=z;
z=Node::from_impl(z->left());
Node* y0=y;
while (top){
if(!comp(key(top->value()),x)){
y=top;
top=Node::from_impl(top->left());
}
else z=Node::from_impl(z->right());
else top=Node::from_impl(top->right());
}
return (y==header||comp(x,key(y->value)))?header:y;
return (y==y0||comp(x,key(y->value())))?y0:y;
}
template<
@@ -77,18 +79,15 @@ template<
typename CompatibleKey,typename CompatibleCompare
>
inline Node* ordered_index_lower_bound(
Node* header,const KeyFromValue& key,const CompatibleKey& x,
Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
const CompatibleCompare& comp)
{
Node* y=header;
Node* z=Node::from_impl(header->parent());
while(z){
if(!comp(key(z->value),x)){
y=z;
z=Node::from_impl(z->left());
while(top){
if(!comp(key(top->value()),x)){
y=top;
top=Node::from_impl(top->left());
}
else z=Node::from_impl(z->right());
else top=Node::from_impl(top->right());
}
return y;
@@ -99,23 +98,46 @@ template<
typename CompatibleKey,typename CompatibleCompare
>
inline Node* ordered_index_upper_bound(
Node* header,const KeyFromValue& key,const CompatibleKey& x,
Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
const CompatibleCompare& comp)
{
Node* y=header;
Node* z=Node::from_impl(header->parent());
while(z){
if(comp(x,key(z->value))){
y=z;
z=Node::from_impl(z->left());
while(top){
if(comp(x,key(top->value()))){
y=top;
top=Node::from_impl(top->left());
}
else z=Node::from_impl(z->right());
else top=Node::from_impl(top->right());
}
return y;
}
template<
typename Node,typename KeyFromValue,
typename CompatibleKey,typename CompatibleCompare
>
inline std::pair<Node*,Node*> ordered_index_equal_range(
Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
const CompatibleCompare& comp)
{
while(top){
if(comp(key(top->value()),x)){
top=Node::from_impl(top->right());
}
else if(comp(x,key(top->value()))){
y=top;
top=Node::from_impl(top->left());
}
else{
return std::pair<Node*,Node*>(
ordered_index_lower_bound(Node::from_impl(top->left()),top,key,x,comp),
ordered_index_upper_bound(Node::from_impl(top->right()),y,key,x,comp));
}
}
return std::pair<Node*,Node*>(y,y);
}
} /* namespace multi_index::detail */
} /* namespace multi_index */
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaqu M Lez Muz.
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
@@ -0,0 +1,176 @@
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
*
* See http://www.boost.org/libs/multi_index for library home page.
*/
#ifndef BOOST_MULTI_INDEX_DETAIL_RND_INDEX_LOADER_HPP
#define BOOST_MULTI_INDEX_DETAIL_RND_INDEX_LOADER_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <algorithm>
#include <boost/detail/allocator_utilities.hpp>
#include <boost/multi_index/detail/auto_space.hpp>
#include <boost/multi_index/detail/prevent_eti.hpp>
#include <boost/multi_index/detail/rnd_index_ptr_array.hpp>
#include <boost/noncopyable.hpp>
#include <cstddef>
namespace boost{
namespace multi_index{
namespace detail{
/* This class implements a serialization rearranger for random access
* indices. In order to achieve O(n) performance, the following strategy
* is followed: the nodes of the index are handled as if in a bidirectional
* list, where the next pointers are stored in the original
* random_access_index_ptr_array and the prev pointers are stored in
* an auxiliary array. Rearranging of nodes in such a bidirectional list
* is constant time. Once all the arrangements are performed (on destruction
* time) the list is traversed in reverse order and
* pointers are swapped and set accordingly so that they recover its
* original semantics ( *(node->up())==node ) while retaining the
* new order.
*/
template<typename Allocator>
class random_access_index_loader_base:private noncopyable
{
protected:
typedef typename prevent_eti<
Allocator,
random_access_index_node_impl<
typename boost::detail::allocator::rebind_to<
Allocator,
char
>::type
>
>::type node_impl_type;
typedef typename node_impl_type::pointer node_impl_pointer;
typedef random_access_index_ptr_array<Allocator> ptr_array;
random_access_index_loader_base(const Allocator& al_,ptr_array& ptrs_):
al(al_),
ptrs(ptrs_),
header(*ptrs.end()),
prev_spc(al,0),
preprocessed(false)
{}
~random_access_index_loader_base()
{
if(preprocessed)
{
node_impl_pointer n=header;
next(n)=n;
for(std::size_t i=ptrs.size();i--;){
n=prev(n);
std::size_t d=position(n);
if(d!=i){
node_impl_pointer m=prev(next_at(i));
std::swap(m->up(),n->up());
next_at(d)=next_at(i);
std::swap(prev_at(d),prev_at(i));
}
next(n)=n;
}
}
}
void rearrange(node_impl_pointer position,node_impl_pointer x)
{
preprocess(); /* only incur this penalty if rearrange() is ever called */
if(position==node_impl_pointer(0))position=header;
next(prev(x))=next(x);
prev(next(x))=prev(x);
prev(x)=position;
next(x)=next(position);
next(prev(x))=prev(next(x))=x;
}
private:
void preprocess()
{
if(!preprocessed){
/* get space for the auxiliary prev array */
auto_space<node_impl_pointer,Allocator> tmp(al,ptrs.size()+1);
prev_spc.swap(tmp);
/* prev_spc elements point to the prev nodes */
std::rotate_copy(
&*ptrs.begin(),&*ptrs.end(),&*ptrs.end()+1,&*prev_spc.data());
/* ptrs elements point to the next nodes */
std::rotate(&*ptrs.begin(),&*ptrs.begin()+1,&*ptrs.end()+1);
preprocessed=true;
}
}
std::size_t position(node_impl_pointer x)const
{
return (std::size_t)(x->up()-ptrs.begin());
}
node_impl_pointer& next_at(std::size_t n)const
{
return *ptrs.at(n);
}
node_impl_pointer& prev_at(std::size_t n)const
{
return *(prev_spc.data()+n);
}
node_impl_pointer& next(node_impl_pointer x)const
{
return *(x->up());
}
node_impl_pointer& prev(node_impl_pointer x)const
{
return prev_at(position(x));
}
Allocator al;
ptr_array& ptrs;
node_impl_pointer header;
auto_space<node_impl_pointer,Allocator> prev_spc;
bool preprocessed;
};
template<typename Node,typename Allocator>
class random_access_index_loader:
private random_access_index_loader_base<Allocator>
{
typedef random_access_index_loader_base<Allocator> super;
typedef typename super::node_impl_pointer node_impl_pointer;
typedef typename super::ptr_array ptr_array;
public:
random_access_index_loader(const Allocator& al_,ptr_array& ptrs_):
super(al_,ptrs_)
{}
void rearrange(Node* position,Node *x)
{
super::rearrange(position?position->impl():node_impl_pointer(0),x->impl());
}
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -0,0 +1,281 @@
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
*
* See http://www.boost.org/libs/multi_index for library home page.
*/
#ifndef BOOST_MULTI_INDEX_DETAIL_RND_INDEX_NODE_HPP
#define BOOST_MULTI_INDEX_DETAIL_RND_INDEX_NODE_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <algorithm>
#include <boost/detail/allocator_utilities.hpp>
#include <boost/math/common_factor_rt.hpp>
#include <boost/multi_index/detail/prevent_eti.hpp>
#include <cstddef>
#include <functional>
namespace boost{
namespace multi_index{
namespace detail{
template<typename Allocator>
struct random_access_index_node_impl
{
typedef typename prevent_eti<
Allocator,
typename boost::detail::allocator::rebind_to<
Allocator,random_access_index_node_impl
>::type
>::type::pointer pointer;
typedef typename prevent_eti<
Allocator,
typename boost::detail::allocator::rebind_to<
Allocator,random_access_index_node_impl
>::type
>::type::const_pointer const_pointer;
typedef typename prevent_eti<
Allocator,
typename boost::detail::allocator::rebind_to<
Allocator,pointer
>::type
>::type::pointer ptr_pointer;
ptr_pointer& up(){return up_;}
ptr_pointer up()const{return up_;}
/* interoperability with rnd_node_iterator */
static void increment(pointer& x)
{
x=*(x->up()+1);
}
static void decrement(pointer& x)
{
x=*(x->up()-1);
}
static void advance(pointer& x,std::ptrdiff_t n)
{
x=*(x->up()+n);
}
static std::ptrdiff_t distance(pointer x,pointer y)
{
return y->up()-x->up();
}
/* algorithmic stuff */
static void relocate(ptr_pointer pos,ptr_pointer x)
{
pointer n=*x;
if(x<pos){
extract(x,pos);
*(pos-1)=n;
n->up()=pos-1;
}
else{
while(x!=pos){
*x=*(x-1);
(*x)->up()=x;
--x;
}
*pos=n;
n->up()=pos;
}
};
static void relocate(ptr_pointer pos,ptr_pointer first,ptr_pointer last)
{
ptr_pointer begin,middle,end;
if(pos<first){
begin=pos;
middle=first;
end=last;
}
else{
begin=first;
middle=last;
end=pos;
}
std::ptrdiff_t n=end-begin;
std::ptrdiff_t m=middle-begin;
std::ptrdiff_t n_m=n-m;
std::ptrdiff_t p=math::gcd(n,m);
for(std::ptrdiff_t i=0;i<p;++i){
pointer tmp=begin[i];
for(std::ptrdiff_t j=i,k;;){
if(j<n_m)k=j+m;
else k=j-n_m;
if(k==i){
*(begin+j)=tmp;
(*(begin+j))->up()=begin+j;
break;
}
else{
*(begin+j)=*(begin+k);
(*(begin+j))->up()=begin+j;
}
if(k<n_m)j=k+m;
else j=k-n_m;
if(j==i){
*(begin+k)=tmp;
(*(begin+k))->up()=begin+k;
break;
}
else{
*(begin+k)=*(begin+j);
(*(begin+k))->up()=begin+k;
}
}
}
};
static void extract(ptr_pointer x,ptr_pointer pend)
{
--pend;
while(x!=pend){
*x=*(x+1);
(*x)->up()=x;
++x;
}
}
static void transfer(
ptr_pointer pbegin0,ptr_pointer pend0,ptr_pointer pbegin1)
{
while(pbegin0!=pend0){
*pbegin1=*pbegin0++;
(*pbegin1)->up()=pbegin1;
++pbegin1;
}
}
static void reverse(ptr_pointer pbegin,ptr_pointer pend)
{
std::ptrdiff_t d=(pend-pbegin)/2;
for(std::ptrdiff_t i=0;i<d;++i){
std::swap(*pbegin,*--pend);
(*pbegin)->up()=pbegin;
(*pend)->up()=pend;
++pbegin;
}
}
private:
ptr_pointer up_;
};
template<typename Super>
struct random_access_index_node_trampoline:
prevent_eti<
Super,
random_access_index_node_impl<
typename boost::detail::allocator::rebind_to<
typename Super::allocator_type,
char
>::type
>
>::type
{
typedef typename prevent_eti<
Super,
random_access_index_node_impl<
typename boost::detail::allocator::rebind_to<
typename Super::allocator_type,
char
>::type
>
>::type impl_type;
};
template<typename Super>
struct random_access_index_node:
Super,random_access_index_node_trampoline<Super>
{
private:
typedef random_access_index_node_trampoline<Super> trampoline;
public:
typedef typename trampoline::impl_type impl_type;
typedef typename trampoline::pointer impl_pointer;
typedef typename trampoline::const_pointer const_impl_pointer;
typedef typename trampoline::ptr_pointer impl_ptr_pointer;
impl_ptr_pointer& up(){return trampoline::up();}
impl_ptr_pointer up()const{return trampoline::up();}
impl_pointer impl()
{
return static_cast<impl_pointer>(
static_cast<impl_type*>(static_cast<trampoline*>(this)));
}
const_impl_pointer impl()const
{
return static_cast<const_impl_pointer>(
static_cast<const impl_type*>(static_cast<const trampoline*>(this)));
}
static random_access_index_node* from_impl(impl_pointer x)
{
return static_cast<random_access_index_node*>(
static_cast<trampoline*>(&*x));
}
static const random_access_index_node* from_impl(const_impl_pointer x)
{
return static_cast<const random_access_index_node*>(
static_cast<const trampoline*>(&*x));
}
/* interoperability with rnd_node_iterator */
static void increment(random_access_index_node*& x)
{
impl_pointer xi=x->impl();
trampoline::increment(xi);
x=from_impl(xi);
}
static void decrement(random_access_index_node*& x)
{
impl_pointer xi=x->impl();
trampoline::decrement(xi);
x=from_impl(xi);
}
static void advance(random_access_index_node*& x,std::ptrdiff_t n)
{
impl_pointer xi=x->impl();
trampoline::advance(xi,n);
x=from_impl(xi);
}
static std::ptrdiff_t distance(
random_access_index_node* x,random_access_index_node* y)
{
return trampoline::distance(x->impl(),y->impl());
}
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -0,0 +1,208 @@
/* Copyright 2003-2009 Joaquin M Lopez Munoz.
* 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)
*
* See http://www.boost.org/libs/multi_index for library home page.
*/
#ifndef BOOST_MULTI_INDEX_DETAIL_RND_INDEX_OPS_HPP
#define BOOST_MULTI_INDEX_DETAIL_RND_INDEX_OPS_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <algorithm>
#include <boost/multi_index/detail/rnd_index_ptr_array.hpp>
#include <functional>
namespace boost{
namespace multi_index{
namespace detail{
/* Common code for random_access_index memfuns having templatized and
* non-templatized versions.
*/
template<typename Node,typename Allocator,typename Predicate>
Node* random_access_index_remove(
random_access_index_ptr_array<Allocator>& ptrs,Predicate pred
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Node))
{
typedef typename Node::value_type value_type;
typedef typename Node::impl_ptr_pointer impl_ptr_pointer;
impl_ptr_pointer first=ptrs.begin(),
res=first,
last=ptrs.end();
for(;first!=last;++first){
if(!pred(
const_cast<const value_type&>(Node::from_impl(*first)->value()))){
if(first!=res){
std::swap(*first,*res);
(*first)->up()=first;
(*res)->up()=res;
}
++res;
}
}
return Node::from_impl(*res);
}
template<typename Node,typename Allocator,class BinaryPredicate>
Node* random_access_index_unique(
random_access_index_ptr_array<Allocator>& ptrs,BinaryPredicate binary_pred
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Node))
{
typedef typename Node::value_type value_type;
typedef typename Node::impl_ptr_pointer impl_ptr_pointer;
impl_ptr_pointer first=ptrs.begin(),
res=first,
last=ptrs.end();
if(first!=last){
for(;++first!=last;){
if(!binary_pred(
const_cast<const value_type&>(Node::from_impl(*res)->value()),
const_cast<const value_type&>(Node::from_impl(*first)->value()))){
++res;
if(first!=res){
std::swap(*first,*res);
(*first)->up()=first;
(*res)->up()=res;
}
}
}
++res;
}
return Node::from_impl(*res);
}
template<typename Node,typename Allocator,typename Compare>
void random_access_index_inplace_merge(
const Allocator& al,
random_access_index_ptr_array<Allocator>& ptrs,
BOOST_DEDUCED_TYPENAME Node::impl_ptr_pointer first1,Compare comp
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Node))
{
typedef typename Node::value_type value_type;
typedef typename Node::impl_pointer impl_pointer;
typedef typename Node::impl_ptr_pointer impl_ptr_pointer;
auto_space<impl_pointer,Allocator> spc(al,ptrs.size());
impl_ptr_pointer first0=ptrs.begin(),
last0=first1,
last1=ptrs.end(),
out=spc.data();
while(first0!=last0&&first1!=last1){
if(comp(
const_cast<const value_type&>(Node::from_impl(*first1)->value()),
const_cast<const value_type&>(Node::from_impl(*first0)->value()))){
*out++=*first1++;
}
else{
*out++=*first0++;
}
}
std::copy(&*first0,&*last0,&*out);
std::copy(&*first1,&*last1,&*out);
first1=ptrs.begin();
out=spc.data();
while(first1!=last1){
*first1=*out++;
(*first1)->up()=first1;
++first1;
}
}
/* sorting */
/* auxiliary stuff */
template<typename Node,typename Compare>
struct random_access_index_sort_compare:
std::binary_function<
typename Node::impl_pointer,
typename Node::impl_pointer,bool>
{
random_access_index_sort_compare(Compare comp_=Compare()):comp(comp_){}
bool operator()(
typename Node::impl_pointer x,typename Node::impl_pointer y)const
{
typedef typename Node::value_type value_type;
return comp(
const_cast<const value_type&>(Node::from_impl(x)->value()),
const_cast<const value_type&>(Node::from_impl(y)->value()));
}
private:
Compare comp;
};
template<typename Node,typename Allocator,class Compare>
void random_access_index_sort(
const Allocator& al,
random_access_index_ptr_array<Allocator>& ptrs,
Compare comp
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Node))
{
/* The implementation is extremely simple: an auxiliary
* array of pointers is sorted using stdlib facilities and
* then used to rearrange the index. This is suboptimal
* in space and time, but has some advantages over other
* possible approaches:
* - Use std::stable_sort() directly on ptrs using some
* special iterator in charge of maintaining pointers
* and up() pointers in sync: we cannot guarantee
* preservation of the container invariants in the face of
* exceptions, if, for instance, std::stable_sort throws
* when ptrs transitorily contains duplicate elements.
* - Rewrite the internal algorithms of std::stable_sort
* adapted for this case: besides being a fair amount of
* work, making a stable sort compatible with Boost.MultiIndex
* invariants (basically, no duplicates or missing elements
* even if an exception is thrown) is complicated, error-prone
* and possibly won't perform much better than the
* solution adopted.
*/
if(ptrs.size()<=1)return;
typedef typename Node::value_type value_type;
typedef typename Node::impl_pointer impl_pointer;
typedef typename Node::impl_ptr_pointer impl_ptr_pointer;
typedef random_access_index_sort_compare<
Node,Compare> ptr_compare;
impl_ptr_pointer first=ptrs.begin();
impl_ptr_pointer last=ptrs.end();
auto_space<
impl_pointer,
Allocator> spc(al,ptrs.size());
impl_ptr_pointer buf=spc.data();
std::copy(&*first,&*last,&*buf);
std::stable_sort(&*buf,&*buf+ptrs.size(),ptr_compare(comp));
while(first!=last){
*first=*buf++;
(*first)->up()=first;
++first;
}
}
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -0,0 +1,143 @@
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
*
* See http://www.boost.org/libs/multi_index for library home page.
*/
#ifndef BOOST_MULTI_INDEX_DETAIL_RND_INDEX_PTR_ARRAY_HPP
#define BOOST_MULTI_INDEX_DETAIL_RND_INDEX_PTR_ARRAY_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <algorithm>
#include <boost/detail/allocator_utilities.hpp>
#include <boost/multi_index/detail/auto_space.hpp>
#include <boost/multi_index/detail/prevent_eti.hpp>
#include <boost/multi_index/detail/rnd_index_node.hpp>
#include <boost/noncopyable.hpp>
#include <cstddef>
namespace boost{
namespace multi_index{
namespace detail{
/* pointer structure for use by random access indices */
template<typename Allocator>
class random_access_index_ptr_array:private noncopyable
{
typedef typename prevent_eti<
Allocator,
random_access_index_node_impl<
typename boost::detail::allocator::rebind_to<
Allocator,
char
>::type
>
>::type node_impl_type;
public:
typedef typename node_impl_type::pointer value_type;
typedef typename prevent_eti<
Allocator,
typename boost::detail::allocator::rebind_to<
Allocator,value_type
>::type
>::type::pointer pointer;
random_access_index_ptr_array(
const Allocator& al,value_type end_,std::size_t size):
size_(size),
capacity_(size),
spc(al,capacity_+1)
{
*end()=end_;
end_->up()=end();
}
std::size_t size()const{return size_;}
std::size_t capacity()const{return capacity_;}
void room_for_one()
{
if(size_==capacity_){
reserve(capacity_<=10?15:capacity_+capacity_/2);
}
}
void reserve(std::size_t c)
{
if(c>capacity_){
auto_space<value_type,Allocator> spc1(spc.get_allocator(),c+1);
node_impl_type::transfer(begin(),end()+1,spc1.data());
spc.swap(spc1);
capacity_=c;
}
}
pointer begin()const{return ptrs();}
pointer end()const{return ptrs()+size_;}
pointer at(std::size_t n)const{return ptrs()+n;}
void push_back(value_type x)
{
*(end()+1)=*end();
(*(end()+1))->up()=end()+1;
*end()=x;
(*end())->up()=end();
++size_;
}
void erase(value_type x)
{
node_impl_type::extract(x->up(),end()+1);
--size_;
}
void clear()
{
*begin()=*end();
(*begin())->up()=begin();
size_=0;
}
void swap(random_access_index_ptr_array& x)
{
std::swap(size_,x.size_);
std::swap(capacity_,x.capacity_);
spc.swap(x.spc);
}
private:
std::size_t size_;
std::size_t capacity_;
auto_space<value_type,Allocator> spc;
pointer ptrs()const
{
return spc.data();
}
};
template<typename Allocator>
void swap(
random_access_index_ptr_array<Allocator>& x,
random_access_index_ptr_array<Allocator>& y)
{
x.swap(y);
}
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -0,0 +1,139 @@
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
*
* See http://www.boost.org/libs/multi_index for library home page.
*/
#ifndef BOOST_MULTI_INDEX_DETAIL_RND_NODE_ITERATOR_HPP
#define BOOST_MULTI_INDEX_DETAIL_RND_NODE_ITERATOR_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/operators.hpp>
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/split_member.hpp>
#endif
namespace boost{
namespace multi_index{
namespace detail{
/* Iterator class for node-based indices with random access iterators. */
template<typename Node>
class rnd_node_iterator:
public random_access_iterator_helper<
rnd_node_iterator<Node>,
typename Node::value_type,
std::ptrdiff_t,
const typename Node::value_type*,
const typename Node::value_type&>
{
public:
rnd_node_iterator(){}
explicit rnd_node_iterator(Node* node_):node(node_){}
const typename Node::value_type& operator*()const
{
return node->value();
}
rnd_node_iterator& operator++()
{
Node::increment(node);
return *this;
}
rnd_node_iterator& operator--()
{
Node::decrement(node);
return *this;
}
rnd_node_iterator& operator+=(std::ptrdiff_t n)
{
Node::advance(node,n);
return *this;
}
rnd_node_iterator& operator-=(std::ptrdiff_t n)
{
Node::advance(node,-n);
return *this;
}
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
/* Serialization. As for why the following is public,
* see explanation in safe_mode_iterator notes in safe_mode.hpp.
*/
BOOST_SERIALIZATION_SPLIT_MEMBER()
typedef typename Node::base_type node_base_type;
template<class Archive>
void save(Archive& ar,const unsigned int)const
{
node_base_type* bnode=node;
ar<<serialization::make_nvp("pointer",bnode);
}
template<class Archive>
void load(Archive& ar,const unsigned int)
{
node_base_type* bnode;
ar>>serialization::make_nvp("pointer",bnode);
node=static_cast<Node*>(bnode);
}
#endif
/* get_node is not to be used by the user */
typedef Node node_type;
Node* get_node()const{return node;}
private:
Node* node;
};
template<typename Node>
bool operator==(
const rnd_node_iterator<Node>& x,
const rnd_node_iterator<Node>& y)
{
return x.get_node()==y.get_node();
}
template<typename Node>
bool operator<(
const rnd_node_iterator<Node>& x,
const rnd_node_iterator<Node>& y)
{
return Node::distance(x.get_node(),y.get_node())>0;
}
template<typename Node>
std::ptrdiff_t operator-(
const rnd_node_iterator<Node>& x,
const rnd_node_iterator<Node>& y)
{
return Node::distance(y.get_node(),x.get_node());
}
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -0,0 +1,105 @@
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
*
* See http://www.boost.org/libs/multi_index for library home page.
*/
#ifndef BOOST_MULTI_INDEX_DETAIL_SAFE_CTR_PROXY_HPP
#define BOOST_MULTI_INDEX_DETAIL_SAFE_CTR_PROXY_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/detail/workaround.hpp>
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
#include <boost/multi_index/detail/safe_mode.hpp>
namespace boost{
namespace multi_index{
namespace detail{
/* A safe iterator is instantiated in the form
* safe_iterator<Iterator,Container>: MSVC++ 6.0 has serious troubles with
* the resulting symbols names, given that index names (which stand for
* Container) are fairly long themselves. safe_ctr_proxy does not statically
* depend on Container, and provides the necessary methods (begin and end) to
* the safe mode framework via an abstract interface. With safe_ctr_proxy,
* instead of deriving from safe_container<Container> the following base class
* must be used:
*
* safe_ctr_proxy_impl<Iterator,Container>
*
* where Iterator is the type of the *unsafe* iterator being wrapped.
* The corresponding safe iterator instantiation is then
*
* safe_iterator<Iterator,safe_ctr_proxy<Iterator> >,
*
* which does not include the name of Container.
*/
template<typename Iterator>
class safe_ctr_proxy:
public safe_mode::safe_container<safe_ctr_proxy<Iterator> >
{
public:
typedef safe_mode::safe_iterator<Iterator,safe_ctr_proxy> iterator;
typedef iterator const_iterator;
iterator begin(){return begin_impl();}
const_iterator begin()const{return begin_impl();}
iterator end(){return end_impl();}
const_iterator end()const{return end_impl();}
protected:
virtual iterator begin_impl()=0;
virtual const_iterator begin_impl()const=0;
virtual iterator end_impl()=0;
virtual const_iterator end_impl()const=0;
};
template<typename Iterator,typename Container>
class safe_ctr_proxy_impl:public safe_ctr_proxy<Iterator>
{
typedef safe_ctr_proxy<Iterator> super;
typedef Container container_type;
public:
typedef typename super::iterator iterator;
typedef typename super::const_iterator const_iterator;
virtual iterator begin_impl(){return container().begin();}
virtual const_iterator begin_impl()const{return container().begin();}
virtual iterator end_impl(){return container().end();}
virtual const_iterator end_impl()const{return container().end();}
private:
container_type& container()
{
return *static_cast<container_type*>(this);
}
const container_type& container()const
{
return *static_cast<const container_type*>(this);
}
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif /* workaround */
#endif /* BOOST_MULTI_INDEX_ENABLE_SAFE_MODE */
#endif
+420 -231
View File
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
/* Copyright 2003-2009 Joaquin M Lopez Munoz.
* 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)
@@ -13,22 +13,11 @@
#pragma once
#endif
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <algorithm>
#include <boost/multi_index/detail/access_specifier.hpp>
#include <boost/multi_index/safe_mode_errors.hpp>
#include <boost/noncopyable.hpp>
namespace boost{
namespace multi_index{
/* Safe mode machinery, in the spirit of Cay Hortmann's "Safe STL"
* (http://www.horstmann.com/safestl.html).
* In this mode, containers of type Container are derived from
* safe_container<Container>, and their corresponding iterators
* are derived from safe_iterator<Container>. These classes provide
* are wrapped with safe_iterator. These classes provide
* an internal record of which iterators are at a given moment associated
* to a given container, and properly mark the iterators as invalid
* when the container gets destroyed.
@@ -36,6 +25,11 @@ namespace multi_index{
* kept by the container. More elaborate data structures would yield better
* performance, but I decided to keep complexity to a minimum since
* speed is not an issue here.
* Safe mode iterators automatically check that only proper operations
* are performed on them: for instance, an invalid iterator cannot be
* dereferenced. Additionally, a set of utilty macros and functions are
* provided that serve to implement preconditions and cooperate with
* the framework within the container.
* Iterators can also be unchecked, i.e. they do not have info about
* which container they belong in. This situation arises when the iterator
* is restored from a serialization archive: only information on the node
@@ -47,182 +41,90 @@ namespace multi_index{
* for use within the limits of Boost.MultiIndex.
*/
namespace safe_mode{
/* Invalidates all iterators equivalent to that given. Defined before
* safe_iterator_base and safe_container_base as these contain friendship
* declarations to this function.
/* Assertion macros. These resolve to no-ops if
* !defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE).
*/
template<typename Iterator>
inline void detach_equivalent_iterators(Iterator& it)
{
if(it.valid()){
Iterator *prev_,*next_;
for(
prev_=static_cast<Iterator*>(&it.cont->header);
(next_=static_cast<Iterator*>(prev_->next))!=0;){
if(next_!=&it&&*next_==it){
prev_->next=next_->next;
next_->cont=0;
}
else prev_=next_;
}
it.detach();
}
}
} /* namespace multi_index::safe_mode */
namespace detail{
class safe_container_base;
class safe_iterator_base
{
public:
bool valid()const{return cont!=0;}
bool unchecked()const{return unchecked_;}
inline void detach();
void uncheck()
{
detach();
unchecked_=true;
}
protected:
safe_iterator_base():cont(0),next(0),unchecked_(false){}
explicit safe_iterator_base(safe_container_base* cont_):
unchecked_(false)
{
attach(cont_);
}
safe_iterator_base(const safe_iterator_base& it):
unchecked_(it.unchecked_)
{
attach(it.cont);
}
safe_iterator_base& operator=(const safe_iterator_base& it)
{
unchecked_=it.unchecked_;
safe_container_base* new_cont=it.cont;
if(cont!=new_cont){
detach();
attach(new_cont);
}
return *this;
}
~safe_iterator_base()
{
detach();
}
const safe_container_base* owner()const{return cont;}
BOOST_MULTI_INDEX_PRIVATE_IF_MEMBER_TEMPLATE_FRIENDS:
friend class safe_container_base;
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template<typename Iterator> friend
void safe_mode::detach_equivalent_iterators(Iterator&);
#if !defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
#undef BOOST_MULTI_INDEX_SAFE_MODE_ASSERT
#define BOOST_MULTI_INDEX_SAFE_MODE_ASSERT(expr,error_code) ((void)0)
#else
#if !defined(BOOST_MULTI_INDEX_SAFE_MODE_ASSERT)
#include <boost/assert.hpp>
#define BOOST_MULTI_INDEX_SAFE_MODE_ASSERT(expr,error_code) BOOST_ASSERT(expr)
#endif
#endif
inline void attach(safe_container_base* cont_);
#define BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it) \
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT( \
safe_mode::check_valid_iterator(it), \
safe_mode::invalid_iterator);
safe_container_base* cont;
safe_iterator_base* next;
bool unchecked_;
};
#define BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(it) \
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT( \
safe_mode::check_dereferenceable_iterator(it), \
safe_mode::not_dereferenceable_iterator);
class safe_container_base:private noncopyable
{
public:
safe_container_base(){}
#define BOOST_MULTI_INDEX_CHECK_INCREMENTABLE_ITERATOR(it) \
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT( \
safe_mode::check_incrementable_iterator(it), \
safe_mode::not_incrementable_iterator);
~safe_container_base()
{
detach_all_iterators();
}
#define BOOST_MULTI_INDEX_CHECK_DECREMENTABLE_ITERATOR(it) \
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT( \
safe_mode::check_decrementable_iterator(it), \
safe_mode::not_decrementable_iterator);
void detach_all_iterators()
{
for(safe_iterator_base* it=header.next;it;it=it->next)it->cont=0;
}
#define BOOST_MULTI_INDEX_CHECK_IS_OWNER(it,cont) \
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT( \
safe_mode::check_is_owner(it,cont), \
safe_mode::not_owner);
void swap(safe_container_base& x)
{
for(safe_iterator_base* it0=header.next;it0;it0=it0->next)it0->cont=&x;
for(safe_iterator_base* it1=x.header.next;it1;it1=it1->next)it1->cont=this;
std::swap(header.cont,x.header.cont);
std::swap(header.next,x.header.next);
}
#define BOOST_MULTI_INDEX_CHECK_SAME_OWNER(it0,it1) \
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT( \
safe_mode::check_same_owner(it0,it1), \
safe_mode::not_same_owner);
BOOST_MULTI_INDEX_PRIVATE_IF_MEMBER_TEMPLATE_FRIENDS:
friend class safe_iterator_base;
#define BOOST_MULTI_INDEX_CHECK_VALID_RANGE(it0,it1) \
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT( \
safe_mode::check_valid_range(it0,it1), \
safe_mode::invalid_range);
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template<typename Iterator> friend
void safe_mode::detach_equivalent_iterators(Iterator&);
#define BOOST_MULTI_INDEX_CHECK_OUTSIDE_RANGE(it,it0,it1) \
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT( \
safe_mode::check_outside_range(it,it0,it1), \
safe_mode::inside_range);
#define BOOST_MULTI_INDEX_CHECK_IN_BOUNDS(it,n) \
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT( \
safe_mode::check_in_bounds(it,n), \
safe_mode::out_of_bounds);
#define BOOST_MULTI_INDEX_CHECK_DIFFERENT_CONTAINER(cont0,cont1) \
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT( \
safe_mode::check_different_container(cont0,cont1), \
safe_mode::same_container);
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <algorithm>
#include <boost/detail/iterator.hpp>
#include <boost/multi_index/detail/access_specifier.hpp>
#include <boost/multi_index/detail/iter_adaptor.hpp>
#include <boost/multi_index/safe_mode_errors.hpp>
#include <boost/noncopyable.hpp>
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
#include <boost/serialization/split_member.hpp>
#endif
safe_iterator_base header;
};
#if defined(BOOST_HAS_THREADS)
#include <boost/detail/lightweight_mutex.hpp>
#endif
void safe_iterator_base::attach(safe_container_base* cont_)
{
cont=cont_;
if(cont){
next=cont->header.next;
cont->header.next=this;
}
}
namespace boost{
void safe_iterator_base::detach()
{
if(cont){
safe_iterator_base *prev_,*next_;
for(prev_=&cont->header;(next_=prev_->next)!=this;prev_=next_){}
prev_->next=next;
cont=0;
}
}
template<typename Container>
class safe_container;
template<typename Container>
class safe_iterator:public safe_iterator_base
{
public:
typedef Container container_type;
safe_iterator():safe_iterator_base(){}
explicit safe_iterator(safe_container<container_type>* cont_):
safe_iterator_base(cont_){}
const container_type* owner()const
{
return
static_cast<const container_type*>(
static_cast<const safe_container<container_type>*>(
safe_iterator_base::owner()));
}
};
template<typename Container>
class safe_container:public safe_container_base
{
public:
void swap(safe_container<Container>& x){safe_container_base::swap(x);}
};
} /* namespace multi_index::detail */
namespace multi_index{
namespace safe_mode{
@@ -310,6 +212,15 @@ inline bool check_outside_range(
return true;
}
template<typename Iterator,typename Difference>
inline bool check_in_bounds(const Iterator& it,Difference n)
{
if(it.unchecked())return true;
if(!it.valid()) return false;
if(n>0) return it.owner()->end()-it>=n;
else return it.owner()->begin()-it<=n;
}
template<typename Container>
inline bool check_different_container(
const Container& cont0,const Container& cont1)
@@ -317,6 +228,341 @@ inline bool check_different_container(
return &cont0!=&cont1;
}
/* Invalidates all iterators equivalent to that given. Safe containers
* must call this when deleting elements: the safe mode framework cannot
* perform this operation automatically without outside help.
*/
template<typename Iterator>
inline void detach_equivalent_iterators(Iterator& it)
{
if(it.valid()){
{
#if defined(BOOST_HAS_THREADS)
boost::detail::lightweight_mutex::scoped_lock lock(it.cont->mutex);
#endif
Iterator *prev_,*next_;
for(
prev_=static_cast<Iterator*>(&it.cont->header);
(next_=static_cast<Iterator*>(prev_->next))!=0;){
if(next_!=&it&&*next_==it){
prev_->next=next_->next;
next_->cont=0;
}
else prev_=next_;
}
}
it.detach();
}
}
template<typename Container> class safe_container; /* fwd decl. */
} /* namespace multi_index::safe_mode */
namespace detail{
class safe_container_base; /* fwd decl. */
class safe_iterator_base
{
public:
bool valid()const{return cont!=0;}
bool unchecked()const{return unchecked_;}
inline void detach();
void uncheck()
{
detach();
unchecked_=true;
}
protected:
safe_iterator_base():cont(0),next(0),unchecked_(false){}
explicit safe_iterator_base(safe_container_base* cont_):
unchecked_(false)
{
attach(cont_);
}
safe_iterator_base(const safe_iterator_base& it):
unchecked_(it.unchecked_)
{
attach(it.cont);
}
safe_iterator_base& operator=(const safe_iterator_base& it)
{
unchecked_=it.unchecked_;
safe_container_base* new_cont=it.cont;
if(cont!=new_cont){
detach();
attach(new_cont);
}
return *this;
}
~safe_iterator_base()
{
detach();
}
const safe_container_base* owner()const{return cont;}
BOOST_MULTI_INDEX_PRIVATE_IF_MEMBER_TEMPLATE_FRIENDS:
friend class safe_container_base;
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template<typename> friend class safe_mode::safe_container;
template<typename Iterator> friend
void safe_mode::detach_equivalent_iterators(Iterator&);
#endif
inline void attach(safe_container_base* cont_);
safe_container_base* cont;
safe_iterator_base* next;
bool unchecked_;
};
class safe_container_base:private noncopyable
{
public:
safe_container_base(){}
BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
friend class safe_iterator_base;
#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
template<typename Iterator> friend
void safe_mode::detach_equivalent_iterators(Iterator&);
#endif
~safe_container_base()
{
/* Detaches all remaining iterators, which by now will
* be those pointing to the end of the container.
*/
for(safe_iterator_base* it=header.next;it;it=it->next)it->cont=0;
header.next=0;
}
void swap(safe_container_base& x)
{
for(safe_iterator_base* it0=header.next;it0;it0=it0->next)it0->cont=&x;
for(safe_iterator_base* it1=x.header.next;it1;it1=it1->next)it1->cont=this;
std::swap(header.cont,x.header.cont);
std::swap(header.next,x.header.next);
}
safe_iterator_base header;
#if defined(BOOST_HAS_THREADS)
boost::detail::lightweight_mutex mutex;
#endif
};
void safe_iterator_base::attach(safe_container_base* cont_)
{
cont=cont_;
if(cont){
#if defined(BOOST_HAS_THREADS)
boost::detail::lightweight_mutex::scoped_lock lock(cont->mutex);
#endif
next=cont->header.next;
cont->header.next=this;
}
}
void safe_iterator_base::detach()
{
if(cont){
#if defined(BOOST_HAS_THREADS)
boost::detail::lightweight_mutex::scoped_lock lock(cont->mutex);
#endif
safe_iterator_base *prev_,*next_;
for(prev_=&cont->header;(next_=prev_->next)!=this;prev_=next_){}
prev_->next=next;
cont=0;
}
}
} /* namespace multi_index::detail */
namespace safe_mode{
/* In order to enable safe mode on a container:
* - The container must derive from safe_container<container_type>,
* - iterators must be generated via safe_iterator, which adapts a
* preexistent unsafe iterator class.
*/
template<typename Container>
class safe_container;
template<typename Iterator,typename Container>
class safe_iterator:
public detail::iter_adaptor<safe_iterator<Iterator,Container>,Iterator>,
public detail::safe_iterator_base
{
typedef detail::iter_adaptor<safe_iterator,Iterator> super;
typedef detail::safe_iterator_base safe_super;
public:
typedef Container container_type;
typedef typename Iterator::reference reference;
typedef typename Iterator::difference_type difference_type;
safe_iterator(){}
explicit safe_iterator(safe_container<container_type>* cont_):
safe_super(cont_){}
template<typename T0>
safe_iterator(const T0& t0,safe_container<container_type>* cont_):
super(Iterator(t0)),safe_super(cont_){}
template<typename T0,typename T1>
safe_iterator(
const T0& t0,const T1& t1,safe_container<container_type>* cont_):
super(Iterator(t0,t1)),safe_super(cont_){}
safe_iterator& operator=(const safe_iterator& x)
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(x);
this->base_reference()=x.base_reference();
safe_super::operator=(x);
return *this;
}
const container_type* owner()const
{
return
static_cast<const container_type*>(
static_cast<const safe_container<container_type>*>(
this->safe_super::owner()));
}
/* get_node is not to be used by the user */
typedef typename Iterator::node_type node_type;
node_type* get_node()const{return this->base_reference().get_node();}
private:
friend class boost::multi_index::detail::iter_adaptor_access;
reference dereference()const
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(*this);
BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(*this);
return *(this->base_reference());
}
bool equal(const safe_iterator& x)const
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(*this);
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(x);
BOOST_MULTI_INDEX_CHECK_SAME_OWNER(*this,x);
return this->base_reference()==x.base_reference();
}
void increment()
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(*this);
BOOST_MULTI_INDEX_CHECK_INCREMENTABLE_ITERATOR(*this);
++(this->base_reference());
}
void decrement()
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(*this);
BOOST_MULTI_INDEX_CHECK_DECREMENTABLE_ITERATOR(*this);
--(this->base_reference());
}
void advance(difference_type n)
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(*this);
BOOST_MULTI_INDEX_CHECK_IN_BOUNDS(*this,n);
this->base_reference()+=n;
}
difference_type distance_to(const safe_iterator& x)const
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(*this);
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(x);
BOOST_MULTI_INDEX_CHECK_SAME_OWNER(*this,x);
return x.base_reference()-this->base_reference();
}
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
/* Serialization. Note that Iterator::save and Iterator:load
* are assumed to be defined and public: at first sight it seems
* like we could have resorted to the public serialization interface
* for doing the forwarding to the adapted iterator class:
* ar<<base_reference();
* ar>>base_reference();
* but this would cause incompatibilities if a saving
* program is in safe mode and the loading program is not, or
* viceversa --in safe mode, the archived iterator data is one layer
* deeper, this is especially relevant with XML archives.
* It'd be nice if Boost.Serialization provided some forwarding
* facility for use by adaptor classes.
*/
friend class boost::serialization::access;
BOOST_SERIALIZATION_SPLIT_MEMBER()
template<class Archive>
void save(Archive& ar,const unsigned int version)const
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(*this);
this->base_reference().save(ar,version);
}
template<class Archive>
void load(Archive& ar,const unsigned int version)
{
this->base_reference().load(ar,version);
safe_super::uncheck();
}
#endif
};
template<typename Container>
class safe_container:public detail::safe_container_base
{
typedef detail::safe_container_base super;
public:
void detach_dereferenceable_iterators()
{
typedef typename Container::iterator iterator;
iterator end_=static_cast<Container*>(this)->end();
iterator *prev_,*next_;
for(
prev_=static_cast<iterator*>(&this->header);
(next_=static_cast<iterator*>(prev_->next))!=0;){
if(*next_!=end_){
prev_->next=next_->next;
next_->cont=0;
}
else prev_=next_;
}
}
void swap(safe_container<Container>& x)
{
super::swap(x);
}
};
} /* namespace multi_index::safe_mode */
} /* namespace multi_index */
@@ -325,61 +571,4 @@ inline bool check_different_container(
#endif /* BOOST_MULTI_INDEX_ENABLE_SAFE_MODE */
/* assertion macros */
#if !defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
#undef BOOST_MULTI_INDEX_SAFE_MODE_ASSERT
#define BOOST_MULTI_INDEX_SAFE_MODE_ASSERT(expr,error_code) ((void)0)
#else
#if !defined(BOOST_MULTI_INDEX_SAFE_MODE_ASSERT)
#include <boost/assert.hpp>
#define BOOST_MULTI_INDEX_SAFE_MODE_ASSERT(expr,error_code) BOOST_ASSERT(expr)
#endif
#endif
#define BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(it) \
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT( \
safe_mode::check_valid_iterator(it), \
safe_mode::invalid_iterator);
#define BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(it) \
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT( \
safe_mode::check_dereferenceable_iterator(it), \
safe_mode::not_dereferenceable_iterator);
#define BOOST_MULTI_INDEX_CHECK_INCREMENTABLE_ITERATOR(it) \
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT( \
safe_mode::check_incrementable_iterator(it), \
safe_mode::not_incrementable_iterator);
#define BOOST_MULTI_INDEX_CHECK_DECREMENTABLE_ITERATOR(it) \
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT(\
safe_mode::check_decrementable_iterator(it), \
safe_mode::not_decrementable_iterator);
#define BOOST_MULTI_INDEX_CHECK_IS_OWNER(it,cont) \
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT( \
safe_mode::check_is_owner(it,cont), \
safe_mode::not_owner);
#define BOOST_MULTI_INDEX_CHECK_SAME_OWNER(it0,it1) \
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT(\
safe_mode::check_same_owner(it0,it1), \
safe_mode::not_same_owner);
#define BOOST_MULTI_INDEX_CHECK_VALID_RANGE(it0,it1) \
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT( \
safe_mode::check_valid_range(it0,it1), \
safe_mode::invalid_range);
#define BOOST_MULTI_INDEX_CHECK_OUTSIDE_RANGE(it,it0,it1) \
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT(\
safe_mode::check_outside_range(it,it0,it1), \
safe_mode::inside_range);
#define BOOST_MULTI_INDEX_CHECK_DIFFERENT_CONTAINER(cont0,cont1) \
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT( \
safe_mode::check_different_container(cont0,cont1), \
safe_mode::same_container);
#endif
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
/* Copyright 2003-2011 Joaquin M Lopez Munoz.
* 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)
@@ -13,6 +13,8 @@
#pragma once
#endif
#include <boost/detail/no_exceptions_support.hpp>
namespace boost{
namespace multi_index{
@@ -24,12 +26,10 @@ namespace detail{
* ScopeGuard.h as defined in:
* Alexandrescu, A., Marginean, P.:"Generic<Programming>: Change the Way You
* Write Exception-Safe Code - Forever", C/C++ Users Jornal, Dec 2000,
* http://www.cuj.com/documents/s=8000/cujcexp1812alexandr/
* http://www.drdobbs.com/184403758
* with the following modifications:
* - General pretty formatting (pretty to my taste at least.)
* - Naming style changed to standard C++ library requirements.
* - safe_execute does not feature a try-catch protection, so we can
* use this even if BOOST_NO_EXCEPTIONS is defined.
* - Added scope_guard_impl4 and obj_scope_guard_impl3, (Boost.MultiIndex
* needs them). A better design would provide guards for many more
* arguments through the Boost Preprocessor Library.
@@ -42,6 +42,18 @@ namespace detail{
*
* NB: CodeWarrior Pro 8 seems to have problems looking up safe_execute
* without an explicit qualification.
*
* We also define the following variants of the idiom:
*
* - make_guard_if_c<bool>( ... )
* - make_guard_if<IntegralConstant>( ... )
* - make_obj_guard_if_c<bool>( ... )
* - make_obj_guard_if<IntegralConstant>( ... )
* which may be used with a compile-time constant to yield
* a "null_guard" if the boolean compile-time parameter is false,
* or conversely, the guard is only constructed if the constant is true.
* This is useful to avoid extra tagging, because the returned
* null_guard can be optimzed comlpetely away by the compiler.
*/
class scope_guard_impl_base
@@ -65,7 +77,13 @@ protected:
}
template<typename J>
static void safe_execute(J& j){if(!j.dismissed_)j.execute();}
static void safe_execute(J& j){
BOOST_TRY{
if(!j.dismissed_)j.execute();
}
BOOST_CATCH(...){}
BOOST_CATCH_END
}
mutable bool dismissed_;
@@ -75,6 +93,35 @@ private:
typedef const scope_guard_impl_base& scope_guard;
struct null_guard : public scope_guard_impl_base
{
template< class T1 >
null_guard( const T1& )
{ }
template< class T1, class T2 >
null_guard( const T1&, const T2& )
{ }
template< class T1, class T2, class T3 >
null_guard( const T1&, const T2&, const T3& )
{ }
template< class T1, class T2, class T3, class T4 >
null_guard( const T1&, const T2&, const T3&, const T4& )
{ }
template< class T1, class T2, class T3, class T4, class T5 >
null_guard( const T1&, const T2&, const T3&, const T4&, const T5& )
{ }
};
template< bool cond, class T >
struct null_guard_return
{
typedef typename boost::mpl::if_c<cond,T,null_guard>::type type;
};
template<typename F>
class scope_guard_impl0:public scope_guard_impl_base
{
@@ -94,6 +141,20 @@ inline scope_guard_impl0<F> make_guard(F fun)
return scope_guard_impl0<F>(fun);
}
template<bool cond, typename F>
inline typename null_guard_return<cond,scope_guard_impl0<F> >::type
make_guard_if_c(F fun)
{
return typename null_guard_return<cond,scope_guard_impl0<F> >::type(fun);
}
template<typename C, typename F>
inline typename null_guard_return<C::value,scope_guard_impl0<F> >::type
make_guard_if(F fun)
{
return make_guard_if<C::value>(fun);
}
template<typename F,typename P1>
class scope_guard_impl1:public scope_guard_impl_base
{
@@ -113,6 +174,20 @@ inline scope_guard_impl1<F,P1> make_guard(F fun,P1 p1)
return scope_guard_impl1<F,P1>(fun,p1);
}
template<bool cond, typename F,typename P1>
inline typename null_guard_return<cond,scope_guard_impl1<F,P1> >::type
make_guard_if_c(F fun,P1 p1)
{
return typename null_guard_return<cond,scope_guard_impl1<F,P1> >::type(fun,p1);
}
template<typename C, typename F,typename P1>
inline typename null_guard_return<C::value,scope_guard_impl1<F,P1> >::type
make_guard_if(F fun,P1 p1)
{
return make_guard_if_c<C::value>(fun,p1);
}
template<typename F,typename P1,typename P2>
class scope_guard_impl2:public scope_guard_impl_base
{
@@ -133,6 +208,20 @@ inline scope_guard_impl2<F,P1,P2> make_guard(F fun,P1 p1,P2 p2)
return scope_guard_impl2<F,P1,P2>(fun,p1,p2);
}
template<bool cond, typename F,typename P1,typename P2>
inline typename null_guard_return<cond,scope_guard_impl2<F,P1,P2> >::type
make_guard_if_c(F fun,P1 p1,P2 p2)
{
return typename null_guard_return<cond,scope_guard_impl2<F,P1,P2> >::type(fun,p1,p2);
}
template<typename C, typename F,typename P1,typename P2>
inline typename null_guard_return<C::value,scope_guard_impl2<F,P1,P2> >::type
make_guard_if(F fun,P1 p1,P2 p2)
{
return make_guard_if_c<C::value>(fun,p1,p2);
}
template<typename F,typename P1,typename P2,typename P3>
class scope_guard_impl3:public scope_guard_impl_base
{
@@ -154,6 +243,20 @@ inline scope_guard_impl3<F,P1,P2,P3> make_guard(F fun,P1 p1,P2 p2,P3 p3)
return scope_guard_impl3<F,P1,P2,P3>(fun,p1,p2,p3);
}
template<bool cond,typename F,typename P1,typename P2,typename P3>
inline typename null_guard_return<cond,scope_guard_impl3<F,P1,P2,P3> >::type
make_guard_if_c(F fun,P1 p1,P2 p2,P3 p3)
{
return typename null_guard_return<cond,scope_guard_impl3<F,P1,P2,P3> >::type(fun,p1,p2,p3);
}
template<typename C,typename F,typename P1,typename P2,typename P3>
inline typename null_guard_return< C::value,scope_guard_impl3<F,P1,P2,P3> >::type
make_guard_if(F fun,P1 p1,P2 p2,P3 p3)
{
return make_guard_if_c<C::value>(fun,p1,p2,p3);
}
template<typename F,typename P1,typename P2,typename P3,typename P4>
class scope_guard_impl4:public scope_guard_impl_base
{
@@ -178,6 +281,22 @@ inline scope_guard_impl4<F,P1,P2,P3,P4> make_guard(
return scope_guard_impl4<F,P1,P2,P3,P4>(fun,p1,p2,p3,p4);
}
template<bool cond, typename F,typename P1,typename P2,typename P3,typename P4>
inline typename null_guard_return<cond,scope_guard_impl4<F,P1,P2,P3,P4> >::type
make_guard_if_c(
F fun,P1 p1,P2 p2,P3 p3,P4 p4)
{
return typename null_guard_return<cond,scope_guard_impl4<F,P1,P2,P3,P4> >::type(fun,p1,p2,p3,p4);
}
template<typename C, typename F,typename P1,typename P2,typename P3,typename P4>
inline typename null_guard_return<C::value,scope_guard_impl4<F,P1,P2,P3,P4> >::type
make_guard_if(
F fun,P1 p1,P2 p2,P3 p3,P4 p4)
{
return make_guard_if_c<C::value>(fun,p1,p2,p3,p4);
}
template<class Obj,typename MemFun>
class obj_scope_guard_impl0:public scope_guard_impl_base
{
@@ -197,6 +316,20 @@ inline obj_scope_guard_impl0<Obj,MemFun> make_obj_guard(Obj& obj,MemFun mem_fun)
return obj_scope_guard_impl0<Obj,MemFun>(obj,mem_fun);
}
template<bool cond, class Obj,typename MemFun>
inline typename null_guard_return<cond,obj_scope_guard_impl0<Obj,MemFun> >::type
make_obj_guard_if_c(Obj& obj,MemFun mem_fun)
{
return typename null_guard_return<cond,obj_scope_guard_impl0<Obj,MemFun> >::type(obj,mem_fun);
}
template<typename C, class Obj,typename MemFun>
inline typename null_guard_return<C::value,obj_scope_guard_impl0<Obj,MemFun> >::type
make_obj_guard_if(Obj& obj,MemFun mem_fun)
{
return make_obj_guard_if_c<C::value>(obj,mem_fun);
}
template<class Obj,typename MemFun,typename P1>
class obj_scope_guard_impl1:public scope_guard_impl_base
{
@@ -219,6 +352,20 @@ inline obj_scope_guard_impl1<Obj,MemFun,P1> make_obj_guard(
return obj_scope_guard_impl1<Obj,MemFun,P1>(obj,mem_fun,p1);
}
template<bool cond, class Obj,typename MemFun,typename P1>
inline typename null_guard_return<cond,obj_scope_guard_impl1<Obj,MemFun,P1> >::type
make_obj_guard_if_c( Obj& obj,MemFun mem_fun,P1 p1)
{
return typename null_guard_return<cond,obj_scope_guard_impl1<Obj,MemFun,P1> >::type(obj,mem_fun,p1);
}
template<typename C, class Obj,typename MemFun,typename P1>
inline typename null_guard_return<C::value,obj_scope_guard_impl1<Obj,MemFun,P1> >::type
make_obj_guard_if( Obj& obj,MemFun mem_fun,P1 p1)
{
return make_obj_guard_if_c<C::value>(obj,mem_fun,p1);
}
template<class Obj,typename MemFun,typename P1,typename P2>
class obj_scope_guard_impl2:public scope_guard_impl_base
{
@@ -243,6 +390,20 @@ make_obj_guard(Obj& obj,MemFun mem_fun,P1 p1,P2 p2)
return obj_scope_guard_impl2<Obj,MemFun,P1,P2>(obj,mem_fun,p1,p2);
}
template<bool cond, class Obj,typename MemFun,typename P1,typename P2>
inline typename null_guard_return<cond,obj_scope_guard_impl2<Obj,MemFun,P1,P2> >::type
make_obj_guard_if_c(Obj& obj,MemFun mem_fun,P1 p1,P2 p2)
{
return typename null_guard_return<cond,obj_scope_guard_impl2<Obj,MemFun,P1,P2> >::type(obj,mem_fun,p1,p2);
}
template<typename C, class Obj,typename MemFun,typename P1,typename P2>
inline typename null_guard_return<C::value,obj_scope_guard_impl2<Obj,MemFun,P1,P2> >::type
make_obj_guard_if(Obj& obj,MemFun mem_fun,P1 p1,P2 p2)
{
return make_obj_guard_if_c<C::value>(obj,mem_fun,p1,p2);
}
template<class Obj,typename MemFun,typename P1,typename P2,typename P3>
class obj_scope_guard_impl3:public scope_guard_impl_base
{
@@ -268,6 +429,20 @@ make_obj_guard(Obj& obj,MemFun mem_fun,P1 p1,P2 p2,P3 p3)
return obj_scope_guard_impl3<Obj,MemFun,P1,P2,P3>(obj,mem_fun,p1,p2,p3);
}
template<bool cond, class Obj,typename MemFun,typename P1,typename P2,typename P3>
inline typename null_guard_return<cond,obj_scope_guard_impl3<Obj,MemFun,P1,P2,P3> >::type
make_obj_guard_if_c(Obj& obj,MemFun mem_fun,P1 p1,P2 p2,P3 p3)
{
return typename null_guard_return<cond,obj_scope_guard_impl3<Obj,MemFun,P1,P2,P3> >::type(obj,mem_fun,p1,p2,p3);
}
template<typename C, class Obj,typename MemFun,typename P1,typename P2,typename P3>
inline typename null_guard_return<C::value,obj_scope_guard_impl3<Obj,MemFun,P1,P2,P3> >::type
make_obj_guard_if(Obj& obj,MemFun mem_fun,P1 p1,P2 p2,P3 p3)
{
return make_obj_guard_if_c<C::value>(obj,mem_fun,p1,p2,p3);
}
} /* namespace multi_index::detail */
} /* namespace multi_index */
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
@@ -13,7 +13,10 @@
#pragma once
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <algorithm>
#include <boost/detail/allocator_utilities.hpp>
#include <boost/multi_index/detail/prevent_eti.hpp>
namespace boost{
@@ -23,48 +26,48 @@ namespace detail{
/* doubly-linked node for use by sequenced_index */
template<typename Allocator>
struct sequenced_index_node_impl
{
sequenced_index_node_impl*& prior(){return prior_;}
sequenced_index_node_impl*const & prior()const{return prior_;}
sequenced_index_node_impl*& next(){return next_;}
sequenced_index_node_impl*const & next()const{return next_;}
typedef typename prevent_eti<
Allocator,
typename boost::detail::allocator::rebind_to<
Allocator,sequenced_index_node_impl
>::type
>::type::pointer pointer;
typedef typename prevent_eti<
Allocator,
typename boost::detail::allocator::rebind_to<
Allocator,sequenced_index_node_impl
>::type
>::type::const_pointer const_pointer;
/* interoperability with index_iterator */
pointer& prior(){return prior_;}
pointer prior()const{return prior_;}
pointer& next(){return next_;}
pointer next()const{return next_;}
static void increment(sequenced_index_node_impl*& x){x=x->next();}
static void decrement(sequenced_index_node_impl*& x){x=x->prior();}
/* interoperability with bidir_node_iterator */
/* interoperability with index_proxy */
static sequenced_index_node_impl* begin(sequenced_index_node_impl* header)
{
return header->next();
}
static sequenced_index_node_impl* end(sequenced_index_node_impl* header)
{
return header;
}
static void increment(pointer& x){x=x->next();}
static void decrement(pointer& x){x=x->prior();}
/* algorithmic stuff */
static void link(
sequenced_index_node_impl* x,sequenced_index_node_impl* header)
static void link(pointer x,pointer header)
{
x->prior()=header->prior();
x->next()=header;
x->prior()->next()=x->next()->prior()=x;
};
static void unlink(sequenced_index_node_impl* x)
static void unlink(pointer x)
{
x->prior()->next()=x->next();
x->next()->prior()=x->prior();
}
static void relink(
sequenced_index_node_impl* position,sequenced_index_node_impl* x)
static void relink(pointer position,pointer x)
{
unlink(x);
x->prior()=position->prior();
@@ -72,14 +75,12 @@ struct sequenced_index_node_impl
x->prior()->next()=x->next()->prior()=x;
}
static void relink(
sequenced_index_node_impl* position,
sequenced_index_node_impl* x,sequenced_index_node_impl* y)
static void relink(pointer position,pointer x,pointer y)
{
/* position is assumed not to be in [x,y) */
if(x!=y){
sequenced_index_node_impl* z=y->prior();
pointer z=y->prior();
x->prior()->next()=y;
y->prior()=x->prior();
x->prior()=position->prior();
@@ -89,17 +90,17 @@ struct sequenced_index_node_impl
}
}
static void reverse(sequenced_index_node_impl* header)
static void reverse(pointer header)
{
sequenced_index_node_impl* x=header;
pointer x=header;
do{
sequenced_index_node_impl* y=x->next();
pointer y=x->next();
std::swap(x->prior(),x->next());
x=y;
}while(x!=header);
}
static void swap(sequenced_index_node_impl* x,sequenced_index_node_impl* y)
static void swap(pointer x,pointer y)
{
/* This swap function does not exchange the header nodes,
* but rather their pointers. This is *not* used for implementing
@@ -129,67 +130,88 @@ struct sequenced_index_node_impl
}
private:
sequenced_index_node_impl();
sequenced_index_node_impl* prior_;
sequenced_index_node_impl* next_;
pointer prior_;
pointer next_;
};
template<typename Super>
struct sequenced_index_node_trampoline:sequenced_index_node_impl{};
struct sequenced_index_node_trampoline:
prevent_eti<
Super,
sequenced_index_node_impl<
typename boost::detail::allocator::rebind_to<
typename Super::allocator_type,
char
>::type
>
>::type
{
typedef typename prevent_eti<
Super,
sequenced_index_node_impl<
typename boost::detail::allocator::rebind_to<
typename Super::allocator_type,
char
>::type
>
>::type impl_type;
};
template<typename Super>
struct sequenced_index_node:Super,sequenced_index_node_trampoline<Super>
{
sequenced_index_node_impl*& prior(){return impl_type::prior();}
sequenced_index_node_impl*const & prior()const{return impl_type::prior();}
sequenced_index_node_impl*& next(){return impl_type::next();}
sequenced_index_node_impl*const & next()const{return impl_type::next();}
private:
typedef sequenced_index_node_trampoline<Super> trampoline;
sequenced_index_node_impl* impl()
{return static_cast<impl_type*>(this);}
const sequenced_index_node_impl* impl()const
{return static_cast<const impl_type*>(this);}
public:
typedef typename trampoline::impl_type impl_type;
typedef typename trampoline::pointer impl_pointer;
typedef typename trampoline::const_pointer const_impl_pointer;
static sequenced_index_node* from_impl(sequenced_index_node_impl *x)
{return static_cast<sequenced_index_node*>(static_cast<impl_type*>(x));}
static const sequenced_index_node* from_impl(
const sequenced_index_node_impl* x)
impl_pointer& prior(){return trampoline::prior();}
impl_pointer prior()const{return trampoline::prior();}
impl_pointer& next(){return trampoline::next();}
impl_pointer next()const{return trampoline::next();}
impl_pointer impl()
{
return static_cast<const sequenced_index_node*>(
static_cast<const impl_type*>(x));
return static_cast<impl_pointer>(
static_cast<impl_type*>(static_cast<trampoline*>(this)));
}
/* interoperability with index_iterator */
const_impl_pointer impl()const
{
return static_cast<const_impl_pointer>(
static_cast<const impl_type*>(static_cast<const trampoline*>(this)));
}
static sequenced_index_node* from_impl(impl_pointer x)
{
return static_cast<sequenced_index_node*>(
static_cast<trampoline*>(&*x));
}
static const sequenced_index_node* from_impl(const_impl_pointer x)
{
return static_cast<const sequenced_index_node*>(
static_cast<const trampoline*>(&*x));
}
/* interoperability with bidir_node_iterator */
static void increment(sequenced_index_node*& x)
{
sequenced_index_node_impl* xi=x->impl();
impl_type::increment(xi);
impl_pointer xi=x->impl();
trampoline::increment(xi);
x=from_impl(xi);
}
static void decrement(sequenced_index_node*& x)
{
sequenced_index_node_impl* xi=x->impl();
impl_type::decrement(xi);
impl_pointer xi=x->impl();
trampoline::decrement(xi);
x=from_impl(xi);
}
/* interoperability with index_proxy */
static sequenced_index_node* begin(sequenced_index_node* header)
{
return from_impl(impl_type::begin(header->impl()));
}
static sequenced_index_node* end(sequenced_index_node* header)
{
return from_impl(impl_type::end(header->impl()));
}
private:
typedef sequenced_index_node_trampoline<Super> impl_type;
};
} /* namespace multi_index::detail */
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
@@ -14,10 +14,11 @@
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/aligned_storage.hpp>
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/multi_index/detail/seq_index_node.hpp>
#include <boost/limits.hpp>
#include <boost/type_traits/aligned_storage.hpp>
#include <boost/type_traits/alignment_of.hpp>
#include <cstddef>
namespace boost{
@@ -59,7 +60,7 @@ template <typename SequencedIndex,typename Compare>
void sequenced_index_merge(SequencedIndex& x,SequencedIndex& y,Compare comp)
{
typedef typename SequencedIndex::iterator iterator;
if(x!=y){
if(&x!=&y){
iterator first0=x.begin(),last0=x.end();
iterator first1=y.begin(),last1=y.end();
while(first0!=last0&&first1!=last1){
@@ -76,24 +77,40 @@ void sequenced_index_merge(SequencedIndex& x,SequencedIndex& y,Compare comp)
template<typename Node,typename Compare>
void sequenced_index_collate(
sequenced_index_node_impl* x,sequenced_index_node_impl* y,Compare comp
BOOST_DEDUCED_TYPENAME Node::impl_type* x,
BOOST_DEDUCED_TYPENAME Node::impl_type* y,
Compare comp
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Node))
{
sequenced_index_node_impl* first0=x->next();
sequenced_index_node_impl* last0=x;
sequenced_index_node_impl* first1=y->next();
sequenced_index_node_impl* last1=y;
typedef typename Node::impl_type impl_type;
typedef typename Node::impl_pointer impl_pointer;
impl_pointer first0=x->next();
impl_pointer last0=x;
impl_pointer first1=y->next();
impl_pointer last1=y;
while(first0!=last0&&first1!=last1){
if(comp(Node::from_impl(first1)->value,Node::from_impl(first0)->value)){
sequenced_index_node_impl* tmp=first1->next();
sequenced_index_node_impl::relink(first0,first1);
if(comp(
Node::from_impl(first1)->value(),Node::from_impl(first0)->value())){
impl_pointer tmp=first1->next();
impl_type::relink(first0,first1);
first1=tmp;
}
else first0=first0->next();
}
sequenced_index_node_impl::relink(last0,first1,last1);
impl_type::relink(last0,first1,last1);
}
/* Some versions of CGG require a bogus typename in counter_spc
* inside sequenced_index_sort if the following is defined
* also inside sequenced_index_sort.
*/
BOOST_STATIC_CONSTANT(
std::size_t,
sequenced_index_sort_max_fill=
(std::size_t)std::numeric_limits<std::size_t>::digits+1);
template<typename Node,typename Compare>
void sequenced_index_sort(Node* header,Compare comp)
{
@@ -110,49 +127,64 @@ void sequenced_index_sort(Node* header,Compare comp)
if(header->next()==header->impl()||
header->next()->next()==header->impl())return;
BOOST_STATIC_CONSTANT(
std::size_t,
max_fill=(std::size_t)std::numeric_limits<std::size_t>::digits+1);
typedef typename Node::impl_type impl_type;
typedef typename Node::impl_pointer impl_pointer;
aligned_storage<
sizeof(sequenced_index_node_impl)> carry_spc;
sequenced_index_node_impl& carry=
*static_cast<sequenced_index_node_impl*>(carry_spc.address());
aligned_storage<
typedef typename aligned_storage<
sizeof(impl_type),
alignment_of<impl_type>::value
>::type carry_spc_type;
carry_spc_type carry_spc;
impl_type& carry=
*static_cast<impl_type*>(static_cast<void*>(&carry_spc));
typedef typename aligned_storage<
sizeof(
sequenced_index_node_impl[max_fill])> counter_spc;
sequenced_index_node_impl* counter=
static_cast<sequenced_index_node_impl*>(counter_spc.address());
std::size_t fill=0;
impl_type
[sequenced_index_sort_max_fill]),
alignment_of<
impl_type
[sequenced_index_sort_max_fill]
>::value
>::type counter_spc_type;
counter_spc_type counter_spc;
impl_type* counter=
static_cast<impl_type*>(static_cast<void*>(&counter_spc));
std::size_t fill=0;
carry.prior()=carry.next()=&carry;
counter[0].prior()=counter[0].next()=&counter[0];
carry.prior()=carry.next()=static_cast<impl_pointer>(&carry);
counter[0].prior()=counter[0].next()=static_cast<impl_pointer>(&counter[0]);
BOOST_TRY{
while(header->next()!=header->impl()){
sequenced_index_node_impl::relink(carry.next(),header->next());
impl_type::relink(carry.next(),header->next());
std::size_t i=0;
while(i<fill&&counter[i].next()!=&counter[i]){
while(i<fill&&counter[i].next()!=static_cast<impl_pointer>(&counter[i])){
sequenced_index_collate<Node>(&carry,&counter[i++],comp);
}
sequenced_index_node_impl::swap(&carry,&counter[i]);
impl_type::swap(
static_cast<impl_pointer>(&carry),
static_cast<impl_pointer>(&counter[i]));
if(i==fill){
++fill;
counter[fill].prior()=counter[fill].next()=&counter[fill];
counter[fill].prior()=counter[fill].next()=
static_cast<impl_pointer>(&counter[fill]);
}
}
for(std::size_t i=1;i<fill;++i){
sequenced_index_collate<Node>(&counter[i],&counter[i-1],comp);
}
sequenced_index_node_impl::swap(header->impl(),&counter[fill-1]);
impl_type::swap(
header->impl(),static_cast<impl_pointer>(&counter[fill-1]));
}
BOOST_CATCH(...)
{
sequenced_index_node_impl::relink(header->impl(),carry.next(),&carry);
impl_type::relink(
header->impl(),carry.next(),static_cast<impl_pointer>(&carry));
for(std::size_t i=0;i<=fill;++i){
sequenced_index_node_impl::relink(
header->impl(),counter[i].next(),&counter[i]);
impl_type::relink(
header->impl(),counter[i].next(),
static_cast<impl_pointer>(&counter[i]));
}
BOOST_RETHROW;
}
@@ -0,0 +1,75 @@
/* Copyright 2003-2010 Joaquin M Lopez Munoz.
* 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)
*
* See http://www.boost.org/libs/multi_index for library home page.
*/
#ifndef BOOST_MULTI_INDEX_DETAIL_SERIALIZATION_VERSION_HPP
#define BOOST_MULTI_INDEX_DETAIL_SERIALIZATION_VERSION_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/serialization/split_member.hpp>
#include <boost/serialization/version.hpp>
namespace boost{
namespace multi_index{
namespace detail{
/* Helper class for storing and retrieving a given type serialization class
* version while avoiding saving the number multiple times in the same
* archive.
* Behavior undefined if template partial specialization is not supported.
*/
template<typename T>
struct serialization_version
{
serialization_version():
value(boost::serialization::version<serialization_version>::value){}
serialization_version& operator=(unsigned int x){value=x;return *this;};
operator unsigned int()const{return value;}
private:
friend class boost::serialization::access;
BOOST_SERIALIZATION_SPLIT_MEMBER()
template<class Archive>
void save(Archive&,const unsigned int)const{}
template<class Archive>
void load(Archive&,const unsigned int version)
{
this->value=version;
}
unsigned int value;
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
namespace serialization {
template<typename T>
struct version<boost::multi_index::detail::serialization_version<T> >
{
BOOST_STATIC_CONSTANT(int,value=version<T>::value);
};
} /* namespace serialization */
#endif
} /* namespace boost */
#endif
@@ -0,0 +1,76 @@
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
*
* See http://www.boost.org/libs/multi_index for library home page.
*/
#ifndef BOOST_MULTI_INDEX_DETAIL_UINTPTR_TYPE_HPP
#define BOOST_MULTI_INDEX_DETAIL_UINTPTR_TYPE_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/mpl/bool.hpp>
namespace boost{
namespace multi_index{
namespace detail{
/* has_uintptr_type is an MPL integral constant determining whether
* there exists an unsigned integral type with the same size as
* void *.
* uintptr_type is such a type if has_uintptr is true, or unsigned int
* otherwise.
* Note that uintptr_type is more restrictive than C99 uintptr_t,
* where an integral type with size greater than that of void *
* would be conformant.
*/
template<int N>struct uintptr_candidates;
template<>struct uintptr_candidates<-1>{typedef unsigned int type;};
template<>struct uintptr_candidates<0> {typedef unsigned int type;};
template<>struct uintptr_candidates<1> {typedef unsigned short type;};
template<>struct uintptr_candidates<2> {typedef unsigned long type;};
#if defined(BOOST_HAS_LONG_LONG)
template<>struct uintptr_candidates<3> {typedef boost::ulong_long_type type;};
#else
template<>struct uintptr_candidates<3> {typedef unsigned int type;};
#endif
#if defined(BOOST_HAS_MS_INT64)
template<>struct uintptr_candidates<4> {typedef unsigned __int64 type;};
#else
template<>struct uintptr_candidates<4> {typedef unsigned int type;};
#endif
struct uintptr_aux
{
BOOST_STATIC_CONSTANT(int,index=
sizeof(void*)==sizeof(uintptr_candidates<0>::type)?0:
sizeof(void*)==sizeof(uintptr_candidates<1>::type)?1:
sizeof(void*)==sizeof(uintptr_candidates<2>::type)?2:
sizeof(void*)==sizeof(uintptr_candidates<3>::type)?3:
sizeof(void*)==sizeof(uintptr_candidates<4>::type)?4:-1);
BOOST_STATIC_CONSTANT(bool,has_uintptr_type=(index>=0));
typedef uintptr_candidates<index>::type type;
};
typedef mpl::bool_<uintptr_aux::has_uintptr_type> has_uintptr_type;
typedef uintptr_aux::type uintptr_type;
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
+51 -7
View File
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
@@ -13,24 +13,68 @@
#pragma once
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/detail/workaround.hpp>
namespace boost{
namespace multi_index{
/* dummy type and variable for use in ordered_index::range() */
namespace detail{
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
/* The default branch actually works for MSVC 6.0, but seems like
* this implementation of unbounded improves the performance of ordered
* indices! This behavior is hard to explain and probably a test artifact,
* but it does not hurt to have the workaround anyway.
*/
struct unbounded_type{};
} /* namespace multi_index::detail */
namespace detail{struct unbounded_type{};}
namespace{
detail::unbounded_type unbounded_obj=detail::unbounded_type();
detail::unbounded_type& unbounded=unbounded_obj;
static detail::unbounded_type unbounded_obj=detail::unbounded_type();
static detail::unbounded_type& unbounded=unbounded_obj;
} /* unnamed */
#else
/* ODR-abiding technique shown at the example attached to
* http://lists.boost.org/Archives/boost/2006/07/108355.php
*/
namespace detail{class unbounded_helper;}
detail::unbounded_helper unbounded(detail::unbounded_helper);
namespace detail{
class unbounded_helper
{
unbounded_helper(){}
unbounded_helper(const unbounded_helper&){}
friend unbounded_helper multi_index::unbounded(unbounded_helper);
};
typedef unbounded_helper (*unbounded_type)(unbounded_helper);
} /* namespace multi_index::detail */
inline detail::unbounded_helper unbounded(detail::unbounded_helper)
{
return detail::unbounded_helper();
}
#endif
/* tags used in the implementation of range */
namespace detail{
struct none_unbounded_tag{};
struct lower_unbounded_tag{};
struct upper_unbounded_tag{};
struct both_unbounded_tag{};
} /* namespace multi_index::detail */
} /* namespace multi_index */
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
@@ -26,14 +26,15 @@ namespace detail{
template<typename Value,typename KeyFromValue,typename Compare>
struct value_comparison:std::binary_function<Value,Value,bool>
{
value_comparison(KeyFromValue key_=KeyFromValue(),Compare comp_=Compare()):
value_comparison(
const KeyFromValue& key_=KeyFromValue(),const Compare& comp_=Compare()):
key(key_),comp(comp_)
{
}
bool operator()(
typename call_traits<Value>::param_type x,
typename call_traits<Value>::param_type y)
typename call_traits<Value>::param_type y)const
{
return comp(key(x),key(y));
}
+188
View File
@@ -0,0 +1,188 @@
/* Copyright 2003-2008 Joaquin M Lopez Munoz.
* 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)
*
* See http://www.boost.org/libs/multi_index for library home page.
*/
#ifndef BOOST_MULTI_INDEX_GLOBAL_FUN_HPP
#define BOOST_MULTI_INDEX_GLOBAL_FUN_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/mpl/if.hpp>
#include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/is_reference.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/utility/enable_if.hpp>
#if !defined(BOOST_NO_SFINAE)
#include <boost/type_traits/is_convertible.hpp>
#endif
namespace boost{
template<class T> class reference_wrapper; /* fwd decl. */
namespace multi_index{
namespace detail{
/* global_fun is a read-only key extractor from Value based on a given global
* (or static member) function with signature:
*
* Type f([const] Value [&]);
*
* Additionally, global_fun and const_global_fun are overloaded to support
* referece_wrappers of Value and "chained pointers" to Value's. By chained
* pointer to T we mean a type P such that, given a p of Type P
* *...n...*x is convertible to T&, for some n>=1.
* Examples of chained pointers are raw and smart pointers, iterators and
* arbitrary combinations of these (vg. T** or auto_ptr<T*>.)
*/
/* NB. Some overloads of operator() have an extra dummy parameter int=0.
* This disambiguator serves several purposes:
* - Without it, MSVC++ 6.0 incorrectly regards some overloads as
* specializations of a previous member function template.
* - MSVC++ 6.0/7.0 seem to incorrectly treat some different memfuns
* as if they have the same signature.
* - If remove_const is broken due to lack of PTS, int=0 avoids the
* declaration of memfuns with identical signature.
*/
template<class Value,typename Type,Type (*PtrToFunction)(Value)>
struct const_ref_global_fun_base
{
typedef typename remove_reference<Type>::type result_type;
template<typename ChainedPtr>
#if !defined(BOOST_NO_SFINAE)
typename disable_if<
is_convertible<const ChainedPtr&,Value>,Type>::type
#else
Type
#endif
operator()(const ChainedPtr& x)const
{
return operator()(*x);
}
Type operator()(Value x)const
{
return PtrToFunction(x);
}
Type operator()(
const reference_wrapper<
typename remove_reference<Value>::type>& x)const
{
return operator()(x.get());
}
Type operator()(
const reference_wrapper<
typename remove_const<
typename remove_reference<Value>::type>::type>& x,int=0)const
{
return operator()(x.get());
}
};
template<class Value,typename Type,Type (*PtrToFunction)(Value)>
struct non_const_ref_global_fun_base
{
typedef typename remove_reference<Type>::type result_type;
template<typename ChainedPtr>
#if !defined(BOOST_NO_SFINAE)
typename disable_if<
is_convertible<ChainedPtr&,Value>,Type>::type
#else
Type
#endif
operator()(const ChainedPtr& x)const
{
return operator()(*x);
}
Type operator()(Value x)const
{
return PtrToFunction(x);
}
Type operator()(
const reference_wrapper<
typename remove_reference<Value>::type>& x)const
{
return operator()(x.get());
}
};
template<class Value,typename Type,Type (*PtrToFunction)(Value)>
struct non_ref_global_fun_base
{
typedef typename remove_reference<Type>::type result_type;
template<typename ChainedPtr>
#if !defined(BOOST_NO_SFINAE)
typename disable_if<
is_convertible<const ChainedPtr&,const Value&>,Type>::type
#else
Type
#endif
operator()(const ChainedPtr& x)const
{
return operator()(*x);
}
Type operator()(const Value& x)const
{
return PtrToFunction(x);
}
Type operator()(const reference_wrapper<const Value>& x)const
{
return operator()(x.get());
}
Type operator()(
const reference_wrapper<
typename remove_const<Value>::type>& x,int=0)const
{
return operator()(x.get());
}
};
} /* namespace multi_index::detail */
template<class Value,typename Type,Type (*PtrToFunction)(Value)>
struct global_fun:
mpl::if_c<
is_reference<Value>::value,
typename mpl::if_c<
is_const<typename remove_reference<Value>::type>::value,
detail::const_ref_global_fun_base<Value,Type,PtrToFunction>,
detail::non_const_ref_global_fun_base<Value,Type,PtrToFunction>
>::type,
detail::non_ref_global_fun_base<Value,Type,PtrToFunction>
>::type
{
};
} /* namespace multi_index */
} /* namespace boost */
#endif
+338 -151
View File
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
/* Copyright 2003-2011 Joaquin M Lopez Munoz.
* 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)
@@ -19,13 +19,17 @@
#include <boost/detail/allocator_utilities.hpp>
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/foreach_fwd.hpp>
#include <boost/limits.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/push_front.hpp>
#include <boost/multi_index/detail/access_specifier.hpp>
#include <boost/multi_index/detail/auto_space.hpp>
#include <boost/multi_index/detail/bucket_array.hpp>
#include <boost/multi_index/detail/hash_index_iterator.hpp>
#include <boost/multi_index/detail/index_node_base.hpp>
#include <boost/multi_index/detail/modify_key_adaptor.hpp>
#include <boost/multi_index/detail/safe_ctr_proxy.hpp>
#include <boost/multi_index/detail/safe_mode.hpp>
#include <boost/multi_index/detail/scope_guard.hpp>
#include <boost/multi_index/hashed_index_fwd.hpp>
@@ -67,23 +71,20 @@ template<
typename KeyFromValue,typename Hash,typename Pred,
typename SuperMeta,typename TagList,typename Category
>
class hashed_index:
BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS SuperMeta::type
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
class hashed_index:
BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS SuperMeta::type,
public hashed_index_proxy<
hashed_index_node<SuperMeta::type::node_type>,
bucket_array<SuperMeta::type::final_allocator_type> >
,public safe_ctr_proxy_impl<
hashed_index_iterator<
hashed_index_node<typename SuperMeta::type::node_type>,
bucket_array<typename SuperMeta::type::final_allocator_type> >,
hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category> >
#else
class hashed_index:
BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS SuperMeta::type,
public safe_container<
,public safe_mode::safe_container<
hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category> >
#endif
#else
class hashed_index:
BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS SuperMeta::type
#endif
{
@@ -102,6 +103,10 @@ class hashed_index:
protected:
typedef hashed_index_node<
typename super::node_type> node_type;
private:
typedef typename node_type::impl_type node_impl_type;
typedef typename node_impl_type::pointer node_impl_pointer;
typedef bucket_array<
typename super::final_allocator_type> bucket_array_type;
@@ -125,23 +130,25 @@ public:
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
typedef hashed_index_iterator<
node_type,bucket_array_type> iterator;
typedef hashed_index_iterator<
node_type,bucket_array_type> const_iterator;
typedef safe_mode::safe_iterator<
hashed_index_iterator<
node_type,bucket_array_type>,
safe_ctr_proxy<
hashed_index_iterator<
node_type,bucket_array_type> > > iterator;
#else
typedef hashed_index_iterator<
node_type,bucket_array_type,hashed_index> iterator;
typedef hashed_index_iterator<
node_type,bucket_array_type,hashed_index> const_iterator;
typedef safe_mode::safe_iterator<
hashed_index_iterator<
node_type,bucket_array_type>,
hashed_index> iterator;
#endif
#else
typedef hashed_index_iterator<
node_type,bucket_array_type> iterator;
typedef hashed_index_iterator<
node_type,bucket_array_type> const_iterator;
#endif
typedef iterator const_iterator;
typedef iterator local_iterator;
typedef const_iterator const_local_iterator;
typedef TagList tag_list;
@@ -170,10 +177,13 @@ protected:
private:
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
typedef hashed_index_proxy<
node_type,bucket_array_type> safe_super;
typedef safe_ctr_proxy_impl<
hashed_index_iterator<
node_type,bucket_array_type>,
hashed_index> safe_super;
#else
typedef safe_container<hashed_index> safe_super;
typedef safe_mode::safe_container<
hashed_index> safe_super;
#endif
#endif
@@ -223,6 +233,19 @@ public:
iterator end(){return make_iterator(header());}
const_iterator end()const{return make_iterator(header());}
const_iterator cbegin()const{return begin();}
const_iterator cend()const{return end();}
iterator iterator_to(const value_type& x)
{
return make_iterator(node_from_value<node_type>(&x));
}
const_iterator iterator_to(const value_type& x)const
{
return make_iterator(node_from_value<node_type>(&x));
}
/* modifiers */
std::pair<iterator,bool> insert(value_param_type x)
@@ -250,42 +273,45 @@ public:
for(;first!=last;++first)hint=insert(hint,*first);
}
void erase(iterator position)
iterator erase(iterator position)
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
/* MSVC++ 6.0 optimizer on safe mode code chokes if this
* this is not added. Left it for all compilers as it does no
* harm.
*/
position.detach();
#endif
this->final_erase_(static_cast<final_node_type*>(position.get_node()));
this->final_erase_(static_cast<final_node_type*>(position++.get_node()));
return position;
}
size_type erase(key_param_type x)
size_type erase(key_param_type k)
{
BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
size_type s=0;
iterator it=find(x); /* caveat: relies on find() returning */
if(it!=end()){ /* the first element */
do{
erase(it++);
++s;
}while(it!=end()&&eq(x,key(*it)));
size_type s=0;
std::size_t buc=buckets.position(hash(k));
node_impl_pointer x=buckets.at(buc);
node_impl_pointer y=x->next();
while(y!=x){
if(eq(k,key(node_type::from_impl(y)->value()))){
bool b;
do{
node_impl_pointer z=y->next();
b=z!=x&&eq(
key(node_type::from_impl(y)->value()),
key(node_type::from_impl(z)->value()));
this->final_erase_(
static_cast<final_node_type*>(node_type::from_impl(y)));
y=z;
++s;
}while(b);
break;
}
y=y->next();
}
return s;
}
void erase(iterator first,iterator last)
iterator erase(iterator first,iterator last)
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(first);
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(last);
@@ -294,8 +320,9 @@ public:
BOOST_MULTI_INDEX_CHECK_VALID_RANGE(first,last);
BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
while(first!=last){
erase(first++);
first=erase(first);
}
return first;
}
bool replace(iterator position,value_param_type x)
@@ -329,6 +356,27 @@ public:
mod,static_cast<final_node_type*>(position.get_node()));
}
template<typename Modifier,typename Rollback>
bool modify(iterator position,Modifier mod,Rollback back)
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
/* MSVC++ 6.0 optimizer on safe mode code chokes if this
* this is not added. Left it for all compilers as it does no
* harm.
*/
position.detach();
#endif
return this->final_modify_(
mod,back,static_cast<final_node_type*>(position.get_node()));
}
template<typename Modifier>
bool modify_key(iterator position,Modifier mod)
{
@@ -340,6 +388,19 @@ public:
position,modify_key_adaptor<Modifier,value_type,KeyFromValue>(mod,key));
}
template<typename Modifier,typename Rollback>
bool modify_key(iterator position,Modifier mod,Rollback back)
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
return modify(
position,
modify_key_adaptor<Modifier,value_type,KeyFromValue>(mod,key),
modify_key_adaptor<Rollback,value_type,KeyFromValue>(back,key));
}
void clear()
{
BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
@@ -377,11 +438,11 @@ public:
const CompatibleKey& k,
const CompatibleHash& hash,const CompatiblePred& eq)const
{
std::size_t buc=buckets.position(hash(k));
hashed_index_node_impl* x=buckets.at(buc);
hashed_index_node_impl* y=x->next();
std::size_t buc=buckets.position(hash(k));
node_impl_pointer x=buckets.at(buc);
node_impl_pointer y=x->next();
while(y!=x){
if(eq(k,key(node_type::from_impl(y)->value))){
if(eq(k,key(node_type::from_impl(y)->value()))){
return make_iterator(node_type::from_impl(y));
}
y=y->next();
@@ -402,16 +463,16 @@ public:
const CompatibleKey& k,
const CompatibleHash& hash,const CompatiblePred& eq)const
{
size_type res=0;
std::size_t buc=buckets.position(hash(k));
hashed_index_node_impl* x=buckets.at(buc);
hashed_index_node_impl* y=x->next();
size_type res=0;
std::size_t buc=buckets.position(hash(k));
node_impl_pointer x=buckets.at(buc);
node_impl_pointer y=x->next();
while(y!=x){
if(eq(k,key(node_type::from_impl(y)->value))){
if(eq(k,key(node_type::from_impl(y)->value()))){
do{
++res;
y=y->next();
}while(y!=x&&eq(k,key(node_type::from_impl(y)->value)));
}while(y!=x&&eq(k,key(node_type::from_impl(y)->value())));
break;
}
y=y->next();
@@ -432,15 +493,15 @@ public:
const CompatibleKey& k,
const CompatibleHash& hash,const CompatiblePred& eq)const
{
std::size_t buc=buckets.position(hash(k));
hashed_index_node_impl* x=buckets.at(buc);
hashed_index_node_impl* y=x->next();
std::size_t buc=buckets.position(hash(k));
node_impl_pointer x=buckets.at(buc);
node_impl_pointer y=x->next();
while(y!=x){
if(eq(k,key(node_type::from_impl(y)->value))){
hashed_index_node_impl* y0=y;
if(eq(k,key(node_type::from_impl(y)->value()))){
node_impl_pointer y0=y;
do{
y=y->next();
}while(y!=x&&eq(k,key(node_type::from_impl(y)->value)));
}while(y!=x&&eq(k,key(node_type::from_impl(y)->value())));
if(y==x){
do{
++y;
@@ -463,9 +524,9 @@ public:
size_type bucket_size(size_type n)const
{
size_type res=0;
hashed_index_node_impl* x=buckets.at(n);
hashed_index_node_impl* y=x->next();
size_type res=0;
node_impl_pointer x=buckets.at(n);
node_impl_pointer y=x->next();
while(y!=x){
++res;
y=y->next();
@@ -485,8 +546,8 @@ public:
const_local_iterator begin(size_type n)const
{
hashed_index_node_impl* x=buckets.at(n);
hashed_index_node_impl* y=x->next();
node_impl_pointer x=buckets.at(n);
node_impl_pointer y=x->next();
if(y==x)return end();
return make_iterator(node_type::from_impl(y));
}
@@ -498,7 +559,7 @@ public:
const_local_iterator end(size_type n)const
{
hashed_index_node_impl* x=buckets.at(n);
node_impl_pointer x=buckets.at(n);
if(x==x->next())return end();
do{
++x;
@@ -506,6 +567,19 @@ public:
return make_iterator(node_type::from_impl(x->next()));
}
const_local_iterator cbegin(size_type n)const{return begin(n);}
const_local_iterator cend(size_type n)const{return end(n);}
local_iterator local_iterator_to(const value_type& x)
{
return make_iterator(node_from_value<node_type>(&x));
}
const_local_iterator local_iterator_to(const value_type& x)const
{
return make_iterator(node_from_value<node_type>(&x));
}
/* hash policy */
float load_factor()const{return static_cast<float>(size())/bucket_count();}
@@ -529,17 +603,11 @@ public:
BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
hashed_index(const ctor_args_list& args_list,const allocator_type& al):
super(args_list.get_tail(),al),
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)&&\
BOOST_WORKAROUND(BOOST_MSVC,<1300)
safe_super(final_header(),buckets),
#endif
key(tuples::get<1>(args_list.get_head())),
hash(tuples::get<2>(args_list.get_head())),
eq(tuples::get<3>(args_list.get_head())),
buckets(al,header()->impl(),tuples::get<0>(args_list.get_head())),
mlf(1.0),
mlf(1.0f),
first_bucket(buckets.size())
{
calculate_max_load();
@@ -549,9 +617,8 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x):
super(x),
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)&&\
BOOST_WORKAROUND(BOOST_MSVC,<1300)
safe_super(final_header(),buckets),
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
safe_super(),
#endif
key(x.key),
@@ -575,25 +642,25 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
iterator make_iterator(node_type* node)
{
return iterator(node,buckets,this);
return iterator(node,&buckets,this);
}
const_iterator make_iterator(node_type* node)const
{
return const_iterator(
node,
const_cast<bucket_array_type&>(buckets),
&const_cast<bucket_array_type&>(buckets),
const_cast<hashed_index*>(this));
}
#else
iterator make_iterator(node_type* node)
{
return iterator(node,buckets);
return iterator(node,&buckets);
}
const_iterator make_iterator(node_type* node)const
{
return const_iterator(node,const_cast<bucket_array_type&>(buckets));
return const_iterator(node,&const_cast<bucket_array_type&>(buckets));
}
#endif
@@ -601,13 +668,13 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,
const copy_map_type& map)
{
for(hashed_index_node_impl* begin_org=x.buckets.begin(),
* begin_cpy=buckets.begin(),
* end_org=x.buckets.end();
for(node_impl_pointer begin_org=x.buckets.begin(),
begin_cpy=buckets.begin(),
end_org=x.buckets.end();
begin_org!=end_org;++begin_org,++begin_cpy){
hashed_index_node_impl* next_org=begin_org->next();
hashed_index_node_impl* cpy=begin_cpy;
node_impl_pointer next_org=begin_org->next();
node_impl_pointer cpy=begin_cpy;
while(next_org!=begin_org){
cpy->next()=
static_cast<node_type*>(
@@ -627,8 +694,8 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
{
reserve(size()+1);
std::size_t buc=find_bucket(v);
hashed_index_node_impl* pos=buckets.at(buc);
std::size_t buc=find_bucket(v);
node_impl_pointer pos=buckets.at(buc);
if(!link_point(v,pos,Category()))return node_type::from_impl(pos);
node_type* res=static_cast<node_type*>(super::insert_(v,x));
@@ -643,8 +710,8 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
{
reserve(size()+1);
std::size_t buc=find_bucket(v);
hashed_index_node_impl* pos=buckets.at(buc);
std::size_t buc=find_bucket(v);
node_impl_pointer pos=buckets.at(buc);
if(!link_point(v,pos,Category()))return node_type::from_impl(pos);
node_type* res=static_cast<node_type*>(super::insert_(v,position,x));
@@ -668,11 +735,11 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
void delete_all_nodes_()
{
for(hashed_index_node_impl* x=buckets.begin(),*x_end=buckets.end();
for(node_impl_pointer x=buckets.begin(),x_end=buckets.end();
x!=x_end;++x){
hashed_index_node_impl* y=x->next();
node_impl_pointer y=x->next();
while(y!=x){
hashed_index_node_impl* z=y->next();
node_impl_pointer z=y->next();
this->final_delete_node_(
static_cast<final_node_type*>(node_type::from_impl(y)));
y=z;
@@ -687,7 +754,7 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
first_bucket=buckets.size();
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
safe_super::detach_all_iterators();
safe_super::detach_dereferenceable_iterators();
#endif
}
@@ -711,16 +778,16 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
bool replace_(value_param_type v,node_type* x)
{
if(eq(key(v),key(x->value))){
if(eq(key(v),key(x->value()))){
return super::replace_(v,x);
}
hashed_index_node_impl* y=prev(x);
node_impl_pointer y=prev(x);
unlink_next(y);
BOOST_TRY{
std::size_t buc=find_bucket(v);
hashed_index_node_impl* pos=buckets.at(buc);
std::size_t buc=find_bucket(v);
node_impl_pointer pos=buckets.at(buc);
if(link_point(v,pos,Category())&&super::replace_(v,x)){
link(x,pos);
if(first_bucket>buc){
@@ -743,28 +810,65 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
bool modify_(node_type* x)
{
unlink(x);
std::size_t buc;
bool b;
BOOST_TRY{
buc=find_bucket(x->value());
b=in_place(x->impl(),key(x->value()),buc,Category());
}
BOOST_CATCH(...){
erase_(x);
BOOST_RETHROW;
}
BOOST_CATCH_END
if(!b){
unlink(x);
BOOST_TRY{
node_impl_pointer pos=buckets.at(buc);
if(!link_point(x->value(),pos,Category())){
first_bucket=buckets.first_nonempty(first_bucket);
super::erase_(x);
std::size_t buc;
hashed_index_node_impl* pos;
BOOST_TRY
{
buc=find_bucket(x->value);
pos=buckets.at(buc);
if(!link_point(x->value,pos,Category())){
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
detach_iterators(x);
#endif
return false;
}
link(x,pos);
if(first_bucket>buc){
first_bucket=buc;
}
else if(first_bucket<buc){
first_bucket=buckets.first_nonempty(first_bucket);
}
}
BOOST_CATCH(...){
first_bucket=buckets.first_nonempty(first_bucket);
super::erase_(x);
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
detach_iterators(x);
#endif
BOOST_RETHROW;
}
BOOST_CATCH_END
}
BOOST_TRY{
if(!super::modify_(x)){
unlink(x);
first_bucket=buckets.first_nonempty(first_bucket);
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
detach_iterators(x);
#endif
return false;
}
else return true;
}
BOOST_CATCH(...){
unlink(x);
first_bucket=buckets.first_nonempty(first_bucket);
super::erase_(x);
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
detach_iterators(x);
@@ -773,9 +877,21 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
BOOST_RETHROW;
}
BOOST_CATCH_END
}
bool modify_rollback_(node_type* x)
{
std::size_t buc=find_bucket(x->value());
if(in_place(x->impl(),key(x->value()),buc,Category())){
return super::modify_rollback_(x);
}
node_impl_pointer y=prev(x);
unlink_next(y);
BOOST_TRY{
if(super::modify_(x)){
node_impl_pointer pos=buckets.at(buc);
if(link_point(x->value(),pos,Category())&&super::modify_rollback_(x)){
link(x,pos);
if(first_bucket>buc){
first_bucket=buc;
@@ -785,21 +901,11 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
}
return true;
}
first_bucket=buckets.first_nonempty(first_bucket);
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
detach_iterators(x);
#endif
link(x,y);
return false;
}
BOOST_CATCH(...){
first_bucket=buckets.first_nonempty(first_bucket);
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
detach_iterators(x);
#endif
link(x,y);
BOOST_RETHROW;
}
BOOST_CATCH_END
@@ -871,11 +977,11 @@ private:
}
bool link_point(
value_param_type v,hashed_index_node_impl*& pos,hashed_unique_tag)
value_param_type v,node_impl_pointer& pos,hashed_unique_tag)
{
hashed_index_node_impl* x=pos->next();
node_impl_pointer x=pos->next();
while(x!=pos){
if(eq(key(v),key(node_type::from_impl(x)->value))){
if(eq(key(v),key(node_type::from_impl(x)->value()))){
pos=x;
return false;
}
@@ -885,12 +991,12 @@ private:
}
bool link_point(
value_param_type v,hashed_index_node_impl*& pos,hashed_non_unique_tag)
value_param_type v,node_impl_pointer& pos,hashed_non_unique_tag)
{
hashed_index_node_impl* prev=pos;
hashed_index_node_impl* x=pos->next();
node_impl_pointer prev=pos;
node_impl_pointer x=pos->next();
while(x!=pos){
if(eq(key(v),key(node_type::from_impl(x)->value))){
if(eq(key(v),key(node_type::from_impl(x)->value()))){
pos=prev;
return true;
}
@@ -900,29 +1006,34 @@ private:
return true;
}
void link(node_type* x,hashed_index_node_impl* pos)
static void link(node_type* x,node_impl_pointer pos)
{
hashed_index_node_impl::link(x->impl(),pos);
node_impl_type::link(x->impl(),pos);
};
void link(hashed_index_node_impl* x,hashed_index_node_impl* pos)
static void link(node_impl_pointer x,node_impl_pointer pos)
{
hashed_index_node_impl::link(x,pos);
node_impl_type::link(x,pos);
};
void unlink(node_type* x)
static void unlink(node_type* x)
{
hashed_index_node_impl::unlink(x->impl());
node_impl_type::unlink(x->impl());
};
static hashed_index_node_impl* prev(node_type* x)
static node_impl_pointer prev(node_type* x)
{
return hashed_index_node_impl::prev(x->impl());
return node_impl_type::prev(x->impl());
}
static void unlink_next(hashed_index_node_impl* x)
static node_impl_pointer prev_from(node_type* x,node_impl_pointer y)
{
hashed_index_node_impl::unlink_next(x);
return node_impl_type::prev_from(x->impl(),y);
}
static void unlink_next(node_impl_pointer x)
{
node_impl_type::unlink_next(x);
}
void calculate_max_load()
@@ -948,12 +1059,12 @@ private:
auto_space<std::size_t,allocator_type> hashes(get_allocator(),size());
std::size_t i=0;
hashed_index_node_impl* x=buckets.begin();
hashed_index_node_impl* x_end=buckets.end();
node_impl_pointer x=buckets.begin();
node_impl_pointer x_end=buckets.end();
for(;x!=x_end;++x){
hashed_index_node_impl* y=x->next();
node_impl_pointer y=x->next();
while(y!=x){
hashes.data()[i++]=hash(key(node_type::from_impl(y)->value));
hashes.data()[i++]=hash(key(node_type::from_impl(y)->value()));
y=y->next();
}
}
@@ -961,11 +1072,11 @@ private:
i=0;
x=buckets.begin();
for(;x!=x_end;++x){
hashed_index_node_impl* y=x->next();
node_impl_pointer y=x->next();
while(y!=x){
hashed_index_node_impl* z=y->next();
std::size_t buc1=buckets1.position(hashes.data()[i++]);
hashed_index_node_impl* x1=buckets1.at(buc1);
node_impl_pointer z=y->next();
std::size_t buc1=buckets1.position(hashes.data()[i++]);
node_impl_pointer x1=buckets1.at(buc1);
link(y,x1);
y=z;
}
@@ -976,6 +1087,68 @@ private:
first_bucket=buckets.first_nonempty(0);
}
bool in_place(
node_impl_pointer x,key_param_type k,std::size_t buc,
hashed_unique_tag)const
{
std::less_equal<node_impl_pointer> leq;
node_impl_pointer bbegin=buckets.begin();
node_impl_pointer bend=buckets.end();
node_impl_pointer pbuc=x->next();
while(!leq(bbegin,pbuc)||!leq(pbuc,bend))pbuc=pbuc->next();
if(buc!=static_cast<std::size_t>(pbuc-bbegin))return false;
node_impl_pointer y=x;
while(y->next()!=x){
y=y->next();
if(y==pbuc)continue;
if(eq(k,key(node_type::from_impl(y)->value())))return false;
}
return true;
}
bool in_place(
node_impl_pointer x,key_param_type k,std::size_t buc,
hashed_non_unique_tag)const
{
std::less_equal<node_impl_pointer> leq;
node_impl_pointer bbegin=buckets.begin();
node_impl_pointer bend=buckets.end();
node_impl_pointer pbuc=x->next();
while(!leq(bbegin,pbuc)||!leq(pbuc,bend))pbuc=pbuc->next();
if(buc!=static_cast<std::size_t>(pbuc-bbegin))return false;
node_impl_pointer y=x->next();
if(y!=pbuc){
if(eq(k,key(node_type::from_impl(y)->value()))){
/* adjacent to equivalent element -> in place */
return true;
}
else{
y=y->next();
while(y!=pbuc){
if(eq(k,key(node_type::from_impl(y)->value())))return false;
y=y->next();
}
}
}
while(y->next()!=x){
y=y->next();
if(eq(k,key(node_type::from_impl(y)->value()))){
while(y->next()!=x){
y=y->next();
if(!eq(k,key(node_type::from_impl(y)->value())))return false;
}
/* after a group of equivalent elements --> in place */
return true;
}
}
return true;
}
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
void detach_iterators(node_type* x)
{
@@ -1013,7 +1186,7 @@ void swap(
} /* namespace multi_index::detail */
/* sequenced index specifiers */
/* hashed index specifiers */
template<typename Arg1,typename Arg2,typename Arg3,typename Arg4>
struct hashed_unique
@@ -1069,6 +1242,20 @@ struct hashed_non_unique
} /* namespace boost */
/* Boost.Foreach compatibility */
template<
typename KeyFromValue,typename Hash,typename Pred,
typename SuperMeta,typename TagList,typename Category
>
inline boost::mpl::true_* boost_foreach_is_noncopyable(
boost::multi_index::detail::hashed_index<
KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>*&,
boost::foreach::tag)
{
return 0;
}
#undef BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT
#endif

Some files were not shown because too many files have changed in this diff Show More