Compare commits
228 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6c810e19fc | |||
| d6932847ec | |||
| 88a418d563 | |||
| 16325e6039 | |||
| 7be686f18e | |||
| 8bdf62586f | |||
| 6fa0f070b9 | |||
| 1130b76e4b | |||
| 2e22bed967 | |||
| 88f3a9ca8b | |||
| 8e573eba2c | |||
| 2e361f8b6a | |||
| 259f87b550 | |||
| bbeb058580 | |||
| 5cd33a9a81 | |||
| 252398ac13 | |||
| 64b5247bea | |||
| bcec2c0467 | |||
| c6e0231bed | |||
| c757629a6d | |||
| 14d94f24fa | |||
| 18c8724a46 | |||
| 5f0ac92335 | |||
| c8e707ddd7 | |||
| f7d22b4de3 | |||
| c16d49acd0 | |||
| 28192c181a | |||
| 444ebbe95b | |||
| 5ecebcbc78 | |||
| 9a782276a4 | |||
| f86dce9db1 | |||
| 2448ba2a95 | |||
| 8ecbfdf080 | |||
| f9c9851ef3 | |||
| 708f8bd4ab | |||
| c21722cd10 | |||
| db3889ceff | |||
| 3be7ae350e | |||
| 2a6813f2e7 | |||
| 842bc1ba70 | |||
| a1944a19a2 | |||
| c2d7a65cfd | |||
| cf84a0dc1c | |||
| 5fec019715 | |||
| c7bfd7cf83 | |||
| 1235106ac0 | |||
| 5e790014c1 | |||
| a9c89540ac | |||
| 1fc02c6b1d | |||
| f54edbf0d3 | |||
| 7274eca56c | |||
| e953c2b4ff | |||
| cf076474d2 | |||
| 4c7a97e890 | |||
| 10fe2cd1ab | |||
| b81ee48320 | |||
| e043cadb7c | |||
| 233fd40984 | |||
| 67c04d598f | |||
| f1dde3d84e | |||
| f8eb1b16ce | |||
| 119d6d4a1c | |||
| 8682a33fcb | |||
| 34da3c9fd5 | |||
| 0bacd6fbed | |||
| 98d4cea748 | |||
| a872178185 | |||
| 027b5105ac | |||
| d18e3fd6a5 | |||
| ae533e1b16 | |||
| 4f6d05b115 | |||
| 1e39e5f9af | |||
| c1f8fc6348 | |||
| f1dcc889ec | |||
| 1669a1fb2d | |||
| 5fd646dc67 | |||
| ac2a6d72a3 | |||
| 8d3cfd51a8 | |||
| 35a151c9b0 | |||
| aa0ef9b10c | |||
| cc3da5b51c | |||
| 83a1b490ea | |||
| 12b9ac21c4 | |||
| 5190a31109 | |||
| 192d43569b | |||
| aa5cfdfb3c | |||
| 519d96871f | |||
| 9c61f94492 | |||
| dd5a6bd9a4 | |||
| 37ca90b823 | |||
| 964d83df51 | |||
| b16c15342a | |||
| e636c5ec72 | |||
| 1654aaa24e | |||
| 4797a93e7b | |||
| 41d3f814ba | |||
| 5aa6cc3b03 | |||
| 2cdc3c3778 | |||
| f30144473d | |||
| 7a6121fbbf | |||
| 538977752f | |||
| 2d346be3fb | |||
| 405e8b2a53 | |||
| 9ca897dae2 | |||
| 683ab3be1d | |||
| aa4edd99cf | |||
| a87b1eea96 | |||
| 3c1395a626 | |||
| 80812e471a | |||
| edd622e5ac | |||
| 4db9b44b75 | |||
| c6a1c3dd92 | |||
| 7aacfe029e | |||
| 1361bfe530 | |||
| b92f05140b | |||
| 95d44a6109 | |||
| c7f63a348f | |||
| f1ad358bff | |||
| cfa63b8a4c | |||
| 41be013bc6 | |||
| 1e00c5139b | |||
| b3de839dee | |||
| 18234ebeee | |||
| 92207dde6a | |||
| 7343ddf980 | |||
| 434680c817 | |||
| b28164d7f8 | |||
| 60c428b518 | |||
| dc0aa687ce | |||
| d1a5e7d40c | |||
| 1da460528a | |||
| b7984c6c83 | |||
| 5eb2679f11 | |||
| 3ed63ed785 | |||
| 4027620ec8 | |||
| 1d844cd539 | |||
| d4ff4dab15 | |||
| 9684b049a4 | |||
| c6ef47da18 | |||
| 8ae46eb0fd | |||
| 5d4107a5fa | |||
| 954004189a | |||
| 3546d0863c | |||
| f1176d462b | |||
| c943abed6c | |||
| c7da511d5e | |||
| 413e30393a | |||
| be06dec001 | |||
| af5b59059f | |||
| bdc4558ca6 | |||
| 6e33d0ef2a | |||
| 94894da751 | |||
| d8ad2dd48b | |||
| 344947128d | |||
| 699b887e18 | |||
| 10a8ae1037 | |||
| a43abdfe5f | |||
| ee6ceb1c60 | |||
| 075c6586e9 | |||
| 4e0e8eed9a | |||
| 7d5451215d | |||
| d5835caad6 | |||
| a3d458229e | |||
| 66db46fd1a | |||
| 64df029256 | |||
| 379bf82caf | |||
| 82be2525e6 | |||
| 0ef0156ba8 | |||
| 1a705d22f5 | |||
| 56f36f9099 | |||
| 22785eb7f3 | |||
| bbd8bf4c68 | |||
| 310f6e6c4b | |||
| 6fe87cd12d | |||
| 99f5892deb | |||
| 8f6461cdba | |||
| 3e7c3879b4 | |||
| 4208367e2b | |||
| 40af222972 | |||
| 006a9a479f | |||
| dec8cc927c | |||
| 1a3b9b55f5 | |||
| 20d9cc1b56 | |||
| 3c21273b61 | |||
| 075581b274 | |||
| 109bbf6d11 | |||
| 4809e1efdd | |||
| 5ebbd58c7e | |||
| bf50b5d7ad | |||
| bcf153b93f | |||
| da11b1c08d | |||
| 40bd426116 | |||
| 226155054d | |||
| 88c4eb4fb8 | |||
| 4c6fd92cde | |||
| 8122d38e4e | |||
| c28c2b60ab | |||
| 4fe662c18e | |||
| 47053672a2 | |||
| f49ca98c71 | |||
| c71f118114 | |||
| 07a48205fa | |||
| 7d0c5e0f9a | |||
| 9b2d916b6c | |||
| b059b7de06 | |||
| 435a1ac087 | |||
| 40b140b279 | |||
| 980b11f00e | |||
| c3f9fef32d | |||
| c6e23f0b81 | |||
| 840d57815b | |||
| 8b3416b6ae | |||
| c27c830958 | |||
| d044f6e769 | |||
| 0b8f770735 | |||
| 4137d4075d | |||
| c94964d198 | |||
| ac2fad60b1 | |||
| f595384267 | |||
| 14b7e52dbd | |||
| 1869a8827d | |||
| b4ba77f9d4 | |||
| f572badb27 | |||
| a1a878a917 | |||
| 12abc914bc | |||
| 2408f508c3 | |||
| d1214cabdd | |||
| 8fd3e2fd3f |
@@ -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 ;
|
||||
@@ -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 "as is" 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á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ó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žení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ö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ženílek for his useful comments and suggestions
|
||||
during the development of this release, and to Rosa Berná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ías Capeletto, John Eddy, Martin Eigel, Guillaume Lazzara,
|
||||
Felipe Magno de Almeida, Julien Pervillé, Hubert Schmid, Toby Smith.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
New member in the family! Thanks to Hé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>© Copyright 2003-2004 Joaquín M López Muñoz.
|
||||
<p>© Copyright 2003-2006 Joaquín M López Muñ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">
|
||||
|
||||
@@ -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><</span>
|
||||
<span class=keyword>int</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>random_access</span><span class=special><>,</span>
|
||||
<span class=identifier>random_access</span><span class=special><></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></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>© Copyright 2003-2004 Joaquín M López Muñoz.
|
||||
<p>© Copyright 2003-2006 Joaquín M López Muñ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">
|
||||
|
||||
@@ -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>© Copyright 2003-2004 Joaquín M López Muñoz.
|
||||
<p>© Copyright 2003-2006 Joaquín M López Muñ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">
|
||||
|
||||
|
After Width: | Height: | Size: 8.2 KiB |
@@ -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>© Copyright 2003-2004 Joaquín M López Muñoz.
|
||||
<p>© Copyright 2003-2006 Joaquín M López Muñ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">
|
||||
|
||||
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 9.7 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 9.5 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 9.6 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 9.7 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 9.5 KiB |
@@ -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>(&*</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>
|
||||
</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><</span><span class=keyword>int</span><span class=special>></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><</span><span class=keyword>int</span><span class=special>></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><</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><</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><</span><span class=keyword>int</span><span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></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>></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> / <i>S<sub>M</sub></i> =
|
||||
<i>S<sub>I</sub></i> / (<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<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<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>© Copyright 2003-2004 Joaquín M López Muñoz.
|
||||
<p>© Copyright 2003-2006 Joaquín M López Muñ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">
|
||||
|
||||
@@ -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><</span><b>consult hashed_unique reference for arguments</b><span class=special>></span>
|
||||
<span class=keyword>struct</span> <span class=identifier>hashed_unique</span><span class=special>;</span>
|
||||
<span class=keyword>template</span><span class=special><</span><b>consult hashed_non_unique reference for arguments</b><span class=special>></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><</span><b>implementation defined</b><span class=special>></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><</span><b>consult hashed_unique reference for arguments</b><span class=special>></span>
|
||||
<span class=keyword>struct</span> <span class=identifier>hashed_unique</span><span class=special>;</span>
|
||||
<span class=keyword>template</span><span class=special><</span><b>consult hashed_non_unique reference for arguments</b><span class=special>></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><</span><b>implementation defined</b><span class=special>></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><</span><b>implementation defined</b><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>&</span> <span class=identifier>x</span><span class=special>,</span><b>index class name</b><span class=special>&</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><</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><</span><span class=identifier>KeyFromValue</span><span class=special>::</span><span class=identifier>result_type</span><span class=special>>,</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><</span><span class=identifier>KeyFromValue</span><span class=special>::</span><span class=identifier>result_type</span><span class=special>></span>
|
||||
<span class=special>></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><</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><</span><span class=identifier>KeyFromValue</span><span class=special>::</span><span class=identifier>result_type</span><span class=special>>,</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><</span><span class=identifier>KeyFromValue</span><span class=special>::</span><span class=identifier>result_type</span><span class=special>></span>
|
||||
<span class=special>></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><</span><b>implementation defined: dependent on types Value, Allocator,
|
||||
TagList, KeyFromValue, Hash, Pred</b><span class=special>></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><</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>></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>&</span> <span class=keyword>operator</span><span class=special>=(</span><span class=keyword>const</span> <b>index class name</b><span class=special>&</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><</span><span class=identifier>iterator</span><span class=special>,</span><span class=keyword>bool</span><span class=special>></span> <span class=identifier>insert</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&</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>&</span> <span class=identifier>x</span><span class=special>);</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>InputIterator</span><span class=special>></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>&</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>&</span> <span class=identifier>x</span><span class=special>);</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>></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><</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>></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>&</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><</span><span class=keyword>typename</span> <span class=identifier>CompatibleKey</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>&</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><</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>></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>&</span> <span class=identifier>x</span><span class=special>,</span>
|
||||
<span class=keyword>const</span> <span class=identifier>CompatibleHash</span><span class=special>&</span> <span class=identifier>hash</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>CompatiblePred</span><span class=special>&</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><</span><span class=keyword>typename</span> <span class=identifier>CompatibleKey</span><span class=special>></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>&</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><</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>></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>&</span> <span class=identifier>x</span><span class=special>,</span>
|
||||
<span class=keyword>const</span> <span class=identifier>CompatibleHash</span><span class=special>&</span> <span class=identifier>hash</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>CompatiblePred</span><span class=special>&</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><</span><span class=keyword>typename</span> <span class=identifier>CompatibleKey</span><span class=special>></span>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>pair</span><span class=special><</span><span class=identifier>iterator</span><span class=special>,</span><span class=identifier>iterator</span><span class=special>></span> <span class=identifier>equal_range</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>CompatibleKey</span><span class=special>&</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><</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>></span>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>pair</span><span class=special><</span><span class=identifier>iterator</span><span class=special>,</span><span class=identifier>iterator</span><span class=special>></span> <span class=identifier>equal_range</span><span class=special>(</span>
|
||||
<span class=keyword>const</span> <span class=identifier>CompatibleKey</span><span class=special>&</span> <span class=identifier>x</span><span class=special>,
|
||||
</span><span class=keyword>const</span> <span class=identifier>CompatibleHash</span><span class=special>&</span> <span class=identifier>hash</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>CompatiblePred</span><span class=special>&</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>&</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><</span><b>implementation defined</b><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>&</span> <span class=identifier>x</span><span class=special>,</span><b>index class name</b><span class=special>&</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<std::size_t>::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>& operator=(const <b>index class name</b>& 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<iterator,bool> insert(const value_type& 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& 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<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& 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& 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<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&</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<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&</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<typename CompatibleKey> iterator find(const CompatibleKey& 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<<br>
|
||||
typename CompatibleKey,typename CompatibleHash, typename CompatiblePred<br>
|
||||
><br>
|
||||
iterator find(<br>
|
||||
const CompatibleKey& x,<br>
|
||||
const CompatibleHash& hash,const CompatiblePred& 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<typename CompatibleKey><br>
|
||||
size_type count(const CompatibleKey& 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<<br>
|
||||
typename CompatibleKey,typename CompatibleHash, typename CompatiblePred<br>
|
||||
><br>
|
||||
size_type count(<br>
|
||||
const CompatibleKey& x,<br>
|
||||
const CompatibleHash& hash,const CompatiblePred& 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<typename CompatibleKey><br>
|
||||
std::pair<iterator,iterator> equal_range(const CompatibleKey& 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<<br>
|
||||
typename CompatibleKey,typename CompatibleHash, typename CompatiblePred<br>
|
||||
><br>
|
||||
std::pair<iterator,iterator> equal_range(</br>
|
||||
const CompatibleKey& x,<br>
|
||||
const CompatibleHash& hash,const CompatiblePred& 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<i>().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<i>().begin()</code>, <code>m.get<i>().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<i>().end(n)</code> for some <code>n</code>, then
|
||||
<code>it'==m'.get<i>().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>© Copyright 2003-2006 Joaquín M López Muñ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>
|
||||
@@ -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>© Copyright 2003-2004 Joaquín M López Muñoz.
|
||||
<p>© Copyright 2003-2006 Joaquín M López Muñ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">
|
||||
|
||||
@@ -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&</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>© Copyright 2003-2004 Joaquín M López Muñoz.
|
||||
<p>© Copyright 2003-2006 Joaquín M López Muñ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">
|
||||
|
||||
@@ -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<Value,IndexSpecifierList,Allocator>& 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>© Copyright 2003-2004 Joaquín M López Muñoz.
|
||||
<p>© Copyright 2003-2006 Joaquín M López Muñ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">
|
||||
|
||||
@@ -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><</span><b>consult ordered_unique reference for arguments</b><span class=special>></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><</span><b>consult ordered_unique reference for arguments</b><span class=special>></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><</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><</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><</span><span class=identifier>KeyFromValue</span><span class=special>::</span><span class=identifier>result_type</span><span class=special>></span>
|
||||
<span class=special>></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><</span><span class=keyword>typename</span> <span class=identifier>InputIterator</span><span class=special>></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>&</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>&</span> <span class=identifier>x</span><span class=special>);</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>></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><</span><span class=keyword>typename</span> <span class=identifier>CompatibleKey</span><span class=special>></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>&</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>&</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><</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>></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>&</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>CompatibleCompare</span><span class=special>&</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><</span><span class=keyword>typename</span> <span class=identifier>CompatibleKey</span><span class=special>></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>&</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>CompatibleCompare</span><span class=special>&</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><</span><span class=keyword>typename</span> <span class=identifier>CompatibleKey</span><span class=special>></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>&</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>&</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><</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>></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>&</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>CompatibleCompare</span><span class=special>&</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><</span><span class=keyword>typename</span> <span class=identifier>CompatibleKey</span><span class=special>></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>&</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>&</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><</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>></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>&</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>CompatibleCompare</span><span class=special>&</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><</span><span class=keyword>typename</span> <span class=identifier>CompatibleKey</span><span class=special>></span>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>pair</span><span class=special><</span><span class=identifier>const_iterator</span><span class=special>,</span><span class=identifier>const_iterator</span><span class=special>></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><</span><span class=identifier>iterator</span><span class=special>,</span><span class=identifier>iterator</span><span class=special>></span> <span class=identifier>equal_range</span><span class=special>(</span>
|
||||
<span class=keyword>const</span> <span class=identifier>CompatibleKey</span><span class=special>&</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><</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>></span>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>pair</span><span class=special><</span><span class=identifier>const_iterator</span><span class=special>,</span><span class=identifier>const_iterator</span><span class=special>></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><</span><span class=identifier>iterator</span><span class=special>,</span><span class=identifier>iterator</span><span class=special>></span> <span class=identifier>equal_range</span><span class=special>(</span>
|
||||
<span class=keyword>const</span> <span class=identifier>CompatibleKey</span><span class=special>&</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>CompatibleCompare</span><span class=special>&</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><</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>></span>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>pair</span><span class=special><</span><span class=identifier>const_iterator</span><span class=special>,</span><span class=identifier>const_iterator</span><span class=special>></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><</span><span class=identifier>iterator</span><span class=special>,</span><span class=identifier>iterator</span><span class=special>></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<typename CompatibleKey> const_iterator find(const CompatibleKey& x)const;
|
||||
<code>template<typename CompatibleKey> iterator find(const CompatibleKey& x)const;
|
||||
</code>
|
||||
|
||||
<blockquote>
|
||||
@@ -713,7 +722,7 @@ interpretations.
|
||||
</blockquote>
|
||||
|
||||
<code>template<typename CompatibleKey,typename CompatibleCompare><br>
|
||||
const_iterator find(const CompatibleKey& x,const CompatibleCompare& comp)const;
|
||||
iterator find(const CompatibleKey& x,const CompatibleCompare& comp)const;
|
||||
</code>
|
||||
|
||||
<blockquote>
|
||||
@@ -747,7 +756,7 @@ is a compatible extension of <code>key_compare</code>.</br>
|
||||
</blockquote>
|
||||
|
||||
<code>template<typename CompatibleKey><br>
|
||||
const_iterator lower_bound(const CompatibleKey& x)const;
|
||||
iterator lower_bound(const CompatibleKey& x)const;
|
||||
</code>
|
||||
|
||||
<blockquote>
|
||||
@@ -760,7 +769,7 @@ not exist.<br>
|
||||
</blockquote>
|
||||
|
||||
<code>template<typename CompatibleKey,typename CompatibleCompare><br>
|
||||
const_iterator lower_bound(const CompatibleKey& x,const CompatibleCompare& comp)const;
|
||||
iterator lower_bound(const CompatibleKey& x,const CompatibleCompare& comp)const;
|
||||
</code>
|
||||
|
||||
<blockquote>
|
||||
@@ -773,7 +782,7 @@ not exist.<br>
|
||||
</blockquote>
|
||||
|
||||
<code>template<typename CompatibleKey><br>
|
||||
const_iterator upper_bound(const CompatibleKey& x)const;
|
||||
iterator upper_bound(const CompatibleKey& x)const;
|
||||
</code>
|
||||
|
||||
<blockquote>
|
||||
@@ -786,7 +795,7 @@ not exist.<br>
|
||||
</blockquote>
|
||||
|
||||
<code>template<typename CompatibleKey,typename CompatibleCompare><br>
|
||||
const_iterator upper_bound(const CompatibleKey& x,const CompatibleCompare& comp)const;
|
||||
iterator upper_bound(const CompatibleKey& x,const CompatibleCompare& comp)const;
|
||||
</code>
|
||||
|
||||
<blockquote>
|
||||
@@ -799,7 +808,7 @@ not exist.<br>
|
||||
</blockquote>
|
||||
|
||||
<code>template<typename CompatibleKey><br>
|
||||
std::pair<const_iterator,const_iterator> equal_range(<br>
|
||||
std::pair<iterator,iterator> equal_range(<br>
|
||||
const CompatibleKey& x)const;
|
||||
</code>
|
||||
|
||||
@@ -811,7 +820,7 @@ std::pair<const_iterator,const_iterator> equal_range(<br>
|
||||
</blockquote>
|
||||
|
||||
<code>template<typename CompatibleKey,typename CompatibleCompare><br>
|
||||
std::pair<const_iterator,const_iterator> equal_range(</br>
|
||||
std::pair<iterator,iterator> equal_range(</br>
|
||||
const CompatibleKey& x,const CompatibleCompare& comp)const;
|
||||
</code>
|
||||
|
||||
@@ -863,7 +872,7 @@ for every <code>upper</code> of type <code>UpperBounder</code>,
|
||||
</p>
|
||||
|
||||
<code>template<typename LowerBounder,typename UpperBounder><br>
|
||||
std::pair<const_iterator,const_iterator> range(<br>
|
||||
std::pair<iterator,iterator> range(<br>
|
||||
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<i>().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<i>().begin()</code>, <code>m.get<i>().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>© Copyright 2003-2004 Joaquín M López Muñoz.
|
||||
<p>© Copyright 2003-2006 Joaquín M López Muñ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">
|
||||
|
||||
@@ -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><</span><span class=keyword>typename</span> <span class=identifier>TagList</span><span class=special>=</span><span class=identifier>tag</span><span class=special><></span> <span class=special>></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><</span><b>implementation defined</b><span class=special>></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><</span><span class=keyword>typename</span> <span class=identifier>TagList</span><span class=special>=</span><span class=identifier>tag</span><span class=special><></span> <span class=special>></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><</span><b>implementation defined</b><span class=special>></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 ==,<,!=,>,>=,<=</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span><b>arg set 1</b><span class=special>,</span><b>arg set 2</b><span class=special>></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><</span><b>arg set 1</b><span class=special>>&</span> <span class=identifier>x</span><span class=special>,</span><span class=keyword>const</span> <b>index class name</b><span class=special><</span><b>arg set 2</b><span class=special>>&</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><</span><b>implementation defined</b><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>&</span> <span class=identifier>x</span><span class=special>,</span><b>index class name</b><span class=special>&</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><</span><span class=keyword>typename</span> <span class=identifier>TagList</span><span class=special>=</span><span class=identifier>tag</span><span class=special><></span> <span class=special>></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><</span><b>implementation defined: dependent on types Value, Allocator, TagList</b><span class=special>></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<iterator></b> <span class=identifier>reverse_iterator</span><span class=special>;</span>
|
||||
<span class=keyword>typedef</span> <b>equivalent to
|
||||
std::reverse_iterator<const_iterator></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>&</span> <span class=keyword>operator</span><span class=special>=(</span><span class=keyword>const</span> <b>index class name</b><span class=special>&</span> <span class=identifier>x</span><span class=special>);</span>
|
||||
|
||||
<span class=keyword>template</span> <span class=special><</span><span class=keyword>class</span> <span class=identifier>InputIterator</span><span class=special>></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>&</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>&</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><</span><span class=identifier>iterator</span><span class=special>,</span><span class=keyword>bool</span><span class=special>></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>&</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><</span><span class=identifier>iterator</span><span class=special>,</span><span class=keyword>bool</span><span class=special>></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>&</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><</span><span class=identifier>iterator</span><span class=special>,</span><span class=keyword>bool</span><span class=special>></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>&</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>&</span> <span class=identifier>x</span><span class=special>);</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>InputIterator</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>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>&</span> <span class=identifier>x</span><span class=special>);</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>></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>&</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>&</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>&</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>&</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>&</span> <span class=identifier>value</span><span class=special>);</span>
|
||||
<span class=keyword>template</span><span class=special><</span><span class=keyword>typename</span> <span class=identifier>Predicate</span><span class=special>></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><</span><span class=keyword>class</span> <span class=identifier>BinaryPredicate</span><span class=special>></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>&</span> <span class=identifier>x</span><span class=special>);</span>
|
||||
<span class=keyword>template</span> <span class=special><</span><span class=keyword>typename</span> <span class=identifier>Compare</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>&</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><</span><span class=keyword>typename</span> <span class=identifier>Compare</span><span class=special>></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><</span><span class=keyword>typename</span> <span class=identifier>InputIterator</span><span class=special>></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><</span><b>arg set 1</b><span class=special>,</span><b>arg set 2</b><span class=special>></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><</span><b>arg set 1</b><span class=special>>&</span> <span class=identifier>x</span><span class=special>,</span>
|
||||
<span class=keyword>const</span> <b>index class name</b><span class=special><</span><b>arg set 2</b><span class=special>>&</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>()&&</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><</span><b>arg set 1</b><span class=special>,</span><b>arg set 2</b><span class=special>></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><</span><b>arg set 1</b><span class=special>>&</span> <span class=identifier>x</span><span class=special>,</span>
|
||||
<span class=keyword>const</span> <b>index class name</b><span class=special><</span><b>arg set 2</b><span class=special>>&</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><</span><b>arg set 1</b><span class=special>,</span><b>arg set 2</b><span class=special>></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><</span><b>arg set 1</b><span class=special>>&</span> <span class=identifier>x</span><span class=special>,</span>
|
||||
<span class=keyword>const</span> <b>index class name</b><span class=special><</span><b>arg set 2</b><span class=special>>&</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><</span><b>arg set 1</b><span class=special>,</span><b>arg set 2</b><span class=special>></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><</span><b>arg set 1</b><span class=special>>&</span> <span class=identifier>x</span>
|
||||
<span class=special>,</span><span class=keyword>const</span> <b>index class name</b><span class=special><</span><b>arg set 2</b><span class=special>>&</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><</span><span class=identifier>x</span><span class=special>;</span>
|
||||
<span class=special>}</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span><b>arg set 1</b><span class=special>,</span><b>arg set 2</b><span class=special>></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><</span><b>arg set 1</b><span class=special>>&</span> <span class=identifier>x</span><span class=special>,</span>
|
||||
<span class=keyword>const</span> <b>index class name</b><span class=special><</span><b>arg set 2</b><span class=special>>&</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><</span><b>arg set 1</b><span class=special>,</span><b>arg set 2</b><span class=special>></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><</span><b>arg set 1</b><span class=special>>&</span> <span class=identifier>x</span><span class=special>,</span>
|
||||
<span class=keyword>const</span> <b>index class name</b><span class=special><</span><b>arg set 2</b><span class=special>>&</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=comment>// index specialized algorithms:</span>
|
||||
|
||||
<span class=keyword>template</span><span class=special><</span><b>implementation defined</b><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>&</span> <span class=identifier>x</span><span class=special>,</span><b>index class name</b><span class=special>&</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<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>& operator=(const <b>index class name</b>& 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 <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& 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><</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()<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& 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>></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><</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<iterator,bool> push_front(const value_type& 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<iterator,bool> push_back(const value_type& 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<iterator,bool> insert(iterator position,const value_type& 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& 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><</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<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& 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<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&</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>& x);</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>position</code> is a valid iterator of the index.
|
||||
<code>&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>& 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>&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>&x==this</code>, no iterator or reference
|
||||
is invalidated.<br>
|
||||
<b>Complexity:</b> If <code>&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>&x==this</code>, <code>nothrow</code>;
|
||||
otherwise, strong.<br>
|
||||
</blockquote>
|
||||
|
||||
<code>void splice(iterator position,<b>index class name&</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>&x==this</code>, no copy or deletion is performed, and insertions are
|
||||
always succesful.<br>
|
||||
<b>Postconditions:</b> If <code>&x==this</code>, no iterator or reference
|
||||
is invalidated.<br>
|
||||
<b>Complexity:</b> If <code>&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>&x==this</code>, <code>nothrow</code>;
|
||||
otherwise, basic.<br>
|
||||
</blockquote>
|
||||
|
||||
<code>void remove(const value_type& 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<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 <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& x);</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>std::less<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<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>&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>&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>&x==this</code>, <code>nothrow</code>;
|
||||
otherwise, basic.<br>
|
||||
</blockquote>
|
||||
|
||||
<code>template <typename Compare> void merge(index class name& 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>&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>&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>&x==this</code>, <code>nothrow</code>;
|
||||
otherwise, basic.<br>
|
||||
</blockquote>
|
||||
|
||||
<code>void sort();</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>std::less<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<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 <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<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<i>().begin()</code>, <code>m.get<i>().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>© Copyright 2003-2006 Joaquín M López Muñ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>
|
||||
@@ -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><</span><span class=keyword>typename</span> <span class=identifier>InputIterator</span><span class=special>></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>></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><</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><</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<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<i>().begin()</code>, <code>m.get<i>().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>© Copyright 2003-2004 Joaquín M López Muñoz.
|
||||
<p>© Copyright 2003-2006 Joaquín M López Muñ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">
|
||||
|
||||
@@ -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>© Copyright 2003-2006 Joaquín M López Muñ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>
|
||||
@@ -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>© Copyright 2003-2004 Joaquín M López Muñoz.
|
||||
<p>© Copyright 2003-2006 Joaquín M López Muñ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">
|
||||
|
||||
@@ -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><</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>></span>
|
||||
<span class=preprocessor>#include</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>ordered_index</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span>
|
||||
<span class=preprocessor>#include</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>identity</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span>
|
||||
<span class=preprocessor>#include</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>member</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></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><</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><N>()</code>
|
||||
<a href="../reference/multi_index_container.html#index_retrieval"><code>get</code></a><code><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<0>()</code>: for instance,
|
||||
<code>es.begin()</code> is equivalent to <code>es.get<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><</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>></span>
|
||||
<span class=preprocessor>#include</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>sequenced_index</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span>
|
||||
<span class=preprocessor>#include</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>ordered_index</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span>
|
||||
<span class=preprocessor>#include</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>identity</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></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><</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>></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><</span><span class=number>1</span><span class=special>>::</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><</span><span class=number>1</span><span class=special>>().</span><span class=identifier>find</span><span class=special>(</span><span class=string>"Judy Smith"</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><</span><span class=number>1</span><span class=special>>::</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><</span><span class=number>1</span><span class=special>>().</span><span class=identifier>find</span><span class=special>(</span><span class=string>"Judy Smith"</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><</span><span class=number>1</span><span class=special>>::</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><</span><span class=number>1</span><span class=special>>().</span><span class=identifier>find</span><span class=special>(</span><span class=string>"Judy Smith"</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><</span><span class=identifier>name</span><span class=special>>::</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><</span><span class=identifier>name</span><span class=special>>().</span><span class=identifier>find</span><span class=special>(</span><span class=string>"Judy Smith"</span><span class=special>);</span> <span class=comment>// get<1> 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>&</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><(</span><span class=keyword>const</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>id</span><span class=special><</span><span class=identifier>e</span><span class=special>.</span><span class=identifier>id</span><span class=special>;}</span>
|
||||
|
||||
<span class=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><</span>
|
||||
<span class=identifier>employee</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=comment>// sort by employee::operator<</span>
|
||||
<span class=identifier>ordered_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=identifier>employee</span><span class=special>></span> <span class=special>>,</span>
|
||||
|
||||
<span class=comment>// sort by less<string> on name</span>
|
||||
<span class=identifier>ordered_non_unique</span><span class=special><</span><span class=identifier>member</span><span class=special><</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>,&</span><span class=identifier>employee</span><span class=special>::</span><span class=identifier>name</span><span class=special>></span> <span class=special>>,</span>
|
||||
|
||||
<span class=comment>// sort by less<int> on name_length()</span>
|
||||
<span class=identifier>ordered_non_unique</span><span class=special><</span>
|
||||
<span class=identifier>const_mem_fun</span><span class=special><</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>,&</span><span class=identifier>employee</span><span class=special>::</span><span class=identifier>name_length</span><span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></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>"Anna Smith"</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><</span>
|
||||
<span class=keyword>int</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span><span class=identifier>sequenced</span><span class=special><></span> <span class=special>></span>
|
||||
<span class=special>></span> <span class=identifier>s</span><span class=special>;</span> <span class=comment>// list-like container</span>
|
||||
<span class=special>></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>© Copyright 2003-2004 Joaquín M López Muñoz.
|
||||
<p>© Copyright 2003-2006 Joaquín M López Muñ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>
|
||||
@@ -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><</span><span class=keyword>typename</span> <span class=identifier>IntegralType</span><span class=special>></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>)<(</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><</span><span class=keyword>unsigned</span> <span class=keyword>int</span><span class=special>,</span><span class=identifier>modulo_less</span><span class=special><</span><span class=keyword>unsigned</span> <span class=keyword>int</span><span class=special>></span> <span class=special>></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><</span><span class=keyword>unsigned</span> <span class=keyword>int</span><span class=special>>(</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>&</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>&</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><</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>></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><</span><span class=identifier>i</span><span class=special>>::</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><</span>
|
||||
<span class=keyword>unsigned</span> <span class=keyword>int</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>hashed_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=keyword>unsigned</span> <span class=keyword>int</span><span class=special>></span> <span class=special>>,</span>
|
||||
<span class=identifier>ordered_non_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=keyword>unsigned</span> <span class=keyword>int</span><span class=special>>,</span> <span class=identifier>modulo_less</span><span class=special><</span><span class=keyword>unsigned</span> <span class=keyword>int</span><span class=special>></span> <span class=special>>,</span>
|
||||
<span class=identifier>sequenced</span><span class=special><>,</span>
|
||||
<span class=identifier>random_access</span><span class=special><></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></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><</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><</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><</span><span class=keyword>unsigned</span> <span class=keyword>int</span><span class=special>>,</span>
|
||||
<span class=identifier>boost</span><span class=special>::</span><span class=identifier>hash</span><span class=special><</span><span class=keyword>unsigned</span> <span class=keyword>int</span><span class=special>>,</span>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>equal_to</span><span class=special><</span><span class=keyword>unsigned</span> <span class=keyword>int</span><span class=special>></span> <span class=special>>,</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><</span>
|
||||
<span class=identifier>identity</span><span class=special><</span><span class=keyword>unsigned</span> <span class=keyword>int</span><span class=special>>,</span>
|
||||
<span class=identifier>modulo_less</span><span class=special><</span><span class=keyword>unsigned</span> <span class=keyword>int</span><span class=special>></span> <span class=special>>,</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><>,</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><></span>
|
||||
<span class=special>></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><</span><span class=number>0</span><span class=special>>::</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><</span><span class=keyword>unsigned</span> <span class=keyword>int</span><span class=special>>(),</span><span class=identifier>modulo_less</span><span class=special><</span><span class=keyword>unsigned</span> <span class=keyword>int</span><span class=special>>(</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><</span><span class=number>2</span><span class=special>>::</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><</span><span class=number>3</span><span class=special>>::</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><</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>></span>
|
||||
<span class=preprocessor>#include</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=special>.</span><span class=identifier>hpp</span><span class=special>></span>
|
||||
<span class=preprocessor>#include</span> <span class=special><</span><span class=identifier>fstream</span><span class=special>></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>&</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>"data"</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><<</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>&</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>"data"</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>>></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>© Copyright 2003-2007 Joaquín M López Muñ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>
|
||||
@@ -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><</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>></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><</span><span class=number>1</span><span class=special>>::</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>>></span><span class=identifier>es</span><span class=special>;</span>
|
||||
<span class=identifier>ar</span><span class=special>>></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><</span><span class=number>1</span><span class=special>>(</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>© Copyright 2003-2006 Joaquín M López Muñ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>
|
||||
@@ -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>© Copyright 2003-2006 Joaquín M López Muñ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>
|
||||
@@ -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"> key-based </td>
|
||||
<td align="center" rowspan="2"> ordered </td>
|
||||
<td align="center"> <code>ordered_unique</code> </td>
|
||||
</tr>
|
||||
<tr class="odd_tr">
|
||||
<td align="center"> <code>ordered_non_unique</code> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" rowspan="2"> hashed </td>
|
||||
<td align="center"> <code>hashed_unique</code> </td>
|
||||
</tr>
|
||||
<tr class="odd_tr">
|
||||
<td align="center"> <code>hashed_non_unique</code> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" rowspan="2" colspan="2"> non key-based </td>
|
||||
<td align="center"><code> sequenced </code></td>
|
||||
</tr>
|
||||
<tr class="odd_tr">
|
||||
<td align="center"><code> random_access </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><</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>></span>
|
||||
<span class=preprocessor>#include</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>hashed_index</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span>
|
||||
<span class=preprocessor>#include</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>ordered_index</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span>
|
||||
<span class=preprocessor>#include</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>identity</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span>
|
||||
<span class=preprocessor>#include</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>member</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></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>&</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><(</span><span class=keyword>const</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>id</span><span class=special><</span><span class=identifier>e</span><span class=special>.</span><span class=identifier>id</span><span class=special>;}</span>
|
||||
<span class=special>};</span>
|
||||
|
||||
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=identifier>employee</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=comment>// sort by employee::operator<</span>
|
||||
<span class=identifier>ordered_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=identifier>employee</span><span class=special>></span> <span class=special>>,</span>
|
||||
|
||||
<span class=comment>// sort by less<string> on name</span>
|
||||
<span class=identifier>ordered_non_unique</span><span class=special><</span><span class=identifier>member</span><span class=special><</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>,&</span><span class=identifier>employee</span><span class=special>::</span><span class=identifier>name</span><span class=special>></span> <span class=special>>,</span>
|
||||
|
||||
<span class=comment>// hashed on ssnumber</span>
|
||||
<span class=identifier>hashed_unique</span><span class=special><</span><span class=identifier>member</span><span class=special><</span><span class=identifier>employee</span><span class=special>,</span><span class=keyword>int</span><span class=special>,&</span><span class=identifier>employee</span><span class=special>::</span><span class=identifier>ssnumber</span><span class=special>></span> <span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></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><[</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>]]]]></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><i>(key extractor)</i><span class=special>[,</span><i>(hash function)</i><span class=special>[,</span><i>(equality predicate)</i><span class=special>]]]></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<KeyFromValue::result_type></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>&</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>&</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>&</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><</span><span class=keyword>int</span><span class=special>>()(</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><</span><span class=keyword>int</span><span class=special>>()(</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><</span><span class=number>2</span><span class=special>>::</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>&</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><</span><span class=number>2</span><span class=special>>();</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><</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>></span>
|
||||
<span class=preprocessor>#include</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>random_access_index</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span>
|
||||
<span class=preprocessor>#include</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>ordered_index</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span>
|
||||
<span class=preprocessor>#include</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>identity</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></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><</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><</span>
|
||||
<span class=identifier>random_access</span><span class=special><>,</span>
|
||||
<span class=identifier>ordered_non_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>></span> <span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></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><</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>>(</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><<</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><[</span><i>(tag)</i><span class=special>]></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><</span>
|
||||
<span class=keyword>int</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>random_access</span><span class=special><>,</span>
|
||||
<span class=identifier>ordered_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=keyword>int</span><span class=special>></span> <span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></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><</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>reference_wrapper</span><span class=special><</span><span class=keyword>const</span> <span class=keyword>int</span><span class=special>></span> <span class=special>></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>&</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><</span><span class=number>1</span><span class=special>>().</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><</span><span class=number>1</span><span class=special>>().</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>© Copyright 2003-2006 Joaquín M López Muñ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>
|
||||
@@ -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<const Key,T></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><</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>></span>
|
||||
<span class=preprocessor>#include</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>ordered_index</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span>
|
||||
<span class=preprocessor>#include</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>identity</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span>
|
||||
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=keyword>int</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>ordered_unique</span><span class=special><</span>
|
||||
<span class=identifier>identity</span><span class=special><</span><span class=keyword>int</span><span class=special>></span> <span class=comment>// the key is the entire element</span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></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><</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>></span>
|
||||
<span class=preprocessor>#include</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>ordered_index</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span>
|
||||
<span class=preprocessor>#include</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>identity</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span>
|
||||
<span class=preprocessor>#include</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>member</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span>
|
||||
|
||||
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=identifier>employee</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>ordered_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=identifier>employee</span><span class=special>></span> <span class=special>>,</span>
|
||||
<span class=identifier>ordered_non_unique</span><span class=special><</span><span class=identifier>member</span><span class=special><</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>,&</span><span class=identifier>employee</span><span class=special>::</span><span class=identifier>name</span><span class=special>></span> <span class=special>>,</span>
|
||||
<span class=identifier>ordered_unique</span><span class=special><</span><span class=identifier>member</span><span class=special><</span><span class=identifier>employee</span><span class=special>,</span><span class=keyword>int</span><span class=special>,&</span><span class=identifier>employee</span><span class=special>::</span><span class=identifier>ssnumber</span><span class=special>></span> <span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></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><</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>></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><</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>></span>
|
||||
<span class=preprocessor>#include</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>ordered_index</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span>
|
||||
<span class=preprocessor>#include</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>identity</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span>
|
||||
<span class=preprocessor>#include</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>member</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span>
|
||||
<span class=preprocessor>#include</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>mem_fun</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></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>&</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><(</span><span class=keyword>const</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>id</span><span class=special><</span><span class=identifier>e</span><span class=special>.</span><span class=identifier>id</span><span class=special>;}</span>
|
||||
|
||||
<span class=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><</span>
|
||||
<span class=identifier>employee</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=comment>// sort by employee::operator<</span>
|
||||
<span class=identifier>ordered_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=identifier>employee</span><span class=special>></span> <span class=special>>,</span>
|
||||
|
||||
<span class=comment>// sort by less<string> on name</span>
|
||||
<span class=identifier>ordered_non_unique</span><span class=special><</span><span class=identifier>member</span><span class=special><</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>,&</span><span class=identifier>employee</span><span class=special>::</span><span class=identifier>name</span><span class=special>></span> <span class=special>>,</span>
|
||||
|
||||
<span class=comment>// sort by less<int> on name_length()</span>
|
||||
<span class=identifier>ordered_non_unique</span><span class=special><</span>
|
||||
<span class=identifier>const_mem_fun</span><span class=special><</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>,&</span><span class=identifier>employee</span><span class=special>::</span><span class=identifier>name_length</span><span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></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><</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>></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>&</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><</span>
|
||||
<span class=identifier>record</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>ordered_non_unique</span><span class=special><</span><span class=identifier>record_year</span><span class=special>></span> <span class=comment>// sorted by record's year</span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></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><</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>></span>
|
||||
<span class=preprocessor>#include</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>ordered_index</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span>
|
||||
<span class=preprocessor>#include</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>member</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></span>
|
||||
<span class=preprocessor>#include</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>composite_key</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>></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><</span>
|
||||
<span class=identifier>phonebook_entry</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</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><</span>
|
||||
<span class=identifier>composite_key</span><span class=special><</span>
|
||||
<span class=identifier>phonebook_entry</span><span class=special>,</span>
|
||||
<span class=identifier>member</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=special>,&</span><span class=identifier>phonebook_entry</span><span class=special>::</span><span class=identifier>family_name</span><span class=special>>,</span>
|
||||
<span class=identifier>member</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=special>,&</span><span class=identifier>phonebook_entry</span><span class=special>::</span><span class=identifier>given_name</span><span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>>,</span>
|
||||
<span class=identifier>ordered_unique</span><span class=special><</span> <span class=comment>// unique as numbers belong to only one subscriber</span>
|
||||
<span class=identifier>member</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=special>,&</span><span class=identifier>phonebook_entry</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=special>></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>"White"</span><span class=special>,</span><span class=string>"Dorothea"</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>-></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><</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>></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>"White"</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><</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>></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>"White"</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><</span>
|
||||
<span class=identifier>phonebook_entry</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>ordered_non_unique</span><span class=special><</span>
|
||||
<span class=identifier>composite_key</span><span class=special><</span>
|
||||
<span class=identifier>phonebook_entry</span><span class=special>,</span>
|
||||
<span class=identifier>member</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=special>,&</span><span class=identifier>phonebook_entry</span><span class=special>::</span><span class=identifier>family_name</span><span class=special>>,</span>
|
||||
<span class=identifier>member</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=special>,&</span><span class=identifier>phonebook_entry</span><span class=special>::</span><span class=identifier>given_name</span><span class=special>></span>
|
||||
<span class=special>>,</span>
|
||||
<span class=identifier>composite_key_compare</span><span class=special><</span>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>less</span><span class=special><</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>>,</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><</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>></span> <span class=comment>// given names reversed</span>
|
||||
<span class=special>></span>
|
||||
<span class=special>>,</span>
|
||||
<span class=identifier>ordered_unique</span><span class=special><</span>
|
||||
<span class=identifier>member</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=special>,&</span><span class=identifier>phonebook_entry</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=special>></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>&</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><</span>
|
||||
<span class=identifier>street_entry</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>hashed_non_unique</span><span class=special><</span> <span class=comment>// indexed by quadrant coordinates</span>
|
||||
<span class=identifier>composite_key</span><span class=special><</span>
|
||||
<span class=identifier>street_entry</span><span class=special>,</span>
|
||||
<span class=identifier>member</span><span class=special><</span><span class=identifier>street_entry</span><span class=special>,</span><span class=keyword>int</span><span class=special>,&</span><span class=identifier>street_entry</span><span class=special>::</span><span class=identifier>x</span><span class=special>>,</span>
|
||||
<span class=identifier>member</span><span class=special><</span><span class=identifier>street_entry</span><span class=special>,</span><span class=keyword>int</span><span class=special>,&</span><span class=identifier>street_entry</span><span class=special>::</span><span class=identifier>y</span><span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>>,</span>
|
||||
<span class=identifier>hashed_non_unique</span><span class=special><</span> <span class=comment>// indexed by street name</span>
|
||||
<span class=identifier>member</span><span class=special><</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>,&</span><span class=identifier>street_entry</span><span class=special>::</span><span class=identifier>name</span><span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></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><</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>></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><<</span><span class=identifier>p</span><span class=special>.</span><span class=identifier>first</span><span class=special>-></span><span class=identifier>name</span><span class=special><<</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><</span>
|
||||
<span class=identifier>street_entry</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>hashed_non_unique</span><span class=special><</span> <span class=comment>// indexed by quadrant coordinates</span>
|
||||
<span class=identifier>composite_key</span><span class=special><</span>
|
||||
<span class=identifier>street_entry</span><span class=special>,</span>
|
||||
<span class=identifier>member</span><span class=special><</span><span class=identifier>street_entry</span><span class=special>,</span><span class=keyword>int</span><span class=special>,&</span><span class=identifier>street_entry</span><span class=special>::</span><span class=identifier>x</span><span class=special>>,</span>
|
||||
<span class=identifier>member</span><span class=special><</span><span class=identifier>street_entry</span><span class=special>,</span><span class=keyword>int</span><span class=special>,&</span><span class=identifier>street_entry</span><span class=special>::</span><span class=identifier>y</span><span class=special>></span>
|
||||
<span class=special>>,</span>
|
||||
<span class=identifier>composite_key_hash</span><span class=special><</span>
|
||||
<span class=identifier>tuned_int_hash</span><span class=special>,</span>
|
||||
<span class=identifier>tuned_int_hash</span>
|
||||
<span class=special>></span>
|
||||
<span class=special>>,</span>
|
||||
<span class=identifier>hashed_non_unique</span><span class=special><</span> <span class=comment>// indexed by street name</span>
|
||||
<span class=identifier>member</span><span class=special><</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>,&</span><span class=identifier>street_entry</span><span class=special>::</span><span class=identifier>name</span><span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></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><</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>></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>&</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</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>.</span><span class=identifier>name</span><span class=special>;}</span>
|
||||
<span class=identifier>result_type</span><span class=special>&</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>-></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><</span>
|
||||
<span class=identifier>employee</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>ordered_unique</span><span class=special><</span><span class=identifier>name_extractor</span><span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></span> <span class=identifier>employee_set</span><span class=special>;</span>
|
||||
|
||||
<span class=comment>// ...as well as elements of type employee *</span>
|
||||
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=identifier>employee</span><span class=special>*,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>ordered_unique</span><span class=special><</span><span class=identifier>name_extractor</span><span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></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><</span>
|
||||
<span class=identifier>employee</span> <span class=special>*,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>ordered_non_unique</span><span class=special><</span><span class=identifier>member</span><span class=special><</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>,&</span><span class=identifier>employee</span><span class=special>::</span><span class=identifier>name</span><span class=special>></span> <span class=special>></span> <span class=special>></span>
|
||||
<span class=special>></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><</span>
|
||||
<span class=identifier>boost</span><span class=special>::</span><span class=identifier>reference_wrapper</span><span class=special><</span><span class=keyword>const</span> <span class=identifier>employee</span><span class=special>>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>ordered_non_unique</span><span class=special><</span><span class=identifier>member</span><span class=special><</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>,&</span><span class=identifier>employee</span><span class=special>::</span><span class=identifier>name</span><span class=special>></span> <span class=special>></span> <span class=special>></span>
|
||||
<span class=special>></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<employee></code>,</li>
|
||||
<li><code>std::list<boost::reference_wrapper<employee> >::iterator</code>,</li>
|
||||
<li><code>employee **</code>,</li>
|
||||
<li><code>boost::shared_ptr<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> key </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<T,int,&T::i></code></td>
|
||||
<td align="center">yes</td>
|
||||
<td align="center">yes</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>j</code></td>
|
||||
<td><code>member<T,const int,&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<T,int,&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<T,int,&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<T></code></td>
|
||||
<td><code>i</code></td>
|
||||
<td><code>member<T,int,&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<T,const int,&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<T,int,&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<T,int,&T::g></code></td>
|
||||
<td align="center">yes</td>
|
||||
<td align="center">no</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td align="center" rowspan="4"><code>reference_wrapper<const T></code></td>
|
||||
<td><code>i</code></td>
|
||||
<td><code>member<T,const int,&T::i></code></td>
|
||||
<td align="center">yes</td>
|
||||
<td align="center">no</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>j</code></td>
|
||||
<td><code>member<T,const int,&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<T,int,&T::f></code></td>
|
||||
<td align="center">yes</td>
|
||||
<td align="center">no</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>g()</code></td>
|
||||
<td colspan="3"> </td>
|
||||
</tr>
|
||||
|
||||
<tr class="odd_tr">
|
||||
<td align="center" rowspan="4">chained pointer to <code>T</code><br>
|
||||
or to <code>reference_wrapper<T></code></td>
|
||||
<td><code>i</code></td>
|
||||
<td><code>member<T,int,&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<T,const int,&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<T,int,&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<T,int,&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<const T></code></td>
|
||||
<td><code>i</code></td>
|
||||
<td><code>member<T,const int,&T::i></code></td>
|
||||
<td align="center">yes</td>
|
||||
<td align="center">no</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>j</code></td>
|
||||
<td><code>member<T,const int,&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<T,int,&T::f></code></td>
|
||||
<td align="center">yes</td>
|
||||
<td align="center">no</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>g()</code></td>
|
||||
<td colspan="3"> </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<const T,int,&T::i></code>, but rather as
|
||||
<code>member<T,const int,&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>© Copyright 2003-2006 Joaquín M López Muñ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 |
@@ -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><</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>></span> <span class=special>-></span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=identifier>Key</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span><span class=identifier>ordered_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=identifier>Key</span><span class=special>>,</span><span class=identifier>Compare</span><span class=special>></span> <span class=special>>,</span>
|
||||
<span class=identifier>Allocator</span>
|
||||
<span class=special>></span>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
In the default case where <code>Compare=std::less<Key></code> and
|
||||
<code>Allocator=std::allocator<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><</span><span class=identifier>Key</span><span class=special>></span> <span class=special>-></span> <span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Key</span><span class=special>></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><</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>></span> <span class=special>-></span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=identifier>Key</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span><span class=identifier>ordered_non_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=identifier>Key</span><span class=special>>,</span><span class=identifier>Compare</span><span class=special>></span> <span class=special>>,</span>
|
||||
<span class=identifier>Allocator</span>
|
||||
<span class=special>></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><</span><span class=identifier>Key</span><span class=special>></span> <span class=special>-></span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=identifier>Key</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span><span class=identifier>ordered_non_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=identifier>Key</span><span class=special>></span> <span class=special>></span> <span class=special>></span>
|
||||
<span class=special>></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&)</code> does not return an
|
||||
<code>iterator</code> as in <code>std::multiset</code>s, but rather a
|
||||
<code>std::pair<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<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><</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>></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>&</span> <span class=identifier>f</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>T2</span><span class=special>&</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><</span><span class=identifier>T1</span><span class=special>,</span><span class=identifier>T2</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>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><</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>></span> <span class=special>-></span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=identifier>Element</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>ordered_unique</span><span class=special><</span><span class=identifier>member</span><span class=special><</span><span class=identifier>Element</span><span class=special>,</span><span class=identifier>Key</span><span class=special>,&</span><span class=identifier>Element</span><span class=special>::</span><span class=identifier>first</span><span class=special>>,</span><span class=identifier>Compare</span><span class=special>></span>
|
||||
<span class=special>>,</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><</span><span class=identifier>Element</span><span class=special>>::</span><span class=identifier>other</span>
|
||||
<span class=special>></span>
|
||||
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>multimap</span><span class=special><</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>></span> <span class=special>-></span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=identifier>Element</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>ordered_non_unique</span><span class=special><</span><span class=identifier>member</span><span class=special><</span><span class=identifier>Element</span><span class=special>,</span><span class=identifier>Key</span><span class=special>,&</span><span class=identifier>Element</span><span class=special>::</span><span class=identifier>first</span><span class=special>>,</span><span class=identifier>Compare</span><span class=special>></span>
|
||||
<span class=special>>,</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><</span><span class=identifier>Element</span><span class=special>>::</span><span class=identifier>other</span>
|
||||
<span class=special>></span>
|
||||
|
||||
(<span class=identifier>with</span> <span class=identifier>Element</span><span class=special>=</span><span class=identifier>mutable_pair</span><span class=special><</span><span class=identifier>Key</span><span class=special>,</span><span class=identifier>T</span><span class=special>></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><</span><span class=identifier>Key</span><span class=special>,</span><span class=identifier>T</span><span class=special>></span> <span class=special>-></span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=identifier>Element</span><span class=special>,
|
||||
</span><span class=identifier>indexed_by</span><span class=special><</span><span class=identifier>ordered_unique</span><span class=special><</span><span class=identifier>member</span><span class=special><</span><span class=identifier>Element</span><span class=special>,</span><span class=identifier>Key</span><span class=special>,&</span><span class=identifier>Element</span><span class=special>::</span><span class=identifier>first</span><span class=special>></span> <span class=special>></span> <span class=special>></span>
|
||||
<span class=special>></span>
|
||||
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>multimap</span><span class=special><</span><span class=identifier>Key</span><span class=special>,</span><span class=identifier>T</span><span class=special>></span> <span class=special>-></span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=identifier>Element</span><span class=special>,
|
||||
</span><span class=identifier>indexed_by</span><span class=special><</span><span class=identifier>ordered_non_unique</span><span class=special><</span><span class=identifier>member</span><span class=special><</span><span class=identifier>Element</span><span class=special>,</span><span class=identifier>Key</span><span class=special>,&</span><span class=identifier>Element</span><span class=special>::</span><span class=identifier>first</span><span class=special>></span> <span class=special>></span> <span class=special>></span>
|
||||
<span class=special>></span>
|
||||
|
||||
(<span class=identifier>with</span> <span class=identifier>Element</span><span class=special>=</span><span class=identifier>mutable_pair</span><span class=special><</span><span class=identifier>Key</span><span class=special>,</span><span class=identifier>T</span><span class=special>></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><</span><span class=keyword>typename</span> <span class=identifier>T</span><span class=special>></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>&</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>&()</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><</span><span class=identifier>T</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>></span> <span class=special>-></span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span>
|
||||
<span class=identifier>Element</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span><span class=identifier>sequenced</span><span class=special><></span> <span class=special>>,</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><</span><span class=identifier>Element</span><span class=special>>::</span><span class=identifier>other</span>
|
||||
<span class=special>></span>
|
||||
|
||||
(<span class=identifier>with</span> <span class=identifier>Element</span><span class=special>=</span><span class=identifier>mutable_value</span><span class=special><</span><span class=identifier>T</span><span class=special>></span>)
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
or, if the default value <code>Allocator=std::allocator<T></code> is used:
|
||||
</p>
|
||||
|
||||
<blockquote><pre>
|
||||
<span class=identifier>std</span><span class=special>::</span><span class=identifier>list</span><span class=special><</span><span class=identifier>T</span><span class=special>></span> <span class=special>-></span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>mutable_value</span><span class=special><</span><span class=identifier>T</span><span class=special>>,</span><span class=identifier>indexed_by</span><span class=special><</span><span class=identifier>sequenced</span><span class=special><></span> <span class=special>></span> <span class=special>></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<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><</span>
|
||||
<span class=keyword>int</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>ordered_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=keyword>int</span><span class=special>></span> <span class=special>>,</span>
|
||||
<span class=identifier>sequenced</span><span class=special><></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></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><</span><span class=identifier>identity</span><span class=special><</span><span class=keyword>int</span><span class=special>></span> <span class=special>></span>
|
||||
<span class=identifier>sequenced</span><span class=special><></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><</span><span class=number>0</span><span class=special>>::</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><</span><span class=number>1</span><span class=special>>::</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><</span><span class=identifier>ordered_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=keyword>int</span><span class=special>></span> <span class=special>>,</span><span class=identifier>sequenced</span><span class=special><></span> <span class=special>></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><</span>
|
||||
<span class=keyword>int</span><span class=special>,</span>
|
||||
<span class=identifier>index_list_t</span>
|
||||
<span class=special>></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><</span>
|
||||
<span class=keyword>int</span><span class=special>,</span>
|
||||
<span class=identifier>indexed_by</span><span class=special><</span>
|
||||
<span class=identifier>ordered_unique</span><span class=special><</span><span class=identifier>identity</span><span class=special><</span><span class=keyword>int</span><span class=special>></span> <span class=special>></span>
|
||||
<span class=special>></span>
|
||||
<span class=special>></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><</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><></span>
|
||||
<span class=special>>::</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><</span>
|
||||
<span class=keyword>int</span><span class=special>,</span>
|
||||
<span class=identifier>index_list_t</span>
|
||||
<span class=special>></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>© Copyright 2003-2006 Joaquín M López Muñ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>
|
||||
@@ -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)
|
||||
;
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
|
||||
@@ -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<>
|
||||
*/
|
||||
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
|
||||
@@ -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<
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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,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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 */
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2004 Joaqu匤 M L�ez Mu�z.
|
||||
/* 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{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2004 Joaqu匤 M L�ez Mu�z.
|
||||
/* 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>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2004 Joaqu匤 M L�ez Mu�z.
|
||||
/* 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>
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||