Compare commits

...

228 Commits

Author SHA1 Message Date
Ronald Garcia 6c810e19fc Created a branch from trunk
[SVN r38959]
2007-08-26 05:34:35 +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 &'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
Joaquín M. López Muñoz 60c428b518 small correction
[SVN r30262]
2005-07-27 07:43:07 +00:00
Joaquín M. López Muñoz dc0aa687ce updated according to latest regression tests results
[SVN r30244]
2005-07-26 09:20:43 +00:00
Joaquín M. López Muñoz d1a5e7d40c added GCC 4.0.1
[SVN r30031]
2005-07-13 06:10:38 +00:00
Joaquín M. López Muñoz 1da460528a updated acknowledgements list
[SVN r29985]
2005-07-11 13:52:19 +00:00
Joaquín M. López Muñoz b7984c6c83 updated according to latest regression tests results
[SVN r29984]
2005-07-11 13:29:26 +00:00
Joaquín M. López Muñoz 5eb2679f11 rewritten previous tweak so as to work with multitoolset bjam invocations (kudos to Markus Schöpflin)
[SVN r29947]
2005-07-08 16:14:55 +00:00
Joaquín M. López Muñoz 3ed63ed785 added entry on random access indices
[SVN r29894]
2005-07-05 06:25:44 +00:00
Joaquín M. López Muñoz 4027620ec8 updated according to latest regression tests results
[SVN r29608]
2005-06-16 09:16:25 +00:00
Joaquín M. López Muñoz 1d844cd539 suppressed warning in vacpp 6.0
[SVN r29554]
2005-06-13 16:07:34 +00:00
Joaquín M. López Muñoz d4ff4dab15 typo
[SVN r29457]
2005-06-07 06:03:13 +00:00
Joaquín M. López Muñoz 9684b049a4 added link to TR1 doc; typo
[SVN r29456]
2005-06-07 06:01:08 +00:00
Joaquín M. López Muñoz c6ef47da18 updated according to latest regression tests results; suppressed a reference to the release regression tests page
[SVN r29404]
2005-06-03 13:13:36 +00:00
Joaquín M. López Muñoz 8ae46eb0fd made boost::hash valid for composite_key_results when there's no template partial specialization
[SVN r29336]
2005-06-01 13:19:46 +00:00
Joaquín M. López Muñoz 5d4107a5fa "template class" -> "class template"
[SVN r29278]
2005-05-30 06:14:23 +00:00
Joaquín M. López Muñoz 954004189a made snippet conformant to serialization stricter rules on saving and constness
[SVN r29245]
2005-05-27 15:08:44 +00:00
Joaquín M. López Muñoz 3546d0863c disabled invariant-checking in GCC 4.0 20041026 (Apple build 4061) due to a compiler bug affecting scope guards
[SVN r29199]
2005-05-26 05:58:51 +00:00
Joaquín M. López Muñoz f1176d462b minor reformatting
[SVN r29055]
2005-05-19 06:00:34 +00:00
Joaquín M. López Muñoz c943abed6c typo
[SVN r29025]
2005-05-18 05:59:46 +00:00
Markus Schöpflin c7da511d5e Don't use debug symbols for all toolsets matching "gcc*" on Tru64.
[SVN r28761]
2005-05-09 09:43:28 +00:00
Eric Niebler 413e30393a min/max fixes
[SVN r28750]
2005-05-09 01:00:41 +00:00
Joaquín M. López Muñoz be06dec001 turned debug symbols off for GCC/Tru64
[SVN r28690]
2005-05-06 07:51:10 +00:00
Joaquín M. López Muñoz af5b59059f silly bug
[SVN r28466]
2005-04-25 06:07:01 +00:00
Joaquín M. López Muñoz bdc4558ca6 protected against serialization tracking due to spurious address sharing; adapted to serialization stricter rules on saving and constness
[SVN r28406]
2005-04-22 08:10:41 +00:00
Joaquín M. López Muñoz 6e33d0ef2a adapted to serialization stricter rules on saving and constness
[SVN r28405]
2005-04-22 08:07:47 +00:00
Joaquín M. López Muñoz 94894da751 copypaste error
[SVN r28377]
2005-04-21 09:22:51 +00:00
Joaquín M. López Muñoz d8ad2dd48b included a smaller part of Boost.Hash
[SVN r28367]
2005-04-21 07:08:33 +00:00
Rene Rivera 344947128d Fix bjam error when Spirit is not found, which is required for use of Boost.Serialization.
[SVN r28347]
2005-04-20 22:12:53 +00:00
Joaquín M. López Muñoz 699b887e18 added links to Boost.Hash docs
[SVN r28342]
2005-04-20 15:29:04 +00:00
Joaquín M. López Muñoz 10a8ae1037 used serialization reset_object_address facility
[SVN r28332]
2005-04-20 06:19:12 +00:00
Vladimir Prus a43abdfe5f Sync with V1 Jamfile
[SVN r28243]
2005-04-14 11:51:29 +00:00
Joaquín M. López Muñoz ee6ceb1c60 typo
[SVN r28057]
2005-04-08 05:57:23 +00:00
Joaquín M. López Muñoz 075c6586e9 typo
[SVN r27899]
2005-03-31 12:55:06 +00:00
Joaquín M. López Muñoz 4e0e8eed9a silly bug
[SVN r27862]
2005-03-29 10:50:36 +00:00
Joaquín M. López Muñoz 7d5451215d added test_hash_ops and test_observers
[SVN r27859]
2005-03-28 13:04:31 +00:00
Joaquín M. López Muñoz d5835caad6 changes to cover hashed indices
[SVN r27858]
2005-03-28 13:03:52 +00:00
Joaquín M. López Muñoz a3d458229e added test_hash_ops and test_observers
[SVN r27857]
2005-03-28 12:58:33 +00:00
Joaquín M. López Muñoz 66db46fd1a replaced ordered indices with hashed ones
[SVN r27856]
2005-03-28 12:57:05 +00:00
Joaquín M. López Muñoz 64df029256 sync comments with docs
[SVN r27855]
2005-03-28 12:55:48 +00:00
Joaquín M. López Muñoz 379bf82caf sync comment with docs
[SVN r27854]
2005-03-28 12:53:28 +00:00
Joaquín M. López Muñoz 82be2525e6 added new example; detabbing
[SVN r27853]
2005-03-28 12:52:44 +00:00
Joaquín M. López Muñoz 0ef0156ba8 mention hashed indices; typo
[SVN r27852]
2005-03-28 12:51:32 +00:00
Joaquín M. López Muñoz 1a705d22f5 added test_hash_ops and test_observers
[SVN r27851]
2005-03-28 12:48:49 +00:00
Joaquín M. López Muñoz 56f36f9099 updated
[SVN r27850]
2005-03-28 12:47:15 +00:00
Joaquín M. López Muñoz 22785eb7f3 changed navigation buttons as per hashed indices
[SVN r27849]
2005-03-28 12:46:18 +00:00
Joaquín M. López Muñoz bbd8bf4c68 typos
[SVN r27848]
2005-03-28 12:45:01 +00:00
Joaquín M. López Muñoz 310f6e6c4b changed bits on MPL sequence concepts; typo
[SVN r27847]
2005-03-28 12:43:41 +00:00
Joaquín M. López Muñoz 6fe87cd12d added hashing facilities of composite keys; some refactoring
[SVN r27846]
2005-03-28 12:42:39 +00:00
Joaquín M. López Muñoz 99f5892deb added hashed indices; changed bits on MPL sequence concepts; typos
[SVN r27845]
2005-03-28 12:41:24 +00:00
Joaquín M. López Muñoz 8f6461cdba added hashed indices
[SVN r27844]
2005-03-28 12:40:12 +00:00
Joaquín M. López Muñoz 3e7c3879b4 added a paragraph on typical uses of the lib; other minor changes
[SVN r27843]
2005-03-28 12:39:32 +00:00
Joaquín M. López Muñoz 4208367e2b removed the part on hashed indices (already implemented)
[SVN r27842]
2005-03-28 12:38:22 +00:00
Joaquín M. López Muñoz 40af222972 added example of use of hashed indices; expanded on the serialziation example
[SVN r27841]
2005-03-28 12:37:27 +00:00
Joaquín M. López Muñoz 006a9a479f added a portability techniques section with stuff from the advanced topics page and some new material; several updates to the info on compiler specifics
[SVN r27840]
2005-03-28 12:36:05 +00:00
Joaquín M. López Muñoz dec8cc927c added section on hashed indices; moved some parts to the complier specifics page; other minor changes
[SVN r27839]
2005-03-28 12:34:15 +00:00
Joaquín M. López Muñoz 1a3b9b55f5 added acknowledgements for 1.33 release
[SVN r27838]
2005-03-28 12:32:26 +00:00
Joaquín M. López Muñoz 20d9cc1b56 added #pragma once
[SVN r27837]
2005-03-28 12:31:18 +00:00
Joaquín M. López Muñoz 3c21273b61 added internal machinery for faster cleanup; removed BOOST_MULTI_INDEX_NO_MEMBER_TEMPLATE_FRIENDS; added #pragma once
[SVN r27836]
2005-03-28 12:30:11 +00:00
Joaquín M. López Muñoz 075581b274 changed the index derivation machinery to shorten symbol names; added #pragma once
[SVN r27835]
2005-03-28 12:28:30 +00:00
Joaquín M. López Muñoz 109bbf6d11 changed the index derivation machinery to shorten symbol names; added internal machinery for faster cleanup; added #pragma once
[SVN r27834]
2005-03-28 12:27:36 +00:00
Joaquín M. López Muñoz 4809e1efdd changed the index derivation machinery to shorten symbol names; use mpl::na instead of null_arg; added #pragma once
[SVN r27833]
2005-03-28 12:26:35 +00:00
Joaquín M. López Muñoz 5ebbd58c7e removed checks additional to BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS; added #pragma once
[SVN r27832]
2005-03-28 12:23:11 +00:00
Joaquín M. López Muñoz bf50b5d7ad added safe_container_base::detach_all_iterators; removed BOOST_MULTI_INDEX_NO_MEMBER_TEMPLATE_FRIENDS; added #pragma once
[SVN r27831]
2005-03-28 12:22:05 +00:00
Joaquín M. López Muñoz bcf153b93f use mpl::na instead of null_arg; added #pragma once
[SVN r27830]
2005-03-28 12:20:29 +00:00
Joaquín M. López Muñoz da11b1c08d renamed unneeded include; added #pragma once
[SVN r27829]
2005-03-28 12:18:33 +00:00
Joaquín M. López Muñoz 40bd426116 renamed some serialization nvps; added #pragma once
[SVN r27828]
2005-03-28 12:16:04 +00:00
Joaquín M. López Muñoz 226155054d added internal machinery for faster cleanup; added #pragma once
[SVN r27827]
2005-03-28 12:15:13 +00:00
Joaquín M. López Muñoz 88c4eb4fb8 changed the index derivation machinery to shorten symbol names; added #pragma once
[SVN r27826]
2005-03-28 12:13:54 +00:00
Joaquín M. López Muñoz 4c6fd92cde added some missing includes; added #pragma once
[SVN r27825]
2005-03-28 12:12:22 +00:00
Joaquín M. López Muñoz 8122d38e4e removed BOOST_MULTI_INDEX_NO_MEMBER_TEMPLATE_FRIENDS; added #pragma once
[SVN r27824]
2005-03-28 12:11:29 +00:00
Joaquín M. López Muñoz c28c2b60ab added hashing facilities; some refactoring; added #pragma once
[SVN r27823]
2005-03-28 12:10:25 +00:00
Joaquín M. López Muñoz 4fe662c18e added #pragma once
[SVN r27822]
2005-03-28 11:15:43 +00:00
Joaquín M. López Muñoz 47053672a2 new test
[SVN r27821]
2005-03-28 11:03:08 +00:00
Joaquín M. López Muñoz f49ca98c71 added hashed indices
[SVN r27820]
2005-03-28 11:03:07 +00:00
Joaquín M. López Muñoz c71f118114 fixed trivial error
[SVN r26889]
2005-01-28 07:37:30 +00:00
Joaquín M. López Muñoz 07a48205fa small correction
[SVN r26830]
2005-01-24 07:07:19 +00:00
Joaquín M. López Muñoz 7d0c5e0f9a corrected fwd declarations with old name for detail::ordered_index
[SVN r26725]
2005-01-18 17:09:23 +00:00
Joaquín M. López Muñoz 9b2d916b6c duplicate #include
[SVN r26724]
2005-01-18 17:07:12 +00:00
Joaquín M. López Muñoz b059b7de06 corrected search functions to return iterators instead of const_iterators
[SVN r26715]
2005-01-17 09:00:59 +00:00
Joaquín M. López Muñoz 435a1ac087 elminated some serialization make_nvp's so as to alleviate MSVC symbol stress
[SVN r26698]
2005-01-14 12:30:46 +00:00
Joaquín M. López Muñoz 40b140b279 changed a serialization nvp tag
[SVN r26697]
2005-01-14 12:27:32 +00:00
Joaquín M. López Muñoz 980b11f00e added iterator serialization
[SVN r26690]
2005-01-13 14:00:55 +00:00
Joaquín M. López Muñoz c3f9fef32d introduced unchecked iterators for serialization purposes
[SVN r26689]
2005-01-13 13:53:29 +00:00
Joaquín M. López Muñoz c6e23f0b81 grammar error
[SVN r26663]
2005-01-10 11:21:38 +00:00
Joaquín M. López Muñoz 840d57815b fixed issues with serialization free functions and ADL
[SVN r26553]
2004-12-20 14:50:46 +00:00
Joaquín M. López Muñoz 8b3416b6ae stray const made an overload invisible to CW
[SVN r26537]
2004-12-17 07:22:15 +00:00
Joaquín M. López Muñoz c27c830958 typo
[SVN r26525]
2004-12-16 12:06:32 +00:00
Joaquín M. López Muñoz d044f6e769 serialization needs CW locale support
[SVN r26524]
2004-12-16 09:15:03 +00:00
Joaquín M. López Muñoz 0b8f770735 stray const made an overload invisible to GCC 3.4.2
[SVN r26523]
2004-12-16 09:11:07 +00:00
Joaquín M. López Muñoz 4137d4075d qualified some non-dependant calls
[SVN r26511]
2004-12-15 11:15:06 +00:00
Joaquín M. López Muñoz c94964d198 added release notes
[SVN r26505]
2004-12-14 18:34:55 +00:00
Joaquín M. López Muñoz ac2fad60b1 added serialization support
[SVN r26504]
2004-12-14 18:34:33 +00:00
Joaquín M. López Muñoz f595384267 added release notes
[SVN r26503]
2004-12-14 18:29:12 +00:00
Joaquín M. López Muñoz 14b7e52dbd improved tag to produce shorter symbol names; added serialization support
[SVN r26502]
2004-12-14 18:28:18 +00:00
Joaquín M. López Muñoz 1869a8827d added serialization support
[SVN r26501]
2004-12-14 18:24:21 +00:00
Joaquín M. López Muñoz b4ba77f9d4 improved to produce shorter symbol names
[SVN r26500]
2004-12-14 18:17:48 +00:00
Joaquín M. López Muñoz f572badb27 typo
[SVN r26312]
2004-11-26 08:49:57 +00:00
Joaquín M. López Muñoz a1a878a917 changed an erroneous check in_place; also, refactored so that it can be used by replace_
[SVN r26311]
2004-11-26 08:48:13 +00:00
Joaquín M. López Muñoz 12abc914bc changed a class which need not be templatized
[SVN r26310]
2004-11-26 08:44:35 +00:00
Joaquín M. López Muñoz 2408f508c3 trivial correction
[SVN r26309]
2004-11-26 08:43:10 +00:00
Joaquín M. López Muñoz d1214cabdd merged changes related to new MPL docs from version 1.32.0
[SVN r26282]
2004-11-24 16:50:22 +00:00
Joaquín M. López Muñoz 8fd3e2fd3f fixed bug in ordered_index_node_impl::restore
[SVN r26180]
2004-11-11 11:53:26 +00:00
152 changed files with 17654 additions and 4183 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 ;
+53 -7
View File
@@ -5,14 +5,17 @@
<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>
<h1><img src="../../../boost.png" alt="boost.png (6897 bytes)" align=
"middle" width="277" height="86">Boost.MultiIndex Acknowledgements</h1>
<div class="prev_link"><a href="future_work.html"><img src="prev.gif" alt="future work" border="0"><br>
Future work
<div class="prev_link"><a href="release_notes.html"><img src="prev.gif" alt="release notes" border="0"><br>
Release notes
</a></div>
<div class="up_link"><a href="index.html"><img src="up.gif" alt="index" border="0"><br>
Index
@@ -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
@@ -102,10 +105,53 @@ lived too fast, died too young.
<br style="clear:all;">
</p>
<h2><a name="boost_1_33">Boost 1.33 release</a></h2>
<p>
Many thanks again to Pavel Vo&#382;en&iacute;lek, who has carefully reviewed
the new material and suggested many improvements. The design of hashed indices
has benefited from discussions with several Boost members, most notably
Howard Hinnant and Daniel James. Daniel has also contributed
<a href="../../functional/hash/index.html">Boost.Hash</a>
to the community: hashed indices depend on this library as
their default hash function provider. Robert Ramey's
<a href="../../serialization/index.html">Boost Serialization Library</a>
provides the very solid framework upon which Boost.MultiIndex serialization
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>
<hr>
<div class="prev_link"><a href="future_work.html"><img src="prev.gif" alt="future work" border="0"><br>
Future work
<div class="prev_link"><a href="release_notes.html"><img src="prev.gif" alt="release notes" border="0"><br>
Release notes
</a></div>
<div class="up_link"><a href="index.html"><img src="up.gif" alt="index" border="0"><br>
Index
@@ -115,9 +161,9 @@ Index
<br>
<p>Revised October 13th 2004</p>
<p>Revised December 21st 2006</p>
<p>&copy; Copyright 2003-2004 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">
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+131 -11
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>
@@ -34,6 +38,10 @@ Tests
<li><a href="#example5">Example 5: sequenced indices</a></li>
<li><a href="#example6">Example 6: complex searches and foreign keys</a></li>
<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>
</ul>
<h2><a name="example1">Example 1: basic usage</a></h2>
@@ -80,7 +88,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>.
@@ -126,7 +134,7 @@ See <a href="../example/complex_structs.cpp">source code</a>.
This program illustrates some advanced techniques that can be applied
for complex data structures using <code>multi_index_container</code>.
Consider a <code>car_model</code> class for storing information
about automobiles. On a fist approach, <code>car_model</code> can
about automobiles. On a first approach, <code>car_model</code> can
be defined as:
</p>
@@ -134,7 +142,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>
@@ -168,8 +176,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>
@@ -249,7 +257,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
@@ -287,9 +295,121 @@ The program exits when the user presses the Enter key at the command prompt.
</p>
<p>
The reader is challenged to add more functionality to the program (for
instance, implementation of the <code>cp</code> command and handling of
absolute paths.)
The reader is challenged to add more functionality to the program; for
instance:
<ul>
<li>Implement additional commands, like <code>cp</code>.</li>
<li>Add handling of absolute paths.</li>
<li>Use <a href="tutorial/creation.html#serialization">serialization</a>
to store and retrieve the filesystem state between program runs.</li>
</ul>
</p>
<h2><a name="example8">Example 8: hashed indices</a></h2>
<p>
See <a href="../example/hashed.cpp">source code</a>.
</p>
<p>
Hashed indices can be used as an alternative to ordered indices when
fast lookup is needed and sorting information is of no interest. The
example features a word counter where duplicate entries are checked
by means of a hashed index. Confront the word counting algorithm with
that of <a href="#example5">example 5</a>.
</p>
<h2><a name="example9">Example 9: serialization and MRU lists</a></h2>
<p>
See <a href="../example/serialization.cpp">source code</a>.
</p>
<p>
A typical application of serialization capabilities allows a program to
restore the user context between executions. The example program asks
the user for words and keeps a record of the ten most recently entered
ones, in the current or in previous sessions. The serialized data structure,
sometimes called an <i>MRU (most recently used) list</i>, has some interest
on its own: an MRU list behaves as a regular FIFO queue, with the exception
that, when inserting a preexistent entry, this does not appear twice, but
instead the entry is moved to the front of the list. You can observe this
behavior in many programs featuring a "Recent files" menu command. This
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>
<hr>
@@ -306,9 +426,9 @@ Tests
<br>
<p>Revised May 28th 2004</p>
<p>Revised March 3rd 2006</p>
<p>&copy; Copyright 2003-2004 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">
+11 -30
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>
@@ -17,8 +21,8 @@ Tests
<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="acknowledgements.html"><img src="next.gif" alt="acknowledgements" border="0"><br>
Acknowledgements
<div class="next_link"><a href="release_notes.html"><img src="next.gif" alt="release notes" border="0"><br>
Release notes
</a></div><br clear="all" style="clear: all;">
<hr>
@@ -33,31 +37,15 @@ principle driving the current internal design of <code>multi_index_container</co
<h2>Contents</h2>
<ul>
<li><a href="#hashed_indices">Hashed indices</a></li>
<li><a href="#ranked_indices">Ranked 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="#serialization">Serialization support</a></li>
<li><a href="#move_semantics">Move semantics</a></li>
</ul>
<h2><a name="hashed_indices">Hashed indices</a></h2>
<p>
Several STL implementations feature hashed sets as a natural
counterpart to <code>std::set</code> and <code>std::multiset</code>.
<code>multi_index_container</code> can also benefit from the inclusion of hashed
indices. As the exact details of the interfaces of hashed sets differ among
library vendors, a good starting point seems Matt Austern's paper
<a href="http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1456.html">A
Proposal to Add Hash Tables to the Standard Library (revision 4)</a>, which
has been submitted for acceptance into the next revision of the
C++ standard.
</p>
<h2><a name="ranked_indices">Ranked indices</a></h2>
<p>
@@ -166,7 +154,7 @@ user can write implementations for her own indices.
<p>
<a href="examples.html#example4">Example 4</a> in the examples section
features a <i>bidirectional map</i>, implemented as an
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
@@ -213,13 +201,6 @@ a careful study when designing the interface of a potential
indexed map.
</p>
<h2><a name="serialization">Serialization support</a></h2>
<p>
Support for archiving/retrieving <code>multi_index_container</code>s
will be added, based on <a href="../../serialization/index.html">Boost.Serialization</a>.
</p>
<h2><a name="move_semantics">Move semantics</a></h2>
<p>
@@ -253,15 +234,15 @@ Tests
<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="acknowledgements.html"><img src="next.gif" alt="acknowledgements" border="0"><br>
Acknowledgements
<div class="next_link"><a href="release_notes.html"><img src="next.gif" alt="release notes" border="0"><br>
Release notes
</a></div><br clear="all" style="clear: all;">
<br>
<p>Revised September 27th 2004</p>
<p>Revised February 6th 2006</p>
<p>&copy; Copyright 2003-2004 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.

After

Width:  |  Height:  |  Size: 8.2 KiB

+31 -7
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;">
@@ -27,7 +29,9 @@ Indices provide interfaces similar to those of STL containers, making using them
familiar. The concept of multi-indexing over the same collection of elements is
borrowed from relational database terminology and allows for the specification of
complex data structures in the spirit of multiply indexed relational tables where
simple sets and maps are not enough.
simple sets and maps are not enough. A wide selection of indices is provided,
modeled after analogous STL containers like <code>std::set</code>,
<code>std::list</code> and hashed sets.
</p>
<p>
@@ -37,17 +41,37 @@ for <code>std::set</code> and <code>set::multiset</code> even when no multi-inde
capabilities are needed.
</p>
<p>
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/basics.html#multiple_sort">Sets with several iteration orders
and search criteria</a>.</li>
<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="tutorial/techniques.html#emulate_std_containers">Emulations of
standard containers</a> taking advantage of the extra functionalities
provided by Boost.MultiIndex.</li>
</ul>
</p>
<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>
<li><a href="examples.html">Examples</a></li>
<li><a href="tests.html">Tests</a></li>
<li><a href="future_work.html">Future work</a></li>
<li><a href="release_notes.html">Release notes</a></li>
<li><a href="acknowledgements.html">Acknowledgements</a></li>
</ul>
@@ -55,15 +79,15 @@ capabilities are needed.
<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 May 28th 2004</p>
<p>Revised February 6th 2006</p>
<p>&copy; Copyright 2003-2004 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

+123 -85
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>
@@ -77,7 +81,7 @@ Examples
<p>
Boost.MultiIndex helps the programmer to avoid the manual construction of cumbersome
compositions of containers when multiindexing capabilities are needed. Furthermore,
compositions of containers when multi-indexing capabilities are needed. Furthermore,
it does so in an efficient manner, both in terms of space and time consumption. The
space savings stem from the compact representation of the underlying data structures,
requiring a single node per element. As for time efficiency, Boost.MultiIndex
@@ -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 September 7th 2004</p>
<p>Revised May 9th 2006</p>
<p>&copy; Copyright 2003-2004 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">
+908
View File
@@ -0,0 +1,908 @@
<!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 - 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>
<h1><img src="../../../../boost.png" alt="boost.png (6897 bytes)" align=
"middle" width="277" height="86">Boost.MultiIndex Hashed indices reference</h1>
<div class="prev_link"><a href="ord_indices.html"><img src="../prev.gif" alt="ordered indices" border="0"><br>
Ordered 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
</a></div>
<div class="next_link"><a href="seq_indices.html"><img src="../next.gif" alt="sequenced indices" border="0"><br>
Sequenced indices
</a></div><br clear="all" style="clear: all;">
<hr>
<h2>Contents</h2>
<ul>
<li><a href="#hash_index_fwd_synopsis">Header
<code>"boost/multi_index/hashed_index_fwd.hpp"</code> synopsis</a></li>
<li><a href="#synopsis">Header
<code>"boost/multi_index/hashed_index.hpp"</code> synopsis</a>
<ul>
<li><a href="#unique_non_unique">
Index specifiers <code>hashed_unique</code> and <code>hashed_non_unique</code>
</a></li>
<li><a href="#hash_indices">Hashed indices</a>
<ul>
<li><a href="#complexity_signature">Complexity signature</a></li>
<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="#modifiers">Modifiers</a></li>
<li><a href="#observers">Observers</a></li>
<li><a href="#lookup">Lookup</a></li>
<li><a href="#hash_policy">Hash policy</a></li>
<li><a href="#serialization">Serialization</a></li>
</ul>
</li>
</ul>
</li>
</ul>
<h2>
<a name="hash_index_fwd_synopsis">Header
<a href="../../../../boost/multi_index/hashed_index_fwd.hpp">
<code>"boost/multi_index/hashed_index_fwd.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=comment>// index specifiers hashed_unique and hashed_non_unique</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>consult hashed_unique reference for arguments</b><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>hashed_unique</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>consult hashed_non_unique reference for arguments</b><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>hashed_non_unique</span><span class=special>;</span>
<span class=comment>// indices</span>
<span class=keyword>namespace</span> <span class=identifier>detail</span><span class=special>{</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>implementation defined</b><span class=special>&gt;</span> <span class=keyword>class</span> <b>index name is implementation defined</b><span class=special>;</span>
<span class=special>}</span> <span class=comment>// namespace boost::multi_index::detail</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>
<p>
<code>hashed_index_fwd.hpp</code> provides forward declarations for index specifiers
<a href="#unique_non_unique"><code>hashed_unique</code> and <code>hashed_non_unique</code></a> and
their associated <a href="#hash_indices">hashed index</a> classes.
</p>
<h2>
<a name="synopsis">Header
<a href="../../../../boost/multi_index/hashed_index.hpp">
<code>"boost/multi_index/hashed_index.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=comment>// index specifiers hashed_unique and hashed_non_unique</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>consult hashed_unique reference for arguments</b><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>hashed_unique</span><span class=special>;</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>consult hashed_non_unique reference for arguments</b><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>hashed_non_unique</span><span class=special>;</span>
<span class=comment>// indices</span>
<span class=keyword>namespace</span> <span class=identifier>detail</span><span class=special>{</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>implementation defined</b><span class=special>&gt;</span> <span class=keyword>class</span> <b>index class name implementation defined</b><span class=special>;</span>
<span class=comment>// index specialized algorithms:</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>implementation defined</b><span class=special>&gt;</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><b>index class name</b><span class=special>&amp;</span> <span class=identifier>y</span><span class=special>);</span>
<span class=special>}</span> <span class=comment>// namespace boost::multi_index::detail</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="unique_non_unique">
Index specifiers <code>hashed_unique</code> and <code>hashed_non_unique</code>
</a></h3>
<p>
These <a href="indices.html#index_specification">index specifiers</a> allow
for insertion of <a href="#hash_indices">hashed indices</a> without and with
allowance of duplicate elements, respectively. The syntax of <code>hashed_unique</code>
and <code>hashed_non_unique</code> coincide, thus we describe them in a grouped manner.
<code>hashed_unique</code> and <code>hashed_non_unique</code> can be instantiated in
two different forms, according to whether a tag list for the index is provided or not:
</p>
<blockquote><pre>
<span class=keyword>template</span><span class=special>&lt;</span>
<span class=keyword>typename</span> <span class=identifier>KeyFromValue</span><span class=special>,</span>
<span class=keyword>typename</span> <span class=identifier>Hash</span><span class=special>=</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>hash</span><span class=special>&lt;</span><span class=identifier>KeyFromValue</span><span class=special>::</span><span class=identifier>result_type</span><span class=special>&gt;,</span>
<span class=keyword>typename</span> <span class=identifier>Pred</span><span class=special>=</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>equal_to</span><span class=special>&lt;</span><span class=identifier>KeyFromValue</span><span class=special>::</span><span class=identifier>result_type</span><span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=keyword>struct</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>;</span>
<span class=keyword>template</span><span class=special>&lt;</span>
<span class=keyword>typename</span> <span class=identifier>TagList</span><span class=special>,</span>
<span class=keyword>typename</span> <span class=identifier>KeyFromValue</span><span class=special>,</span>
<span class=keyword>typename</span> <span class=identifier>Hash</span><span class=special>=</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>hash</span><span class=special>&lt;</span><span class=identifier>KeyFromValue</span><span class=special>::</span><span class=identifier>result_type</span><span class=special>&gt;,</span>
<span class=keyword>typename</span> <span class=identifier>Pred</span><span class=special>=</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>equal_to</span><span class=special>&lt;</span><span class=identifier>KeyFromValue</span><span class=special>::</span><span class=identifier>result_type</span><span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=keyword>struct</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>;</span>
</pre></blockquote>
<p>
If provided, <code>TagList</code> must be an instantiation of the class template
<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.
</p>
<h3><a name="hash_indices">Hashed indices</a></h3>
<p>
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/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>
that retrieves keys from elements of <code>multi_index_container</code>, a <code>Hash</code>
function object which returns hash values for the keys and a binary predicate <code>Pred</code>
acting as an equivalence relation on values of <code>Key</code>.
</p>
<p>
There are two variants of hashed indices: <i>unique</i>, which do
not allow duplicate elements (with respect to its associated equality
predicate) and <i>non-unique</i>, which accept those duplicates.
The interface of these two variants is the same, so they are documented
together, with minor differences explicitly stated when they exist.
</p>
<p>
Except where noted, hashed indices (both unique and non-unique) are models of
<code>Unordered Associative Container</code>, in the spirit of
<code>std::tr1::unordered_set</code>s. Validity of iterators and references to
elements is preserved in all cases. Occasionally, the exception safety guarantees provided
are actually stronger than required by the extension draft. We only provide descriptions
of those types and operations that are either not present in the concepts modeled or
do not exactly conform to the requirements for unordered associative containers.
</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>detail</span><span class=special>{</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>implementation defined: dependent on types Value, Allocator,
TagList, KeyFromValue, Hash, Pred</b><span class=special>&gt;</span>
<span class=keyword>class</span> <b>name is implementation defined</b>
<span class=special>{</span>
<span class=keyword>public</span><span class=special>:</span>
<span class=comment>// types:</span>
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>KeyFromValue</span><span class=special>::</span><span class=identifier>result_type</span> <span class=identifier>key_type</span><span class=special>;</span>
<span class=keyword>typedef</span> <span class=identifier>Value</span> <span class=identifier>value_type</span><span class=special>;</span>
<span class=keyword>typedef</span> <span class=identifier>KeyFromValue</span> <span class=identifier>key_from_value</span><span class=special>;</span>
<span class=keyword>typedef</span> <span class=identifier>Hash</span> <span class=identifier>hasher</span><span class=special>;</span>
<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>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>
<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>
<span class=keyword>typedef</span> <b>implementation defined </b><span class=identifier>size_type</span><span class=special>;</span>
<span class=keyword>typedef</span> <b>implementation defined </b><span class=identifier>difference_type</span><span class=special>;</span>
<span class=keyword>typedef</span> <b>implementation defined </b><span class=identifier>iterator</span><span class=special>;</span>
<span class=keyword>typedef</span> <b>implementation defined </b><span class=identifier>const_iterator</span><span class=special>;</span>
<span class=keyword>typedef</span> <b>implementation defined </b><span class=identifier>local_iterator</span><span class=special>;</span>
<span class=keyword>typedef</span> <b>implementation defined </b><span class=identifier>const_local_iterator</span><span class=special>;</span>
<span class=comment>// construct/destroy/copy:</span>
<b>index class name</b><span class=special>&amp;</span> <span class=keyword>operator</span><span class=special>=(</span><span class=keyword>const</span> <b>index class name</b><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=identifier>allocator_type</span> <span class=identifier>get_allocator</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=comment>// size and 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>
<span class=identifier>size_type</span> <span class=identifier>size</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>size_type</span> <span class=identifier>max_size</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=comment>// iterators:</span>
<span class=identifier>iterator</span> <span class=identifier>begin</span><span class=special>();</span>
<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=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>
<span class=identifier>iterator</span> <span class=identifier>insert</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>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=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=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>&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>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>
<span class=comment>// observers:</span>
<span class=identifier>key_from_value</span> <span class=identifier>key_extractor</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>hasher</span> <span class=identifier>hash_function</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>key_equal</span> <span class=identifier>key_eq</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=comment>// lookup:</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>CompatibleKey</span><span class=special>&gt;</span>
<span class=identifier>iterator</span> <span class=identifier>find</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>CompatibleKey</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>template</span><span class=special>&lt;</span>
<span class=keyword>typename</span> <span class=identifier>CompatibleKey</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>CompatibleHash</span><span class=special>,</span> <span class=keyword>typename</span> <span class=identifier>CompatiblePred</span>
<span class=special>&gt;</span>
<span class=identifier>iterator</span> <span class=identifier>find</span><span class=special>(</span>
<span class=keyword>const</span> <span class=identifier>CompatibleKey</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>,</span>
<span class=keyword>const</span> <span class=identifier>CompatibleHash</span><span class=special>&amp;</span> <span class=identifier>hash</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>CompatiblePred</span><span class=special>&amp;</span> <span class=identifier>eq</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>CompatibleKey</span><span class=special>&gt;</span>
<span class=identifier>size_type</span> <span class=identifier>count</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>CompatibleKey</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>template</span><span class=special>&lt;</span>
<span class=keyword>typename</span> <span class=identifier>CompatibleKey</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>CompatibleHash</span><span class=special>,</span> <span class=keyword>typename</span> <span class=identifier>CompatiblePred</span>
<span class=special>&gt;</span>
<span class=identifier>size_type</span> <span class=identifier>count</span><span class=special>(</span>
<span class=keyword>const</span> <span class=identifier>CompatibleKey</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>,</span>
<span class=keyword>const</span> <span class=identifier>CompatibleHash</span><span class=special>&amp;</span> <span class=identifier>hash</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>CompatiblePred</span><span class=special>&amp;</span> <span class=identifier>eq</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>CompatibleKey</span><span class=special>&gt;</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=identifier>iterator</span><span class=special>&gt;</span> <span class=identifier>equal_range</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>CompatibleKey</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>template</span><span class=special>&lt;</span>
<span class=keyword>typename</span> <span class=identifier>CompatibleKey</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>CompatibleHash</span><span class=special>,</span> <span class=keyword>typename</span> <span class=identifier>CompatiblePred</span>
<span class=special>&gt;</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=identifier>iterator</span><span class=special>&gt;</span> <span class=identifier>equal_range</span><span class=special>(</span>
<span class=keyword>const</span> <span class=identifier>CompatibleKey</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>,
</span><span class=keyword>const</span> <span class=identifier>CompatibleHash</span><span class=special>&amp;</span> <span class=identifier>hash</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>CompatiblePred</span><span class=special>&amp;</span> <span class=identifier>eq</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=comment>// bucket interface:</span>
<span class=identifier>size_type</span> <span class=identifier>bucket_count</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>size_type</span> <span class=identifier>max_bucket_count</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>size_type</span> <span class=identifier>bucket_size</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>size_type</span> <span class=identifier>bucket</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>key_type</span><span class=special>&amp;</span> <span class=identifier>k</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>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=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=comment>// hash policy:</span>
<span class=keyword>float</span> <span class=identifier>load_factor</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=keyword>float</span> <span class=identifier>max_load_factor</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=keyword>void</span> <span class=identifier>max_load_factor</span><span class=special>(</span><span class=keyword>float</span> <span class=identifier>z</span><span class=special>);</span>
<span class=keyword>void</span> <span class=identifier>rehash</span><span class=special>(</span><span class=identifier>size_type</span> <span class=identifier>n</span><span class=special>);</span>
<span class=special>};</span>
<span class=comment>// index specialized algorithms:</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>implementation defined</b><span class=special>&gt;</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><b>index class name</b><span class=special>&amp;</span> <span class=identifier>y</span><span class=special>);</span>
<span class=special>}</span> <span class=comment>// namespace boost::multi_index::detail</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>
<h4><a name="complexity_signature">Complexity signature</a></h4>
<p>
Here and in the descriptions of operations of hashed indices, we adopt the
scheme outlined in the
<a href="indices.html#complexity_signature">complexity signature
section</a>. The complexity signature of hashed indices is:
<ul>
<li>copying: <code>c(n)=n*log(n)</code>,</li>
<li>insertion: average case <code>i(n)=1</code> (constant),
worst case <code>i(n)=n</code>,</li>
<li>hinted insertion: average case <code>h(n)=1</code> (constant),
worst case <code>h(n)=n</code>,</li>
<li>deletion: average case <code>d(n)=1</code> (constant),
worst case <code>d(n)=n</code>,</li>
<li>replacement:
<ul>
<li>if the new element key is equivalent to the original, <code>r(n)=1</code> (constant),</li>
<li>otherwise, average case <code>r(n)=1</code> (constant),
worst case <code>r(n)=n</code>,</li>
</ul></li>
<li>modifying: average case <code>m(n)=1</code> (constant),
worst case <code>m(n)=n</code>.</li>
</ul>
</p>
<h4><a name="instantiation_types">Instantiation types</a></h4>
<p>Hashed indices are instantiated internally to <code>multi_index_container</code> and
specified by means of <a href="indices.html#indexed_by"><code>indexed_by</code></a>
with <a href="#unique_non_unique"> index specifiers <code>hashed_unique</code>
and <code>hashed_non_unique</code></a>. 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>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>
</ul>
<code>TagList</code> must be an instantiation of
<a href="indices.html#tag"><code>tag</code></a>. The type <code>KeyFromValue</code>,
which determines the mechanism for extracting a key from <code>Value</code>,
must be a model of <a href="key_extraction.html#key_extractors">
<code>Key Extractor</code></a> from <code>Value</code>. <code>Hash</code> is a
<a href="http://www.sgi.com/tech/stl/UnaryFunction.html"><code>Unary Function</code></a>
taking a single argument of type <code>KeyFromValue::result_type</code> and returning a
value of type <code>std::size_t</code> in the range
<code>[0, std::numeric_limits&lt;std::size_t&gt;::max())</code>.
<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 elements of <code>KeyFromValue::result_type</code>. It is required that
the <code>Hash</code> object return the same value for keys
equivalent under <code>Pred</code>.
</p>
<h4><a name="types">Nested types</a></h4>
<code>ctor_args</code>
<blockquote>
The first element of this tuple indicates the minimum number of buckets
set up by the index on construction time. If the default value 0 is used,
an implementation defined number is used instead.
</blockquote>
<code>iterator<br>
const_iterator<br>
local_iterator<br>
const_local_iterator</code>
<blockquote>
These types are models of
<a href="http://www.sgi.com/tech/stl/ForwardIterator.html"><code>Forward
Iterator</code></a>.
</blockquote>
<h4><a name="constructors">Constructors, copy and assignment</a></h4>
<p>
As explained in the <a href="indices.html#index_concepts">index
concepts section</a>, indices do not have public constructors or destructors.
Assignment, on the other hand, is provided. Upon construction,
<code>max_load_factor()</code> is 1.0.
</p>
<code><b>index class name</b>&amp; operator=(const <b>index class name</b>&amp; x);</code>
<blockquote>
<b>Effects:</b>
<blockquote><pre>
<span class=identifier>a</span><span class=special>=</span><span class=identifier>b</span><span class=special>;</span>
</pre></blockquote>
where <code>a</code> and <code>b</code> are the <code>multi_index_container</code>
objects to which <code>*this</code> and <code>x</code> belong, respectively.<br>
<b>Returns:</b> <code>*this</code>.<br>
</blockquote>
<h4><a name="modifiers">Modifiers</a></h4>
<code>std::pair&lt;iterator,bool> insert(const value_type&amp; x);</code>
<blockquote>
<b>Effects:</b> Inserts <code>x</code> into the <code>multi_index_container</code> to which
the index belongs if
<ul>
<li>the index is non-unique OR no other element exists with
equivalent key,</li>
<li>AND insertion is allowed by all other indices of the
<code>multi_index_container</code>.</li>
</ul>
<b>Returns:</b> The return value is a pair <code>p</code>. <code>p.second</code>
is <code>true</code> if and only if insertion took place. On successful insertion,
<code>p.first</code> points to the element inserted; otherwise, <code>p.first</code>
points to an element that caused the insertion to be banned. Note that more than
one element can be causing insertion not to be allowed.<br>
<b>Complexity:</b> <code>O(I(n))</code>.<br>
<b>Exception safety:</b> Strong.<br>
</blockquote>
<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>Effects:</b> Inserts <code>x</code> into the <code>multi_index_container</code> to which
the index belongs if
<ul>
<li>the index is non-unique OR no other element exists with
equivalent key,</li>
<li>AND insertion is allowed by all other indices of the
<code>multi_index_container</code>.</li>
</ul>
<code>position</code> is used as a hint to improve the efficiency of the
operation.<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
allowed.<br>
<b>Complexity:</b> <code>O(H(n))</code>.<br>
<b>Exception safety:</b> Strong.<br>
</blockquote>
<code>template&lt;typename InputIterator><br>
void insert(InputIterator first,InputIterator last);</code>
<blockquote>
<b>Requires:</b> <code>InputIterator</code> is a model of
<a href="http://www.sgi.com/tech/stl/InputIterator.html">
<code>Input Iterator</code></a> over elements of type
<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>
<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>
<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>hint</span><span class=special>=</span><span class=identifier>insert</span><span class=special>(</span><span class=identifier>hint</span><span class=special>,*</span><span class=identifier>first</span><span class=special>++);</span>
</pre></blockquote>
<b>Complexity:</b> <code>O(m*H(n+m))</code>, where
<code>m</code> is the number of elements in [<code>first</code>,
<code>last</code>).<br>
<b>Exception safety:</b> Basic.<br>
</blockquote>
<code>iterator erase(iterator position);</code>
<blockquote>
<b>Requires:</b> <code>position</code> is a valid dereferenceable iterator
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>
<code>size_type erase(const key_type&amp; x);</code>
<blockquote>
<b>Effects:</b> Deletes the elements with key equivalent to <code>x</code>.<br>
<b>Returns:</b> Number of elements deleted.<br>
<b>Complexity:</b> Average case, <code>O(1 + m*D(n))</code>, worst case
<code>O(n + m*D(n))</code>, where <code>m</code> is
the number of elements deleted.<br>
<b>Exception safety:</b> Basic.<br>
</blockquote>
<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>
</blockquote>
<a name="replace"><code>bool replace(iterator position,const value_type&amp; x);</code></a>
<blockquote>
<b>Requires:</b> <code>position</code> is a valid dereferenceable iterator
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>
<ul>
<li>the index is non-unique OR no other element exists
(except possibly <code>*position</code>) with equivalent key,</li>
<li>AND replacing is allowed by all other indices of the
<code>multi_index_container</code>.</li>
</ul>
<b>Postconditions:</b> Validity of <code>position</code> is preserved
in all cases.<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>
<b>Exception safety:</b> Strong. If an exception is thrown by some
user-provided operation the <code>multi_index_container</code> to which the index
belongs remains in its original state.
</blockquote>
<a name="modify">
<code>template&lt;typename Modifier> bool modify(iterator position,Modifier mod);</code></a>
<blockquote>
<b>Requires:</b> <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>value_type&amp;</code>. <code>position</code> is a valid dereferenceable
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
<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.
</blockquote>
<a name="modify_key">
<code>template&lt;typename Modifier> bool modify_key(iterator position,Modifier mod);</code></a>
<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> 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.
</blockquote>
<h4><a name="observers">Observers</a></h4>
<p>Apart from standard <code>hash_function</code> and <code>key_eq</code>,
hashed indices have a member function for retrieving the internal key extractor
used.
</p>
<code>key_from_value key_extractor()const;</code>
<blockquote>
Returns a copy of the <code>key_from_value</code> object used to construct
the index.<br>
<b>Complexity:</b> Constant.
</blockquote>
<h4><a name="lookup">Lookup</a></h4>
<p>
Hashed indices provide the full lookup functionality required by
unordered associative containers, namely <code>find</code>,
<code>count</code>, and <code>equal_range</code>. Additionally,
these member functions are templatized to allow for non-standard
arguments, so extending the types of search operations allowed.
The kind of arguments permissible when invoking the lookup member
functions is defined by the following concept.
</p>
<p>
Consider a pair (<code>Hash</code>, <code>Pred</code>) where
<code>Hash</code> is a hash functor over values of type <code>Key</code>
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>, 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>
of (<code>Hash</code>, <code>Pred</code>) if
<ol>
<li><code>CompatibleHash</code> is a hash functor on values of
type <code>CompatibleKey</code>,</li>
<li><code>CompatiblePred</code> is a
<a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">
<code>Binary Predicate</code></a> over (<code>Key</code>,
<code>CompatibleKey</code>),</li>
<li><code>CompatiblePred</code> is a
<a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">
<code>Binary Predicate</code></a> over (<code>CompatibleKey</code>,
<code>Key</code>),</li>
<li>if <code>c_eq(ck,k1)</code> then <code>c_eq(k1,ck)</code>,</li>
<li>if <code>c_eq(ck,k1)</code> and <code>eq(k1,k2)</code> then
<code>c_eq(ck,k2)</code>,</li>
<li>if <code>c_eq(ck,k1)</code> and <code>c_eq(ck,k2)</code> then
<code>eq(k1,k2)</code>,</li>
<li>if <code>c_eq(ck,k1)</code> then <code>c_hash(ck)==hash(k1)</code>,</li>
</ol>
for every <code>c_hash</code> of type <code>CompatibleHash</code>,
<code>c_eq</code> of type <code>CompatiblePred</code>,
<code>hash</code> of type <code>Hash</code>,
<code>eq</code> of type <code>Pred</code>, <code>ck</code> of type
<code>CompatibleKey</code> and <code>k1</code>, <code>k2</code> of type
<code>Key</code>.
</p>
<p>Additionally, a type <code>CompatibleKey</code> is said to be a
<i>compatible key</i> of (<code>Hash</code>, <code>Pred</code>) if
(<code>CompatibleKey</code>, <code>Hash</code>, <code>Pred</code>)
is a compatible extension of (<code>Hash</code>, <code>Pred</code>).
This implies that <code>Hash</code> and <code>Pred</code> accept arguments
of type <code>CompatibleKey</code>, which usually means they have
several overloads of therir corresponding <code>operator()</code>
member functions.
</p>
<p>
In the context of a compatible extension or a compatible key, the expression
"equivalent key" takes on its obvious interpretation.
</p>
<code>template&lt;typename CompatibleKey> iterator find(const CompatibleKey&amp; x)const;
</code>
<blockquote>
<b>Requires:</b> <code>CompatibleKey</code> is a compatible key of
(<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
<code>O(n)</code>.<br>
</blockquote>
<code>template&lt;<br>
&nbsp;&nbsp;typename CompatibleKey,typename CompatibleHash, typename CompatiblePred<br>
&gt;<br>
iterator find(<br>
&nbsp;&nbsp;const CompatibleKey&amp; x,<br>
&nbsp;&nbsp;const CompatibleHash&amp; hash,const CompatiblePred&amp; eq)const;
</code>
<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>
<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
<code>O(n)</code>.<br>
</blockquote>
<code>template&lt;typename CompatibleKey><br>
size_type count(const CompatibleKey&amp; x)const;
</code>
<blockquote>
<b>Requires:</b> <code>CompatibleKey</code> is a compatible key of
(<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>
</blockquote>
<code>template&lt;<br>
&nbsp;&nbsp;typename CompatibleKey,typename CompatibleHash, typename CompatiblePred<br>
&gt;<br>
size_type count(<br>
&nbsp;&nbsp;const CompatibleKey&amp; x,<br>
&nbsp;&nbsp;const CompatibleHash&amp; hash,const CompatiblePred&amp; eq)const;
</code>
<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>
<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>
</blockquote>
<code>template&lt;typename CompatibleKey><br>
std::pair&lt;iterator,iterator> equal_range(const CompatibleKey&amp; x)const;
</code>
<blockquote>
<b>Requires:</b> <code>CompatibleKey</code> is a compatible key of
(<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>
<b>Complexity:</b> Average case <code>O(count(x))</code>, worst case
<code>O(n)</code>.<br>
</blockquote>
<code>template&lt;<br>
&nbsp;&nbsp;typename CompatibleKey,typename CompatibleHash, typename CompatiblePred<br>
&gt;<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>
<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>
<b>Effects:</b> Returns a range containing all elements with keys equivalent
to <code>x</code> (and only those).<br>
<b>Complexity:</b> Average case <code>O(count(x,hash,eq))</code>, worst case
<code>O(n)</code>.<br>
</blockquote>
<h4><a name="hash_policy">Hash policy</a></h4>
<code>void rehash(size_type n);</code>
<blockquote>
<b>Effects:</b> Increases if necessary the number of internal buckets
so that <code>size()/bucket_count()</code> does not exceed the maximum
load factor, and <code>bucket_count()>=n</code>.<br>
<b>Postconditions:</b> Validity of iterators and references to the
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>Exception safety:</b> Strong.
</blockquote>
<h4><a name="serialization">Serialization</a></h4>
<p>
Indices cannot be serialized on their own, but only as part of the
<code>multi_index_container</code> into which they are embedded. In describing
the additional preconditions and guarantees associated to hashed indices
with respect to serialization of their embedding containers, we
use the concepts defined in the <code>multi_index_container</code>
<a href="multi_index_container.html#serialization">serialization section</a>.
</p>
Operation: saving of a <code>multi_index_container</code> <code>m</code> to an
output archive (XML archive) <code>ar</code>.
<blockquote>
<b>Requires:</b> No additional requirements to those imposed by the container.
</blockquote>
Operation: loading of a <code>multi_index_container</code> <code>m'</code> from an
input archive (XML archive) <code>ar</code>.
<blockquote>
<b>Requires:</b> Additionally to the general requirements, <code>key_eq()</code>
must be serialization-compatible with <code>m.get&lt;i&gt;().key_eq()</code>,
where <code>i</code> is the position of the hashed index in the container.<br>
<b>Postconditions:</b> On succesful loading, the range
[<code>begin()</code>, <code>end()</code>) contains restored copies of every
element in [<code>m.get&lt;i&gt;().begin()</code>, <code>m.get&lt;i&gt;().end()</code>),
though not necessarily in the same order.
</blockquote>
Operation: saving of an <code>iterator</code> or <code>const_iterator</code>
<code>it</code> to an output archive (XML archive) <code>ar</code>.
<blockquote>
<b>Requires:</b> <code>it</code> is a valid iterator of the index. The associated
<code>multi_index_container</code> has been previously saved.
</blockquote>
Operation: loading of an <code>iterator</code> or <code>const_iterator</code>
<code>it'</code> from an input archive (XML archive) <code>ar</code>.
<blockquote>
<b>Postconditions:</b> On succesful loading, if <code>it</code> was dereferenceable
then <code>*it'</code> is the restored copy of <code>*it</code>, otherwise
<code>it'==end()</code>.<br>
<b>Note:</b> It is allowed that <code>it</code> be a <code>const_iterator</code>
and the restored <code>it'</code> an <code>iterator</code>, or viceversa.
</blockquote>
Operation: saving of a <code>local_iterator</code> or
<code>const_local_iterator</code>
<code>it</code> to an output archive (XML archive) <code>ar</code>.
<blockquote>
<b>Requires:</b> <code>it</code> is a valid local iterator of the index. The
associated <code>multi_index_container</code> has been previously saved.
</blockquote>
Operation: loading of a <code>local_iterator</code> or
<code>const_local_iterator</code>
<code>it'</code> from an input archive (XML archive) <code>ar</code>.
<blockquote>
<b>Postconditions:</b> On succesful loading, if <code>it</code> was dereferenceable
then <code>*it'</code> is the restored copy of <code>*it</code>; if <code>it</code>
was <code>m.get&lt;i&gt;().end(n)</code> for some <code>n</code>, then
<code>it'==m'.get&lt;i&gt;().end(n)</code> (where <code>m</code> is the original
<code>multi_index_container</code>, <code>m'</code> its restored copy
and <code>i</code> is the ordinal of the index.)<br>
<b>Note:</b> It is allowed that <code>it</code> be a <code>const_local_iterator</code>
and the restored <code>it'</code> a <code>local_iterator</code>, or viceversa.
</blockquote>
<hr>
<div class="prev_link"><a href="ord_indices.html"><img src="../prev.gif" alt="ordered indices" border="0"><br>
Ordered 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
</a></div>
<div class="next_link"><a href="seq_indices.html"><img src="../next.gif" alt="sequenced indices" border="0"><br>
Sequenced indices
</a></div><br clear="all" style="clear: all;">
<br>
<p>Revised July 13th 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>
+30 -8
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
@@ -27,10 +31,12 @@ Index
<ul>
<li><a href="#header_dependencies">Header dependencies</a></li>
<li><a href="multi_index_container.html">Template class <code>multi_index_container</code></a></li>
<li><a href="multi_index_container.html">Class template <code>multi_index_container</code></a></li>
<li><a href="indices.html">Index reference</a></li>
<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>
@@ -53,6 +59,13 @@ The following dependencies among headers of Boost.MultiIndex hold:
<code>"boost/multi_index/tag.hpp"</code></a>.</li>
</ul>
</li>
<li><a href="hash_indices.html#synopsis">
<code>"boost/multi_index/hashed_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="seq_indices.html#synopsis">
<code>"boost/multi_index/sequenced_index.hpp"</code></a> includes
<ul>
@@ -60,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>
@@ -85,14 +105,16 @@ provided by Boost.MultiIndex are automatically included with
</p>
<p>
Boost.MultiIndex is a header-only library, requiring no linking with additional
In order to use the serialization capabilities of Boost.MultiIndex,
the appropriate Boost.Serialization library module must be linked. Other
than that, Boost.MultiIndex is a header-only library, requiring no additional
object modules.
</p>
<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
@@ -103,9 +125,9 @@ Index
<br>
<p>Revised May 28th 2004</p>
<p>Revised February 6th 2005</p>
<p>&copy; Copyright 2003-2004 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">
+78 -20
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>
@@ -32,14 +36,14 @@ Ordered indices
<li><a href="#indexed_by_synopsis">Header
<code>"boost/multi_index/indexed_by.hpp"</code> synopsis</a>
<ul>
<li><a href="#indexed_by">Template class <code>indexed_by</code></a></li>
<li><a href="#indexed_by">Class template <code>indexed_by</code></a></li>
</ul>
</li>
<li><a href="#tags">Tags</a></li>
<li><a href="#tag_synopsis">Header
<code>"boost/multi_index/tag.hpp"</code> synopsis</a>
<ul>
<li><a href="#tag">Template class <code>tag</code></a></li>
<li><a href="#tag">Class template <code>tag</code></a></li>
</ul>
</li>
<li><a href="#index_catalog">Indices provided by Boost.MultiIndex</a>
@@ -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">
@@ -151,8 +156,8 @@ an instantiation of <code>multi_index_container</code>
with <code>N</code> indices labelled <code>0</code>,...,<code>N-1</code>
whose complexity signatures are
(<code>c<sub>i</sub></code>,<code>i<sub>i</sub></code>,<code>h<sub>i</sub></code>,<code>d<sub>i</sub></code>,<code>r<sub>i</sub></code>,<code>m<sub>i</sub></code>);
the insertion of an element in such a set is then of complexity
<code>O(I<sub>0</sub>(n)+···+I<sub>N-1</sub>(n))</code> where <code>n</code>
the insertion of an element in such a container is then of complexity
<code>O(i<sub>0</sub>(n)+···+i<sub>N-1</sub>(n))</code> where <code>n</code>
is the number of elements. To abbreviate notation, we adopt the
following definitions:
<ul>
@@ -181,11 +186,18 @@ the corresponding indices. Future releases of Boost.MultiIndex may allow for
specification of user-defined indices. Meanwhile, the requirements for an index
specifier remain implementation defined. Currently, Boost.MultiIndex provides the
index specifiers
<a href="ord_indices.html#unique_non_unique"><code>ordered_unique</code> and
<code>ordered_non_unique</code></a> for
<a href="ord_indices.html">ordered indices</a> and
<a href="seq_indices.html#sequenced"><code>sequenced</code></a> for
<a href="seq_indices.html">sequenced indices</a>.
<ul>
<li><a href="ord_indices.html#unique_non_unique"><code>ordered_unique</code> and
<code>ordered_non_unique</code></a> for
<a href="ord_indices.html">ordered indices</a>,</li>
<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><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>
<h2>
@@ -206,12 +218,14 @@ index specifiers
<span class=special>}</span> <span class=comment>// namespace boost</span>
</pre></blockquote>
<h3><a name="indexed_by">Template class <code>indexed_by</code></a></h3>
<h3><a name="indexed_by">Class template <code>indexed_by</code></a></h3>
<p>
<code>indexed_by</code> is a
<a href="../../../../libs/mpl/doc/ref/Forward_Sequence.html">
<code>MPL Forward Sequence</code></a> meant to be used to specify a
<code>indexed_by</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> meant to be used to specify a
compile-time list of indices as the <code>IndexSpecifierList</code> of
<code>multi_index_container</code>.
</p>
@@ -256,7 +270,7 @@ class template <a href="#tag"><code>tag</code></a>.
<span class=special>}</span> <span class=comment>// namespace boost</span>
</pre></blockquote>
<h3><a name="tag">Template class <code>tag</code></a></h3>
<h3><a name="tag">Class template <code>tag</code></a></h3>
<p>
<code>tag</code> is a typelist construct used to specify a compile-time
@@ -287,7 +301,7 @@ reference</a>.
<ul>
<li><a href="ord_indices.html">Ordered indices</a> sort the elements
on the key and provide fast lookup capabilites.</li>
<li>Hashed indices (<b>not currently implemented</b>) offer high
<li><a href="hash_indices.html">Hashed indices</a> offer high
efficiency access through hashing techniques.</li>
</ul>
</p>
@@ -297,7 +311,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>
@@ -315,9 +373,9 @@ Ordered indices
<br>
<p>Revised July 15th 2004</p>
<p>Revised February 6th 2006</p>
<p>&copy; Copyright 2003-2004 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">
File diff suppressed because it is too large Load Diff
+83 -19
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>
@@ -32,7 +36,7 @@ Index reference
<li><a href="#synopsis">Header
<code>"boost/multi_index_container.hpp"</code> synopsis</a>
<ul>
<li><a href="#multi_index_container">Template class <code>multi_index_container</code></a>
<li><a href="#multi_index_container">Class template <code>multi_index_container</code></a>
<ul>
<li><a href="#complexity">Complexity</a></li>
<li><a href="#instantiation_types">Instantiation types</a></li>
@@ -41,6 +45,7 @@ Index reference
<li><a href="#constructors">Constructors, copy and assignment</a></li>
<li><a href="#index_retrieval">Index retrieval operations</a></li>
<li><a href="#projection">Projection operations</a></li>
<li><a href="#serialization">Serialization</a></li>
</ul>
</li>
</ul>
@@ -208,7 +213,7 @@ synopsis</a>
</pre></blockquote>
<h3><a name="multi_index_container">
Template class <code>multi_index_container</code>
Class template <code>multi_index_container</code>
</a></h3>
<p>
@@ -223,7 +228,7 @@ and for access to the indices held.
<p>
A <code>multi_index_container</code> type is instantiated with the type of the
elements contained and a non-empty
<a href="../../../../libs/mpl/doc/ref/Forward_Sequence.html">
<a href="../../../../libs/mpl/doc/refmanual/forward-sequence.html">
<code>MPL Forward Sequence</code></a> specifying which indices conform the
class.
</p>
@@ -491,8 +496,10 @@ scheme outlined in the
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/ref/Forward_Sequence.html">
<code>MPL Forward Sequence</code></a> of index specifiers. For
<a href="../../../../libs/mpl/doc/refmanual/forward-sequence.html">
<code>MPL Forward Sequence</code></a> (and, preferrably,
an <a href="../../../../libs/mpl/doc/refmanual/random-access-sequence.html">
<code>MPL Random Access Sequence</code></a>) of index specifiers. For
syntactic convenience, the
<a href="indices.html#indexed_by"><code>indexed_by</code></a>
MPL sequence can be used.
@@ -529,25 +536,28 @@ involved are default constructible.
<code>index_specifier_type_list</code>
<blockquote>
<a href="../../../../libs/mpl/doc/ref/Forward_Sequence.html">
<code>MPL Forward Sequence</code></a> containing the types of the index specifiers
used in the instantiation of the <code>multi_index_container</code>, in the same order as
they were provided.
Same type as <code>IndexSpecifierList</code>.
</blockquote>
<code>index_type_list</code>
<blockquote>
<a href="../../../../libs/mpl/doc/ref/Forward_Sequence.html">
<code>MPL Forward Sequence</code></a> containing the types of the indices held by
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 of the indices held by
the <code>multi_index_container</code>, in the same order as they were specified.
</blockquote>
<code>iterator_type_list</code>
<blockquote>
<a href="../../../../libs/mpl/doc/ref/Forward_Sequence.html">
<code>MPL Forward Sequence</code></a> containing the types of the iterators of
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 of the iterators of
the indices held by the <code>multi_index_container</code>, in the same order as they were
specified.
</blockquote>
@@ -555,8 +565,11 @@ specified.
<code>const_iterator_type_list</code>
<blockquote>
<a href="../../../../libs/mpl/doc/ref/Forward_Sequence.html">
<code>MPL Forward Sequence</code></a> containing the types of the constant
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 of the constant
iterators of the indices held by the <code>multi_index_container</code>, in the same order
as they were specified.
</blockquote>
@@ -658,7 +671,7 @@ of the <code>multi_index_container</code> is preserved as well.<br>
<blockquote>
<b>Effects:</b> Destroys the <code>multi_index_container</code> and all the elements
contained. The order in which the elements are destroyed is not specified.<br>
<b>Complexity:</b> <code>O(n*D(n))</code>.
<b>Complexity:</b> <code>O(n)</code>.
</blockquote>
<code>multi_index_container&lt;Value,IndexSpecifierList,Allocator>&amp; operator=(<br>
@@ -670,7 +683,7 @@ with copies from <code>x</code>.<br>
<b>Postconditions:</b> <code>*this==x</code>. The order on every index
of the <code>multi_index_container</code> is preserved as well.<br>
<b>Returns:</b> <code>*this</code>.<br>
<b>Complexity:</b> <code>O(n*D(n) + x.size()*log(x.size()) +
<b>Complexity:</b> <code>O(n + x.size()*log(x.size()) +
C(x.size()))</code>.<br>
<b>Exception safety:</b> Strong, provided the copy and assignment operations
of the types of <code>ctor_args_list</code> do not throw.
@@ -804,6 +817,57 @@ iterator equivalent to <code>it</code>.<br>
<b>Exception safety:</b> <code>nothrow</code>.
</blockquote>
<h4><a name="serialization">Serialization</a></h4>
<p>
<code>multi_index_container</code>s can be archived/retrieved by means of
<a href="../../../serialization/index.html">Boost.Serialization</a>.
Boost.MultiIndex does not expose a public serialization interface, as this
is provided by Boost.Serialization itself. Both regular and XML
archives are supported.
</p>
<p>
Each of the indices comprising a given <code>multi_index_container</code> contributes
its own preconditions as well as guarantees on the retrieved containers. In describing
these, the following concepts are used. A type <code>T</code> is <i>serializable</i>
(resp. XML-serializable) if any object of type <code>T</code> can be saved to an output
archive (XML archive) and later retrieved from an input archive (XML archive) associated to
the same storage. If <code>x'</code> of type <code>T</code> is loaded from the
serialization information saved from another object <code>x</code>, we say that
<code>x'</code> is a <i>restored copy</i> of <code>x</code>. Given a
<a href="http://www.sgi.com/tech/stl/BinaryPredicate.html"><code>Binary Predicate</code></a>
<code>Pred</code> over (<code>T</code>, <code>T</code>), and objects <code>p</code>
and <code>q</code> of type <code>Pred</code>, we say that <code>q</code>
is <i>serialization-compatible</i> with <code>p</code> if
<blockquote>
<code>p(x,y) == q(x',y')</code>
</blockquote>
for every <code>x</code> and <code>y</code> of type <code>T</code> and <code>x'</code> and
<code>y'</code> being restored copies of <code>x</code> and <code>y</code>,
respectively.
</p>
Operation: saving of a <code>multi_index_container</code> <code>m</code> to an
output archive (XML archive) <code>ar</code>.
<blockquote>
<b>Requires:</b> <code>Value</code> is serializable (XML-serializable). Additionally,
each of the indices of <code>m</code> can impose another requirements.<br>
<b>Exception safety:</b> Strong with respect to <code>m</code>. If an exception
is thrown, <code>ar</code> may be left in an inconsistent state.
</blockquote>
Operation: loading of a <code>multi_index_container</code> <code>m'</code> from an
input archive (XML archive) <code>ar</code>.
<blockquote>
<b>Requires:</b> <code>Value</code> is serializable (XML-serializable). Additionally,
each of the indices of <code>m'</code> can impose another requirements.<br>
<b>Exception safety:</b> Basic. If an exception is thrown, <code>ar</code> may be
left in an inconsistent state.
</blockquote>
<hr>
<div class="prev_link"><a href="index.html"><img src="../prev.gif" alt="Boost.MultiIndex reference" border="0"><br>
@@ -818,9 +882,9 @@ Index reference
<br>
<p>Revised May 28th 2004</p>
<p>Revised February 6th 2006</p>
<p>&copy; Copyright 2003-2004 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">
+93 -35
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>
@@ -17,8 +21,8 @@ Index reference
<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="seq_indices.html"><img src="../next.gif" alt="sequenced indices" border="0"><br>
Sequenced indices
<div class="next_link"><a href="hash_indices.html"><img src="../next.gif" alt="hashed indices" border="0"><br>
Hashed indices
</a></div><br clear="all" style="clear: all;">
<hr>
@@ -43,6 +47,7 @@ Sequenced indices
<li><a href="#observers">Observers</a></li>
<li><a href="#set_operations">Set operations</a></li>
<li><a href="#range_operations">Range operations</a></li>
<li><a href="#serialization">Serialization</a></li>
</ul>
</li>
</ul>
@@ -59,7 +64,7 @@ Sequenced indices
<span class=keyword>namespace</span> <span class=identifier>multi_index</span><span class=special>{</span>
<span class=comment>// index specifiers unique and ordered_non_unique</span>
<span class=comment>// index specifiers ordered_unique and ordered_non_unique</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>consult ordered_unique reference for arguments</b><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>ordered_unique</span><span class=special>;</span>
@@ -80,7 +85,7 @@ Sequenced indices
</pre></blockquote>
<p>
<code>index_fwd.hpp</code> provides forward declarations for index specifiers
<code>ordered_index_fwd.hpp</code> provides forward declarations for index specifiers
<a href="#unique_non_unique"><code>ordered_unique</code> and <code>ordered_non_unique</code></a> and
their associated <a href="#ord_indices">ordered index</a> classes.
</p>
@@ -95,7 +100,7 @@ their associated <a href="#ord_indices">ordered index</a> classes.
<span class=keyword>namespace</span> <span class=identifier>multi_index</span><span class=special>{</span>
<span class=comment>// index specifiers unique and ordered_non_unique</span>
<span class=comment>// index specifiers ordered_unique and ordered_non_unique</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>consult ordered_unique reference for arguments</b><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>ordered_unique</span><span class=special>;</span>
@@ -144,7 +149,7 @@ two different forms, according to whether a tag list for the index is provided o
<blockquote><pre>
<span class=keyword>template</span><span class=special>&lt;</span>
<span class=keyword>typename</span> <span class=identifier>KeyFromValue</span><span class=special>,</span>
<span class=keyword>typename</span> <span class=identifier>Compare</span><span class=special>=</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>less</span><span class=special>&lt;</span><span class=identifier>KeyFromValue</span><span class=special>::</span><span class=identifier>result_type</span>
<span class=keyword>typename</span> <span class=identifier>Compare</span><span class=special>=</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>less</span><span class=special>&lt;</span><span class=identifier>KeyFromValue</span><span class=special>::</span><span class=identifier>result_type</span><span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=special>(</span><span class=identifier>ordered_unique</span> <span class=special>|</span> <span class=identifier>ordered_non_unique</span><span class=special>)</span><span class=special>;</span>
@@ -158,7 +163,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.
@@ -261,9 +266,9 @@ 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>
@@ -281,9 +286,9 @@ requirements for these types of containers.
<span class=comment>// set operations:</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>CompatibleKey</span><span class=special>&gt;</span>
<span class=identifier>const_iterator</span> <span class=identifier>find</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>CompatibleKey</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>iterator</span> <span class=identifier>find</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>CompatibleKey</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>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>CompatibleKey</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>CompatibleCompare</span><span class=special>&gt;</span>
<span class=identifier>const_iterator</span> <span class=identifier>find</span><span class=special>(</span>
<span class=identifier>iterator</span> <span class=identifier>find</span><span class=special>(</span>
<span class=keyword>const</span> <span class=identifier>CompatibleKey</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>CompatibleCompare</span><span class=special>&amp;</span> <span class=identifier>comp</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>CompatibleKey</span><span class=special>&gt;</span>
@@ -292,28 +297,28 @@ requirements for these types of containers.
<span class=identifier>size_type</span> <span class=identifier>count</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>CompatibleKey</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>CompatibleCompare</span><span class=special>&amp;</span> <span class=identifier>comp</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>CompatibleKey</span><span class=special>&gt;</span>
<span class=identifier>const_iterator</span> <span class=identifier>lower_bound</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>CompatibleKey</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>iterator</span> <span class=identifier>lower_bound</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>CompatibleKey</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>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>CompatibleKey</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>CompatibleCompare</span><span class=special>&gt;</span>
<span class=identifier>const_iterator</span> <span class=identifier>lower_bound</span><span class=special>(</span>
<span class=identifier>iterator</span> <span class=identifier>lower_bound</span><span class=special>(</span>
<span class=keyword>const</span> <span class=identifier>CompatibleKey</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>CompatibleCompare</span><span class=special>&amp;</span> <span class=identifier>comp</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>CompatibleKey</span><span class=special>&gt;</span>
<span class=identifier>const_iterator</span> <span class=identifier>upper_bound</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>CompatibleKey</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>iterator</span> <span class=identifier>upper_bound</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>CompatibleKey</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>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>CompatibleKey</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>CompatibleCompare</span><span class=special>&gt;</span>
<span class=identifier>const_iterator</span> <span class=identifier>upper_bound</span><span class=special>(</span>
<span class=identifier>iterator</span> <span class=identifier>upper_bound</span><span class=special>(</span>
<span class=keyword>const</span> <span class=identifier>CompatibleKey</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>CompatibleCompare</span><span class=special>&amp;</span> <span class=identifier>comp</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>CompatibleKey</span><span class=special>&gt;</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>pair</span><span class=special>&lt;</span><span class=identifier>const_iterator</span><span class=special>,</span><span class=identifier>const_iterator</span><span class=special>&gt;</span> <span class=identifier>equal_range</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>iterator</span><span class=special>,</span><span class=identifier>iterator</span><span class=special>&gt;</span> <span class=identifier>equal_range</span><span class=special>(</span>
<span class=keyword>const</span> <span class=identifier>CompatibleKey</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>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>CompatibleKey</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>CompatibleCompare</span><span class=special>&gt;</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>pair</span><span class=special>&lt;</span><span class=identifier>const_iterator</span><span class=special>,</span><span class=identifier>const_iterator</span><span class=special>&gt;</span> <span class=identifier>equal_range</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>iterator</span><span class=special>,</span><span class=identifier>iterator</span><span class=special>&gt;</span> <span class=identifier>equal_range</span><span class=special>(</span>
<span class=keyword>const</span> <span class=identifier>CompatibleKey</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>CompatibleCompare</span><span class=special>&amp;</span> <span class=identifier>comp</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=comment>// range:</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>LowerBounder</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>UpperBounder</span><span class=special>&gt;</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>pair</span><span class=special>&lt;</span><span class=identifier>const_iterator</span><span class=special>,</span><span class=identifier>const_iterator</span><span class=special>&gt;</span> <span class=identifier>range</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>iterator</span><span class=special>,</span><span class=identifier>iterator</span><span class=special>&gt;</span> <span class=identifier>range</span><span class=special>(</span>
<span class=identifier>LowerBounder</span> <span class=identifier>lower</span><span class=special>,</span><span class=identifier>UpperBounder</span> <span class=identifier>upper</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=special>};</span>
@@ -391,7 +396,7 @@ section</a>. The complexity signature of ordered indices is:
<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>
<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
@@ -509,12 +514,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>
<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>
@@ -526,15 +534,16 @@ of the index.</br>
<b>Returns:</b> Number of elements deleted.<br>
<b>Complexity:</b> <code>O(log(n) + m*D(n))</code>, where <code>m</code> is
the number of elements deleted.<br>
<b>Exception safety:</b> <code>nothrow</code>.<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>
@@ -701,7 +710,7 @@ In the context of a compatible extension or a compatible key, the expressions
interpretations.
</p>
<code>template&lt;typename CompatibleKey> const_iterator find(const CompatibleKey&amp; x)const;
<code>template&lt;typename CompatibleKey> iterator find(const CompatibleKey&amp; x)const;
</code>
<blockquote>
@@ -713,7 +722,7 @@ interpretations.
</blockquote>
<code>template&lt;typename CompatibleKey,typename CompatibleCompare><br>
const_iterator find(const CompatibleKey&amp; x,const CompatibleCompare&amp; comp)const;
iterator find(const CompatibleKey&amp; x,const CompatibleCompare&amp; comp)const;
</code>
<blockquote>
@@ -747,7 +756,7 @@ is a compatible extension of <code>key_compare</code>.</br>
</blockquote>
<code>template&lt;typename CompatibleKey><br>
const_iterator lower_bound(const CompatibleKey&amp; x)const;
iterator lower_bound(const CompatibleKey&amp; x)const;
</code>
<blockquote>
@@ -760,7 +769,7 @@ not exist.<br>
</blockquote>
<code>template&lt;typename CompatibleKey,typename CompatibleCompare><br>
const_iterator lower_bound(const CompatibleKey&amp; x,const CompatibleCompare&amp; comp)const;
iterator lower_bound(const CompatibleKey&amp; x,const CompatibleCompare&amp; comp)const;
</code>
<blockquote>
@@ -773,7 +782,7 @@ not exist.<br>
</blockquote>
<code>template&lt;typename CompatibleKey><br>
const_iterator upper_bound(const CompatibleKey&amp; x)const;
iterator upper_bound(const CompatibleKey&amp; x)const;
</code>
<blockquote>
@@ -786,7 +795,7 @@ not exist.<br>
</blockquote>
<code>template&lt;typename CompatibleKey,typename CompatibleCompare><br>
const_iterator upper_bound(const CompatibleKey&amp; x,const CompatibleCompare&amp; comp)const;
iterator upper_bound(const CompatibleKey&amp; x,const CompatibleCompare&amp; comp)const;
</code>
<blockquote>
@@ -799,7 +808,7 @@ not exist.<br>
</blockquote>
<code>template&lt;typename CompatibleKey><br>
std::pair&lt;const_iterator,const_iterator> equal_range(<br>
std::pair&lt;iterator,iterator> equal_range(<br>
&nbsp;&nbsp;const CompatibleKey&amp; x)const;
</code>
@@ -811,7 +820,7 @@ std::pair&lt;const_iterator,const_iterator> equal_range(<br>
</blockquote>
<code>template&lt;typename CompatibleKey,typename CompatibleCompare><br>
std::pair&lt;const_iterator,const_iterator> equal_range(</br>
std::pair&lt;iterator,iterator> equal_range(</br>
&nbsp;&nbsp;const CompatibleKey&amp; x,const CompatibleCompare&amp; comp)const;
</code>
@@ -863,7 +872,7 @@ for every <code>upper</code> of type <code>UpperBounder</code>,
</p>
<code>template&lt;typename LowerBounder,typename UpperBounder><br>
std::pair&lt;const_iterator,const_iterator> range(<br>
std::pair&lt;iterator,iterator> range(<br>
&nbsp;&nbsp;LowerBounder lower,UpperBounder upper)const;
</code>
@@ -882,6 +891,55 @@ provided. This acts as a predicate which all values of type <code>key_type</code
satisfy.<br>
</blockquote>
<h4><a name="serialization">Serialization</a></h4>
<p>
Indices cannot be serialized on their own, but only as part of the
<code>multi_index_container</code> into which they are embedded. In describing
the additional preconditions and guarantees associated to ordered indices
with respect to serialization of their embedding containers, we
use the concepts defined in the <code>multi_index_container</code>
<a href="multi_index_container.html#serialization">serialization section</a>.
</p>
Operation: saving of a <code>multi_index_container</code> <code>m</code> to an
output archive (XML archive) <code>ar</code>.
<blockquote>
<b>Requires:</b> No additional requirements to those imposed by the container.
</blockquote>
Operation: loading of a <code>multi_index_container</code> <code>m'</code> from an
input archive (XML archive) <code>ar</code>.
<blockquote>
<b>Requires:</b> Additionally to the general requirements, <code>value_comp()</code>
must be serialization-compatible with <code>m.get&lt;i&gt;().value_comp()</code>,
where <code>i</code> is the position of the ordered index in the container.<br>
<b>Postconditions:</b> On succesful loading, each of the elements of
[<code>begin()</code>, <code>end()</code>) is a restored copy of the corresponding
element in [<code>m.get&lt;i&gt;().begin()</code>, <code>m.get&lt;i&gt;().end()</code>).
</blockquote>
Operation: saving of an <code>iterator</code> or <code>const_iterator</code>
<code>it</code> to an output archive (XML archive) <code>ar</code>.
<blockquote>
<b>Requires:</b> <code>it</code> is a valid iterator of the index. The associated
<code>multi_index_container</code> has been previously saved.
</blockquote>
Operation: loading of an <code>iterator</code> or <code>const_iterator</code>
<code>it'</code> from an input archive (XML archive) <code>ar</code>.
<blockquote>
<b>Postconditions:</b> On succesful loading, if <code>it</code> was dereferenceable
then <code>*it'</code> is the restored copy of <code>*it</code>, otherwise
<code>it'==end()</code>.<br>
<b>Note:</b> It is allowed that <code>it</code> be a <code>const_iterator</code>
and the restored <code>it'</code> an <code>iterator</code>, or viceversa.
</blockquote>
<hr>
<div class="prev_link"><a href="indices.html"><img src="../prev.gif" alt="index reference" border="0"><br>
@@ -890,15 +948,15 @@ Index reference
<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="seq_indices.html"><img src="../next.gif" alt="sequenced indices" border="0"><br>
Sequenced indices
<div class="next_link"><a href="hash_indices.html"><img src="../next.gif" alt="hashed indices" border="0"><br>
Hashed indices
</a></div><br clear="all" style="clear: all;">
<br>
<p>Revised July 20th 2004</p>
<p>Revised March 31st 2006</p>
<p>&copy; Copyright 2003-2004 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">
+959
View File
@@ -0,0 +1,959 @@
<!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 - Random access indices reference</title>
<link rel="stylesheet" href="../style.css" type="text/css">
<link rel="start" href="../index.html">
<link rel="prev" href="seq_indices.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 Random access indices reference</h1>
<div class="prev_link"><a href="seq_indices.html"><img src="../prev.gif" alt="sequenced indices" border="0"><br>
Sequenced 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
</a></div>
<div class="next_link"><a href="key_extraction.html"><img src="../next.gif" alt="key extraction" border="0"><br>
Key extraction
</a></div><br clear="all" style="clear: all;">
<hr>
<h2>Contents</h2>
<ul>
<li><a href="#rnd_index_fwd_synopsis">Header
<code>"boost/multi_index/random_access_index_fwd.hpp"</code> synopsis</a></li>
<li><a href="#synopsis">Header
<code>"boost/multi_index/random_access_index.hpp"</code> synopsis</a>
<ul>
<li><a href="#random_access"><code>random_access</code> index specifier</a></li>
<li><a href="#rnd_indices">Random access indices</a>
<ul>
<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="#capacity">Capacity operations</a></li>
<li><a href="#modifiers">Modifiers</a></li>
<li><a href="#list_operations">List operations</a></li>
<li><a href="#rearrange_operations">Rearrange operations</a></li>
<li><a href="#serialization">Serialization</a></li>
</ul>
</li>
</ul>
</li>
</ul>
<h2>
<a name="rnd_index_fwd_synopsis">Header
<a href="../../../../boost/multi_index/random_access_index_fwd.hpp">
<code>"boost/multi_index/random_access_index_fwd.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=comment>// random_access index specifier</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>TagList</span><span class=special>=</span><span class=identifier>tag</span><span class=special>&lt;&gt;</span> <span class=special>&gt;</span> <span class=keyword>struct</span> <span class=identifier>random_access</span><span class=special>;</span>
<span class=comment>// indices</span>
<span class=keyword>namespace</span> <span class=identifier>detail</span><span class=special>{</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>implementation defined</b><span class=special>&gt;</span> <span class=keyword>class</span> <b>index class name implementation defined</b><span class=special>;</span>
<span class=special>}</span> <span class=comment>// namespace boost::multi_index::detail</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>
<p>
<code>random_access_index_fwd.hpp</code> provides forward declarations for the
<a href="#random_access"><code>random_access</code></a> index specifier and
its associated <a href="#rnd_indices">random access index</a> class.
</p>
<h2>
<a name="synopsis">Header
<a href="../../../../boost/multi_index/random_access_index.hpp">
<code>"boost/multi_index/random_access_index.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=comment>// random_access index specifier</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>TagList</span><span class=special>=</span><span class=identifier>tag</span><span class=special>&lt;&gt;</span> <span class=special>&gt;</span> <span class=keyword>struct</span> <span class=identifier>random_access</span><span class=special>;</span>
<span class=comment>// indices</span>
<span class=keyword>namespace</span> <span class=identifier>detail</span><span class=special>{</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>implementation defined</b><span class=special>&gt;</span> <span class=keyword>class</span> <b>index class name implementation defined</b><span class=special>;</span>
<span class=comment>// index comparison:</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><b>arg set 1</b><span class=special>,</span><b>arg set 2</b><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=keyword>operator</span> <b><i>OP</i></b><span class=special>(</span>
<span class=keyword>const</span> <b>index class name</b><span class=special>&lt;</span><b>arg set 1</b><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <b>index class name</b><span class=special>&lt;</span><b>arg set 2</b><span class=special>&gt;&amp;</span> <span class=identifier>y</span><span class=special>);</span>
<span class=comment>// index specialized algorithms:</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>implementation defined</b><span class=special>&gt;</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><b>index class name</b><span class=special>&amp;</span> <span class=identifier>y</span><span class=special>);</span>
<span class=special>}</span> <span class=comment>// namespace boost::multi_index::detail</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="random_access">
<code>random_access</code> index specifier
</a></h3>
<p>
This index specifier allows for insertion of a <a href="#rnd_indices">random
access index</a>.</p>
<blockquote><pre>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>TagList</span><span class=special>=</span><span class=identifier>tag</span><span class=special>&lt;&gt;</span> <span class=special>&gt;</span> <span class=keyword>struct</span> <span class=identifier>random_access</span><span class=special>;</span>
</pre></blockquote>
<p>If provided, <code>TagList</code> must be an instantiation of
<a href="indices.html#tag"><code>tag</code></a>.
</p>
<h3><a name="rnd_indices">Random access indices</a></h3>
<p>
Random access indices are free-order sequences with constant time
positional access and random access iterators. Elements in a
random access 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
random access index; additionally, facilities are provided
for further rearrangement of the elements. The public interface of
random access indices includes that of
<a href="seq_indices.html">sequenced indices</a>, with differences in
the complexity of the operations, plus extra operations for
positional access (<code>operator[]</code> and <code>at()</code>) and
for capacity handling. Validity of iterators and references to elements
is preserved in all operations, regardless of the capacity status.
</p>
<p>
As is the case with sequenced indices, random access indices have the
following limitations with respect to STL sequence containers:
<ul>
<li>Random access indices are not <a href="http://www.sgi.com/tech/stl/Assignable.html">
<code>Assignable</code></a> (like any other index.)</li>
<li>Insertions into a random access index may fail due to clashings
with other indices. This alters the semantics of the operations
provided with respect to their analogues in STL sequence containers.
</li>
<li>Elements in a random access index are not mutable, and can only be changed
by means of <a href="#replace"><code>replace</code></a> and
<a href="#modify"><code>modify</code></a> member functions.
</li>
</ul>
Having these restrictions into account, random access indices are models
of <a href="http://www.sgi.com/tech/stl/RandomAccessContainer.html">
<code>Random Access Container</code></a> and
<a href="http://www.sgi.com/tech/stl/BackInsertionSequence.html">
<code>Back Insertion Sequence</code></a>. Although these indices do
not model
<a href="http://www.sgi.com/tech/stl/FrontInsertionSequence.html">
<code>Front Insertion Sequence</code></a>, because front insertion
and deletion take linear time, front operations are nonetheless provided
to match the interface of sequenced indices.
We only describe those types and operations that are
either not present in the concepts modeled or do not exactly conform
to the requirements for these types of containers.
</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>detail</span><span class=special>{</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>implementation defined: dependent on types Value, Allocator, TagList</b><span class=special>&gt;</span>
<span class=keyword>class</span> <b>name is implementation defined</b>
<span class=special>{</span>
<span class=keyword>public</span><span class=special>:</span>
<span class=comment>// types:</span>
<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=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>
<span class=keyword>typedef</span> <b>implementation defined</b> <span class=identifier>const_iterator</span><span class=special>;</span>
<span class=keyword>typedef</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>size_t</span> <span class=identifier>size_type</span><span class=special>;</span>
<span class=keyword>typedef</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>ptrdiff_t</span> <span class=identifier>difference_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>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_type</span><span class=special>::</span><span class=identifier>const_pointer</span> <span class=identifier>const_pointer</span><span class=special>;</span>
<span class=keyword>typedef</span> <b>equivalent to
std::reverse_iterator&lt;iterator&gt;</b> <span class=identifier>reverse_iterator</span><span class=special>;</span>
<span class=keyword>typedef</span> <b>equivalent to
std::reverse_iterator&lt;const_iterator&gt;</b> <span class=identifier>const_reverse_iterator</span><span class=special>;</span>
<span class=comment>// construct/copy/destroy:</span>
<b>index class name</b><span class=special>&amp;</span> <span class=keyword>operator</span><span class=special>=(</span><span class=keyword>const</span> <b>index class name</b><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>class</span> <span class=identifier>InputIterator</span><span class=special>&gt;</span>
<span class=keyword>void</span> <span class=identifier>assign</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>assign</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=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>value</span><span class=special>);</span>
<span class=identifier>allocator_type</span> <span class=identifier>get_allocator</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=comment>// iterators:</span>
<span class=identifier>iterator</span> <span class=identifier>begin</span><span class=special>();</span>
<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>reverse_iterator</span> <span class=identifier>rbegin</span><span class=special>();</span>
<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=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>
<span class=identifier>size_type</span> <span class=identifier>size</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>size_type</span> <span class=identifier>max_size</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>size_type</span> <span class=identifier>capacity</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=keyword>void</span> <span class=identifier>reserve</span><span class=special>(</span><span class=identifier>size_type</span> <span class=identifier>m</span><span class=special>);</span>
<span class=keyword>void</span> <span class=identifier>resize</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=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>=</span><span class=identifier>value_type</span><span class=special>());</span>
<span class=comment>// access:</span>
<span class=identifier>const_reference</span> <span class=keyword>operator</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_reference</span> <span class=identifier>at</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_reference</span> <span class=identifier>front</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>const_reference</span> <span class=identifier>back</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>push_front</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>void</span> <span class=identifier>pop_front</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>iterator</span><span class=special>,</span><span class=keyword>bool</span><span class=special>&gt;</span> <span class=identifier>push_back</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>void</span> <span class=identifier>pop_back</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>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=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>void</span> <span class=identifier>insert</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>m</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>InputIterator</span><span class=special>&gt;</span>
<span class=keyword>void</span> <span class=identifier>insert</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</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=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>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>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>
<span class=comment>// list operations:</span>
<span class=keyword>void</span> <span class=identifier>splice</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</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>splice</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</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=identifier>iterator</span> <span class=identifier>i</span><span class=special>);</span>
<span class=keyword>void</span> <span class=identifier>splice</span><span class=special>(</span>
<span class=identifier>iterator</span> <span class=identifier>position</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=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>void</span> <span class=identifier>remove</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>value</span><span class=special>);</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Predicate</span><span class=special>&gt;</span> <span class=keyword>void</span> <span class=identifier>remove_if</span><span class=special>(</span><span class=identifier>Predicate</span> <span class=identifier>pred</span><span class=special>);</span>
<span class=keyword>void</span> <span class=identifier>unique</span><span class=special>();</span>
<span class=keyword>template</span> <span class=special>&lt;</span><span class=keyword>class</span> <span class=identifier>BinaryPredicate</span><span class=special>&gt;</span>
<span class=keyword>void</span> <span class=identifier>unique</span><span class=special>(</span><span class=identifier>BinaryPredicate</span> <span class=identifier>binary_pred</span><span class=special>);</span>
<span class=keyword>void</span> <span class=identifier>merge</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>template</span> <span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Compare</span><span class=special>&gt;</span> <span class=keyword>void</span> <span class=identifier>merge</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=identifier>Compare</span> <span class=identifier>comp</span><span class=special>);</span>
<span class=keyword>void</span> <span class=identifier>sort</span><span class=special>();</span>
<span class=keyword>template</span> <span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Compare</span><span class=special>&gt;</span> <span class=keyword>void</span> <span class=identifier>sort</span><span class=special>(</span><span class=identifier>Compare</span> <span class=identifier>comp</span><span class=special>);</span>
<span class=keyword>void</span> <span class=identifier>reverse</span><span class=special>();</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>
<span class=keyword>template</span><span class=special>&lt;</span><b>arg set 1</b><span class=special>,</span><b>arg set 2</b><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>==(</span>
<span class=keyword>const</span> <b>index class name</b><span class=special>&lt;</span><b>arg set 1</b><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>,</span>
<span class=keyword>const</span> <b>index class name</b><span class=special>&lt;</span><b>arg set 2</b><span class=special>&gt;&amp;</span> <span class=identifier>y</span><span class=special>)</span>
<span class=special>{</span>
<span class=keyword>return</span> <span class=identifier>x</span><span class=special>.</span><span class=identifier>size</span><span class=special>()==</span><span class=identifier>y</span><span class=special>.</span><span class=identifier>size</span><span class=special>()&amp;&amp;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>equal</span><span class=special>(</span><span class=identifier>x</span><span class=special>.</span><span class=identifier>begin</span><span class=special>(),</span><span class=identifier>x</span><span class=special>.</span><span class=identifier>end</span><span class=special>(),</span><span class=identifier>y</span><span class=special>.</span><span class=identifier>begin</span><span class=special>());</span>
<span class=special>}</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>arg set 1</b><span class=special>,</span><b>arg set 2</b><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>&lt;(</span>
<span class=keyword>const</span> <b>index class name</b><span class=special>&lt;</span><b>arg set 1</b><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>,</span>
<span class=keyword>const</span> <b>index class name</b><span class=special>&lt;</span><b>arg set 2</b><span class=special>&gt;&amp;</span> <span class=identifier>y</span><span class=special>)</span>
<span class=special>{</span>
<span class=keyword>return</span> <span class=identifier>std</span><span class=special>::</span><span class=identifier>lexicographical_compare</span><span class=special>(</span><span class=identifier>x</span><span class=special>.</span><span class=identifier>begin</span><span class=special>(),</span><span class=identifier>x</span><span class=special>.</span><span class=identifier>end</span><span class=special>(),</span><span class=identifier>y</span><span class=special>.</span><span class=identifier>begin</span><span class=special>(),</span><span class=identifier>y</span><span class=special>.</span><span class=identifier>end</span><span class=special>());</span>
<span class=special>}</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>arg set 1</b><span class=special>,</span><b>arg set 2</b><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>!=(</span>
<span class=keyword>const</span> <b>index class name</b><span class=special>&lt;</span><b>arg set 1</b><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>,</span>
<span class=keyword>const</span> <b>index class name</b><span class=special>&lt;</span><b>arg set 2</b><span class=special>&gt;&amp;</span> <span class=identifier>y</span><span class=special>)</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>y</span><span class=special>);</span>
<span class=special>}</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>arg set 1</b><span class=special>,</span><b>arg set 2</b><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>&gt;(</span>
<span class=keyword>const</span> <b>index class name</b><span class=special>&lt;</span><b>arg set 1</b><span class=special>&gt;&amp;</span> <span class=identifier>x</span>
<span class=special>,</span><span class=keyword>const</span> <b>index class name</b><span class=special>&lt;</span><b>arg set 2</b><span class=special>&gt;&amp;</span> <span class=identifier>y</span><span class=special>)</span>
<span class=special>{</span>
<span class=keyword>return</span> <span class=identifier>y</span><span class=special>&lt;</span><span class=identifier>x</span><span class=special>;</span>
<span class=special>}</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>arg set 1</b><span class=special>,</span><b>arg set 2</b><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>&gt;=(</span>
<span class=keyword>const</span> <b>index class name</b><span class=special>&lt;</span><b>arg set 1</b><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>,</span>
<span class=keyword>const</span> <b>index class name</b><span class=special>&lt;</span><b>arg set 2</b><span class=special>&gt;&amp;</span> <span class=identifier>y</span><span class=special>)</span>
<span class=special>{</span>
<span class=keyword>return</span> <span class=special>!(</span><span class=identifier>x</span><span class=special>&lt;</span><span class=identifier>y</span><span class=special>);</span>
<span class=special>}</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>arg set 1</b><span class=special>,</span><b>arg set 2</b><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=keyword>operator</span><span class=special>&lt;=(</span>
<span class=keyword>const</span> <b>index class name</b><span class=special>&lt;</span><b>arg set 1</b><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>,</span>
<span class=keyword>const</span> <b>index class name</b><span class=special>&lt;</span><b>arg set 2</b><span class=special>&gt;&amp;</span> <span class=identifier>y</span><span class=special>)</span>
<span class=special>{</span>
<span class=keyword>return</span> <span class=special>!(</span><span class=identifier>x</span><span class=special>&gt;</span><span class=identifier>y</span><span class=special>);</span>
<span class=special>}</span>
<span class=comment>// index specialized algorithms:</span>
<span class=keyword>template</span><span class=special>&lt;</span><b>implementation defined</b><span class=special>&gt;</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><b>index class name</b><span class=special>&amp;</span> <span class=identifier>y</span><span class=special>);</span>
<span class=special>}</span> <span class=comment>// namespace boost::multi_index::detail</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>
<h4><a name="complexity_signature">Complexity signature</a></h4>
<p>
Here and in the descriptions of operations of random access indices, we
adopt the scheme outlined in the
<a href="indices.html#complexity_signature">complexity signature
section</a>. The complexity signature of random access indices is:
<ul>
<li>copying: <code>c(n)=n*log(n)</code>,</li>
<li>insertion: <code>i(n)=1</code> (amortized constant),</li>
<li>hinted insertion: <code>h(n)=1</code> (amortized constant),</li>
<li>deletion: <code>d(n)=m</code>, where <code>m</code> is the distance
from the deleted element to the end of the sequence,</li>
<li>replacement: <code>r(n)=1</code> (constant),</li>
<li>modifying: <code>m(n)=1</code> (constant).</li>
</ul>
The following expressions are also used as a convenience for writing down some
of the complexity formulas:
</p>
<blockquote>
<code>shl(a,b)</code> = <code>a+b</code> if a is nonzero, <code>0</code> otherwise.<br>
<code>rel(a,b,c)</code> = if <code>a&lt;b</code>, <code>c-a</code>, else <code>a-b</code>,
</blockquote>
<p>
(<code>shl</code> and <code>rel</code> stand for <i>shift left</i> and
<i>relocate</i>, respetively.)
</p>
<h4><a name="instantiation_types">Instantiation types</a></h4>
<p>Random access indices are instantiated internally to <code>multi_index_container</code>
and specified by means of <a href="indices.html#indexed_by">
<code>indexed_by</code></a> with the <a href="#random_access"><code>random_access</code></a>
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>
</ul>
<code>TagList</code> must be an instantiation of
<a href="indices.html#tag"><code>tag</code></a>.
</p>
<h4><a name="constructors">Constructors, copy and assignment</a></h4>
<p>
As explained in the <a href="indices.html#index_concepts">index
concepts section</a>, indices do not have public constructors or destructors.
Assignment, on the other hand, is provided.
</p>
<code><b>index class name</b>&amp; operator=(const <b>index class name</b>&amp; x);</code>
<blockquote>
<b>Effects:</b>
<blockquote><pre>
<span class=identifier>a</span><span class=special>=</span><span class=identifier>b</span><span class=special>;</span>
</pre></blockquote>
where <code>a</code> and <code>b</code> are the <code>multi_index_container</code>
objects to which <code>*this</code> and <code>x</code> belong, respectively.<br>
<b>Returns:</b> <code>*this</code>.<br>
</blockquote>
<code>template &lt;class InputIterator><br>
void assign(InputIterator first,InputIterator last);</code>
<blockquote>
<b>Requires:</b> <code>InputIterator</code> is a model of
<a href="http://www.sgi.com/tech/stl/InputIterator.html">
<code>Input Iterator</code></a> over elements of type
<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>
<b>Effects:</b>
<blockquote><pre>
<span class=identifier>clear</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>first</span><span class=special>,</span><span class=identifier>last</span><span class=special>);</span>
</pre></blockquote>
</blockquote>
<code>void assign(size_type n,const value_type&amp; value);</code>
<blockquote>
<b>Effects:</b>
<blockquote><pre>
<span class=identifier>clear</span><span class=special>();</span>
<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>n</span><span class=special>)</span><span class=identifier>push_back</span><span class=special>(</span><span class=identifier>v</span><span class=special>);</span>
</pre></blockquote>
</blockquote>
<h4><a name="capacity">Capacity operations</a></h4>
<a name="capacity_memfun"><code>size_type capacity()const;</code></a>
<blockquote>
<b>Returns:</b> The total number of elements <code>c</code> such that, when
<code>size()&lt;c</code>, back insertions happen in constant time (the
general case as described by
<a href="#complexity_signature"><code>i(n)</code></a> is <i>amortized</i>
constant time.)<br>
<b>Note:</b> Validity of iterators and references to elements
is preserved in all insertions, regardless of the capacity status.
</blockquote>
<a name="reserve"><code>void reserve(size_type m);</code></a>
<blockquote>
<b>Effects:</b> If the previous value of <code>capacity()</code>
was greater than or equal to <code>m</code>, nothing is done;
otherwise, the internal capacity is changed so that
<code>capacity()>=m</code>.<br>
<b>Complexity:</b> If the capacity is not changed, constant;
otherwise <code>O(n)</code>.<br>
<b>Exception safety:</b> If the capacity is not changed, <code>nothrow</code>;
otherwise, strong.<br>
</blockquote>
<code>void resize(size_type n,const value_type&amp; x=value_type());</code>
<blockquote>
<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>
</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.)
</blockquote>
<h4><a name="modifiers">Modifiers</a></h4>
<code>std::pair&lt;iterator,bool> push_front(const value_type&amp; x);</code>
<blockquote>
<b>Effects:</b> Inserts <code>x</code> at the beginning of the sequence if
no other index of the <code>multi_index_container</code> bans the insertion.<br>
<b>Returns:</b> The return value is a pair <code>p</code>. <code>p.second</code>
is <code>true</code> if and only if insertion took place. On successful
insertion, <code>p.first</code> points to the element inserted; otherwise,
<code>p.first</code> points to an element that caused the insertion to be banned.
Note that more than one element can be causing insertion not to be allowed.<br>
<b>Complexity:</b> <code>O(n+I(n))</code>.<br>
<b>Exception safety:</b> Strong.
</blockquote>
<code>std::pair&lt;iterator,bool> push_back(const value_type&amp; x);</code>
<blockquote>
<b>Effects:</b> Inserts <code>x</code> at the end of the sequence if
no other index of the <code>multi_index_container</code> bans the insertion.<br>
<b>Returns:</b> The return value is a pair <code>p</code>. <code>p.second</code>
is <code>true</code> if and only if insertion took place. On successful
insertion, <code>p.first</code> points to the element inserted; otherwise,
<code>p.first</code> points to an element that caused the insertion to be banned.
Note that more than one element can be causing insertion not to be allowed.<br>
<b>Complexity:</b> <code>O(I(n))</code>.<br>
<b>Exception safety:</b> Strong.
</blockquote>
<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>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>
is <code>true</code> if and only if insertion took place. On successful
insertion, <code>p.first</code> points to the element inserted; otherwise,
<code>p.first</code> points to an element that caused the insertion to be banned.
Note that more than one element can be causing insertion not to be allowed.<br>
<b>Complexity:</b> <code>O(shl(end()-position,1) + I(n))</code>.<br>
<b>Exception safety:</b> Strong.
</blockquote>
<code>void insert(iterator position,size_type m,const value_type&amp; x);</code>
<blockquote>
<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>m</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>
</pre></blockquote>
<b>Complexity:</b> <code>O(shl(end()-position,m) + m*I(n+m))</code>.
</blockquote>
<code>template&lt;typename InputIterator><br>
void insert(iterator position,InputIterator first,InputIterator last);</code>
<blockquote>
<b>Requires:</b> <code>position</code> is a valid iterator of the index.
<code>InputIterator</code> is a model of
<a href="http://www.sgi.com/tech/stl/InputIterator.html">
<code>Input Iterator</code></a> over elements of type
<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>
<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>
</pre></blockquote>
<b>Complexity:</b> <code>O(shl(end()-position,m) + m*I(n+m))</code>,
where <code>m</code> is the number of elements in
[<code>first</code>,<code>last</code>).<br>
<b>Exception safety:</b> Basic.
</blockquote>
<code>iterator erase(iterator position);</code>
<blockquote>
<b>Requires:</b> <code>position</code> is a valid dereferenceable iterator
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>
<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>
</blockquote>
<a name="replace"><code>bool replace(iterator position,const value_type&amp; x);</code></a>
<blockquote>
<b>Requires:</b> <code>position</code> is a valid dereferenceable iterator
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
<code>multi_index_container</code>.<br>
<b>Postconditions:</b> Validity of <code>position</code> is preserved
in all cases.<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>
<b>Exception safety:</b> Strong. If an exception is thrown by some
user-provided operation the <code>multi_index_container</code> to which the index
belongs remains in its original state.
</blockquote>
<a name="modify">
<code>template&lt;typename Modifier> bool modify(iterator position,Modifier mod);</code></a>
<blockquote>
<b>Requires:</b> <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>value_type&amp;</code>. <code>position</code> is a valid dereferenceable
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
rancom access 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 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.
</blockquote>
<h4><a name="list_operations">List operations</a></h4>
<p>
Random access indices replicate the interface of sequenced indices, which
in turn includes the list operations provided by <code>std::list</code>.
The syntax and behavior of these operations exactly matches those
of sequenced indices, but the associated complexity bounds differ in general.
</p>
<code>void splice(iterator position,<b>index class name</b>&amp; x);</code>
<blockquote>
<b>Requires:</b> <code>position</code> is a valid iterator of the index.
<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>
<b>Complexity:</b> <code>O(shl(end()-position,x.size()) + x.size()*I(n+x.size()) + x.size()*D(x.size()))</code>.<br>
<b>Exception safety:</b> Basic.<br>
</blockquote>
<code>void splice(iterator position,<b>index class name</b>&amp; x,iterator i);</code>
<blockquote>
<b>Requires:</b> <code>position</code> is a valid iterator of the index.
<code>i</code> is a valid dereferenceable iterator <code>x</code>.<br>
<b>Effects:</b> Inserts the element pointed to by <code>i</code> before
<code>position</code>: if insertion is succesful, the element is erased from
<code>x</code>. In the special case <code>&amp;x==this</code>, no copy or
deletion is performed, and the operation is always succesful. If
<code>position==i</code>, no operation is performed.<br>
<b>Postconditions:</b> If <code>&amp;x==this</code>, no iterator or reference
is invalidated.<br>
<b>Complexity:</b> If <code>&amp;x==this</code>, <code>O(rel(position,i,i+1))</code>;
otherwise <code>O(shl(end()-position,1) + I(n) + D(n))</code>.<br>
<b>Exception safety:</b> If <code>&amp;x==this</code>, <code>nothrow</code>;
otherwise, strong.<br>
</blockquote>
<code>void splice(iterator position,<b>index class name&amp;</b> x,iterator first,iterator last);</code>
<blockquote>
<b>Requires:</b> <code>position</code> is a valid iterator of the index.
<code>first</code> and <code>last</code> are valid iterators of <code>x</code>.
<code>last</code> is reachable from <code>first</code>. <code>position</code>
is not in the range [<code>first</code>,<code>last</code>).<br>
<b>Effects:</b> For each element in the range [<code>first</code>,<code>last</code>),
insertion is tried before <code>position</code>; if the operation is succesful,
the element is erased from <code>x</code>. In the special case
<code>&amp;x==this</code>, no copy or deletion is performed, and insertions are
always succesful.<br>
<b>Postconditions:</b> If <code>&amp;x==this</code>, no iterator or reference
is invalidated.<br>
<b>Complexity:</b> If <code>&amp;x==this</code>,
<code>O(rel(position,first,last))</code>; otherwise
<code>O(shl(end()-position,m) + m*I(n+m) + m*D(x.size()))</code>
where <code>m</code> is the number of elements in [<code>first</code>,<code>last</code>).<br>
<b>Exception safety:</b> If <code>&amp;x==this</code>, <code>nothrow</code>;
otherwise, basic.<br>
</blockquote>
<code>void remove(const value_type&amp; value);</code>
<blockquote>
<b>Effects:</b> Erases all elements of the index which compare equal to
<code>value</code>.<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.
</blockquote>
<code>template&lt;typename Predicate> void remove_if(Predicate pred);</code>
<blockquote>
<b>Effects:</b> Erases all elements <code>x</code> of the index for which
<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.
</blockquote>
<code>void unique();</code>
<blockquote>
<b>Effects:</b> Eliminates all but the first element from every consecutive
group of equal elements referred to by the iterator <code>i</code> in the range
[<code>first+1</code>,<code>last</code>) for which <code>*i==*(i-1)</code>.<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.
</blockquote>
<code>template &lt;class BinaryPredicate> void unique(BinaryPredicate binary_pred);</code>
<blockquote>
<b>Effects:</b> Eliminates all but the first element from every consecutive
group of elements referred to by the iterator <code>i</code> in the range
[<code>first+1</code>,<code>last</code>) for which
<code>binary_pred(*i,*(i-1))</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.
</blockquote>
<code>void merge(index class name&amp; x);</code>
<blockquote>
<b>Requires:</b> <code>std::less&lt;value_type></code> is a
<a href="http://www.sgi.com/tech/stl/StrictWeakOrdering.html">
<code>Strict Weak Ordering</code></a> over <code>value_type</code>.
Both the index and <code>x</code> are sorted according to
<code>std::less&lt;value_type></code>.<br>
<b>Effects:</b> Attempts to insert every element of <code>x</code> into the
corresponding position of the index (according to the order). Elements
successfully inserted are erased from <code>x</code>. The resulting sequence
is stable, i.e. equivalent elements of either container preserve their
relative position. In the special case <code>&amp;x==this</code>, no operation
is performed.<br>
<b>Postconditions:</b> Elements in the index and remaining elements in
<code>x</code> are sorted.
Validity of iterators to the index and of non-erased elements of <code>x</code>
references is preserved.<br>
<b>Complexity:</b> If <code>&amp;x==this</code>, constant; otherwise
<code>O(n + x.size()*I(n+x.size()) + x.size()*D(x.size()))</code>.<br>
<b>Exception safety:</b> If <code>&amp;x==this</code>, <code>nothrow</code>;
otherwise, basic.<br>
</blockquote>
<code>template &lt;typename Compare> void merge(index class name&amp; x,Compare comp);</code>
<blockquote>
<b>Requires:</b> <code>Compare</code> is a
<a href="http://www.sgi.com/tech/stl/StrictWeakOrdering.html">
<code>Strict Weak Ordering</code></a> over <code>value_type</code>.
Both the index and <code>x</code> are sorted according to <code>comp</code>.<br>
<b>Effects:</b> Attempts to insert every element of <code>x</code> into the
corresponding position of the index (according to <code>comp</code>).
Elements successfully inserted are erased from <code>x</code>. The resulting
sequence is stable, i.e. equivalent elements of either container preserve
their relative position. In the special case <code>&amp;x==this</code>, no
operation is performed.<br>
<b>Postconditions:</b> Elements in the index and remaining elements in
<code>x</code> are sorted according to <code>comp</code>.
Validity of iterators to the index and of non-erased elements of <code>x</code>
references is preserved.<br>
<b>Complexity:</b> If <code>&amp;x==this</code>, constant; otherwise
<code>O(n + x.size()*I(n+x.size()) + x.size()*D(x.size()))</code>.<br>
<b>Exception safety:</b> If <code>&amp;x==this</code>, <code>nothrow</code>;
otherwise, basic.<br>
</blockquote>
<code>void sort();</code>
<blockquote>
<b>Requires:</b> <code>std::less&lt;value_type></code> is a
<a href="http://www.sgi.com/tech/stl/StrictWeakOrdering.html">
<code>Strict Weak Ordering</code></a> over <code>value_type</code>.<br>
<b>Effects:</b> Sorts the index according to
<code>std::less&lt;value_type></code>. The sorting is stable, i.e.
equivalent elements preserve their relative position.<br>
<b>Postconditions:</b> Validity of iterators and references is preserved.<br>
<b>Complexity:</b> <code>O(n*log(n))</code>.<br>
<b>Exception safety:</b> Basic.
</blockquote>
<code>template &lt;typename Compare> void sort(Compare comp);</code>
<blockquote>
<b>Requires:</b> <code>Compare</code> is a
<a href="http://www.sgi.com/tech/stl/StrictWeakOrdering.html">
<code>Strict Weak Ordering</code></a> over <code>value_type</code>.<br>
<b>Effects:</b> Sorts the index according to <code>comp</code>. The sorting
is stable, i.e. equivalent elements preserve their relative position.<br>
<b>Postconditions:</b> Validity of iterators and references is preserved.<br>
<b>Complexity:</b> <code>O(n*log(n))</code>.<br>
<b>Exception safety:</b> Basic.
</blockquote>
<code>void reverse();</code>
<blockquote>
<b>Effects:</b> Reverses the order of the elements in the index.<br>
<b>Postconditions:</b> Validity of iterators and references is preserved.<br>
<b>Complexity:</b> <code>O(n)</code>.<br>
<b>Exception safety:</b> <code>nothrow</code>.
</blockquote>
<h4><a name="rearrange_operations">Rearrange operations</a></h4>
<p>
These operations, without counterpart in STL sequence containers
(although <code>std::list::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>
<blockquote>
<b>Requires:</b> <code>position</code> is a valid iterator of the index.
<code>i</code> is a valid dereferenceable iterator of the index.<br>
<b>Effects:</b> Inserts the element pointed to by <code>i</code> before
<code>position</code>. If <code>position==i</code>, no operation is
performed.<br>
<b>Postconditions:</b> No iterator or reference is invalidated.<br>
<b>Complexity:</b> <code>O(rel(position,i,i+1))</code>.<br>
<b>Exception safety:</b> <code>nothrow</code>.<br>
</blockquote>
<code>void relocate(iterator position,iterator first,iterator last);</code>
<blockquote>
<b>Requires:</b> <code>position</code> is a valid iterator of the index.
<code>first</code> and <code>last</code> are valid iterators of the index.
<code>last</code> is reachable from <code>first</code>. <code>position</code>
is not in the range [<code>first</code>,<code>last</code>).<br>
<b>Effects:</b> The range of elements [<code>first</code>,<code>last</code>)
is repositioned just before <code>position</code>.<br>
<b>Postconditions:</b> No iterator or reference is invalidated.<br>
<b>Complexity:</b> <code>O(rel(position,first,last))</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>
Indices cannot be serialized on their own, but only as part of the
<code>multi_index_container</code> into which they are embedded. In describing
the additional preconditions and guarantees associated to random access indices
with respect to serialization of their embedding containers, we
use the concepts defined in the <code>multi_index_container</code>
<a href="multi_index_container.html#serialization">serialization section</a>.
</p>
Operation: saving of a <code>multi_index_container</code> <code>m</code> to an
output archive (XML archive) <code>ar</code>.
<blockquote>
<b>Requires:</b> No additional requirements to those imposed by the container.
</blockquote>
Operation: loading of a <code>multi_index_container</code> <code>m'</code> from an
input archive (XML archive) <code>ar</code>.
<blockquote>
<b>Requires:</b> No additional requirements to those imposed by the container.<br>
<b>Postconditions:</b> On succesful loading, each of the elements of
[<code>begin()</code>, <code>end()</code>) is a restored copy of the corresponding
element in [<code>m.get&lt;i&gt;().begin()</code>, <code>m.get&lt;i&gt;().end()</code>),
where <code>i</code> is the position of the random access index in the container.
</blockquote>
Operation: saving of an <code>iterator</code> or <code>const_iterator</code>
<code>it</code> to an output archive (XML archive) <code>ar</code>.
<blockquote>
<b>Requires:</b> <code>it</code> is a valid iterator of the index. The associated
<code>multi_index_container</code> has been previously saved.
</blockquote>
Operation: loading of an <code>iterator</code> or <code>const_iterator</code>
<code>it'</code> from an input archive (XML archive) <code>ar</code>.
<blockquote>
<b>Postconditions:</b> On succesful loading, if <code>it</code> was dereferenceable
then <code>*it'</code> is the restored copy of <code>*it</code>, otherwise
<code>it'==end()</code>.<br>
<b>Note:</b> It is allowed that <code>it</code> be a <code>const_iterator</code>
and the restored <code>it'</code> an <code>iterator</code>, or viceversa.
</blockquote>
<hr>
<div class="prev_link"><a href="seq_indices.html"><img src="../prev.gif" alt="sequenced indices" border="0"><br>
Sequenced 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
</a></div>
<div class="next_link"><a href="key_extraction.html"><img src="../next.gif" alt="key extraction" border="0"><br>
Key extraction
</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>
+95 -23
View File
@@ -5,20 +5,24 @@
<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>
<h1><img src="../../../../boost.png" alt="boost.png (6897 bytes)" align=
"middle" width="277" height="86">Boost.MultiIndex Sequenced indices reference</h1>
<div class="prev_link"><a href="ord_indices.html"><img src="../prev.gif" alt="ordered indices" border="0"><br>
Ordered indices
<div class="prev_link"><a href="hash_indices.html"><img src="../prev.gif" alt="hashed indices" border="0"><br>
Hashed 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
</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>
@@ -40,7 +44,8 @@ Key extraction
<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>
</ul>
@@ -144,7 +149,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>
@@ -169,7 +175,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>
@@ -281,10 +287,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>
@@ -437,7 +444,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.)
@@ -591,7 +602,7 @@ the element pointed to by <code>position</code> is erased.
<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
@@ -664,7 +675,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.
@@ -778,14 +789,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>
@@ -815,23 +825,85 @@ 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>
Indices cannot be serialized on their own, but only as part of the
<code>multi_index_container</code> into which they are embedded. In describing
the additional preconditions and guarantees associated to sequenced indices
with respect to serialization of their embedding containers, we
use the concepts defined in the <code>multi_index_container</code>
<a href="multi_index_container.html#serialization">serialization section</a>.
</p>
Operation: saving of a <code>multi_index_container</code> <code>m</code> to an
output archive (XML archive) <code>ar</code>.
<blockquote>
<b>Requires:</b> No additional requirements to those imposed by the container.
</blockquote>
Operation: loading of a <code>multi_index_container</code> <code>m'</code> from an
input archive (XML archive) <code>ar</code>.
<blockquote>
<b>Requires:</b> No additional requirements to those imposed by the container.<br>
<b>Postconditions:</b> On succesful loading, each of the elements of
[<code>begin()</code>, <code>end()</code>) is a restored copy of the corresponding
element in [<code>m.get&lt;i&gt;().begin()</code>, <code>m.get&lt;i&gt;().end()</code>),
where <code>i</code> is the position of the sequenced index in the container.
</blockquote>
Operation: saving of an <code>iterator</code> or <code>const_iterator</code>
<code>it</code> to an output archive (XML archive) <code>ar</code>.
<blockquote>
<b>Requires:</b> <code>it</code> is a valid iterator of the index. The associated
<code>multi_index_container</code> has been previously saved.
</blockquote>
Operation: loading of an <code>iterator</code> or <code>const_iterator</code>
<code>it'</code> from an input archive (XML archive) <code>ar</code>.
<blockquote>
<b>Postconditions:</b> On succesful loading, if <code>it</code> was dereferenceable
then <code>*it'</code> is the restored copy of <code>*it</code>, otherwise
<code>it'==end()</code>.<br>
<b>Note:</b> It is allowed that <code>it</code> be a <code>const_iterator</code>
and the restored <code>it'</code> an <code>iterator</code>, or viceversa.
</blockquote>
<hr>
<div class="prev_link"><a href="ord_indices.html"><img src="../prev.gif" alt="ordered indices" border="0"><br>
Ordered indices
<div class="prev_link"><a href="hash_indices.html"><img src="../prev.gif" alt="hashed indices" border="0"><br>
Hashed 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
</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 September 28th 2004</p>
<p>Revised February 6th 2006</p>
<p>&copy; Copyright 2003-2004 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">
+153
View File
@@ -0,0 +1,153 @@
<!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 - 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>
<h1><img src="../../../boost.png" alt="boost.png (6897 bytes)" align=
"middle" width="277" height="86">Boost.MultiIndex Release notes</h1>
<div class="prev_link"><a href="future_work.html"><img src="prev.gif" alt="future work" border="0"><br>
Future work
</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="acknowledgements.html"><img src="next.gif" alt="acknowledgements" border="0"><br>
Acknowledgements
</a></div><br clear="all" style="clear: all;">
<hr>
<h2>Contents</h2>
<ul>
<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_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="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>
<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>
memfuns now perform faster.
</li>
<li>Internal changes aimed at reducing the length of symbol names generated
by the compiler; cuts of up to a 50% can be achieved with respect to the
Boost 1.32 release. This results in much shorter and more readable error
messages and has also a beneficial impact on compilers with strict limits on
symbol name lengths. Additionally, a section on further
<a href="compiler_specifics.html#symbol_reduction">reduction of symbol name
lengths</a> has been added.
</li>
<li>Restructured some parts of the documentation, new examples.</li>
<li>Maintenance fixes.</li>
</ul>
</p>
<hr>
<div class="prev_link"><a href="future_work.html"><img src="prev.gif" alt="future work" border="0"><br>
Future work
</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="acknowledgements.html"><img src="next.gif" alt="acknowledgements" border="0"><br>
Acknowledgements
</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>
+35 -18
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>
@@ -58,33 +63,41 @@ with some of the least common features offered by Boost.MultiIndex.
</tr>
<tr>
<td><a href="../test/test_conv_iterators.cpp"><code>test_conv_iterators.cpp</code></a></td>
<td>Checks convertibility of constant to non-constant iterators.</td>
<td>Checks convertibility of non-constant to constant iterators.</td>
</tr>
<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>
<td>Hashing operations.</td>
</tr>
<tr class="odd_tr">
<td><a href="../test/test_iterators.cpp"><code>test_iterators.cpp</code></a></td>
<td>Constant and non-constant iterators and their reverse variants.</td>
</tr>
<tr class="odd_tr">
<tr>
<td><a href="../test/test_key_extractors.cpp"><code>test_key_extractors.cpp</code></a></td>
<td>Covers all use cases of key extractors shipped with the library.</td>
</tr>
<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>
</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 and random access indices.</td>
</tr>
<tr>
<td><a href="../test/test_modifiers.cpp"><code>test_modifiers.cpp</code></a></td>
<td>Checks the family of insertion and erasing operations.</td>
</tr>
<tr>
<tr class="odd_tr">
<td><a href="../test/test_mpl_ops.cpp"><code>test_mpl_ops.cpp</code></a></td>
<td>Metaprogramming manipulations of <code>multi_index_container</code> types.</td>
</tr>
<tr>
<td><a href="../test/test_observers.cpp"><code>test_observers.cpp</code></a></td>
<td>Checks observer member functions of ordered and hashed indices.</td>
</tr>
<tr class="odd_tr">
<td><a href="../test/test_projection.cpp"><code>test_projection.cpp</code></a></td>
<td>Projection of iterators among indices.</td>
@@ -94,23 +107,27 @@ 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 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></td>
<td>Serialization support.</td>
</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 class="odd_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>
<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>
</tr>
<tr class="odd_tr">
<tr>
<td><a href="../test/test_update.cpp"><code>test_update.cpp</code></a></td>
<td><code>replace</code>, <code>modify</code> and <code>modify_key</code>.</td>
</tr>
@@ -132,9 +149,9 @@ Future work
<br>
<p>Revised May 28th 2004</p>
<p>Revised March 2nd 2006</p>
<p>&copy; Copyright 2003-2004 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">
+132 -199
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>
@@ -220,9 +156,9 @@ 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
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 +238,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 +304,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 +338,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 +396,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 +448,51 @@ 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>
<p>
Additionally, <code>multi_index_container</code>s provide shortcut
definitions to the iterator types of their constituent indices:
</p>
<blockquote><pre>
<span class=identifier>employee_set</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>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>
There is a variation of the expression above for use with
<a href="#tagging">tags</a>:
</p>
<blockquote><pre>
<span class=identifier>employee_set</span><span class=special>::</span><span class=identifier>index_iterator</span><span class=special>&lt;</span><span class=identifier>name</span><span class=special>&gt;::</span><span class=identifier>type</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=identifier>name</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> <span class=comment>// get&lt;1&gt; would also work</span>
</pre></blockquote>
<h2>
<a name="index_types">Index types</a>
</h2>
@@ -521,9 +507,19 @@ Currently, Boost.MultiIndex provides the following index types:
<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>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 all of these
indices.
The examples in the <a href="#intro">introduction</a> exercise ordered and sequenced
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>
@@ -647,13 +643,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
@@ -681,78 +677,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#const_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>
@@ -841,7 +770,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
@@ -916,9 +845,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>
@@ -954,7 +883,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>
@@ -990,7 +919,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>
@@ -1033,12 +962,9 @@ process of calling <code>modify</code>, the element is erased and the method ret
<p>
A key-based version of <code>modify</code>, named
<a href="reference/ord_indices.html#modify_key"><code>modify_key</code></a>, is
<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>.
the <code>key_value</code> part of the element instead of the whole object.
</p>
<blockquote><pre>
@@ -1067,7 +993,7 @@ as <code>const_mem_fun</code>.
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
<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>
@@ -1081,6 +1007,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>
@@ -1101,10 +1034,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>
@@ -1171,15 +1104,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>
@@ -1188,7 +1121,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
@@ -1250,33 +1183,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 July 26th 2004</p>
<p>Revised July 13th 2006</p>
<p>&copy; Copyright 2003-2004 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, 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>
+298
View File
@@ -0,0 +1,298 @@
<!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="#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="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 February 27th 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>
+677
View File
@@ -0,0 +1,677 @@
<!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="#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>
</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="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 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>
+845
View File
@@ -0,0 +1,845 @@
<!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>
</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>
<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=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="4"><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 class="odd_tr">
<td align="center" rowspan="4"><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>
<td align="center" rowspan="4"><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 class="odd_tr">
<td align="center" rowspan="4">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>
<td align="center" rowspan="4">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>
</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 case is for <code>T::g</code> when
the elements are raw <code>T</code> objects, which make sense as we are dealing
with a non-constant member function: this also implies that <code>multi_index_container</code>s
of elements of <code>T</code> cannot be sorted by <code>T::g</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 the 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 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>

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_iterator&lt;n>::type</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 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>
+22 -3
View File
@@ -1,14 +1,12 @@
# Boost.MultiIndex examples Jamfile
#
# Copyright 2003-2004 Joaquín M López Muñoz.
# Copyright 2003-2006 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,6 +27,11 @@ exe composite_keys
: <include>$(BOOST_ROOT)
;
exe hashed
: hashed.cpp
: <include>$(BOOST_ROOT)
;
exe memfun_key
: memfun_key.cpp
: <include>$(BOOST_ROOT)
@@ -39,7 +42,23 @@ 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)
;
exe serialization
: serialization.cpp
/boost/serialization//boost_serialization
: <include>$(BOOST_ROOT)
;
+2 -2
View File
@@ -1,6 +1,6 @@
/* Boost.MultiIndex basic example.
*
* Copyright 2003-2004 Joaquín M López Muñoz.
* 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)
@@ -47,7 +47,7 @@ struct id{};
struct name{};
struct age{};
/* see Advanced topics: Use of member_offset for info on
/* see Compiler specifics: Use of member_offset for info on
* BOOST_MULTI_INDEX_MEMBER
*/
+2 -2
View File
@@ -1,6 +1,6 @@
/* Boost.MultiIndex example of a bidirectional map.
*
* Copyright 2003-2004 Joaquín M López Muñoz.
* 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)
@@ -42,7 +42,7 @@ struct bidirectional_map
defined(BOOST_INTEL_CXX_VERSION)&&defined(_MSC_VER)&&\
(BOOST_INTEL_CXX_VERSION<=700)
/* see Advanced topics: Use of member_offset for info on member<> and
/* see Compiler specifics: Use of member_offset for info on member<> and
* member_offset<>
*/
+2 -2
View File
@@ -1,6 +1,6 @@
/* Boost.MultiIndex example: complex searches and foreign keys.
*
* Copyright 2003-2004 Joaquín M López Muñoz.
* 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)
@@ -88,7 +88,7 @@ struct car_model
}
};
/* see Advanced topics: Use of member_offset for info on
/* see Compiler specifics: Use of member_offset for info on
* BOOST_MULTI_INDEX_MEMBER
*/
+5 -6
View File
@@ -1,6 +1,6 @@
/* Boost.MultiIndex example of composite keys.
*
* Copyright 2003-2004 Joaquín M López Muñoz.
* 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)
@@ -56,9 +56,8 @@ struct file_entry
* file and size. These indices are firstly ordered by directory, as commands
* work on a current directory basis. Composite keys are just fine to model
* this.
* NB: We use derivation here instead of simple typedef's as MSVC++ 6.0
* chokes otherwise. Seems to be related with the complexity of the type
* generated.
* NB: The use of derivation here instead of simple typedef is explained in
* Compiler specifics: type hiding.
*/
struct name_key:composite_key<
@@ -73,8 +72,8 @@ struct size_key:composite_key<
BOOST_MULTI_INDEX_MEMBER(file_entry,unsigned,size)
>{};
/* see Advanced topics: composite_key in compilers without partial template
* specialization, for info on composite_key_result_less
/* see Compiler specifics: composite_key in compilers without partial
* template specialization, for info on composite_key_result_less
*/
typedef multi_index_container<
+122
View File
@@ -0,0 +1,122 @@
/* Boost.MultiIndex example of use of hashed indices.
*
* 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.
*/
#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/hashed_index.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/tokenizer.hpp>
#include <iomanip>
#include <iostream>
#include <string>
using boost::multi_index_container;
using namespace boost::multi_index;
/* word_counter keeps the ocurrences of words inserted. A hashed
* index allows for fast checking of preexisting entries.
*/
struct word_counter_entry
{
std::string word;
unsigned int occurrences;
word_counter_entry(std::string word_):word(word_),occurrences(0){}
};
/* see Compiler specifics: Use of member_offset for info on
* BOOST_MULTI_INDEX_MEMBER
*/
typedef multi_index_container<
word_counter_entry,
indexed_by<
ordered_non_unique<
BOOST_MULTI_INDEX_MEMBER(word_counter_entry,unsigned int,occurrences),
std::greater<unsigned int> /* sorted beginning with most frequent */
>,
hashed_unique<
BOOST_MULTI_INDEX_MEMBER(word_counter_entry,std::string,word)
>
>
> word_counter;
/* utilities */
template<typename T>
struct increment
{
void operator()(T& x)const{++x;}
};
typedef boost::tokenizer<boost::char_separator<char> > text_tokenizer;
int main()
{
std::string text=
"En un lugar de la Mancha, de cuyo nombre no quiero acordarme, no ha "
"mucho tiempo que vivía un hidalgo de los de lanza en astillero, adarga "
"antigua, rocín flaco y galgo corredor. Una olla de algo más vaca que "
"carnero, salpicón las más noches, duelos y quebrantos los sábados, "
"lantejas los viernes, algún palomino de añadidura los domingos, "
"consumían las tres partes de su hacienda. El resto della concluían sayo "
"de velarte, calzas de velludo para las fiestas, con sus pantuflos de lo "
"mesmo, y los días de entresemana se honraba con su vellorí de lo más "
"fino. Tenía en su casa una ama que pasaba de los cuarenta, y una "
"sobrina que no llegaba a los veinte, y un mozo de campo y plaza, que "
"así ensillaba el rocín como tomaba la podadera. Frisaba la edad de "
"nuestro hidalgo con los cincuenta años; era de complexión recia, seco "
"de carnes, enjuto de rostro, gran madrugador y amigo de la caza. "
"Quieren decir que tenía el sobrenombre de Quijada, o Quesada, que en "
"esto hay alguna diferencia en los autores que deste caso escriben; "
"aunque, por conjeturas verosímiles, se deja entender que se llamaba "
"Quejana. Pero esto importa poco a nuestro cuento; basta que en la "
"narración dél no se salga un punto de la verdad.";
/* feed the text into the container */
word_counter wc;
text_tokenizer tok(text,boost::char_separator<char>(" \t\n.,;:!?'\"-"));
unsigned int total_occurrences=0;
for(text_tokenizer::iterator it=tok.begin(),it_end=tok.end();
it!=it_end;++it){
/* Insert the word into the container. If duplicate, wit will point to
* the preexistent entry.
*/
++total_occurrences;
word_counter::iterator wit=wc.insert(*it).first;
/* Increment occurrences.
* In a lambda-capable compiler, this can be written as:
* wc.modify_key(wit,++_1);
*/
wc.modify_key(wit,increment<unsigned int>());
}
/* list words by frequency of appearance */
std::cout<<std::fixed<<std::setprecision(2);
for(word_counter::iterator wit=wc.begin(),wit_end=wc.end();
wit!=wit_end;++wit){
std::cout<<std::setw(11)<<wit->word<<": "
<<std::setw(5) <<100.0*wit->occurrences/total_occurrences<<"%"
<<std::endl;
}
return 0;
}
+7 -4
View File
@@ -1,6 +1,6 @@
/* Boost.MultiIndex example of member functions used as key extractors.
*
* Copyright 2003-2004 Joaquín M López Muñoz.
* Copyright 2003-2006 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)
@@ -29,8 +29,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 +46,10 @@ private:
std::string family_name;
};
/* multi_index_container with only one index based on name_record::name() */
/* multi_index_container with only one index based on name_record::name().
* See Compiler specifics: Use of const_mem_fun_explicit and
* mem_fun_explicit for info on BOOST_MULTI_INDEX_CONST_MEM_FUN.
*/
typedef multi_index_container<
name_record,
+102
View File
@@ -0,0 +1,102 @@
/* Boost.MultiIndex example of use of random access indices.
*
* Copyright 2003-2006 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.
*/
#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-2006 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.
*/
#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 -2
View File
@@ -1,6 +1,6 @@
/* Boost.MultiIndex example of use of sequenced indices.
*
* Copyright 2003-2004 Joaquín M López Muñoz.
* 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)
@@ -14,7 +14,6 @@
#endif
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/sequenced_index.hpp>
+144
View File
@@ -0,0 +1,144 @@
/* Boost.MultiIndex example of serialization of a MRU list.
*
* Copyright 2003-2006 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.
*/
#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/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <fstream>
#include <iostream>
#include <iterator>
#include <sstream>
#include <string>
using namespace boost::multi_index;
/* An MRU (most recently used) list keeps record of the last n
* inserted items, listing first the newer ones. Care has to be
* taken when a duplicate item is inserted: instead of letting it
* appear twice, the MRU list relocates it to the first position.
*/
template <typename Item>
class mru_list
{
typedef multi_index_container<
Item,
indexed_by<
sequenced<>,
hashed_unique<identity<Item> >
>
> item_list;
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_){}
void insert(const item_type& item)
{
std::pair<iterator,bool> p=il.push_front(item);
if(!p.second){ /* duplicate item */
il.relocate(il.begin(),p.first); /* put in front */
}
else if(il.size()>max_num_items){ /* keep the length <= max_num_items */
il.pop_back();
}
}
iterator begin(){return il.begin();}
iterator end(){return il.end();}
/* Utilities to save and load the MRU list, internally
* based on Boost.Serialization.
*/
void save_to_file(const char* file_name)const
{
std::ofstream ofs(file_name);
boost::archive::text_oarchive oa(ofs);
oa<<boost::serialization::make_nvp("mru",*this);
}
void load_from_file(const char* file_name)
{
std::ifstream ifs(file_name);
if(ifs){
boost::archive::text_iarchive ia(ifs);
ia>>boost::serialization::make_nvp("mru",*this);
}
}
private:
item_list il;
std::size_t max_num_items;
/* serialization support */
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive& ar,const unsigned int)
{
ar&BOOST_SERIALIZATION_NVP(il);
ar&BOOST_SERIALIZATION_NVP(max_num_items);
}
};
int main()
{
const char* mru_store="mru_store";
/* Construct a MRU limited to 10 items and retrieve its
* previous contents.
*/
mru_list<std::string> mru(10);
mru.load_from_file(mru_store);
/* main loop */
for(;;){
std::cout<<"enter a term: ";
std::string line;
std::getline(std::cin,line);
if(line.empty())break;
std::string term;
std::istringstream iss(line);
iss>>term;
if(term.empty())break;
mru.insert(term);
std::cout<<"most recently entered terms:"<<std::endl;
std::copy(
mru.begin(),mru.end(),
std::ostream_iterator<std::string>(std::cout,"\n"));
}
/* persist the MRU list */
mru.save_to_file(mru_store);
return 0;
}
File diff suppressed because it is too large Load Diff
@@ -1,4 +1,4 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
/* Copyright 2003-2006 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)
@@ -9,26 +9,19 @@
#ifndef BOOST_MULTI_INDEX_DETAIL_ACCESS_SPECIFIER_HPP
#define BOOST_MULTI_INDEX_DETAIL_ACCESS_SPECIFIER_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
/* In those compilers that do not accept the member template friend syntax,
* some protected and private sections might need to be specified as
* public.
* As per a discussion on the Boost mailing list, and pending the
* resolution of whether BOOST_NO_MEMBER_TEMPLATE_FRIENDS should
* apply to MSVC 8.0, I act here as if it did. The relevant
* discussion can be found at:
* [boost] [config] seems like VC 8.0 needsBOOST_NO_MEMBER_TEMPLATE_FRIENDS
* http://lists.boost.org/MailArchives/boost/msg68369.php
*/
#if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) ||\
defined(BOOST_MSVC)&&(BOOST_MSVC==1400)
#define BOOST_MULTI_INDEX_NO_MEMBER_TEMPLATE_FRIENDS
#endif
#if defined(BOOST_MULTI_INDEX_NO_MEMBER_TEMPLATE_FRIENDS)
#if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
#define BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS public
#define BOOST_MULTI_INDEX_PRIVATE_IF_MEMBER_TEMPLATE_FRIENDS public
#else
@@ -41,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,79 @@
/* 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_ARCHIVE_CONSTRUCTED_HPP
#define BOOST_MULTI_INDEX_DETAIL_ARCHIVE_CONSTRUCTED_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/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{
namespace multi_index{
namespace detail{
/* constructs a stack-based object from a serialization archive */
template<typename T>
struct archive_constructed:private noncopyable
{
template<class Archive>
archive_constructed(Archive& ar,const unsigned int version)
{
serialization::load_construct_data_adl(ar,&get(),version);
BOOST_TRY{
ar>>get();
}
BOOST_CATCH(...){
(&get())->~T();
BOOST_RETHROW;
}
BOOST_CATCH_END
}
template<class Archive>
archive_constructed(const char* name,Archive& ar,const unsigned int version)
{
serialization::load_construct_data_adl(ar,&get(),version);
BOOST_TRY{
ar>>serialization::make_nvp(name,get());
}
BOOST_CATCH(...){
(&get())->~T();
BOOST_RETHROW;
}
BOOST_CATCH_END
}
~archive_constructed()
{
(&get())->~T();
}
T& get(){return *static_cast<T*>(static_cast<void*>(&space));}
private:
typename aligned_storage<sizeof(T),alignment_of<T>::value>::type space;
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -1,4 +1,4 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
/* 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)
@@ -9,6 +9,12 @@
#ifndef BOOST_MULTI_INDEX_DETAIL_AUTO_SPACE_HPP
#define BOOST_MULTI_INDEX_DETAIL_AUTO_SPACE_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/noncopyable.hpp>
#include <memory>
@@ -47,7 +53,15 @@ struct auto_space:private noncopyable
if(n_)al_.deallocate(data_,n_);
}
Allocator get_allocator()const{return al_;}
T* data()const{return data_;}
void swap(auto_space& x)
{
std::swap(n_,x.n_);
std::swap(data_,x.data_);
}
private:
typename boost::detail::allocator::rebind_to<
@@ -56,6 +70,12 @@ private:
T* data_;
};
template<typename T,typename Allocator>
void swap(auto_space<T,Allocator>& x,auto_space<T,Allocator>& y)
{
x.swap(y);
}
} /* namespace multi_index::detail */
} /* namespace multi_index */
+31 -28
View File
@@ -1,4 +1,4 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
/* 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)
@@ -9,18 +9,18 @@
#ifndef BOOST_MULTI_INDEX_DETAIL_BASE_TYPE_HPP
#define BOOST_MULTI_INDEX_DETAIL_BASE_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/detail/workaround.hpp>
#include <boost/mpl/bind.hpp>
#include <boost/mpl/reverse_iter_fold.hpp>
#include <boost/mpl/deref.hpp>
#include <boost/multi_index_container_fwd.hpp>
#include <boost/multi_index/detail/header_holder.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/apply.hpp>
#include <boost/mpl/size.hpp>
#include <boost/multi_index/detail/index_base.hpp>
#include <boost/multi_index/detail/is_index_list.hpp>
#include <boost/multi_index/detail/msvc_index_specifier.hpp>
#include <boost/multi_index/ordered_index_fwd.hpp>
#include <boost/multi_index/detail/prevent_eti.hpp>
#include <boost/static_assert.hpp>
namespace boost{
@@ -36,43 +36,46 @@ namespace detail{
#if BOOST_WORKAROUND(BOOST_MSVC,<1310)
struct index_applier
{
template<typename IndexSpecifierIterator,typename Super>
template<typename IndexSpecifierMeta,typename SuperMeta>
struct apply:
msvc_index_specifier< mpl::deref<IndexSpecifierIterator>::type>::
template result_index_class<Super>
msvc_index_specifier<IndexSpecifierMeta::type>::
template result_index_class<SuperMeta>
{
};
};
#else
struct index_applier
{
template<typename IndexSpecifierIterator,typename Super>
template<typename IndexSpecifierMeta,typename SuperMeta>
struct apply
{
typedef typename mpl::deref<IndexSpecifierIterator>::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
template<int N,typename Value,typename IndexSpecifierList,typename Allocator>
struct nth_layer
{
BOOST_STATIC_CONSTANT(int,length=mpl::size<IndexSpecifierList>::value);
typedef typename mpl::eval_if_c<
N==length,
mpl::identity<index_base<Value,IndexSpecifierList,Allocator> >,
mpl::apply2<
index_applier,
mpl::at_c<IndexSpecifierList,N>,
nth_layer<N+1,Value,IndexSpecifierList,Allocator>
>
>::type type;
};
template<typename Value,typename IndexSpecifierList,typename Allocator>
struct multi_index_base_type
struct multi_index_base_type:nth_layer<0,Value,IndexSpecifierList,Allocator>
{
BOOST_STATIC_ASSERT(detail::is_index_list<IndexSpecifierList>::value);
typedef typename prevent_eti<
multi_index_container<Value,IndexSpecifierList,Allocator>,
typename mpl::reverse_iter_fold<
IndexSpecifierList,
index_base<Value,IndexSpecifierList,Allocator>,
mpl::bind2<
index_applier,
mpl::_2,
mpl::_1
>
>::type
>::type type;
};
} /* namespace multi_index::detail */
@@ -0,0 +1,111 @@
/* Copyright 2003-2006 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_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,typename Derived=mpl::na>
class bidir_node_iterator:
public bidirectional_iterator_helper<
bidir_node_iterator<Node,Derived>,
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();
}
friend bool operator==(
const bidir_node_iterator& x,const bidir_node_iterator& y)
{
return x.node==y.node;
}
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;
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -0,0 +1,198 @@
/* 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_BUCKET_ARRAY_HPP
#define BOOST_MULTI_INDEX_DETAIL_BUCKET_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/multi_index/detail/auto_space.hpp>
#include <boost/multi_index/detail/hash_index_node.hpp>
#include <boost/noncopyable.hpp>
#include <cstddef>
#include <limits.h>
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
#include <boost/archive/archive_exception.hpp>
#include <boost/serialization/access.hpp>
#include <boost/throw_exception.hpp>
#endif
namespace boost{
namespace multi_index{
namespace detail{
/* bucket structure for use by hashed indices */
class bucket_array_base:private noncopyable
{
protected:
inline static std::size_t next_prime(std::size_t n)
{
static const std::size_t prime_list[]={
53ul, 97ul, 193ul, 389ul, 769ul,
1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
1610612741ul, 3221225473ul,
#if ((((ULONG_MAX>>16)>>16)>>16)>>15)==0 /* unsigned long less than 64 bits */
4294967291ul
#else
/* obtained with aid from
* http://javaboutique.internet.com/prime_numb/
* http://www.rsok.com/~jrm/next_ten_primes.html
* and verified with
* http://www.alpertron.com.ar/ECM.HTM
*/
6442450939ul, 12884901893ul, 25769803751ul, 51539607551ul,
103079215111ul, 206158430209ul, 412316860441ul, 824633720831ul,
1649267441651ul, 3298534883309ul, 6597069766657ul, 13194139533299ul,
26388279066623ul, 52776558133303ul, 105553116266489ul, 211106232532969ul,
422212465066001ul, 844424930131963ul, 1688849860263953ul,
3377699720527861ul, 6755399441055731ul, 13510798882111483ul,
27021597764222939ul, 54043195528445957ul, 108086391056891903ul,
216172782113783843ul, 432345564227567621ul, 864691128455135207ul,
1729382256910270481ul, 3458764513820540933ul, 6917529027641081903ul,
13835058055282163729ul, 18446744073709551557ul
#endif
};
static const std::size_t prime_list_size=
sizeof(prime_list)/sizeof(prime_list[0]);
std::size_t const *bound=
std::lower_bound(prime_list,prime_list+prime_list_size,n);
if(bound==prime_list+prime_list_size)bound--;
return *bound;
}
};
template<typename Allocator>
class bucket_array:public bucket_array_base
{
public:
bucket_array(const Allocator& al,hashed_index_node_impl* end_,std::size_t size):
size_(bucket_array_base::next_prime(size)),
spc(al,size_+1)
{
clear();
end()->next()=end_;
end_->next()=end();
}
std::size_t size()const
{
return size_;
}
std::size_t position(std::size_t hash)const
{
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];}
std::size_t first_nonempty(std::size_t n)const
{
for(;;++n){
hashed_index_node_impl* 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;
}
void swap(bucket_array& x)
{
std::swap(size_,x.size_);
spc.swap(x.spc);
}
private:
std::size_t size_;
auto_space<hashed_index_node_impl,Allocator> spc;
hashed_index_node_impl* buckets()const
{
return spc.data();
}
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
friend class boost::serialization::access;
/* bucket_arrays do not emit any kind of serialization info. They are
* fed to Boost.Serialization as hashed index iterators need to track
* them during serialization.
*/
template<class Archive>
void serialize(Archive&,const unsigned int)
{
}
#endif
};
template<typename Allocator>
void swap(bucket_array<Allocator>& x,bucket_array<Allocator>& y)
{
x.swap(y);
}
} /* namespace multi_index::detail */
} /* namespace multi_index */
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
/* bucket_arrays never get constructed directly by Boost.Serialization,
* as archives are always fed pointers to previously existent
* arrays. So, if this is called it means we are dealing with a
* somehow invalid archive.
*/
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
namespace serialization{
#else
namespace multi_index{
namespace detail{
#endif
template<class Archive,typename Allocator>
inline void load_construct_data(
Archive&,boost::multi_index::detail::bucket_array<Allocator>*,
const unsigned int)
{
throw_exception(
archive::archive_exception(archive::archive_exception::other_exception));
}
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
} /* namespace serialization */
#else
} /* namespace multi_index::detail */
} /* namespace multi_index */
#endif
#endif
} /* namespace boost */
#endif
@@ -1,4 +1,4 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
/* 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)
@@ -9,6 +9,10 @@
#ifndef BOOST_MULTI_INDEX_DETAIL_CONVERTER_HPP
#define BOOST_MULTI_INDEX_DETAIL_CONVERTER_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
namespace boost{
namespace multi_index{
+12 -8
View File
@@ -1,4 +1,4 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
/* 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)
@@ -9,6 +9,10 @@
#ifndef BOOST_MULTI_INDEX_DETAIL_COPY_MAP_HPP
#define BOOST_MULTI_INDEX_DETAIL_COPY_MAP_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/no_exceptions_support.hpp>
@@ -65,14 +69,14 @@ public:
{
if(!released){
for(std::size_t i=0;i<n;++i){
boost::detail::allocator::destroy(&spc.data()[i].second->value);
boost::detail::allocator::destroy(&spc.data()[i].second->value());
deallocate(spc.data()[i].second);
}
}
}
const_iterator begin()const{return &spc.data()[0];}
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)
{
@@ -80,7 +84,7 @@ public:
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);
@@ -89,15 +93,15 @@ public:
BOOST_CATCH_END
++n;
if(n==size_)std::sort(&spc.data()[0],&spc.data()[size_]);
if(n==size_)std::sort(spc.data(),spc.data()+size_);
}
Node* find(Node* node)const
{
if(node==header_org_)return header_cpy_;
return std::lower_bound(
&spc.data()[0],&spc.data()[n],copy_map_entry<Node>(node,0))->second;
};
begin(),end(),copy_map_entry<Node>(node,0))->second;
}
void release()
{
@@ -1,4 +1,4 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
/* 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)
@@ -9,6 +9,10 @@
#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)
@@ -0,0 +1,120 @@
/* Copyright 2003-2006 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_DUPLICATES_ITERATOR_HPP
#define BOOST_MULTI_INDEX_DETAIL_DUPLICATES_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 <cstddef>
#include <iterator>
namespace boost{
namespace multi_index{
namespace detail{
/* duplicates_operator is given a range of ordered elements and
* passes only over those which are duplicated.
*/
template<typename Node,typename Predicate>
class duplicates_iterator
{
public:
typedef typename Node::value_type value_type;
typedef std::ptrdiff_t difference_type;
typedef const typename Node::value_type* pointer;
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_)
{
advance();
}
duplicates_iterator(Node* end_,Predicate pred_):
node(end_),begin_chunk(end_),end(end_),pred(pred_)
{
}
reference operator*()const
{
return node->value();
}
pointer operator->()const
{
return &node->value();
}
duplicates_iterator& operator++()
{
Node::increment(node);
sync();
return *this;
}
duplicates_iterator operator++(int)
{
duplicates_iterator tmp(*this);
++(*this);
return tmp;
}
Node* get_node()const{return node;}
private:
void sync()
{
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;
}
begin_chunk=node;
}
Node* node;
Node* begin_chunk;
Node* end;
Predicate pred;
};
template<typename Node,typename Predicate>
bool operator==(
const duplicates_iterator<Node,Predicate>& x,
const duplicates_iterator<Node,Predicate>& y)
{
return x.get_node()==y.get_node();
}
template<typename Node,typename Predicate>
bool operator!=(
const duplicates_iterator<Node,Predicate>& x,
const duplicates_iterator<Node,Predicate>& y)
{
return !(x==y);
}
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
+5 -1
View File
@@ -1,4 +1,4 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
/* 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)
@@ -9,6 +9,10 @@
#ifndef BOOST_MULTI_INDEX_DETAIL_HAS_TAG_HPP
#define BOOST_MULTI_INDEX_DETAIL_HAS_TAG_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/contains.hpp>
@@ -0,0 +1,107 @@
/* 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_ARGS_HPP
#define BOOST_MULTI_INDEX_DETAIL_HASH_INDEX_ARGS_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/functional/hash/hash.hpp>
#include <boost/mpl/aux_/na.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/mpl/if.hpp>
#include <boost/multi_index/tag.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_same.hpp>
#include <functional>
namespace boost{
template<class T> struct hash; /* fwd decl. */
namespace multi_index{
namespace detail{
/* Hashed index specifiers can be instantiated in two forms:
*
* (hashed_unique|hashed_non_unique)<
* KeyFromValue,
* Hash=boost::hash<KeyFromValue::result_type>,
* Pred=std::equal_to<KeyFromValue::result_type> >
* (hashed_unique|hashed_non_unique)<
* TagList,
* KeyFromValue,
* Hash=boost::hash<KeyFromValue::result_type>,
* Pred=std::equal_to<KeyFromValue::result_type> >
*
* hashed_index_args implements the machinery to accept this
* argument-dependent polymorphism.
*/
template<typename KeyFromValue>
struct index_args_default_hash
{
typedef ::boost::hash<typename KeyFromValue::result_type> type;
};
template<typename KeyFromValue>
struct index_args_default_pred
{
typedef std::equal_to<typename KeyFromValue::result_type> type;
};
template<typename Arg1,typename Arg2,typename Arg3,typename Arg4>
struct hashed_index_args
{
typedef is_tag<Arg1> full_form;
typedef typename mpl::if_<
full_form,
Arg1,
tag< > >::type tag_list_type;
typedef typename mpl::if_<
full_form,
Arg2,
Arg1>::type key_from_value_type;
typedef typename mpl::if_<
full_form,
Arg3,
Arg2>::type supplied_hash_type;
typedef typename mpl::eval_if<
mpl::is_na<supplied_hash_type>,
index_args_default_hash<key_from_value_type>,
mpl::identity<supplied_hash_type>
>::type hash_type;
typedef typename mpl::if_<
full_form,
Arg4,
Arg3>::type supplied_pred_type;
typedef typename mpl::eval_if<
mpl::is_na<supplied_pred_type>,
index_args_default_pred<key_from_value_type>,
mpl::identity<supplied_pred_type>
>::type pred_type;
BOOST_STATIC_ASSERT(is_tag<tag_list_type>::value);
BOOST_STATIC_ASSERT(!mpl::is_na<key_from_value_type>::value);
BOOST_STATIC_ASSERT(!mpl::is_na<hash_type>::value);
BOOST_STATIC_ASSERT(!mpl::is_na<pred_type>::value);
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -0,0 +1,109 @@
/* Copyright 2003-2006 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_HPP
#define BOOST_MULTI_INDEX_DETAIL_HASH_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/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 hashed indices.
*/
template<typename Node,typename BucketArray,typename Derived=mpl::na>
class hashed_index_iterator:
public forward_iterator_helper<
hashed_index_iterator<Node,BucketArray,Derived>,
typename Node::value_type,
std::ptrdiff_t,
const typename Node::value_type*,
const typename Node::value_type&>
{
public:
hashed_index_iterator(){}
hashed_index_iterator(Node* node_,BucketArray* buckets_):
node(node_),buckets(buckets_)
{}
const typename Node::value_type& operator*()const
{
return node->value();
}
friend bool operator==(
const hashed_index_iterator& x,const hashed_index_iterator& y)
{
return x.node==y.node;
}
hashed_index_iterator& operator++()
{
Node::increment(node,buckets->begin(),buckets->end());
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);
ar<<serialization::make_nvp("pointer",buckets);
}
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);
ar>>serialization::make_nvp("pointer",buckets);
}
#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;
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -0,0 +1,117 @@
/* Copyright 2003-2006 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_NODE_HPP
#define BOOST_MULTI_INDEX_DETAIL_HASH_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 <functional>
namespace boost{
namespace multi_index{
namespace detail{
/* singly-linked node for use by hashed_index */
struct hashed_index_node_impl
{
hashed_index_node_impl*& next(){return next_;}
hashed_index_node_impl* next()const{return next_;}
/* algorithmic stuff */
static void increment(
hashed_index_node_impl*& x,
hashed_index_node_impl* bbegin,hashed_index_node_impl* bbend)
{
std::less_equal<hashed_index_node_impl*> leq;
x=x->next();
if(leq(bbegin,x)&&leq(x,bbend)){ /* bucket node */
do{
++x;
}while(x->next()==x);
x=x->next();
}
}
static void link(
hashed_index_node_impl* x,hashed_index_node_impl* pos)
{
x->next()=pos->next();
pos->next()=x;
};
static void unlink(hashed_index_node_impl* x)
{
hashed_index_node_impl* 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)
{
hashed_index_node_impl* y=x->next();
while(y->next()!=x){y=y->next();}
return y;
}
static void unlink_next(hashed_index_node_impl* x)
{
x->next()=x->next()->next();
}
private:
hashed_index_node_impl* next_;
};
template<typename Super>
struct hashed_index_node_trampoline:hashed_index_node_impl{};
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);}
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)
{
return static_cast<const hashed_index_node*>(
static_cast<const impl_type*>(x));
}
static void increment(
hashed_index_node*& x,
hashed_index_node_impl* bbegin,hashed_index_node_impl* bend)
{
hashed_index_node_impl* xi=x->impl();
impl_type::increment(xi,bbegin,bend);
x=from_impl(xi);
}
private:
typedef hashed_index_node_trampoline<Super> impl_type;
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -1,4 +1,4 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
/* 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)
@@ -9,8 +9,11 @@
#ifndef BOOST_MULTI_INDEX_DETAIL_HEADER_HOLDER_HPP
#define BOOST_MULTI_INDEX_DETAIL_HEADER_HOLDER_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/noncopyable.hpp>
#include <boost/utility/base_from_member.hpp>
namespace boost{
@@ -18,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
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);}
NodeType* member;
private:
typedef base_from_member<NodeType*> super;
Final& final(){return *static_cast<Final*>(this);}
};
@@ -1,4 +1,4 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
/* 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)
@@ -9,6 +9,10 @@
#ifndef BOOST_MULTI_INDEX_DETAIL_INDEX_BASE_HPP
#define BOOST_MULTI_INDEX_DETAIL_INDEX_BASE_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/call_traits.hpp>
#include <boost/detail/workaround.hpp>
@@ -19,6 +23,11 @@
#include <boost/tuple/tuple.hpp>
#include <utility>
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
#include <boost/multi_index/detail/index_loader.hpp>
#include <boost/multi_index/detail/index_saver.hpp>
#endif
namespace boost{
namespace multi_index{
@@ -54,6 +63,16 @@ protected:
final_node_type,
final_allocator_type> copy_map_type;
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
typedef index_saver<
node_type,
final_allocator_type> index_saver_type;
typedef index_loader<
node_type,
final_node_type,
final_allocator_type> index_loader_type;
#endif
private:
typedef typename call_traits<Value>::param_type value_param_type;
@@ -66,31 +85,48 @@ 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());
}
void clear_(){}
void swap_(index_base<Value,IndexSpecifierList,Allocator>&){}
bool replace_(value_param_type v,node_type* x)
{
x->value=v;
x->value()=v;
return true;
}
bool modify_(node_type*){return true;}
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
/* serialization */
template<typename Archive>
void save_(Archive&,const unsigned int,const index_saver_type&)const{}
template<typename Archive>
void load_(Archive&,const unsigned int,const index_loader_type&){}
#endif
#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
/* invariant stuff */
@@ -115,6 +151,11 @@ protected:
{return final().insert_(x,position);}
void final_erase_(final_node_type* x){final().erase_(x);}
void final_delete_node_(final_node_type* x){final().delete_node_(x);}
void final_delete_all_nodes_(){final().delete_all_nodes_();}
void final_clear_(){final().clear_();}
void final_swap_(final_type& x){final().swap_(x);}
bool final_replace_(
value_param_type k,final_node_type* x)
@@ -1,140 +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_INDEX_ITERATOR_HPP
#define BOOST_MULTI_INDEX_DETAIL_INDEX_ITERATOR_HPP
#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>
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;
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -1,40 +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_INDEX_ITERATOR_FWD_HPP
#define BOOST_MULTI_INDEX_DETAIL_INDEX_ITERATOR_FWD_HPP
#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
@@ -0,0 +1,138 @@
/* 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_LOADER_HPP
#define BOOST_MULTI_INDEX_DETAIL_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/archive/archive_exception.hpp>
#include <boost/noncopyable.hpp>
#include <boost/multi_index/detail/auto_space.hpp>
#include <boost/serialization/nvp.hpp>
#include <boost/throw_exception.hpp>
#include <cstddef>
namespace boost{
namespace multi_index{
namespace detail{
/* Counterpart of index_saver (check index_saver.hpp for serialization
* details.)* multi_index_container is in charge of supplying the info about
* the base sequence, and each index can subsequently load itself using the
* const interface of index_loader.
*/
template<typename Node,typename FinalNode,typename Allocator>
class index_loader:private noncopyable
{
public:
index_loader(const Allocator& al,std::size_t size):
spc(al,size),size_(size),n(0),sorted(false)
{
}
template<class Archive>
void add(Node* node,Archive& ar,const unsigned int)
{
ar>>serialization::make_nvp("position",*node);
entries()[n++]=node;
}
template<class Archive>
void add_track(Node* node,Archive& ar,const unsigned int)
{
ar>>serialization::make_nvp("position",*node);
}
/* A rearranger is passed two nodes, and is expected to
* reposition the second after the first.
* If the first node is 0, then the second should be moved
* to the beginning of the sequence.
*/
template<typename Rearranger,class Archive>
void load(Rearranger r,Archive& ar,const unsigned int)const
{
FinalNode* prev=unchecked_load_node(ar);
if(!prev)return;
if(!sorted){
std::sort(entries(),entries()+size_);
sorted=true;
}
check_node(prev);
for(;;){
for(;;){
FinalNode* node=load_node(ar);
if(!node)break;
if(node==prev)prev=0;
r(prev,node);
prev=node;
}
prev=load_node(ar);
if(!prev)break;
}
}
private:
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.
*/
template<class Archive>
FinalNode* unchecked_load_node(Archive& ar)const
{
Node* node=0;
ar>>serialization::make_nvp("pointer",node);
return static_cast<FinalNode*>(node);
}
template<class Archive>
FinalNode* load_node(Archive& ar)const
{
Node* node=0;
ar>>serialization::make_nvp("pointer",node);
check_node(node);
return static_cast<FinalNode*>(node);
}
void check_node(Node* node)const
{
if(node!=0&&!std::binary_search(entries(),entries()+size_,node)){
throw_exception(
archive::archive_exception(
archive::archive_exception::other_exception));
}
}
auto_space<Node*,Allocator> spc;
std::size_t size_;
std::size_t n;
mutable bool sorted;
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -0,0 +1,248 @@
/* 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_MATCHER_HPP
#define BOOST_MULTI_INDEX_DETAIL_INDEX_MATCHER_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/noncopyable.hpp>
#include <boost/multi_index/detail/auto_space.hpp>
#include <cstddef>
#include <functional>
namespace boost{
namespace multi_index{
namespace detail{
/* index_matcher compares a sequence of elements against a
* base sequence, identifying those elements that belong to the
* longest subsequence which is ordered with respect to the base.
* For instance, if the base sequence is:
*
* 0 1 2 3 4 5 6 7 8 9
*
* and the compared sequence (not necesarilly the same length):
*
* 1 4 2 3 0 7 8 9
*
* the elements of the longest ordered subsequence are:
*
* 1 2 3 7 8 9
*
* The algorithm for obtaining such a subsequence is called
* Patience Sorting, described in ch. 1 of:
* Aldous, D., Diaconis, P.: "Longest increasing subsequences: from
* patience sorting to the Baik-Deift-Johansson Theorem", Bulletin
* of the American Mathematical Society, vol. 36, no 4, pp. 413-432,
* July 1999.
* http://www.ams.org/bull/1999-36-04/S0273-0979-99-00796-X/
* S0273-0979-99-00796-X.pdf
*
* This implementation is not fully generic since it assumes that
* the sequences given are pointed to by index iterators (having a
* get_node() memfun.)
*/
namespace index_matcher{
/* The algorithm stores the nodes of the base sequence and a number
* of "piles" that are dynamically updated during the calculation
* stage. From a logical point of view, nodes form an independent
* sequence from piles. They are stored together so as to minimize
* allocated memory.
*/
struct entry
{
entry(void* node_,std::size_t pos_=0):node(node_),pos(pos_){}
/* node stuff */
void* node;
std::size_t pos;
entry* previous;
bool ordered;
struct less_by_node
{
bool operator()(
const entry& x,const entry& y)const
{
return std::less<void*>()(x.node,y.node);
}
};
/* pile stuff */
std::size_t pile_top;
entry* pile_top_entry;
struct less_by_pile_top
{
bool operator()(
const entry& x,const entry& y)const
{
return x.pile_top<y.pile_top;
}
};
};
/* common code operating on void *'s */
template<typename Allocator>
class algorithm_base:private noncopyable
{
protected:
algorithm_base(const Allocator& al,std::size_t size):
spc(al,size),size_(size),n(0),sorted(false)
{
}
void add(void* node)
{
entries()[n]=entry(node,n);
++n;
}
void begin_algorithm()const
{
if(!sorted){
std::sort(entries(),entries()+size_,entry::less_by_node());
sorted=true;
}
num_piles=0;
}
void add_node_to_algorithm(void* node)const
{
entry* ent=
std::lower_bound(
entries(),entries()+size_,
entry(node),entry::less_by_node()); /* localize entry */
ent->ordered=false;
std::size_t n=ent->pos; /* get its position */
entry dummy(0);
dummy.pile_top=n;
entry* pile_ent= /* find the first available pile */
std::lower_bound( /* to stack the entry */
entries(),entries()+num_piles,
dummy,entry::less_by_pile_top());
pile_ent->pile_top=n; /* stack the entry */
pile_ent->pile_top_entry=ent;
/* if not the first pile, link entry to top of the preceding pile */
if(pile_ent>&entries()[0]){
ent->previous=(pile_ent-1)->pile_top_entry;
}
if(pile_ent==&entries()[num_piles]){ /* new pile? */
++num_piles;
}
}
void finish_algorithm()const
{
if(num_piles>0){
/* Mark those elements which are in their correct position, i.e. those
* belonging to the longest increasing subsequence. These are those
* elements linked from the top of the last pile.
*/
entry* ent=entries()[num_piles-1].pile_top_entry;
for(std::size_t n=num_piles;n--;){
ent->ordered=true;
ent=ent->previous;
}
}
}
bool is_ordered(void * node)const
{
return std::lower_bound(
entries(),entries()+size_,
entry(node),entry::less_by_node())->ordered;
}
private:
entry* entries()const{return spc.data();}
auto_space<entry,Allocator> spc;
std::size_t size_;
std::size_t n;
mutable bool sorted;
mutable std::size_t num_piles;
};
/* The algorithm has three phases:
* - Initialization, during which the nodes of the base sequence are added.
* - Execution.
* - Results querying, through the is_ordered memfun.
*/
template<typename Node,typename Allocator>
class algorithm:private algorithm_base<Allocator>
{
typedef algorithm_base<Allocator> super;
public:
algorithm(const Allocator& al,std::size_t size):super(al,size){}
void add(Node* node)
{
super::add(node);
}
template<typename IndexIterator>
void execute(IndexIterator first,IndexIterator last)const
{
super::begin_algorithm();
for(IndexIterator it=first;it!=last;++it){
add_node_to_algorithm(get_node(it));
}
super::finish_algorithm();
}
bool is_ordered(Node* node)const
{
return super::is_ordered(node);
}
private:
void add_node_to_algorithm(Node* node)const
{
super::add_node_to_algorithm(node);
}
template<typename IndexIterator>
static Node* get_node(IndexIterator it)
{
return static_cast<Node*>(it.get_node());
}
};
} /* namespace multi_index::detail::index_matcher */
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -1,4 +1,4 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
/* Copyright 2003-2006 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)
@@ -9,6 +9,20 @@
#ifndef BOOST_MULTI_INDEX_DETAIL_INDEX_NODE_BASE_HPP
#define BOOST_MULTI_INDEX_DETAIL_INDEX_NODE_BASE_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/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>
#endif
namespace boost{
namespace multi_index{
@@ -20,20 +34,99 @@ namespace detail{
*/
template<typename Value>
struct index_node_base
struct pod_value_holder
{
typedef Value value_type;
value_type value;
typename aligned_storage<
sizeof(Value),
alignment_of<Value>::value
>::type space;
};
template<typename Value>
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()
{
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;
/* nodes do not emit any kind of serialization info. They are
* fed to Boost.Serialization so that pointers to nodes are
* tracked correctly.
*/
template<class Archive>
void serialize(Archive&,const unsigned int)
{
}
#endif
};
template<typename Node,typename Value>
Node* node_from_value(
const Value* p
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Node))
{
return static_cast<Node*>(index_node_base<Value>::from_value(p));
}
} /* namespace multi_index::detail */
} /* namespace multi_index */
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
/* Index nodes never get constructed directly by Boost.Serialization,
* as archives are always fed pointers to previously existent
* nodes. So, if this is called it means we are dealing with a
* somehow invalid archive.
*/
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
namespace serialization{
#else
namespace multi_index{
namespace detail{
#endif
template<class Archive,typename Value>
inline void load_construct_data(
Archive&,boost::multi_index::detail::index_node_base<Value>*,
const unsigned int)
{
throw_exception(
archive::archive_exception(archive::archive_exception::other_exception));
}
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
} /* namespace serialization */
#else
} /* namespace multi_index::detail */
} /* namespace multi_index */
#endif
#endif
} /* namespace boost */
#endif
@@ -1,78 +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_INDEX_PROXY_HPP
#define BOOST_MULTI_INDEX_DETAIL_INDEX_PROXY_HPP
#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
@@ -0,0 +1,135 @@
/* 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_SAVER_HPP
#define BOOST_MULTI_INDEX_DETAIL_INDEX_SAVER_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/multi_index/detail/index_matcher.hpp>
#include <boost/noncopyable.hpp>
#include <boost/serialization/nvp.hpp>
#include <cstddef>
namespace boost{
namespace multi_index{
namespace detail{
/* index_saver accepts a base sequence of previously saved elements
* and saves a possibly reordered subsequence in an efficient manner,
* serializing only the information needed to rearrange the subsequence
* based on the original order of the base.
* multi_index_container is in charge of supplying the info about the
* base sequence, and each index can subsequently save itself using the
* const interface of index_saver.
*/
template<typename Node,typename Allocator>
class index_saver:private noncopyable
{
public:
index_saver(const Allocator& al,std::size_t size):alg(al,size){}
template<class Archive>
void add(Node* node,Archive& ar,const unsigned int)
{
ar<<serialization::make_nvp("position",*node);
alg.add(node);
}
template<class Archive>
void add_track(Node* node,Archive& ar,const unsigned int)
{
ar<<serialization::make_nvp("position",*node);
}
template<typename IndexIterator,class Archive>
void save(
IndexIterator first,IndexIterator last,Archive& ar,
const unsigned int)const
{
/* calculate ordered positions */
alg.execute(first,last);
/* Given a consecutive subsequence of displaced elements
* x1,...,xn, the following information is serialized:
*
* p0,p1,...,pn,0
*
* where pi is a pointer to xi and p0 is a pointer to the element
* preceding x1. Crealy, from this information is possible to
* restore the original order on loading time. If x1 is the first
* element in the sequence, the following is serialized instead:
*
* p1,p1,...,pn,0
*
* For each subsequence of n elements, n+2 pointers are serialized.
* An optimization policy is applied: consider for instance the
* sequence
*
* a,B,c,D
*
* where B and D are displaced, but c is in its correct position.
* Applying the schema described above we would serialize 6 pointers:
*
* p(a),p(B),0
* p(c),p(D),0
*
* but this can be reduced to 5 pointers by treating c as a displaced
* element:
*
* p(a),p(B),p(c),p(D),0
*/
std::size_t last_saved=3; /* distance to last pointer saved */
for(IndexIterator it=first,prev=first;it!=last;prev=it++,++last_saved){
if(!alg.is_ordered(get_node(it))){
if(last_saved>1)save_node(get_node(prev),ar);
save_node(get_node(it),ar);
last_saved=0;
}
else if(last_saved==2)save_node(null_node(),ar);
}
if(last_saved<=2)save_node(null_node(),ar);
/* marks the end of the serialization info for [first,last) */
save_node(null_node(),ar);
}
private:
template<typename IndexIterator>
static Node* get_node(IndexIterator it)
{
return it.get_node();
}
static Node* null_node(){return 0;}
template<typename Archive>
static void save_node(Node* node,Archive& ar)
{
ar<<serialization::make_nvp("pointer",node);
}
index_matcher::algorithm<Node,Allocator> alg;
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -1,4 +1,4 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
/* 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)
@@ -9,6 +9,10 @@
#ifndef BOOST_MULTI_INDEX_DETAIL_INVARIANT_ASSERT_HPP
#define BOOST_MULTI_INDEX_DETAIL_INVARIANT_ASSERT_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#if !defined(BOOST_MULTI_INDEX_INVARIANT_ASSERT)
#include <boost/assert.hpp>
#define BOOST_MULTI_INDEX_INVARIANT_ASSERT BOOST_ASSERT
@@ -1,4 +1,4 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
/* 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)
@@ -9,6 +9,10 @@
#ifndef BOOST_MULTI_INDEX_DETAIL_IS_INDEX_LIST_HPP
#define BOOST_MULTI_INDEX_DETAIL_IS_INDEX_LIST_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/empty.hpp>
#include <boost/mpl/is_sequence.hpp>
@@ -0,0 +1,273 @@
/* 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_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.
*/
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<>
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<>
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<>
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-2004 Joaquín M López Muñoz.
/* 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)
@@ -9,6 +9,10 @@
#ifndef BOOST_MULTI_INDEX_DETAIL_MODIFY_KEY_ADAPTOR_HPP
#define BOOST_MULTI_INDEX_DETAIL_MODIFY_KEY_ADAPTOR_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
namespace boost{
namespace multi_index{
@@ -1,4 +1,4 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
/* 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)
@@ -9,6 +9,10 @@
#ifndef BOOST_MULTI_INDEX_DETAIL_MSVC_INDEX_SPECIFIER_HPP
#define BOOST_MULTI_INDEX_DETAIL_MSVC_INDEX_SPECIFIER_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>
@@ -1,4 +1,4 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
/* 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)
@@ -9,6 +9,10 @@
#ifndef BOOST_MULTI_INDEX_DETAIL_NO_DUPLICATE_TAGS_HPP
#define BOOST_MULTI_INDEX_DETAIL_NO_DUPLICATE_TAGS_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/fold.hpp>
#include <boost/mpl/set/set0.hpp>
@@ -1,4 +1,4 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
/* 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)
@@ -9,6 +9,10 @@
#ifndef BOOST_MULTI_INDEX_DETAIL_NODE_TYPE_HPP
#define BOOST_MULTI_INDEX_DETAIL_NODE_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/detail/workaround.hpp>
#include <boost/mpl/bind.hpp>
@@ -19,7 +23,6 @@
#include <boost/multi_index/detail/index_node_base.hpp>
#include <boost/multi_index/detail/is_index_list.hpp>
#include <boost/multi_index/detail/msvc_index_specifier.hpp>
#include <boost/multi_index/detail/prevent_eti.hpp>
#include <boost/static_assert.hpp>
namespace boost{
@@ -1,4 +1,4 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
/* 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)
@@ -9,7 +9,12 @@
#ifndef BOOST_MULTI_INDEX_DETAIL_ORD_INDEX_ARGS_HPP
#define BOOST_MULTI_INDEX_DETAIL_ORD_INDEX_ARGS_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/aux_/na.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/mpl/if.hpp>
@@ -35,14 +40,6 @@ namespace detail{
* polymorphism.
*/
struct null_arg{};
template<typename T>
struct not_is_null_arg
{
BOOST_STATIC_CONSTANT(bool,value=!(is_same<null_arg,T>::value));
};
template<typename KeyFromValue>
struct index_args_default_compare
{
@@ -67,14 +64,14 @@ struct ordered_index_args
Arg3,
Arg2>::type supplied_compare_type;
typedef typename mpl::eval_if<
is_same<supplied_compare_type,null_arg>,
mpl::is_na<supplied_compare_type>,
index_args_default_compare<key_from_value_type>,
mpl::identity<supplied_compare_type>
>::type compare_type;
BOOST_STATIC_ASSERT(is_tag<tag_list_type>::value);
BOOST_STATIC_ASSERT(not_is_null_arg<key_from_value_type>::value);
BOOST_STATIC_ASSERT(not_is_null_arg<compare_type>::value);
BOOST_STATIC_ASSERT(!mpl::is_na<key_from_value_type>::value);
BOOST_STATIC_ASSERT(!mpl::is_na<compare_type>::value);
};
} /* namespace multi_index::detail */
@@ -1,4 +1,4 @@
/* Copyright 2003-2004 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)
@@ -36,9 +36,20 @@
#ifndef BOOST_MULTI_INDEX_DETAIL_ORD_INDEX_NODE_HPP
#define BOOST_MULTI_INDEX_DETAIL_ORD_INDEX_NODE_HPP
#include <algorithm>
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <cstddef>
#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>
#endif
namespace boost{
namespace multi_index{
@@ -48,19 +59,147 @@ 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
struct ordered_index_node_impl; /* fwd decl. */
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 ordered_index_color& color_ref;
typedef ordered_index_node_impl*& parent_ref;
/* interoperability with index_iterator */
ordered_index_color& color(){return color_;}
ordered_index_color color()const{return color_;}
ordered_index_node_impl*& parent(){return parent_;}
ordered_index_node_impl* parent()const{return parent_;}
ordered_index_node_impl*& left(){return left_;}
ordered_index_node_impl* left()const{return left_;}
ordered_index_node_impl*& right(){return right_;}
ordered_index_node_impl* right()const{return right_;}
private:
ordered_index_color color_;
ordered_index_node_impl* parent_;
ordered_index_node_impl* left_;
ordered_index_node_impl* 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
struct ordered_index_node_compressed_base
{
struct color_ref
{
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 ordered_index_node_impl*()const
{
return (ordered_index_node_impl*)(void*)(*r&~uintptr_type(1));
}
parent_ref& operator=(ordered_index_node_impl* p)
{
*r=((uintptr_type)(void*)p)|(*r&uintptr_type(1));
return *this;
}
parent_ref& operator=(const parent_ref& x)
{
return operator=(x.operator ordered_index_node_impl*());
}
ordered_index_node_impl* operator->()const
{
return operator ordered_index_node_impl*();
}
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_);}
ordered_index_node_impl* parent()const
{
return (ordered_index_node_impl*)(void*)(parentcolor_&~uintptr_type(1));
}
ordered_index_node_impl*& left(){return left_;}
ordered_index_node_impl* left()const{return left_;}
ordered_index_node_impl*& right(){return right_;}
ordered_index_node_impl* right()const{return right_;}
private:
uintptr_type parentcolor_;
ordered_index_node_impl* left_;
ordered_index_node_impl* right_;
};
#if defined(BOOST_MSVC)
#pragma warning(pop)
#endif
#endif
struct ordered_index_node_impl:
#if !defined(BOOST_MULTI_INDEX_DISABLE_COMPRESSED_ORDERED_INDEX_NODES)
mpl::if_c<
!(has_uintptr_type::value)||
(alignment_of<ordered_index_node_compressed_base>::value%2),
ordered_index_node_std_base,
ordered_index_node_compressed_base
>::type
#else
ordered_index_node_std_base
#endif
{
/* interoperability with bidir_node_iterator */
static void increment(ordered_index_node_impl*& x)
{
@@ -97,22 +236,10 @@ 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)
ordered_index_node_impl* x,parent_ref root)
{
ordered_index_node_impl* y=x->right();
x->right()=y->left();
@@ -139,7 +266,7 @@ struct ordered_index_node_impl
}
static void rotate_right(
ordered_index_node_impl* x,ordered_index_node_impl*& root)
ordered_index_node_impl* x,parent_ref root)
{
ordered_index_node_impl* y=x->left();
x->left()=y->right();
@@ -154,7 +281,7 @@ struct ordered_index_node_impl
}
static void rebalance(
ordered_index_node_impl* x,ordered_index_node_impl*& root)
ordered_index_node_impl* x,parent_ref root)
{
x->color()=red;
while(x!=root&&x->parent()->color()==red){
@@ -198,8 +325,35 @@ struct ordered_index_node_impl
root->color()=black;
}
static void link(
ordered_index_node_impl* x,
ordered_index_side side,ordered_index_node_impl* position,
ordered_index_node_impl* header)
{
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{
position->right()=x;
if(position==header->right()){
header->right()=x; /* maintain rightmost pointing to max node */
}
}
x->parent()=position;
x->left()=0;
x->right()=0;
ordered_index_node_impl::rebalance(x,header->parent());
}
static ordered_index_node_impl* rebalance_for_erase(
ordered_index_node_impl* z,ordered_index_node_impl*& root,
ordered_index_node_impl* z,parent_ref root,
ordered_index_node_impl*& leftmost,ordered_index_node_impl*& rightmost)
{
ordered_index_node_impl* y=z;
@@ -236,7 +390,9 @@ 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 */
@@ -332,32 +488,16 @@ struct ordered_index_node_impl
}
static void restore(
ordered_index_node_impl* x,ordered_index_node_impl* prior,
ordered_index_node_impl* next,ordered_index_node_impl* header)
ordered_index_node_impl* x,ordered_index_node_impl* position,
ordered_index_node_impl* header)
{
if(next==header){
header->parent()=x;
header->left()=x;
header->right()=x;
x->parent()=header;
if(position->left()==0||position->left()==header){
link(x,to_left,position,header);
}
else if(next->left()==0){
next->left()=x;
x->parent()=next;
if(next==header->left()){
header->left()=x; /* maintain leftmost pointing to min node */
}
else{
decrement(position);
link(x,to_right,position,header);
}
else{ /* prior->right() must be null */
prior->right()=x;
x->parent()=prior;
if(prior==header->right()){
header->right()=x; /* maintain rightmost pointing to max node */
}
}
x->left()=0;
x->right()=0;
rebalance(x,header->parent());
}
#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
@@ -376,14 +516,6 @@ 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>
@@ -392,14 +524,20 @@ struct ordered_index_node_trampoline:ordered_index_node_impl{};
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> impl_type;
typedef typename impl_type::color_ref color_ref;
typedef typename impl_type::parent_ref parent_ref;
public:
color_ref color(){return impl_type::color();}
ordered_index_color color()const{return impl_type::color();}
parent_ref parent(){return impl_type::parent();}
ordered_index_node_impl* parent()const{return impl_type::parent();}
ordered_index_node_impl*& left(){return impl_type::left();}
ordered_index_node_impl* left()const{return impl_type::left();}
ordered_index_node_impl*& right(){return impl_type::right();}
ordered_index_node_impl* right()const{return impl_type::right();}
ordered_index_node_impl* impl(){return static_cast<impl_type*>(this);}
const ordered_index_node_impl* impl()const
@@ -416,7 +554,7 @@ struct ordered_index_node:Super,ordered_index_node_trampoline<Super>
static_cast<const impl_type*>(x));
}
/* interoperability with index_iterator */
/* interoperability with bidir_node_iterator */
static void increment(ordered_index_node*& x)
{
@@ -431,21 +569,6 @@ struct ordered_index_node:Super,ordered_index_node_trampoline<Super>
impl_type::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-2004 Joaquín M López Muñoz.
/* 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)
@@ -36,6 +36,10 @@
#ifndef BOOST_MULTI_INDEX_DETAIL_ORD_INDEX_OPS_HPP
#define BOOST_MULTI_INDEX_DETAIL_ORD_INDEX_OPS_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
namespace boost{
namespace multi_index{
@@ -58,14 +62,14 @@ inline Node* ordered_index_find(
Node* z=Node::from_impl(header->parent());
while (z){
if(!comp(key(z->value),x)){
if(!comp(key(z->value()),x)){
y=z;
z=Node::from_impl(z->left());
}
else z=Node::from_impl(z->right());
}
return (y==header||comp(x,key(y->value)))?header:y;
return (y==header||comp(x,key(y->value())))?header:y;
}
template<
@@ -80,7 +84,7 @@ inline Node* ordered_index_lower_bound(
Node* z=Node::from_impl(header->parent());
while(z){
if(!comp(key(z->value),x)){
if(!comp(key(z->value()),x)){
y=z;
z=Node::from_impl(z->left());
}
@@ -102,7 +106,7 @@ inline Node* ordered_index_upper_bound(
Node* z=Node::from_impl(header->parent());
while(z){
if(comp(x,key(z->value))){
if(comp(x,key(z->value()))){
y=z;
z=Node::from_impl(z->left());
}
@@ -1,4 +1,4 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
/* 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)
@@ -9,6 +9,10 @@
#ifndef BOOST_MULTI_INDEX_DETAIL_PREVENT_ETI_HPP
#define BOOST_MULTI_INDEX_DETAIL_PREVENT_ETI_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>
@@ -0,0 +1,163 @@
/* Copyright 2003-2006 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_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/multi_index/detail/auto_space.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 random_access_index_node_impl node_type;
typedef random_access_index_ptr_array<Allocator> ptr_array_type;
random_access_index_loader_base(const Allocator& al_,ptr_array_type& ptrs_):
al(al_),
ptrs(ptrs_),
header(*ptrs.end()),
prev_spc(al,0),
preprocessed(false)
{}
~random_access_index_loader_base()
{
if(preprocessed)
{
node_type* 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_type* 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_type* position,node_type *x)
{
preprocess(); /* only incur this penalty if rearrange() is ever called */
if(!position)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_type*,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_type* x)const
{
return (std::size_t)(x->up()-ptrs.begin());
}
node_type*& next_at(std::size_t n)const
{
return *ptrs.at(n);
}
node_type*& prev_at(std::size_t n)const
{
return prev_spc.data()[n];
}
node_type*& next(node_type* x)const
{
return *(x->up());
}
node_type*& prev(node_type* x)const
{
return prev_at(position(x));
}
Allocator al;
ptr_array_type& ptrs;
node_type* header;
auto_space<node_type*,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::ptr_array_type ptr_array_type;
public:
random_access_index_loader(const Allocator& al_,ptr_array_type& ptrs_):
super(al_,ptrs_)
{}
void rearrange(Node* position,Node *x)
{
super::rearrange(position?position->impl():0,x->impl());
}
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -0,0 +1,240 @@
/* Copyright 2003-2006 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_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/math/common_factor_rt.hpp>
#include <cstddef>
#include <functional>
namespace boost{
namespace multi_index{
namespace detail{
struct random_access_index_node_impl
{
random_access_index_node_impl**& up(){return up_;}
random_access_index_node_impl** up()const{return up_;}
/* interoperability with rnd_node_iterator */
static void increment(random_access_index_node_impl*& x)
{
x=*(x->up()+1);
}
static void decrement(random_access_index_node_impl*& x)
{
x=*(x->up()-1);
}
static void advance(
random_access_index_node_impl*& x,std::ptrdiff_t n)
{
x=*(x->up()+n);
}
static std::ptrdiff_t distance(
random_access_index_node_impl* x,random_access_index_node_impl* y)
{
return y->up()-x->up();
}
/* algorithmic stuff */
static void relocate(
random_access_index_node_impl** pos,
random_access_index_node_impl** x)
{
random_access_index_node_impl* 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(
random_access_index_node_impl** pos,
random_access_index_node_impl** first,
random_access_index_node_impl** last)
{
random_access_index_node_impl** 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){
random_access_index_node_impl* 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(
random_access_index_node_impl** x,
random_access_index_node_impl** pend)
{
--pend;
while(x!=pend){
*x=*(x+1);
(*x)->up()=x;
++x;
}
}
static void transfer(
random_access_index_node_impl** pbegin0,
random_access_index_node_impl** pend0,
random_access_index_node_impl** pbegin1)
{
while(pbegin0!=pend0){
*pbegin1=*pbegin0++;
(*pbegin1)->up()=pbegin1;
++pbegin1;
}
}
static void reverse(
random_access_index_node_impl** pbegin,
random_access_index_node_impl** 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:
random_access_index_node_impl** up_;
};
template<typename Super>
struct random_access_index_node_trampoline:random_access_index_node_impl{};
template<typename Super>
struct random_access_index_node:
Super,random_access_index_node_trampoline<Super>
{
random_access_index_node_impl**& up(){return impl_type::up();}
random_access_index_node_impl** up()const{return impl_type::up();}
random_access_index_node_impl* impl()
{return static_cast<impl_type*>(this);}
const random_access_index_node_impl* impl()const
{return static_cast<const impl_type*>(this);}
static random_access_index_node* from_impl(random_access_index_node_impl *x)
{
return static_cast<random_access_index_node*>(
static_cast<impl_type*>(x));
}
static const random_access_index_node* from_impl(
const random_access_index_node_impl* x)
{
return static_cast<const random_access_index_node*>(
static_cast<const impl_type*>(x));
}
/* interoperability with rnd_node_iterator */
static void increment(random_access_index_node*& x)
{
random_access_index_node_impl* xi=x->impl();
impl_type::increment(xi);
x=from_impl(xi);
}
static void decrement(random_access_index_node*& x)
{
random_access_index_node_impl* xi=x->impl();
impl_type::decrement(xi);
x=from_impl(xi);
}
static void advance(random_access_index_node*& x,std::ptrdiff_t n)
{
random_access_index_node_impl* xi=x->impl();
impl_type::advance(xi,n);
x=from_impl(xi);
}
static std::ptrdiff_t distance(
random_access_index_node* x,random_access_index_node* y)
{
return impl_type::distance(x->impl(),y->impl());
}
private:
typedef random_access_index_node_trampoline<Super> impl_type;
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -0,0 +1,200 @@
/* 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_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;
random_access_index_node_impl** 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;
random_access_index_node_impl** 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,
random_access_index_node_impl** first1,Compare comp
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Node))
{
typedef typename Node::value_type value_type;
auto_space<random_access_index_node_impl*,Allocator> spc(al,ptrs.size());
random_access_index_node_impl** 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<
const typename Node::value_type*,const typename Node::value_type*,bool>
{
random_access_index_sort_compare(Compare comp_=Compare()):comp(comp_){}
bool operator()(
random_access_index_node_impl* x,
random_access_index_node_impl* 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.
*/
typedef typename Node::value_type value_type;
typedef random_access_index_sort_compare<
Node,Compare> ptr_compare;
random_access_index_node_impl** first=ptrs.begin();
random_access_index_node_impl** last=ptrs.end();
auto_space<
random_access_index_node_impl*,
Allocator> spc(al,ptrs.size());
random_access_index_node_impl** 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,125 @@
/* 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_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/multi_index/detail/auto_space.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
{
public:
typedef random_access_index_node_impl* value_type;
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);
random_access_index_node_impl::transfer(begin(),end()+1,spc1.data());
spc.swap(spc1);
capacity_=c;
}
}
value_type* begin()const{return &ptrs()[0];}
value_type* end()const{return &ptrs()[size_];}
value_type* 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)
{
random_access_index_node_impl::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;
value_type* 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,133 @@
/* Copyright 2003-2006 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_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,typename Derived=mpl::na>
class rnd_node_iterator:
public random_access_iterator_helper<
rnd_node_iterator<Node,Derived>,
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();
}
friend bool operator==(
const rnd_node_iterator& x,const rnd_node_iterator& y)
{
return x.node==y.node;
}
friend bool operator<(
const rnd_node_iterator& x,const rnd_node_iterator& y)
{
return Node::distance(x.node,y.node)>0;
}
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;
}
friend std::ptrdiff_t operator-(
const rnd_node_iterator& x,const rnd_node_iterator& y)
{
return Node::distance(y.node,x.node);
}
#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;
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
@@ -0,0 +1,105 @@
/* Copyright 2003-2006 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_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
+488 -259
View File
@@ -1,4 +1,4 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
/* Copyright 2003-2006 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)
@@ -9,22 +9,15 @@
#ifndef BOOST_MULTI_INDEX_DETAIL_SAFE_MODE_HPP
#define BOOST_MULTI_INDEX_DETAIL_SAFE_MODE_HPP
#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{
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
/* 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.
@@ -32,255 +25,26 @@ 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.
* This is not a full-fledged safe mode framework, and is only inteded
* 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
* is available, and it is not possible to determine to which container
* the iterator is associated to. The only sensible policy is to assume
* unchecked iterators are valid, though this can certainly generate false
* positive safe mode checks.
* This is not a full-fledged safe mode framework, and is only intended
* 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;}
inline void detach();
protected:
safe_iterator_base():cont(0),next(0){}
explicit safe_iterator_base(safe_container_base* cont_){attach(cont_);}
safe_iterator_base(const safe_iterator_base& it){attach(it.cont);}
safe_iterator_base& operator=(const safe_iterator_base& it)
{
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_MULTI_INDEX_NO_MEMBER_TEMPLATE_FRIENDS)
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;
};
class safe_container_base:private noncopyable
{
public:
safe_container_base(){}
~safe_container_base()
{
for(safe_iterator_base* it=header.next;it;it=it->next)it->cont=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);
}
BOOST_MULTI_INDEX_PRIVATE_IF_MEMBER_TEMPLATE_FRIENDS:
friend class safe_iterator_base;
#if !defined(BOOST_MULTI_INDEX_NO_MEMBER_TEMPLATE_FRIENDS)
template<typename Iterator> friend
void safe_mode::detach_equivalent_iterators(Iterator&);
#endif
safe_iterator_base header;
};
void safe_iterator_base::attach(safe_container_base* cont_)
{
cont=cont_;
if(cont){
next=cont->header.next;
cont->header.next=this;
}
}
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 safe_mode{
/* checking routines */
template<typename Iterator>
inline bool check_valid_iterator(const Iterator& it)
{
return it.valid();
}
template<typename Iterator>
inline bool check_dereferenceable_iterator(const Iterator& it)
{
return it.valid()&&it!=it.owner()->end();
}
template<typename Iterator>
inline bool check_incrementable_iterator(const Iterator& it)
{
return it.valid()&&it!=it.owner()->end();
}
template<typename Iterator>
inline bool check_decrementable_iterator(const Iterator& it)
{
return it.valid()&&it!=it.owner()->begin();
}
template<typename Iterator>
inline bool check_is_owner(
const Iterator& it,const typename Iterator::container_type& cont)
{
return it.valid()&&it.owner()==&cont;
}
template<typename Iterator>
inline bool check_same_owner(const Iterator& it0,const Iterator& it1)
{
return it0.valid()&&it1.valid()&&it0.owner()==it1.owner();
}
template<typename Iterator>
inline bool check_valid_range(const Iterator& it0,const Iterator& it1)
{
if(!it0.valid()||!it1.valid()||it0.owner()!=it1.owner())return false;
Iterator last=it0.owner()->end();
if(it1==last)return true;
for(Iterator first=it0;first!=last;++first){
if(first==it1)return true;
}
return false;
}
template<typename Iterator>
inline bool check_outside_range(
const Iterator& it,const Iterator& it0,const Iterator& it1)
{
if(!it0.valid()||!it1.valid()||it0.owner()!=it1.owner())return false;
Iterator last=it0.owner()->end();
bool found=false;
Iterator first=it0;
for(;first!=last;++first){
if(first==it1)break;
/* crucial that this check goes after previous break */
if(first==it)found=true;
}
if(first!=it1)return false;
return !found;
}
template<typename Container>
inline bool check_different_container(
const Container& cont0,const Container& cont1)
{
return &cont0!=&cont1;
}
} /* namespace multi_index::safe_mode */
} /* namespace multi_index */
} /* namespace boost */
#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)
@@ -307,7 +71,7 @@ inline bool check_different_container(
safe_mode::not_incrementable_iterator);
#define BOOST_MULTI_INDEX_CHECK_DECREMENTABLE_ITERATOR(it) \
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT(\
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT( \
safe_mode::check_decrementable_iterator(it), \
safe_mode::not_decrementable_iterator);
@@ -317,7 +81,7 @@ inline bool check_different_container(
safe_mode::not_owner);
#define BOOST_MULTI_INDEX_CHECK_SAME_OWNER(it0,it1) \
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT(\
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT( \
safe_mode::check_same_owner(it0,it1), \
safe_mode::not_same_owner);
@@ -327,13 +91,478 @@ inline bool check_different_container(
safe_mode::invalid_range);
#define BOOST_MULTI_INDEX_CHECK_OUTSIDE_RANGE(it,it0,it1) \
BOOST_MULTI_INDEX_SAFE_MODE_ASSERT(\
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
#if defined(BOOST_HAS_THREADS)
#include <boost/detail/lightweight_mutex.hpp>
#endif
namespace boost{
namespace multi_index{
namespace safe_mode{
/* Checking routines. Assume the best for unchecked iterators
* (i.e. they pass the checking when there is not enough info
* to know.)
*/
template<typename Iterator>
inline bool check_valid_iterator(const Iterator& it)
{
return it.valid()||it.unchecked();
}
template<typename Iterator>
inline bool check_dereferenceable_iterator(const Iterator& it)
{
return it.valid()&&it!=it.owner()->end()||it.unchecked();
}
template<typename Iterator>
inline bool check_incrementable_iterator(const Iterator& it)
{
return it.valid()&&it!=it.owner()->end()||it.unchecked();
}
template<typename Iterator>
inline bool check_decrementable_iterator(const Iterator& it)
{
return it.valid()&&it!=it.owner()->begin()||it.unchecked();
}
template<typename Iterator>
inline bool check_is_owner(
const Iterator& it,const typename Iterator::container_type& cont)
{
return it.valid()&&it.owner()==&cont||it.unchecked();
}
template<typename Iterator>
inline bool check_same_owner(const Iterator& it0,const Iterator& it1)
{
return it0.valid()&&it1.valid()&&it0.owner()==it1.owner()||
it0.unchecked()||it1.unchecked();
}
template<typename Iterator>
inline bool check_valid_range(const Iterator& it0,const Iterator& it1)
{
if(!check_same_owner(it0,it1))return false;
if(it0.valid()){
Iterator last=it0.owner()->end();
if(it1==last)return true;
for(Iterator first=it0;first!=last;++first){
if(first==it1)return true;
}
return false;
}
return true;
}
template<typename Iterator>
inline bool check_outside_range(
const Iterator& it,const Iterator& it0,const Iterator& it1)
{
if(!check_same_owner(it0,it1))return false;
if(it0.valid()){
Iterator last=it0.owner()->end();
bool found=false;
Iterator first=it0;
for(;first!=last;++first){
if(first==it1)break;
/* crucial that this check goes after previous break */
if(first==it)found=true;
}
if(first!=it1)return false;
return !found;
}
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)
{
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()){
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 */
} /* namespace boost */
#endif /* BOOST_MULTI_INDEX_ENABLE_SAFE_MODE */
#endif
@@ -1,4 +1,4 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
/* 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)
@@ -9,6 +9,10 @@
#ifndef BOOST_MULTI_INDEX_DETAIL_SCOPE_GUARD_HPP
#define BOOST_MULTI_INDEX_DETAIL_SCOPE_GUARD_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
namespace boost{
namespace multi_index{
@@ -1,4 +1,4 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
/* Copyright 2003-2006 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)
@@ -9,6 +9,10 @@
#ifndef BOOST_MULTI_INDEX_DETAIL_SEQ_INDEX_NODE_HPP
#define BOOST_MULTI_INDEX_DETAIL_SEQ_INDEX_NODE_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <algorithm>
namespace boost{
@@ -21,28 +25,16 @@ namespace detail{
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_;}
sequenced_index_node_impl*& prior(){return prior_;}
sequenced_index_node_impl* prior()const{return prior_;}
sequenced_index_node_impl*& next(){return next_;}
sequenced_index_node_impl* next()const{return next_;}
/* interoperability with index_iterator */
/* interoperability with bidir_node_iterator */
static void increment(sequenced_index_node_impl*& x){x=x->next();}
static void decrement(sequenced_index_node_impl*& x){x=x->prior();}
/* 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;
}
/* algorithmic stuff */
static void link(
@@ -125,8 +117,6 @@ struct sequenced_index_node_impl
}
private:
sequenced_index_node_impl();
sequenced_index_node_impl* prior_;
sequenced_index_node_impl* next_;
};
@@ -137,10 +127,10 @@ struct sequenced_index_node_trampoline:sequenced_index_node_impl{};
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();}
sequenced_index_node_impl*& prior(){return impl_type::prior();}
sequenced_index_node_impl* prior()const{return impl_type::prior();}
sequenced_index_node_impl*& next(){return impl_type::next();}
sequenced_index_node_impl* next()const{return impl_type::next();}
sequenced_index_node_impl* impl()
{return static_cast<impl_type*>(this);}
@@ -156,7 +146,7 @@ struct sequenced_index_node:Super,sequenced_index_node_trampoline<Super>
static_cast<const impl_type*>(x));
}
/* interoperability with index_iterator */
/* interoperability with bidir_node_iterator */
static void increment(sequenced_index_node*& x)
{
@@ -172,18 +162,6 @@ struct sequenced_index_node:Super,sequenced_index_node_trampoline<Super>
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;
};
@@ -1,4 +1,4 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
/* Copyright 2003-2006 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)
@@ -9,11 +9,16 @@
#ifndef BOOST_MULTI_INDEX_DETAIL_SEQ_INDEX_OPS_HPP
#define BOOST_MULTI_INDEX_DETAIL_SEQ_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 <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{
@@ -55,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){
@@ -80,7 +85,8 @@ void sequenced_index_collate(
sequenced_index_node_impl* first1=y->next();
sequenced_index_node_impl* last1=y;
while(first0!=last0&&first1!=last1){
if(comp(Node::from_impl(first1)->value,Node::from_impl(first0)->value)){
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);
first1=tmp;
@@ -90,6 +96,16 @@ void sequenced_index_collate(
sequenced_index_node_impl::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)
{
@@ -106,19 +122,24 @@ 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);
aligned_storage<
sizeof(sequenced_index_node_impl)> carry_spc;
sizeof(sequenced_index_node_impl),
alignment_of<
sequenced_index_node_impl>::value
>::type carry_spc;
sequenced_index_node_impl& carry=
*static_cast<sequenced_index_node_impl*>(carry_spc.address());
*static_cast<sequenced_index_node_impl*>(static_cast<void*>(&carry_spc));
aligned_storage<
sizeof(
sequenced_index_node_impl[max_fill])> counter_spc;
sequenced_index_node_impl
[sequenced_index_sort_max_fill]),
alignment_of<
sequenced_index_node_impl
[sequenced_index_sort_max_fill]
>::value
>::type counter_spc;
sequenced_index_node_impl* counter=
static_cast<sequenced_index_node_impl*>(counter_spc.address());
static_cast<sequenced_index_node_impl*>(static_cast<void*>(&counter_spc));
std::size_t fill=0;
carry.prior()=carry.next()=&carry;
@@ -0,0 +1,69 @@
/* 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_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 unsigned long long type;};
#else
template<>struct uintptr_candidates<3> {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:-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
+20 -3
View File
@@ -1,4 +1,4 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
/* Copyright 2003-2006 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)
@@ -9,6 +9,13 @@
#ifndef BOOST_MULTI_INDEX_DETAIL_UNBOUNDED_HPP
#define BOOST_MULTI_INDEX_DETAIL_UNBOUNDED_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>
namespace boost{
namespace multi_index{
@@ -23,8 +30,18 @@ struct unbounded_type{};
namespace{
detail::unbounded_type unbounded_obj=detail::unbounded_type();
detail::unbounded_type& unbounded=unbounded_obj;
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
/* The default branch actually works for MSVC 6.0, but seems like
* the const qualifier reduces 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.
*/
static detail::unbounded_type unbounded_obj=detail::unbounded_type();
static detail::unbounded_type& unbounded=unbounded_obj;
#else
const detail::unbounded_type unbounded=detail::unbounded_type();
#endif
} /* unnamed */
@@ -1,4 +1,4 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
/* 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)
@@ -9,6 +9,10 @@
#ifndef BOOST_MULTI_INDEX_DETAIL_VALUE_COMPARE_HPP
#define BOOST_MULTI_INDEX_DETAIL_VALUE_COMPARE_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/call_traits.hpp>
#include <functional>
@@ -29,7 +33,7 @@ struct value_comparison:std::binary_function<Value,Value,bool>
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));
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,58 @@
/* 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_HASHED_INDEX_FWD_HPP
#define BOOST_MULTI_INDEX_HASHED_INDEX_FWD_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/multi_index/detail/hash_index_args.hpp>
namespace boost{
namespace multi_index{
namespace detail{
template<
typename KeyFromValue,typename Hash,typename Pred,
typename SuperMeta,typename TagList,typename Category
>
class hashed_index;
template<
typename KeyFromValue,typename Hash,typename Pred,
typename SuperMeta,typename TagList,typename Category
>
void swap(
hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,
hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& y);
} /* namespace multi_index::detail */
/* hashed_index specifiers */
template<
typename Arg1,typename Arg2=mpl::na,
typename Arg3=mpl::na,typename Arg4=mpl::na
>
struct hashed_unique;
template<
typename Arg1,typename Arg2=mpl::na,
typename Arg3=mpl::na,typename Arg4=mpl::na
>
struct hashed_non_unique;
} /* namespace multi_index */
} /* namespace boost */
#endif
+27 -3
View File
@@ -1,4 +1,4 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
/* Copyright 2003-2006 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)
@@ -9,11 +9,20 @@
#ifndef BOOST_MULTI_INDEX_IDENTITY_HPP
#define BOOST_MULTI_INDEX_IDENTITY_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/config.hpp>
#include <boost/mpl/if.hpp>
#include <boost/multi_index/identity_fwd.hpp>
#include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/utility/enable_if.hpp>
#if !defined(BOOST_NO_SFINAE)
#include <boost/type_traits/is_convertible.hpp>
#endif
namespace boost{
@@ -49,7 +58,14 @@ struct const_identity_base
typedef Type result_type;
template<typename ChainedPtr>
Type& operator()(const ChainedPtr& x)const
#if !defined(BOOST_NO_SFINAE)
typename disable_if<is_convertible<const ChainedPtr&,Type&>,Type&>::type
#else
Type&
#endif
operator()(const ChainedPtr& x)const
{
return operator()(*x);
}
@@ -79,7 +95,15 @@ struct non_const_identity_base
/* templatized for pointer-like types */
template<typename ChainedPtr>
Type& operator()(const ChainedPtr& x)const
#if !defined(BOOST_NO_SFINAE)
typename disable_if<
is_convertible<const ChainedPtr&,const Type&>,Type&>::type
#else
Type&
#endif
operator()(const ChainedPtr& x)const
{
return operator()(*x);
}
+5 -1
View File
@@ -1,4 +1,4 @@
/* Copyright 2003-2004 Joaqu M Lez Muz.
/* 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)
@@ -9,6 +9,10 @@
#ifndef BOOST_MULTI_INDEX_IDENTITY_HPP
#define BOOST_MULTI_INDEX_IDENTITY_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
namespace boost{
namespace multi_index{
+5 -1
View File
@@ -1,4 +1,4 @@
/* Copyright 2003-2004 Joaqu M Lez Muz.
/* 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)
@@ -9,6 +9,10 @@
#ifndef BOOST_MULTI_INDEX_INDEXED_BY_HPP
#define BOOST_MULTI_INDEX_INDEXED_BY_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/vector.hpp>
#include <boost/preprocessor/cat.hpp>
+5 -1
View File
@@ -1,4 +1,4 @@
/* Copyright 2003-2004 Joaqu M Lez Muz.
/* 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)
@@ -9,6 +9,10 @@
#ifndef BOOST_MULTI_INDEX_KEY_EXTRACTORS_HPP
#define BOOST_MULTI_INDEX_KEY_EXTRACTORS_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/multi_index/composite_key.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/member.hpp>
+50 -9
View File
@@ -1,4 +1,4 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
/* Copyright 2003-2006 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)
@@ -9,9 +9,18 @@
#ifndef BOOST_MULTI_INDEX_MEM_FUN_HPP
#define BOOST_MULTI_INDEX_MEM_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/remove_reference.hpp>
#include <boost/utility/enable_if.hpp>
#if !defined(BOOST_NO_SFINAE)
#include <boost/type_traits/is_convertible.hpp>
#endif
namespace boost{
@@ -46,7 +55,15 @@ struct const_mem_fun
typedef typename remove_reference<Type>::type result_type;
template<typename ChainedPtr>
Type operator()(const ChainedPtr& x)const
#if !defined(BOOST_NO_SFINAE)
typename disable_if<
is_convertible<const ChainedPtr&,const Class&>,Type>::type
#else
Type
#endif
operator()(const ChainedPtr& x)const
{
return operator()(*x);
}
@@ -73,7 +90,15 @@ struct mem_fun
typedef typename remove_reference<Type>::type result_type;
template<typename ChainedPtr>
Type operator()(const ChainedPtr& x)const
#if !defined(BOOST_NO_SFINAE)
typename disable_if<
is_convertible<ChainedPtr&,Class&>,Type>::type
#else
Type
#endif
operator()(const ChainedPtr& x)const
{
return operator()(*x);
}
@@ -107,7 +132,15 @@ struct const_mem_fun_explicit
typedef typename remove_reference<Type>::type result_type;
template<typename ChainedPtr>
Type operator()(const ChainedPtr& x)const
#if !defined(BOOST_NO_SFINAE)
typename disable_if<
is_convertible<const ChainedPtr&,const Class&>,Type>::type
#else
Type
#endif
operator()(const ChainedPtr& x)const
{
return operator()(*x);
}
@@ -136,7 +169,15 @@ struct mem_fun_explicit
typedef typename remove_reference<Type>::type result_type;
template<typename ChainedPtr>
Type operator()(const ChainedPtr& x)const
#if !defined(BOOST_NO_SFINAE)
typename disable_if<
is_convertible<ChainedPtr&,Class&>,Type>::type
#else
Type
#endif
operator()(const ChainedPtr& x)const
{
return operator()(*x);
}
@@ -160,17 +201,17 @@ struct mem_fun_explicit
#define BOOST_MULTI_INDEX_CONST_MEM_FUN(Class,Type,MemberFunName) \
::boost::multi_index::const_mem_fun_explicit<\
Class,Type,Type (Class::*)()const,&Class::MemberFunName>
Class,Type,Type (Class::*)()const,&Class::MemberFunName >
#define BOOST_MULTI_INDEX_MEM_FUN(Class,Type,MemberFunName) \
::boost::multi_index::mem_fun_explicit<\
Class,Type,Type (Class::*)(),&Class::MemberFunName>
Class,Type,Type (Class::*)(),&Class::MemberFunName >
#else
#define BOOST_MULTI_INDEX_CONST_MEM_FUN(Class,Type,MemberFunName) \
::boost::multi_index::const_mem_fun<Class,Type,&Class::MemberFunName>
::boost::multi_index::const_mem_fun< Class,Type,&Class::MemberFunName >
#define BOOST_MULTI_INDEX_MEM_FUN(Class,Type,MemberFunName) \
::boost::multi_index::mem_fun<Class,Type,&Class::MemberFunName>
::boost::multi_index::mem_fun< Class,Type,&Class::MemberFunName >
#endif
+50 -16
View File
@@ -1,4 +1,4 @@
/* Copyright 2003-2004 Joaquín M López Muñoz.
/* Copyright 2003-2006 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)
@@ -9,11 +9,20 @@
#ifndef BOOST_MULTI_INDEX_MEMBER_HPP
#define BOOST_MULTI_INDEX_MEMBER_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/utility/enable_if.hpp>
#include <cstddef>
#if !defined(BOOST_NO_SFINAE)
#include <boost/type_traits/is_convertible.hpp>
#endif
namespace boost{
template<class T> class reference_wrapper; /* fwd decl. */
@@ -48,7 +57,15 @@ struct const_member_base
typedef Type result_type;
template<typename ChainedPtr>
Type& operator()(const ChainedPtr& x)const
#if !defined(BOOST_NO_SFINAE)
typename disable_if<
is_convertible<const ChainedPtr&,const Class&>,Type&>::type
#else
Type&
#endif
operator()(const ChainedPtr& x)const
{
return operator()(*x);
}
@@ -63,7 +80,7 @@ struct const_member_base
return operator()(x.get());
}
Type& operator()(const reference_wrapper<Class> x,int=0)const
Type& operator()(const reference_wrapper<Class>& x,int=0)const
{
return operator()(x.get());
}
@@ -75,7 +92,15 @@ struct non_const_member_base
typedef Type result_type;
template<typename ChainedPtr>
Type& operator()(const ChainedPtr& x)const
#if !defined(BOOST_NO_SFINAE)
typename disable_if<
is_convertible<const ChainedPtr&,const Class&>,Type&>::type
#else
Type&
#endif
operator()(const ChainedPtr& x)const
{
return operator()(*x);
}
@@ -135,7 +160,15 @@ struct const_member_offset_base
typedef Type result_type;
template<typename ChainedPtr>
Type& operator()(const ChainedPtr& x)const
#if !defined(BOOST_NO_SFINAE)
typename disable_if<
is_convertible<const ChainedPtr&,const Class&>,Type&>::type
#else
Type&
#endif
operator()(const ChainedPtr& x)const
{
return operator()(*x);
}
@@ -165,7 +198,15 @@ struct non_const_member_offset_base
typedef Type result_type;
template<typename ChainedPtr>
Type& operator()(const ChainedPtr& x)const
#if !defined(BOOST_NO_SFINAE)
typename disable_if<
is_convertible<const ChainedPtr&,const Class&>,Type&>::type
#else
Type&
#endif
operator()(const ChainedPtr& x)const
{
return operator()(*x);
}
@@ -211,21 +252,14 @@ struct member_offset:
/* BOOST_MULTI_INDEX_MEMBER resolves to member in the normal cases,
* and to member_offset as a workaround in those defective compilers for
* which BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS is defined.
* This latter defect macro was included in Boost.Config starting from
* Boost 1.32, but we keep some additional checking of our own to
* remain compatible with Boost 1.31.
*/
#if defined(BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS) ||\
defined(BOOST_MSVC)&&(BOOST_MSVC<1310) ||\
defined(BOOST_INTEL_CXX_VERSION)&&defined(_MSC_VER)&&\
(BOOST_INTEL_CXX_VERSION<=700) ||\
defined(__IBMCPP__)&&(__IBMCPP__<=600)
#if defined(BOOST_NO_POINTER_TO_MEMBER_TEMPLATE_PARAMETERS)
#define BOOST_MULTI_INDEX_MEMBER(Class,Type,MemberName) \
::boost::multi_index::member_offset<Class,Type,offsetof(Class,MemberName)>
::boost::multi_index::member_offset< Class,Type,offsetof(Class,MemberName) >
#else
#define BOOST_MULTI_INDEX_MEMBER(Class,Type,MemberName) \
::boost::multi_index::member<Class,Type,&Class::MemberName>
::boost::multi_index::member< Class,Type,&Class::MemberName >
#endif
} /* namespace multi_index */

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