Compare commits

...

3 Commits

Author SHA1 Message Date
Daniel James 9c810acb7a Merge from trunk.
[SVN r40260]
2007-10-21 07:28:23 +00:00
Daniel James 4287912dc8 Merge with the offending files removed.
[SVN r39995]
2007-10-13 23:18:35 +00:00
Daniel James 93c8694b4a Create a development branch for the hash library.
[SVN r38869]
2007-08-23 19:28:19 +00:00
77 changed files with 3614 additions and 1081 deletions
+14 -2
View File
@@ -148,6 +148,18 @@ codebase.
<br style="clear:all;">
</p>
<h2><a name="boost_1_35">Boost 1.35 release</a></h2>
<p>
<a href="tutorial/key_extraction.html#global_fun"><code>global_fun</code></a>
was included after a proposal by Markus Werle. Bruno Mart&iacute;nez Aguerre
suggested the inclusion of
<a href="tutorial/indices.html#iterator_to"><code>iterator_to</code></a>. The
rollback versions of <code>modify</code> and <code>modify_key</code> arose
from discussions with Mat&iacute;as Capeletto. Steven Watanabe spotted an
include guard bug present from the first release of the library.
</p>
<hr>
<div class="prev_link"><a href="release_notes.html"><img src="prev.gif" alt="release notes" border="0"><br>
@@ -161,9 +173,9 @@ Index
<br>
<p>Revised December 21st 2006</p>
<p>Revised September 3rd 2007</p>
<p>&copy; Copyright 2003-2006 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
<p>&copy; Copyright 2003-2007 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
+32 -8
View File
@@ -31,7 +31,7 @@ Tests
<ul>
<li><a href="#example1">Example 1: basic usage</a></li>
<li><a href="#example2">Example 2: using member functions as keys</a></li>
<li><a href="#example2">Example 2: using functions as keys</a></li>
<li><a href="#example3">Example 3: constructing <code>multi_index_container</code>s
with <code>ctor_args_list</code></a></li>
<li><a href="#example4">Example 4: bidirectional map</a></li>
@@ -42,6 +42,7 @@ Tests
<li><a href="#example9">Example 9: serialization and MRU lists</a></li>
<li><a href="#example10">Example 10: random access indices</a></li>
<li><a href="#example11">Example 11: index rearrangement</a></li>
<li><a href="#example12">Example 12: using Boost.Interprocess allocators</a></li>
</ul>
<h2><a name="example1">Example 1: basic usage</a></h2>
@@ -55,23 +56,23 @@ Basic program showing the multi-indexing capabilities of Boost.MultiIndex
with an admittedly boring set of <code>employee</code> records.
</p>
<h2><a name="example2">Example 2: using member functions as keys</a></h2>
<h2><a name="example2">Example 2: using functions as keys</a></h2>
<p>
See <a href="../example/memfun_key.cpp">source code</a>.
See <a href="../example/fun_key.cpp">source code</a>.
</p>
<p>
Usually keys assigned to an index are based on a member variable of the
element, but key extractors can be defined which take their value from
a member function. This has some similarity with the concept of
a member function or a global function. This has some similarity with the concept of
<i>calculated keys</i> supported by some relational database engines.
The example shows how to use the predefined <code>const_mem_fun</code>
key extractor to deal with this situation.
and <code>global_fun</code> key extractors to deal with this situation.
</p>
<p>
Keys based on member functions usually will not be actual references,
Keys based on functions usually will not be actual references,
but rather the temporary values resulting from the invocation of the
member function used. This implies that <code>modify_key</code> cannot be
applied to this type of extractors, which is a perfectly logical
@@ -111,6 +112,12 @@ for both keys. The program features a tiny Spanish-English
dictionary with online query of words in both languages.
</p>
<p>
This bidirectional map can be considered as a primitive precursor
to the full-fledged container provided by
<a href="../../bimap/index.html">Boost.Bimap</a>.
</p>
<h2><a name="example5">Example 5: sequenced indices</a></h2>
<p>
@@ -412,6 +419,23 @@ is used to apply to the deck a shuffle performed externally on an
auxiliary data structure.
</p>
<h2><a name="example12">Example 12: using Boost.Interprocess allocators</a></h2>
<p>
See <a href="../example/ip_allocator.cpp">source code</a>.
</p>
<p>
Boost.MultiIndex supports special allocators such as those provided by
<a href="../../interprocess/index.html">Boost.Interprocess</a>,
which allows for <code>multi_index_container</code>s to be placed in shared
memory. The example features a front-end to a small book database
implemented by means of a <code>multi_index_container</code> stored
in a Boost.Interprocess memory mapped file. The reader can verify that several
instances of the program correctly work simultaneously and immediately see
the changes to the database performed by any other instance.
</p>
<hr>
<div class="prev_link"><a href="performance.html"><img src="prev.gif" alt="performance" border="0"><br>
@@ -426,9 +450,9 @@ Tests
<br>
<p>Revised March 3rd 2006</p>
<p>Revised July 16th 2007</p>
<p>&copy; Copyright 2003-2006 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
<p>&copy; Copyright 2003-2007 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
+2 -16
View File
@@ -41,7 +41,6 @@ principle driving the current internal design of <code>multi_index_container</co
<li><a href="#notifying">Notifying indices</a></li>
<li><a href="#constraints">Constraints</a></li>
<li><a href="#user_defined_indices">User-defined indices</a></li>
<li><a href="#bimap">Bidirectional map</a></li>
<li><a href="#indexed_maps">Indexed maps</a></li>
<li><a href="#move_semantics">Move semantics</a></li>
</ul>
@@ -150,19 +149,6 @@ simple enough to make them worth documenting so that the (bold)
user can write implementations for her own indices.
</p>
<h2><a name="bimap">Bidirectional map</a></h2>
<p>
<a href="examples.html#example4">Example 4</a> in the examples section
features a <i>bidirectional map</i>, implemented as a
<code>multi_index_container</code> with two unique ordered indices. This particular
structure is deemed important enough as to provide it as a separate
class template, relying internally in <code>multi_index_container</code>. As
feedback is collected from the users of Boost.MultiIndex, other singular
instantiations of <code>multi_index_container</code> might be encapsulated
to form a component library of ready to use containers.
</p>
<h2><a name="indexed_maps">Indexed maps</a></h2>
<p>
@@ -240,9 +226,9 @@ Release notes
<br>
<p>Revised February 6th 2006</p>
<p>Revised July 5th 2007</p>
<p>&copy; Copyright 2003-2006 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
<p>&copy; Copyright 2003-2007 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
+106 -24
View File
@@ -44,9 +44,11 @@ Sequenced indices
<li><a href="#instantiation_types">Instantiation types</a></li>
<li><a href="#types">Nested types</a></li>
<li><a href="#constructors">Constructors, copy and assignment</a></li>
<li><a href="#iterators">Iterators</a></li>
<li><a href="#modifiers">Modifiers</a></li>
<li><a href="#observers">Observers</a></li>
<li><a href="#lookup">Lookup</a></li>
<li><a href="#bucket_interface">Bucket interface</a></li>
<li><a href="#hash_policy">Hash policy</a></li>
<li><a href="#serialization">Serialization</a></li>
</ul>
@@ -248,7 +250,12 @@ do not exactly conform to the requirements for unordered associative containers.
<span class=identifier>const_iterator</span> <span class=identifier>begin</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>iterator</span> <span class=identifier>end</span><span class=special>();</span>
<span class=identifier>const_iterator</span> <span class=identifier>end</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>const_iterator</span> <span class=identifier>cbegin</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>const_iterator</span> <span class=identifier>cend</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>iterator</span> <span class=identifier>iterator_to</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=identifier>const_iterator</span> <span class=identifier>iterator_to</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=comment>// modifiers:</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>pair</span><span class=special>&lt;</span><span class=identifier>iterator</span><span class=special>,</span><span class=keyword>bool</span><span class=special>&gt;</span> <span class=identifier>insert</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
@@ -262,7 +269,11 @@ do not exactly conform to the requirements for unordered associative containers.
<span class=keyword>bool</span> <span class=identifier>replace</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>&gt;</span> <span class=keyword>bool</span> <span class=identifier>modify</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>);</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Rollback</span><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=identifier>modify</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>,</span><span class=identifier>Rollback</span> <span class=identifier>back</span><span class=special>);</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>&gt;</span> <span class=keyword>bool</span> <span class=identifier>modify_key</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>);</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Rollback</span><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=identifier>modify_key</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>,</span><span class=identifier>Rollback</span> <span class=identifier>back</span><span class=special>);</span>
<span class=keyword>void</span> <span class=identifier>clear</span><span class=special>();</span>
<span class=keyword>void</span> <span class=identifier>swap</span><span class=special>(</span><b>index class name</b><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
@@ -313,6 +324,11 @@ do not exactly conform to the requirements for unordered associative containers.
<span class=identifier>const_local_iterator</span> <span class=identifier>begin</span><span class=special>(</span><span class=identifier>size_type</span> <span class=identifier>n</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>local_iterator</span> <span class=identifier>end</span><span class=special>(</span><span class=identifier>size_type</span> <span class=identifier>n</span><span class=special>);</span>
<span class=identifier>const_local_iterator</span> <span class=identifier>end</span><span class=special>(</span><span class=identifier>size_type</span> <span class=identifier>n</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>const_local_iterator</span> <span class=identifier>cbegin</span><span class=special>(</span><span class=identifier>size_type</span> <span class=identifier>n</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>const_local_iterator</span> <span class=identifier>cend</span><span class=special>(</span><span class=identifier>size_type</span> <span class=identifier>n</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>local_iterator</span> <span class=identifier>local_iterator_to</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=identifier>const_local_iterator</span> <span class=identifier>local_iterator_to</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=comment>// hash policy:</span>
@@ -434,6 +450,18 @@ objects to which <code>*this</code> and <code>x</code> belong, respectively.<br>
<b>Returns:</b> <code>*this</code>.<br>
</blockquote>
<h4><a name="iterators">Iterators</a></h4>
<code>iterator&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iterator_to(const value_type&amp; x);</br>
const_iterator iterator_to(const value_type&amp; x)const;</code>
<blockquote>
<b>Requires:</b> <code>x</code> is a reference to an element of the container.</br>
<b>Returns:</b> An iterator to <code>x</code>.<br>
<b>Complexity:</b> Constant.<br>
<b>Exception safety:</b> <code>nothrow</code>.<br>
</blockquote>
<h4><a name="modifiers">Modifiers</a></h4>
<code>std::pair&lt;iterator,bool> insert(const value_type&amp; x);</code>
@@ -589,6 +617,41 @@ user-provided operation (except possibly <code>mod</code>), then
the element pointed to by <code>position</code> is erased.
</blockquote>
<code>template&lt;typename Modifier,typename Rollback><br>
bool modify(iterator position,Modifier mod,Rollback back);</code>
<blockquote>
<b>Requires:</b> <code>Modifier</code> and <code>Rollback</code> are models of
<a href="http://www.sgi.com/tech/stl/UnaryFunction.html">
<code>Unary Function</code></a> accepting arguments of type
<code>value_type&amp;</code>. <code>position</code> is a valid dereferenceable
iterator of the index. The sequence of operations <code>mod(e)</code>,
<code>back(e)</code>, where <code>e</code> is the element
pointed to by <code>position</code>, restores all keys of the element
to their original state.</br>
<b>Effects:</b> Calls <code>mod(e)</code> where <code>e</code> is the element
pointed to by <code>position</code> and tries to rearrange <code>*position</code> into
all the indices of the <code>multi_index_container</code>. Rearrangement is successful if
<ul>
<li>the index is non-unique OR no other element exists
with equivalent key,</li>
<li>AND rearrangement is allowed by all other indices of the
<code>multi_index_container</code>.</li>
</ul>
If the rearrangement fails, <code>back(e)</code> is invoked and the
element is kept at its original position in all indices.<br>
<b>Postconditions:</b> Validity of <code>position</code> is preserved except if
the element is erased under the conditions described below.<br>
<b>Returns:</b> <code>true</code> if the operation succeeded, <code>false</code>
otherwise.<br>
<b>Complexity:</b> <code>O(M(n))</code>.<br>
<b>Exception safety:</b> Strong, except if <code>back</code> throws an
exception, in which case the modified element is erased. If <code>back</code>
throws inside the handling code executing after some other user-provided
operation has thrown, it is the exception generated by <code>back</code> that
is rethrown.
</blockquote>
<a name="modify_key">
<code>template&lt;typename Modifier> bool modify_key(iterator position,Modifier mod);</code></a>
@@ -600,26 +663,31 @@ from <code>value_type</code>. <code>Modifier</code> is a model of
<code>Unary Function</code></a> accepting arguments of type
<code>key_type&amp;</code>. <code>position</code> is a valid dereferenceable
iterator of the index.</br>
<b>Effects:</b> Calls <code>mod(k)</code> where <code>k</code> is the key
obtained by the internal <code>KeyFromValue</code> object of the index from
the element pointed to by <code>position</code>, and rearranges
<code>*position</code> into all the indices of the <code>multi_index_container</code>.
Rearrangement is successful if
<ul>
<li>the index is non-unique OR no other element exists
with equivalent key,</li>
<li>AND rearrangement is allowed by all other indices of the
<code>multi_index_container</code>.</li>
</ul>
If the rearrangement fails, the element is erased.<br>
<b>Postconditions:</b>Validity of <code>position</code> is preserved if
the operation succeeds.<br>
<b>Returns:</b> <code>true</code> if the operation succeeded, <code>false</code>
otherwise.<br>
<b>Complexity:</b> <code>O(M(n))</code>.<br>
<b>Exception safety:</b> Basic. If an exception is thrown by some
user-provided operation (except possibly <code>mod</code>), then
the element pointed to by <code>position</code> is erased.
<b>Effects:</b> Equivalent to <code>modify(position,mod')</code>,
with <code>mod'</code> defined in such a way that
<code>mod'(x)</code> is the same as <code>mod(key(x))</code>, where
<code>key</code> is the internal <code>KeyFromValue</code> object of the index.
</blockquote>
<code>template&lt;typename Modifier,typename Rollback><br>
bool modify_key(iterator position,Modifier mod,Rollback back);</code>
<blockquote>
<b>Requires:</b> <code>key_from_value</code> is a read/write
<a href="key_extraction.html#key_extractors"><code>Key Extractor</code></a>
from <code>value_type</code>. <code>Modifier</code> and <code>Rollback</code>
are models of <a href="http://www.sgi.com/tech/stl/UnaryFunction.html">
<code>Unary Function</code></a> accepting arguments of type
<code>key_type&amp;</code>. <code>position</code> is a valid dereferenceable
iterator of the index.
The sequence of operations <code>mod(k)</code>,
<code>back(k)</code>, where <code>k</code> is the key of the element
pointed to by <code>position</code>, restores k to its original state.</br>
<b>Effects:</b> Equivalent to <code>modify(position,mod',back')</code>,
with <code>mod'</code> and <code>back</code> defined in such a way that
<code>mod'(x)</code> is the same as <code>mod(key(x))</code> and
<code>back'(x)</code> is the same as <code>back(key(x))</code>, where
<code>key</code> is the internal <code>KeyFromValue</code> object of the index.
</blockquote>
<h4><a name="observers">Observers</a></h4>
@@ -768,7 +836,8 @@ std::pair&lt;iterator,iterator> equal_range(const CompatibleKey&amp; x)const;
<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>
to <code>x</code> (and only those), or (<code>end()</code>,<code>end()</code>)
if no such elements exist.<br>
<b>Complexity:</b> Average case <code>O(count(x))</code>, worst case
<code>O(n)</code>.<br>
</blockquote>
@@ -786,11 +855,24 @@ std::pair&lt;iterator,iterator> equal_range(</br>
<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>
to <code>x</code> (and only those), or (<code>end()</code>,<code>end()</code>)
if no such elements exist.<br>
<b>Complexity:</b> Average case <code>O(count(x,hash,eq))</code>, worst case
<code>O(n)</code>.<br>
</blockquote>
<h4><a name="bucket_interface">Bucket interface</a></h4>
<code>local_iterator&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;local_iterator_to(const value_type&amp; x);</br>
const_local_iterator local_iterator_to(const value_type&amp; x)const;</code>
<blockquote>
<b>Requires:</b> <code>x</code> is a reference to an element of the container.</br>
<b>Returns:</b> An iterator to <code>x</code>.<br>
<b>Complexity:</b> Constant.<br>
<b>Exception safety:</b> <code>nothrow</code>.<br>
</blockquote>
<h4><a name="hash_policy">Hash policy</a></h4>
@@ -895,9 +977,9 @@ Sequenced indices
<br>
<p>Revised July 13th 2006</p>
<p>Revised July 2nd 2007</p>
<p>&copy; Copyright 2003-2006 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
<p>&copy; Copyright 2003-2007 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
+5 -3
View File
@@ -88,7 +88,9 @@ The following dependencies among headers of Boost.MultiIndex hold:
<li><a href="key_extraction.html#member_synopsis">
<code>"boost/multi_index/member.hpp"</code></a>,</li>
<li><a href="key_extraction.html#mem_fun_synopsis">
<code>"boost/multi_index/mem_fun.hpp"</code></a> and</li>
<code>"boost/multi_index/mem_fun.hpp"</code></a>,</li>
<li><a href="key_extraction.html#global_fun_synopsis">
<code>"boost/multi_index/global_fun.hpp"</code></a> and</li>
<li><a href="key_extraction.html#composite_key_synopsis">
<code>"boost/multi_index/composite_key.hpp"</code></a>.</li>
</ul>
@@ -125,9 +127,9 @@ Index
<br>
<p>Revised February 6th 2005</p>
<p>Revised June 19th 2007</p>
<p>&copy; Copyright 2003-2006 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
<p>&copy; Copyright 2003-2007 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
+171 -9
View File
@@ -63,6 +63,12 @@ Compiler specifics
<li><a href="#boost_multi_index_mem_fun">Macro <code>BOOST_MULTI_INDEX_MEM_FUN</code></a></li>
</ul>
</li>
<li><a href="#global_fun_synopsis">Header
<code>"boost/multi_index/global_fun.hpp"</code> synopsis</a>
<ul>
<li><a href="#global_fun">Class template <code>global_fun</code></a></li>
</ul>
</li>
<li><a href="#composite_key_synopsis">Header
<code>"boost/multi_index/composite_key.hpp"</code> synopsis</a>
<ul>
@@ -131,12 +137,13 @@ for every <code>k1</code> of type <code>const KeyFromValue</code> and
</p>
<p>
Boost.MultiIndex provides five general-purpose key extractors:
Boost.MultiIndex provides six general-purpose key extractors:
<ul>
<li><a href="#identity"><code>identity</code></a>,</li>
<li><a href="#member"><code>member</code></a>,</li>
<li><a href="#const_mem_fun"><code>const_mem_fun</code></a>,</li>
<li><a href="#mem_fun"><code>mem_fun</code></a> and</li>
<li><a href="#mem_fun"><code>mem_fun</code></a>,</li>
<li><a href="#global_fun"><code>global_fun</code></a> and</li>
<li><a href="#composite_key"><code>composite_key</code></a>,</li>
</ul>
plus replacements for some of them:
@@ -178,6 +185,7 @@ ultimately dereferencing to values of <code>Type&amp;</code> or
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>identity</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>member</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>mem_fun</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>global_fun</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>composite_key</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
</pre></blockquote>
@@ -769,6 +777,147 @@ but it resolves to
for MSVC++ 6.0 or lower.
</p>
<h2>
<a name="global_fun_synopsis">Header
<a href="../../../../boost/multi_index/global_fun.hpp">
<code>"boost/multi_index/global_fun.hpp"</code></a> synopsis</a></h2>
<blockquote><pre>
<span class=keyword>namespace</span> <span class=identifier>boost</span><span class=special>{</span>
<span class=keyword>namespace</span> <span class=identifier>multi_index</span><span class=special>{</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>class</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Type</span><span class=special>,</span><span class=identifier>Type</span> <span class=special>(*</span><span class=identifier>PtrToFunction</span><span class=special>)(</span><span class=identifier>Value</span><span class=special>)&gt;</span>
<span class=keyword>struct</span> <span class=identifier>global_fun</span><span class=special>;</span>
<span class=special>}</span> <span class=comment>// namespace boost::multi_index</span>
<span class=special>}</span> <span class=comment>// namespace boost</span>
</pre></blockquote>
<h3><a name="global_fun">Class template <code>global_fun</code></a></h3>
<p>
<code>global_fun</code> is a <a href="#key_extractors"><code>Key Extractor</code></a>
based on a given global or static member function accepting the base type as argument
and returning the associated key.
</p>
<blockquote><pre>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>class</span> <span class=identifier>Value</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Type</span><span class=special>,</span><span class=identifier>Type</span> <span class=special>(*</span><span class=identifier>PtrToFunction</span><span class=special>)(</span><span class=identifier>Value</span><span class=special>)&gt;</span>
<span class=keyword>struct</span> <span class=identifier>global_fun</span>
<span class=special>{</span>
<span class=keyword>typedef</span> <span class=keyword>typename</span> <span class=identifier>remove_reference</span><span class=special>&lt;</span><span class=identifier>Type</span><span class=special>&gt;::</span><span class=identifier>type</span> <span class=identifier>result_type</span><span class=special>;</span>
<span class=comment>// Only provided under the following circumstances:
// - If Value is a reference to a constant type, only provided
// when const ChainedPtr&amp; is not convertible to Value;
// - if Value is a reference to a non-const type, only provided
// when ChainedPtr&amp; is not convertible to Value;
// - else, only provided when const ChainedPtr&amp; is not
// convertible to const Value&amp;.</span>
<span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>ChainedPtr</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=comment>// only provided if Value is a reference type</span>
<span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=identifier>Value</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=comment>// only provided if Value is not a reference type</span>
<span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>Value</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=comment>// only provided if Value is not a reference type</span>
<span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span><span class=keyword>const</span> <span class=identifier>reference_wrapper</span><span class=special>&lt;</span><span class=keyword>const</span> <span class=identifier>Value</span><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=comment>// only provided if Value is a reference type</span>
<span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span>
<span class=keyword>const</span> <span class=identifier>reference_wrapper</span><span class=special>&lt;</span>
<span class=identifier>remove_reference</span><span class=special>&lt;</span><span class=identifier>Value</span><span class=special>&gt;::</span><span class=identifier>type</span><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=comment>// only provided if Value is not a reference type or is
// a reference to a constant type</span>
<span class=identifier>Type</span> <span class=keyword>operator</span><span class=special>()(</span>
<span class=keyword>const</span> <span class=identifier>reference_wrapper</span><span class=special>&lt;</span>
<span class=keyword>typename</span> <span class=identifier>remove_const</span><span class=special>&lt;</span>
<span class=keyword>typename</span> <span class=identifier>remove_reference</span><span class=special>&lt;</span><span class=identifier>Value</span><span class=special>&gt;::</span><span class=identifier>type</span><span class=special>&gt;::</span><span class=identifier>type</span><span class=special>&gt;&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=special>};</span>
</pre></blockquote>
<p>
<code>PtrToFunction</code> specifies the particular function used to extract
the key of type <code>Type</code> from some <code>BaseType</code>.
<code>global_fun</code> supports the following function signatures:
<ul>
<li><code>Type f(BaseType)</code> (<code>Value</code> is <code>BaseType</code>),</li>
<li><code>Type f(const BaseType&amp;)</code> (<code>Value</code> is <code>const BaseType&amp;</code>),</li>
<li><code>Type f(BaseType&amp;)</code> (<code>Value</code> is <code>BaseType&amp;</code>).</li>
</ul>
<code>global_fun&lt;Type,Value,PtrToFunction&gt;</code> is a model of:
<ul>
<li><a href="#key_extractors"><code>Key Extractor</code></a>
from <code>reference_wrapper&lt;BaseType></code>,</li>
<li><a href="#key_extractors"><code>Key Extractor</code></a>
from any <a href="#chained_pointers">chained pointer</a>
to <code>BaseType</code>.</li>
</ul>
When <code>Value</code> is <code>BaseType</code> or
<code>const BaseType&amp;</code>,
<code>global_fun&lt;Type,Value,PtrToFunction&gt;</code> is also a model of:
<ul>
<li><a href="#key_extractors"><code>Key Extractor</code></a>
from <code>BaseType</code>,</li>
<li><a href="#key_extractors"><code>Key Extractor</code></a>
from <code>reference_wrapper&lt;const BaseType></code>,</li>
<li><a href="#key_extractors"><code>Key Extractor</code></a>
from any <a href="#chained_pointers">chained pointer</a>
to <code>const BaseType</code>.</li>
</ul>
</p>
<h4><code>global_fun</code> members</h4>
<code>template&lt;typename ChainedPtr> Type operator()(const ChainedPtr&amp; x)const;</code>
<blockquote>
<b>Requires:</b> <code>ChainedPtr</code> is a <a href="#chained_pointers">chained pointer</a>
type to <code>Value</code>.<br>
<b>Returns:</b> <code>PtrToFunction)(y)</code>, where <code>y</code> is the
object chained-pointed to by <code>x</code>.
</blockquote>
<code>Type operator()(Value x)const;</code>
<blockquote>
<b>Returns:</b> <code>PtrToFunction(x)</code>.
</blockquote>
<code>Type operator()(const Value&amp; x)const;</code>
<blockquote>
<b>Returns:</b> <code>PtrToFunction(x)</code>.
</blockquote>
<code>Type operator()(const reference_wrapper&lt;const Value&gt;&amp; x)const;</code>
<blockquote>
<b>Returns:</b> <code>PtrToFunction(x.get())</code>.
</blockquote>
<code>
Type operator()(<br>
&nbsp;&nbsp;const reference_wrapper&lt;remove_reference&lt;Value&gt;::type&gt;&amp; x)const;</code>
<blockquote>
<b>Returns:</b> <code>PtrToFunction(x.get())</code>.
</blockquote>
<code>Type operator()(<br>
&nbsp;&nbsp;const reference_wrapper&lt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;typename remove_const&lt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;typename remove_reference&lt;Value&gt;::type&gt;::type&gt;&amp; x)const;</code>
<blockquote>
<b>Returns:</b> <code>PtrToFunction(x.get())</code>.
</blockquote>
<h2>
<a name="composite_key_synopsis">Header
<a href="../../../../boost/multi_index/composite_key.hpp">
@@ -787,7 +936,7 @@ for MSVC++ 6.0 or lower.
<span class=comment>// comparison operators for composite_key_result:</span>
<span class=comment>// <b>OP</b> is any of =,&lt;,!=,&gt;,&gt;=,&lt;=</span>
<span class=comment>// <b>OP</b> is any of ==,&lt;,!=,&gt;,&gt;=,&lt;=</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>CompositeKey1</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>CompositeKey2</span><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=keyword>operator</span> <b><i>OP</i></b><span class=special>(</span>
@@ -1005,7 +1154,7 @@ instantiations as their extracted key.
<span class=comment>// comparison:</span>
<span class=comment>// <b>OP</b> is any of =,&lt;,!=,&gt;,&gt;=,&lt;=</span>
<span class=comment>// <b>OP</b> is any of ==,&lt;,!=,&gt;,&gt;=,&lt;=</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>CompositeKey1</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>CompositeKey2</span><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=keyword>operator</span> <b><i>OP</i></b><span class=special>(</span>
@@ -2072,9 +2221,22 @@ is lexicographical. Also, the following types are
<code>composite_key_result&lt;composite_key&lt;K0,...,Kk> ></code>, with
<code>Ki::result_type = Qi</code> for all <code>i = 0,...,k</code>.
</blockquote>
provided that each <code>Qi</code> is either <code>Ti</code> or a
<a href="ord_indices.html#set_operations"><code>Compatible Key</code></a>
of <code>Comparei</code>. In this case, the comparison is done
provided that
<ul>
<li>for <code>i = 0,...,min(j,k)-1</code>, <code>Qi</code> is either <code>Ti</code>
or <i>not coarser</i> than <code>Ti</code> (<code>Qi</code> is a
<a href="ord_indices.html#set_operations"><code>Compatible Key</code></a>
of <code>Comparei</code> and there are no two distinct elements of
<code>Ti</code> equivalent to one single element of <code>Qi</code>);
</li>
<li>
<code>Qm</code> (with <code>m = min(j,k)</code>) is either <code>Tm</code> or a
<a href="ord_indices.html#set_operations"><code>Compatible Key</code></a>
of <code>Comparem</code>.
</li>
</ul>
In this case, the comparison is done
lexicographically only on the first <code>1+min(j,k)</code> elements.
</p>
@@ -2101,9 +2263,9 @@ Compiler specifics
<br>
<p>Revised July 13th 2006</p>
<p>Revised August 2nd 2007</p>
<p>&copy; Copyright 2003-2006 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
<p>&copy; Copyright 2003-2007 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
+25 -5
View File
@@ -493,7 +493,8 @@ scheme outlined in the
<ol>
<li><code>Value</code> is the
<a href="http://www.sgi.com/tech/stl/Assignable.html"><code>Assignable</code></a>
type of the elements contained.</li>
type of the elements contained.
</li>
<li><code>IndexSpecifierList</code> specifies the indices that the
<code>multi_index_container</code> is composed of. It must be a non-empty
<a href="../../../../libs/mpl/doc/refmanual/forward-sequence.html">
@@ -503,8 +504,27 @@ scheme outlined in the
syntactic convenience, the
<a href="indices.html#indexed_by"><code>indexed_by</code></a>
MPL sequence can be used.
<li><code>Allocator</code> must comply with the C++ requirements for
allocators <b>[lib.allocator.requirements]</b>.
</li>
<li><code>Allocator</code> must be an allocator of <code>Value</code> objects
satisfying the associated C++ requirements at <b>[lib.allocator.requirements]</b>.
The following relaxations to the standard requirements are allowed:
<ul>
<li>Non-equal allocator instances are supported: swapping two non-equal
instances must not throw any exception.
</li>
<li>For every type <code>T</code>,
the type <code>Allocator::rebind&lt;T&gt;::other::pointer</code> can be any
kind of
<a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html"><code>Random
Access Iterator</code></a>, provided that it is explicitly constructible from
the literal <code>0</code> (standing here as the null pointer) or from any
<code>p</code> of type <code>T*</code> pointing into an area allocated by
some instance of <code>Allocator</code> or some other allocator type rebound
from <code>Allocator</code>. A <code>pointer</code> constructed from
<code>p</code> shall dereference to <code>*p</code>.
</li>
</ul>
</li>
</ol>
Indices of a given <code>multi_index_container</code> instantiation cannot have
duplicate <a href="indices.html#tags">tags</a>, either within a single
@@ -882,9 +902,9 @@ Index reference
<br>
<p>Revised February 6th 2006</p>
<p>Revised July 17th 2007</p>
<p>&copy; Copyright 2003-2006 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
<p>&copy; Copyright 2003-2007 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
+88 -24
View File
@@ -43,6 +43,7 @@ Hashed indices
<li><a href="#complexity_signature">Complexity signature</a></li>
<li><a href="#instantiation_types">Instantiation types</a></li>
<li><a href="#constructors">Constructors, copy and assignment</a></li>
<li><a href="#iterators">Iterators</a></li>
<li><a href="#modifiers">Modifiers</a></li>
<li><a href="#observers">Observers</a></li>
<li><a href="#set_operations">Set operations</a></li>
@@ -205,7 +206,7 @@ requirements for these types of containers.
<span class=keyword>namespace</span> <span class=identifier>multi_index</span><span class=special>{</span>
<span class=keyword>namespace</span><span class=special>{</span> <b>implementation defined </b><span class=identifier>unbounded</span><span class=special>;</span> <span class=special>}</span> <span class=comment>// see range()</span>
<b>implementation defined </b><span class=identifier>unbounded</span><span class=special>;</span> <span class=comment>// see range()</span>
<span class=keyword>namespace</span> <span class=identifier>detail</span><span class=special>{</span>
@@ -252,7 +253,14 @@ requirements for these types of containers.
<span class=identifier>const_reverse_iterator</span> <span class=identifier>rbegin</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>reverse_iterator</span> <span class=identifier>rend</span><span class=special>();</span>
<span class=identifier>const_reverse_iterator</span> <span class=identifier>rend</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>const_iterator</span> <span class=identifier>cbegin</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>const_iterator</span> <span class=identifier>cend</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>const_reverse_iterator</span> <span class=identifier>crbegin</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>const_reverse_iterator</span> <span class=identifier>crend</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>iterator</span> <span class=identifier>iterator_to</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=identifier>const_iterator</span> <span class=identifier>iterator_to</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=comment>// capacity:</span>
<span class=keyword>bool</span> <span class=identifier>empty</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
@@ -272,7 +280,11 @@ requirements for these types of containers.
<span class=keyword>bool</span> <span class=identifier>replace</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>&gt;</span> <span class=keyword>bool</span> <span class=identifier>modify</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>);</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Rollback</span><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=identifier>modify</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>,</span><span class=identifier>Rollback</span> <span class=identifier>back</span><span class=special>);</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>&gt;</span> <span class=keyword>bool</span> <span class=identifier>modify_key</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>);</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Rollback</span><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=identifier>modify_key</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>,</span><span class=identifier>Rollback</span> <span class=identifier>back</span><span class=special>);</span>
<span class=keyword>void</span> <span class=identifier>swap</span><span class=special>(</span><b>index class name</b><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=keyword>void</span> <span class=identifier>clear</span><span class=special>();</span>
@@ -395,7 +407,7 @@ section</a>. The complexity signature of ordered indices is:
<li>copying: <code>c(n)=n*log(n)</code>,</li>
<li>insertion: <code>i(n)=log(n)</code>,</li>
<li>hinted insertion: <code>h(n)=1</code> (constant) if the hint element
precedes the point of insertion, <code>h(n)=log(n)</code> otherwise,</li>
is immediately after the point of insertion, <code>h(n)=log(n)</code> otherwise,</li>
<li>deletion: <code>d(n)=1</code> (amortized constant),</li>
<li>replacement: <code>r(n)=1</code> (constant) if the element position does not
change, <code>r(n)=log(n)</code> otherwise,</li>
@@ -448,6 +460,18 @@ objects to which <code>*this</code> and <code>x</code> belong, respectively.<br>
<b>Returns:</b> <code>*this</code>.<br>
</blockquote>
<h4><a name="iterators">Iterators</a></h4>
<code>iterator&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iterator_to(const value_type&amp; x);</br>
const_iterator iterator_to(const value_type&amp; x)const;</code>
<blockquote>
<b>Requires:</b> <code>x</code> is a reference to an element of the container.</br>
<b>Returns:</b> An iterator to <code>x</code>.<br>
<b>Complexity:</b> Constant.<br>
<b>Exception safety:</b> <code>nothrow</code>.<br>
</blockquote>
<h4><a name="modifiers">Modifiers</a></h4>
<code>std::pair&lt;iterator,bool> insert(const value_type&amp; x);</code>
@@ -602,6 +626,41 @@ user-provided operation (except possibly <code>mod</code>), then
the element pointed to by <code>position</code> is erased.
</blockquote>
<code>template&lt;typename Modifier,typename Rollback><br>
bool modify(iterator position,Modifier mod,Rollback back);</code>
<blockquote>
<b>Requires:</b> <code>Modifier</code> and <code>Rollback</code> are models of
<a href="http://www.sgi.com/tech/stl/UnaryFunction.html">
<code>Unary Function</code></a> accepting arguments of type
<code>value_type&amp;</code>. <code>position</code> is a valid dereferenceable
iterator of the index. The sequence of operations <code>mod(e)</code>,
<code>back(e)</code>, where <code>e</code> is the element
pointed to by <code>position</code>, restores all keys of the element
to their original state.</br>
<b>Effects:</b> Calls <code>mod(e)</code> where <code>e</code> is the element
pointed to by <code>position</code> and tries to rearrange <code>*position</code> into
all the indices of the <code>multi_index_container</code>. Rearrangement is successful if
<ul>
<li>the index is non-unique OR no other element exists
with equivalent key,</li>
<li>AND rearrangement is allowed by all other indices of the
<code>multi_index_container</code>.</li>
</ul>
If the rearrangement fails, <code>back(e)</code> is invoked and the
element is kept at its original position in all indices.<br>
<b>Postconditions:</b> Validity of <code>position</code> is preserved except if
the element is erased under the conditions described below.<br>
<b>Returns:</b> <code>true</code> if the operation succeeded, <code>false</code>
otherwise.<br>
<b>Complexity:</b> <code>O(M(n))</code>.<br>
<b>Exception safety:</b> Strong, except if <code>back</code> throws an
exception, in which case the modified element is erased. If <code>back</code>
throws inside the handling code executing after some other user-provided
operation has thrown, it is the exception generated by <code>back</code> that
is rethrown.
</blockquote>
<a name="modify_key">
<code>template&lt;typename Modifier> bool modify_key(iterator position,Modifier mod);</code></a>
@@ -613,26 +672,31 @@ from <code>value_type</code>. <code>Modifier</code> is a model of
<code>Unary Function</code></a> accepting arguments of type
<code>key_type&amp;</code>. <code>position</code> is a valid dereferenceable
iterator of the index.</br>
<b>Effects:</b> Calls <code>mod(k)</code> where <code>k</code> is the key
obtained by the internal <code>KeyFromValue</code> object of the index from
the element pointed to by <code>position</code>, and rearranges
<code>*position</code> into all the indices of the <code>multi_index_container</code>.
Rearrangement is successful if
<ul>
<li>the index is non-unique OR no other element exists
with equivalent key,</li>
<li>AND rearrangement is allowed by all other indices of the
<code>multi_index_container</code>.</li>
</ul>
If the rearrangement fails, the element is erased.<br>
<b>Postconditions:</b>Validity of <code>position</code> is preserved if
the operation succeeds.<br>
<b>Returns:</b> <code>true</code> if the operation succeeded, <code>false</code>
otherwise.<br>
<b>Complexity:</b> <code>O(M(n))</code>.<br>
<b>Exception safety:</b> Basic. If an exception is thrown by some
user-provided operation (except possibly <code>mod</code>), then
the element pointed to by <code>position</code> is erased.
<b>Effects:</b> Equivalent to <code>modify(position,mod')</code>,
with <code>mod'</code> defined in such a way that
<code>mod'(x)</code> is the same as <code>mod(key(x))</code>, where
<code>key</code> is the internal <code>KeyFromValue</code> object of the index.
</blockquote>
<code>template&lt;typename Modifier,typename Rollback><br>
bool modify_key(iterator position,Modifier mod,Rollback back);</code>
<blockquote>
<b>Requires:</b> <code>key_from_value</code> is a read/write
<a href="key_extraction.html#key_extractors"><code>Key Extractor</code></a>
from <code>value_type</code>. <code>Modifier</code> and <code>Rollback</code>
are models of <a href="http://www.sgi.com/tech/stl/UnaryFunction.html">
<code>Unary Function</code></a> accepting arguments of type
<code>key_type&amp;</code>. <code>position</code> is a valid dereferenceable
iterator of the index.
The sequence of operations <code>mod(k)</code>,
<code>back(k)</code>, where <code>k</code> is the key of the element
pointed to by <code>position</code>, restores k to its original state.</br>
<b>Effects:</b> Equivalent to <code>modify(position,mod',back')</code>,
with <code>mod'</code> and <code>back</code> defined in such a way that
<code>mod'(x)</code> is the same as <code>mod(key(x))</code> and
<code>back'(x)</code> is the same as <code>back(key(x))</code>, where
<code>key</code> is the internal <code>KeyFromValue</code> object of the index.
</blockquote>
<h4><a name="observers">Observers</a></h4>
@@ -954,9 +1018,9 @@ Hashed indices
<br>
<p>Revised March 31st 2006</p>
<p>Revised July 2nd 2007</p>
<p>&copy; Copyright 2003-2006 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
<p>&copy; Copyright 2003-2007 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
+58 -5
View File
@@ -41,6 +41,7 @@ Key extraction
<li><a href="#complexity_signature">Complexity signature</a></li>
<li><a href="#instantiation_types">Instantiation types</a></li>
<li><a href="#constructors">Constructors, copy and assignment</a></li>
<li><a href="#iterators">Iterators</a></li>
<li><a href="#capacity">Capacity operations</a></li>
<li><a href="#modifiers">Modifiers</a></li>
<li><a href="#list_operations">List operations</a></li>
@@ -238,6 +239,13 @@ to the requirements for these types of containers.
<span class=identifier>const_reverse_iterator</span> <span class=identifier>rbegin</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>reverse_iterator</span> <span class=identifier>rend</span><span class=special>();</span>
<span class=identifier>const_reverse_iterator</span> <span class=identifier>rend</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>const_iterator</span> <span class=identifier>cbegin</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>const_iterator</span> <span class=identifier>cend</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>const_reverse_iterator</span> <span class=identifier>crbegin</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>const_reverse_iterator</span> <span class=identifier>crend</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>iterator</span> <span class=identifier>iterator_to</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=identifier>const_iterator</span> <span class=identifier>iterator_to</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=comment>// capacity:</span>
@@ -273,6 +281,8 @@ to the requirements for these types of containers.
<span class=keyword>bool</span> <span class=identifier>replace</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>&gt;</span> <span class=keyword>bool</span> <span class=identifier>modify</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>);</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Rollback</span><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=identifier>modify</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>,</span><span class=identifier>Rollback</span> <span class=identifier>back</span><span class=special>);</span>
<span class=keyword>void</span> <span class=identifier>swap</span><span class=special>(</span><b>index class name</b><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
@@ -396,7 +406,7 @@ of the complexity formulas:
<p>
(<code>shl</code> and <code>rel</code> stand for <i>shift left</i> and
<i>relocate</i>, respetively.)
<i>relocate</i>, respectively.)
</p>
<h4><a name="instantiation_types">Instantiation types</a></h4>
@@ -462,6 +472,18 @@ index of the <code>multi_index_container</code> to which this index belongs.
</pre></blockquote>
</blockquote>
<h4><a name="iterators">Iterators</a></h4>
<code>iterator&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iterator_to(const value_type&amp; x);</br>
const_iterator iterator_to(const value_type&amp; x)const;</code>
<blockquote>
<b>Requires:</b> <code>x</code> is a reference to an element of the container.</br>
<b>Returns:</b> An iterator to <code>x</code>.<br>
<b>Complexity:</b> Constant.<br>
<b>Exception safety:</b> <code>nothrow</code>.<br>
</blockquote>
<h4><a name="capacity">Capacity operations</a></h4>
<a name="capacity_memfun"><code>size_type capacity()const;</code></a>
@@ -634,8 +656,8 @@ 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
random access indices does not change the position of the element with respect
to the index; rearrangement on other indices may or might not succeed. If the
rearrangement fails, the element is erased.<br>
<b>Postconditions:</b> Validity of <code>position</code> is preserved if the
operation succeeds.<br>
@@ -647,6 +669,37 @@ user-provided operation (except possibly <code>mod</code>), then
the element pointed to by <code>position</code> is erased.
</blockquote>
<code>template&lt;typename Modifier,typename Rollback><br>
bool modify(iterator position,Modifier mod,Rollback back);</code>
<blockquote>
<b>Requires:</b> <code>Modifier</code> and <code>Rollback</code> are models of
<a href="http://www.sgi.com/tech/stl/UnaryFunction.html">
<code>Unary Function</code></a> accepting arguments of type
<code>value_type&amp;</code>. <code>position</code> is a valid dereferenceable
iterator of the index. The sequence of operations <code>mod(e)</code>,
<code>back(e)</code>, where <code>e</code> is the element
pointed to by <code>position</code>, restores all keys of the element
to their original state.</br>
<b>Effects:</b> Calls <code>mod(e)</code> where <code>e</code> is the element
pointed to by <code>position</code> and tries to rearrange <code>*position</code> into
all the indices of the <code>multi_index_container</code>. Rearrangement on
random access indices does not change the position of the element with respect
to the index; rearrangement on other indices may or might not succeed. If the
rearrangement fails, <code>back(e)</code> is invoked and the
element is kept at its original position in all indices.<br>
<b>Postconditions:</b> Validity of <code>position</code> is preserved except if
the element is erased under the conditions described below.<br>
<b>Returns:</b> <code>true</code> if the operation succeeded, <code>false</code>
otherwise.<br>
<b>Complexity:</b> <code>O(M(n))</code>.<br>
<b>Exception safety:</b> Strong, except if <code>back</code> throws an
exception, in which case the modified element is erased. If <code>back</code>
throws inside the handling code executing after some other user-provided
operation has thrown, it is the exception generated by <code>back</code> that
is rethrown.
</blockquote>
<h4><a name="list_operations">List operations</a></h4>
<p>
@@ -946,9 +999,9 @@ Key extraction
<br>
<p>Revised February 6th 2006</p>
<p>Revised July 2nd 2007</p>
<p>&copy; Copyright 2003-2006 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
<p>&copy; Copyright 2003-2007 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
+56 -3
View File
@@ -41,6 +41,7 @@ Random access indices
<li><a href="#complexity_signature">Complexity signature</a></li>
<li><a href="#instantiation_types">Instantiation types</a></li>
<li><a href="#constructors">Constructors, copy and assignment</a></li>
<li><a href="#iterators">Iterators</a></li>
<li><a href="#capacity">Capacity operations</a></li>
<li><a href="#modifiers">Modifiers</a></li>
<li><a href="#list_operations">List operations</a></li>
@@ -229,6 +230,13 @@ types of containers.
<span class=identifier>const_reverse_iterator</span> <span class=identifier>rbegin</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>reverse_iterator</span> <span class=identifier>rend</span><span class=special>();</span>
<span class=identifier>const_reverse_iterator</span> <span class=identifier>rend</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>const_iterator</span> <span class=identifier>cbegin</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>const_iterator</span> <span class=identifier>cend</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>const_reverse_iterator</span> <span class=identifier>crbegin</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>const_reverse_iterator</span> <span class=identifier>crend</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=identifier>iterator</span> <span class=identifier>iterator_to</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=identifier>const_iterator</span> <span class=identifier>iterator_to</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>)</span><span class=keyword>const</span><span class=special>;</span>
<span class=comment>// capacity:</span>
@@ -260,6 +268,8 @@ types of containers.
<span class=keyword>bool</span> <span class=identifier>replace</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=keyword>const</span> <span class=identifier>value_type</span><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>&gt;</span> <span class=keyword>bool</span> <span class=identifier>modify</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>);</span>
<span class=keyword>template</span><span class=special>&lt;</span><span class=keyword>typename</span> <span class=identifier>Modifier</span><span class=special>,</span><span class=keyword>typename</span> <span class=identifier>Rollback</span><span class=special>&gt;</span>
<span class=keyword>bool</span> <span class=identifier>modify</span><span class=special>(</span><span class=identifier>iterator</span> <span class=identifier>position</span><span class=special>,</span><span class=identifier>Modifier</span> <span class=identifier>mod</span><span class=special>,</span><span class=identifier>Rollback</span> <span class=identifier>back</span><span class=special>);</span>
<span class=keyword>void</span> <span class=identifier>swap</span><span class=special>(</span><b>index class name</b><span class=special>&amp;</span> <span class=identifier>x</span><span class=special>);</span>
@@ -436,6 +446,18 @@ index of the <code>multi_index_container</code> to which this index belongs.
</pre></blockquote>
</blockquote>
<h4><a name="iterators">Iterators</a></h4>
<code>iterator&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iterator_to(const value_type&amp; x);</br>
const_iterator iterator_to(const value_type&amp; x)const;</code>
<blockquote>
<b>Requires:</b> <code>x</code> is a reference to an element of the container.</br>
<b>Returns:</b> An iterator to <code>x</code>.<br>
<b>Complexity:</b> Constant.<br>
<b>Exception safety:</b> <code>nothrow</code>.<br>
</blockquote>
<h4><a name="capacity">Capacity operations</a></h4>
<code>void resize(size_type n,const value_type&amp; x=value_type());</code>
@@ -587,7 +609,7 @@ iterator of the index.</br>
pointed to by <code>position</code> and rearranges <code>*position</code> into
all the indices of the <code>multi_index_container</code>. Rearrangement on sequenced
indices does not change the position of the element with respect to the index;
rearrangement on other indices may or might not suceed. If the rearrangement
rearrangement on other indices may or might not succeed. If the rearrangement
fails, the element is erased.<br>
<b>Postconditions:</b> Validity of <code>position</code> is preserved if the
operation succeeds.<br>
@@ -599,6 +621,37 @@ user-provided operation (except possibly <code>mod</code>), then
the element pointed to by <code>position</code> is erased.
</blockquote>
<code>template&lt;typename Modifier,typename Rollback><br>
bool modify(iterator position,Modifier mod,Rollback back);</code>
<blockquote>
<b>Requires:</b> <code>Modifier</code> and <code>Rollback</code> are models of
<a href="http://www.sgi.com/tech/stl/UnaryFunction.html">
<code>Unary Function</code></a> accepting arguments of type
<code>value_type&amp;</code>. <code>position</code> is a valid dereferenceable
iterator of the index. The sequence of operations <code>mod(e)</code>,
<code>back(e)</code>, where <code>e</code> is the element
pointed to by <code>position</code>, restores all keys of the element
to their original state.</br>
<b>Effects:</b> Calls <code>mod(e)</code> where <code>e</code> is the element
pointed to by <code>position</code> and tries to rearrange <code>*position</code> into
all the indices of the <code>multi_index_container</code>. Rearrangement on sequenced
indices does not change the position of the element with respect to the index;
rearrangement on other indices may or might not succeed. If the rearrangement
fails, <code>back(e)</code> is invoked and the
element is kept at its original position in all indices.<br>
<b>Postconditions:</b> Validity of <code>position</code> is preserved except if
the element is erased under the conditions described below.<br>
<b>Returns:</b> <code>true</code> if the operation succeeded, <code>false</code>
otherwise.<br>
<b>Complexity:</b> <code>O(M(n))</code>.<br>
<b>Exception safety:</b> Strong, except if <code>back</code> throws an
exception, in which case the modified element is erased. If <code>back</code>
throws inside the handling code executing after some other user-provided
operation has thrown, it is the exception generated by <code>back</code> that
is rethrown.
</blockquote>
<h4><a name="list_operations">List operations</a></h4>
<p>
@@ -901,9 +954,9 @@ Random access indices
<br>
<p>Revised February 6th 2006</p>
<p>Revised July 2nd 2007</p>
<p>&copy; Copyright 2003-2006 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
<p>&copy; Copyright 2003-2007 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
+67 -2
View File
@@ -31,11 +31,76 @@ Acknowledgements
<h2>Contents</h2>
<ul>
<li><a href="#boost_1_35">Boost 1.35 release</a></li>
<li><a href="#boost_1_34">Boost 1.34 release</a></li>
<li><a href="#boost_1_33_1">Boost 1.33.1 release</a></li>
<li><a href="#boost_1_33">Boost 1.33 release</a></li>
</ul>
<h2><a name="boost_1_35">Boost 1.35 release</a></h2>
<p>
<ul>
<li>New <a href="tutorial/key_extraction.html#global_fun"><code>global_fun</code></a>
predefined key extractor.
</li>
<li>Added <a href="tutorial/indices.html#iterator_to"><code>iterator_to</code></a>
facility.
</li>
<li>Included <a href="tutorial/creation.html#special_allocator">support for
non-standard allocators</a> such as those of
<a href="../../interprocess/index.html">Boost.Interprocess</a>, which makes
<code>multi_index_container</code>s placeable in shared memory.
</li>
<li>New versions of <code>modify</code> and <code>modify_key</code> with
rollback, as described in the
<a href="tutorial/basics.html#ord_updating">tutorial</a>.
</li>
<li>Indices provide the new <code>cbegin</code>, <code>cend</code> and,
when applicable, <code>crbegin</code> and <code>crend</code>
member functions, in accordance with the latest drafts of the next
revision of the C++ standard.
</li>
<li>Hinted insertion in ordered indices fully conforms to the resolutions of
C++ Standard Library
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#233">Defect
Report 233</a>. The new requirement that the point of insertion
be always as close as possible to the hint induces a different behavior than
exhibited in former releases of Boost.MultiIndex, which can potentially cause
backwards compatibility problems; in any case, the likelihood of these
compatibility issues arising in a real scenario is very low.
</li>
<li>Sequenced and random access indices now follow the requirements of the
C++ standard for sequence containers with respect to the operations
<code>assign(f,l)</code> and <code>insert(p,f,l)</code> (23.1.1/9): if
<code>f</code> and <code>l</code> are of the same integral type, the
iterator-based overloads of these member functions are avoided:
<blockquote><pre>
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=keyword>int</span><span class=special>,</span><span class=identifier>indexed_by</span><span class=special>&lt;</span><span class=identifier>sequenced</span><span class=special>&lt;&gt;</span> <span class=special>&gt;</span>
<span class=special>&gt;</span> <span class=identifier>sequenced_container</span><span class=special>;</span>
<span class=identifier>std</span><span class=special>::</span><span class=identifier>list</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;</span> <span class=identifier>l</span><span class=special>(...);</span>
<span class=identifier>sequenced_container</span> <span class=identifier>c</span><span class=special>;</span>
<span class=comment>// iterator-based overload of assign</span>
<span class=identifier>c</span><span class=special>.</span><span class=identifier>assign</span><span class=special>(</span><span class=identifier>l</span><span class=special>.</span><span class=identifier>begin</span><span class=special>(),</span><span class=identifier>l</span><span class=special>.</span><span class=identifier>end</span><span class=special>());</span>
<span class=comment>// The following is equivalent to
// c.assign(
// static_cast&lt;sequenced_container::size_type&gt;(10),100);
// that is, &quot;10&quot; and &quot;100&quot; are not taken to be iterators as
// in the previous expression.</span>
<span class=identifier>c</span><span class=special>.</span><span class=identifier>assign</span><span class=special>(</span><span class=number>10</span><span class=special>,</span><span class=number>100</span><span class=special>);</span>
</pre></blockquote>
</li>
<li>The performance of ordered indices <code>range</code> and
<code>equal_range</code> has been improved.
</li>
<li>Maintenance fixes.</li>
</ul>
</p>
<h2><a name="boost_1_34">Boost 1.34 release</a></h2>
<p>
@@ -140,9 +205,9 @@ Acknowledgements
<br>
<p>Revised February 6th 2006</p>
<p>Revised October 11th 2007</p>
<p>&copy; Copyright 2003-2006 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
<p>&copy; Copyright 2003-2007 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
+4 -3
View File
@@ -116,7 +116,8 @@ with some of the least common features offered by Boost.MultiIndex.
</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>
<a href="../test/test_serialization2.cpp"><code>test_serialization2.cpp</code></a><br>
<a href="../test/test_serialization3.cpp"><code>test_serialization3.cpp</code></a></td>
<td>Serialization support.</td>
</tr>
<tr>
@@ -149,9 +150,9 @@ Future work
<br>
<p>Revised March 2nd 2006</p>
<p>Revised July 11th 2007</p>
<p>&copy; Copyright 2003-2006 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
<p>&copy; Copyright 2003-2007 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
+64 -10
View File
@@ -956,15 +956,69 @@ original value is kept and the method returns without altering the container, bu
leaves no trace of the previous value of the element. Integrity constraints
thus lead to the following policy: when a collision happens in the
process of calling <code>modify</code>, the element is erased and the method returns
<code>false</code>. This difference in behavior between <code>replace</code> and
<code>modify</code> has to be considered by the programmer on a case-by-case basis.
<code>false</code>. There is a further version of <code>modify</code> which
accepts a <i>rollback</i> functor to undo the changes in case of collision:
</p>
<blockquote><pre>
<span class=keyword>struct</span> <span class=identifier>change_id</span>
<span class=special>{</span>
<span class=identifier>change_id</span><span class=special>(</span><span class=keyword>int</span> <span class=identifier>new_id</span><span class=special>):</span><span class=identifier>new_id</span><span class=special>(</span><span class=identifier>new_id</span><span class=special>){}</span>
<span class=keyword>void</span> <span class=keyword>operator</span><span class=special>()(</span><span class=identifier>employee</span><span class=special>&amp;</span> <span class=identifier>e</span><span class=special>)</span>
<span class=special>{</span>
<span class=identifier>e</span><span class=special>.</span><span class=identifier>id</span><span class=special>=</span><span class=identifier>new_id</span><span class=special>;</span>
<span class=special>}</span>
<span class=keyword>private</span><span class=special>:</span>
<span class=keyword>int</span> <span class=identifier>new_id</span><span class=special>;</span>
<span class=special>};</span>
<span class=special>...</span>
<span class=identifier>employee_set</span><span class=special>::</span><span class=identifier>iterator</span> <span class=identifier>it</span><span class=special>=...</span>
<span class=keyword>int</span> <span class=identifier>old_id</span><span class=special>=</span><span class=identifier>it</span><span class=special>-&gt;</span><span class=identifier>id</span><span class=special>;</span> <span class=comment>// keep the original id
// try to modify the id, restore it in case of collisions</span>
<span class=identifier>es</span><span class=special>.</span><span class=identifier>modify</span><span class=special>(</span><span class=identifier>it</span><span class=special>,</span><span class=identifier>change_id</span><span class=special>(</span><span class=number>321</span><span class=special>),</span><span class=identifier>change_id</span><span class=special>(</span><span class=identifier>old_id</span><span class=special>));</span>
</pre></blockquote>
<p>In the example, <code>change_id(old_id)</code> is invoked to restore the original
conditions when the modification results in collisions with some other element.
The differences in behavior between <code>replace</code>, <code>modify</code> and
<code>modify</code> with rollback have to be considered by the programmer on a
case-by-case basis to determine the best updating mechanism.
</p>
<p align="center">
<table cellspacing="0">
<caption><b>Behavior of the different updating mechanisms.</b></caption>
<tr>
<th align="center">updating function</th>
<th>If there is a collision...</th>
</tr>
<tr>
<td align="center"><code>replace(it,x)</code></td>
<td>replacement does not take place.</td>
</tr>
<tr class="odd_tr">
<td align="center"><code>modify(it,mod)</code></td>
<td>the element is erased.</td>
</tr>
<tr>
<td align="center"><code>modify(it,mod,back)</code></td>
<td><code>back</code> is used to restore the original conditions.
(If <code>back</code> throws, the element is erased.)
</td>
</tr>
</table>
</p>
<p>
A key-based version of <code>modify</code>, named
<a href="../reference/ord_indices.html#modify_key"><code>modify_key</code></a>, is
provided as well. In this case, the modifying functor is passed a reference to
the <code>key_value</code> part of the element instead of the whole object.
Key-based versions of <code>modify</code>, named
<a href="../reference/ord_indices.html#modify_key"><code>modify_key</code></a>, are
provided as well. In this case, the modifying functors are passed a reference to
the <code>key_type</code> part of the element instead of the whole object.
</p>
<blockquote><pre>
@@ -990,8 +1044,8 @@ the <code>key_value</code> part of the element instead of the whole object.
</pre></blockquote>
<p>
Just as <code>modify</code> does, <code>modify_key</code> erases the element if
the modification results in collisions in some index. <code>modify</code> and
Like <code>modify</code>, there are versions of <code>modify_key</code> with and
without rollback. <code>modify</code> and
<code>modify_key</code> are particularly well suited to use in conjunction to
<a href="../../../../libs/lambda/index.html">Boost.Lambda</a>
for defining the modifying functors:
@@ -1205,9 +1259,9 @@ Index types
<br>
<p>Revised July 13th 2006</p>
<p>Revised July 17th 2007</p>
<p>&copy; Copyright 2003-2006 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
<p>&copy; Copyright 2003-2007 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
+56 -1
View File
@@ -32,6 +32,7 @@ Debugging support
<ul>
<li><a href="#value_semantics">Value semantics</a></li>
<li><a href="#ctor_args_list">Use of <code>ctor_args_list</code></a></li>
<li><a href="#special_allocator">Special allocator support</a></li>
<li><a href="#serialization">Serialization</a></li>
</ul>
@@ -191,6 +192,60 @@ A program is provided in the <a href="../examples.html#example3">examples sectio
puts in practise these concepts.
</p>
<h2><a name="special_allocator">Special allocator support</a></h2>
<p>
Boost.MultiIndex allows for a slightly more general class of allocators
than strictly required by the C++ standard, as explained in detail in the
<a href="../reference/multi_index_container.html#instantiation_types">reference</a>.
An important type of non-standard allocators supported are those provided by the
<a href="../../../interprocess/index.html">Boost Interprocess Library</a>;
this opens up the possibility of placing <code>multi_index_container</code>s
in shared memory.
</p>
<blockquote><pre>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>interprocess</span><span class=special>/</span><span class=identifier>allocators</span><span class=special>/</span><span class=identifier>allocator</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>interprocess</span><span class=special>/</span><span class=identifier>managed_shared_memory</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=keyword>namespace</span> <span class=identifier>bip</span><span class=special>=</span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>interprocess</span><span class=special>;</span>
<span class=comment>// a shared memory compatible allocator of ints</span>
<span class=keyword>typedef</span> <span class=identifier>bip</span><span class=special>::</span><span class=identifier>allocator</span><span class=special>&lt;</span>
<span class=keyword>int</span><span class=special>,</span><span class=identifier>bip</span><span class=special>::</span><span class=identifier>managed_shared_memory</span><span class=special>::</span><span class=identifier>segment_manager</span>
<span class=special>&gt;</span> <span class=identifier>shared_int_allocator</span><span class=special>;</span>
<span class=comment>// define a shared memory compatible multi_index_container
// using shared_int_allocator</span>
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=keyword>int</span><span class=special>,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span>
<span class=identifier>sequenced</span><span class=special>&lt;&gt;,</span>
<span class=identifier>ordered_unique</span><span class=special>&lt;</span><span class=identifier>identity</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;</span> <span class=special>&gt;</span>
<span class=special>&gt;,</span>
<span class=identifier>shared_int_allocator</span>
<span class=special>&gt;</span> <span class=identifier>unique_int_list</span><span class=special>;</span>
<span class=special>...</span>
<span class=comment>// create a managed memory segment</span>
<span class=identifier>bip</span><span class=special>::</span><span class=identifier>managed_shared_memory</span> <span class=identifier>seg</span><span class=special>(</span>
<span class=identifier>bip</span><span class=special>::</span><span class=identifier>create_only</span><span class=special>,</span><span class=string>&quot;SharedMemoryID&quot;</span><span class=special>,</span><span class=number>65536</span><span class=special>);</span>
<span class=comment>// construct a unique_int_list into the segment</span>
<span class=identifier>unique_int_list</span><span class=special>*</span> <span class=identifier>puil</span><span class=special>=</span><span class=identifier>seg</span><span class=special>.</span><span class=identifier>construct</span><span class=special>&lt;</span><span class=identifier>unique_int_list</span><span class=special>&gt;</span>
<span class=special>(</span><span class=string>&quot;UniqueIntListID&quot;</span><span class=special>)</span> <span class=comment>// object identifier within the segment
// Construction args: first a ctor arg list, then a
// shared memory allocator obtained from the segment object.</span>
<span class=special>(</span><span class=identifier>unique_int_list</span><span class=special>::</span><span class=identifier>ctor_args_list</span><span class=special>(),</span>
<span class=identifier>unique_int_list</span><span class=special>::</span><span class=identifier>allocator_type</span><span class=special>(</span><span class=identifier>seg</span><span class=special>.</span><span class=identifier>get_segment_manager</span><span class=special>()));</span>
</pre></blockquote>
<p>
The examples section includes a <a href="../examples.html#example12">program</a>
that further explores this capability.
</p>
<h2><a name="serialization">Serialization</a></h2>
<p>
@@ -285,7 +340,7 @@ Debugging support
<br>
<p>Revised February 27th 2007</p>
<p>Revised July 17th 2007</p>
<p>&copy; Copyright 2003-2007 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
+57 -3
View File
@@ -48,6 +48,7 @@ Key extraction
</ul>
</li>
<li><a href="#rearrange">Index rearranging</a></li>
<li><a href="#iterator_to"><code>iterator_to</code></a></li>
<li><a href="#ordered_node_compression">Ordered indices node compression</a></li>
</ul>
@@ -90,6 +91,7 @@ some added benefits, functionally or in the area of performance.
</tr>
<tr class="odd_tr">
<td align="center"><code>&nbsp;&nbsp;random_access&nbsp;&nbsp;</code></td>
</tr>
</table>
</p>
@@ -608,7 +610,8 @@ thus, <code>rearrange</code> does not accept the following:
<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>
<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
@@ -617,6 +620,57 @@ See <a href="../examples.html#example11">example 11</a> in the examples section
for a demonstration of use of <code>rearrange</code>.
</p>
<h2><a name="iterator_to"><code>iterator_to</code></a></h2>
<p>
All indices of Boost.MultiIndex provide a member function called <code>iterator_to</code>
which returns an iterator to a given element of the container:
</p>
<blockquote><pre>
<span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=keyword>int</span><span class=special>,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span><span class=identifier>sequenced</span><span class=special>&lt;&gt;</span> <span class=special>&gt;</span>
<span class=special>&gt;</span> <span class=identifier>c</span><span class=special>;</span>
<span class=special>...</span>
<span class=comment>// convoluted way to do c.pop_back()</span>
<span class=identifier>c</span><span class=special>.</span><span class=identifier>erase</span><span class=special>(</span><span class=identifier>c</span><span class=special>.</span><span class=identifier>iterator_to</span><span class=special>(</span><span class=identifier>c</span><span class=special>.</span><span class=identifier>back</span><span class=special>()));</span>
<span class=comment>// The following, though similar to the previous code,
// does not work: iterator_to accepts a reference to
// the element in the container, not a copy.</span>
<span class=keyword>int</span> <span class=identifier>x</span><span class=special>=</span><span class=identifier>c</span><span class=special>.</span><span class=identifier>back</span><span class=special>();</span>
<span class=identifier>c</span><span class=special>.</span><span class=identifier>erase</span><span class=special>(</span><span class=identifier>c</span><span class=special>.</span><span class=identifier>iterator_to</span><span class=special>(</span><span class=identifier>x</span><span class=special>));</span> <span class=comment>// run-time failure ensues</span>
</pre></blockquote>
<p>
<code>iterator_to</code> provides a way to retrieve an iterator to an element
from a pointer to the element, thus making iterators and pointers interchangeable
for the purposes of element pointing (not so for traversal) in many situations.
This notwithstanding, it is not the aim of <code>iterator_to</code> to
promote the usage of pointers as substitutes for real iterators: the latter are
specifically designed for handling the elements of a container,
and not only benefit from the iterator orientation of container interfaces,
but are also capable of exposing many more programming bugs than raw pointers, both
at compile and run time. <code>iterator_to</code> is thus meant to be used
in scenarios where access via iterators is not suitable or desireable:
<ul>
<li>Interoperability with preexisting APIs based on pointers or references.</li>
<li>Publication of pointer-based interfaces (for instance, when
designing a C-compatible library).
</li>
<li>The exposure of pointers in place of iterators can act as a <i>type
erasure</i> barrier effectively decoupling the user of the code
from the implementation detail of which particular container is being
used. Similar techniques, like the famous Pimpl idiom, are used
in large projects to reduce dependencies and build times.
</li>
<li>Self-referencing contexts where an element acts upon its owner
container and no iterator to itself is available.
</li>
</ul>
</p>
<h2><a name="ordered_node_compression">Ordered indices node compression</a></h2>
<p>
@@ -664,9 +718,9 @@ Key extraction
<br>
<p>Revised February 6th 2006</p>
<p>Revised October 15th 2007</p>
<p>&copy; Copyright 2003-2006 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
<p>&copy; Copyright 2003-2007 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
+139 -16
View File
@@ -41,6 +41,7 @@ Container creation
<li><a href="#member"><code>member</code></a></li>
<li><a href="#const_mem_fun"><code>const_mem_fun</code>
and <code>mem_fun</code></a></li>
<li><a href="#global_fun"><code>global_fun</code></a></li>
</ul>
</li>
<li><a href="#user_defined_key_extractors">User-defined key extractors</a></li>
@@ -244,6 +245,68 @@ of Boost.MultiIndex key extractors</a>.
provides a complete program showing how to use <code>const_mem_fun</code>.
<p>
<h3><a name="global_fun"><code>global_fun</code></a></h3>
<p>
Whereas <code>const_mem_fun</code> and <code>mem_fun</code> are based on a
given member function of the base type from where the key is extracted,
<a href="../reference/key_extraction.html#global_fun"><code>global_fun</code></a>
takes a global function (or static member function) accepting the base
type as its parameter and returning the key:
</p>
<blockquote><pre>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index_container</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>ordered_index</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=preprocessor>#include</span> <span class=special>&lt;</span><span class=identifier>boost</span><span class=special>/</span><span class=identifier>multi_index</span><span class=special>/</span><span class=identifier>global_fun</span><span class=special>.</span><span class=identifier>hpp</span><span class=special>&gt;</span>
<span class=keyword>struct</span> <span class=identifier>rectangle</span>
<span class=special>{</span>
<span class=keyword>int</span> <span class=identifier>x0</span><span class=special>,</span><span class=identifier>y0</span><span class=special>;</span>
<span class=keyword>int</span> <span class=identifier>x1</span><span class=special>,</span><span class=identifier>y1</span><span class=special>;</span>
<span class=special>};</span>
<span class=keyword>unsigned</span> <span class=keyword>long</span> <span class=identifier>area</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>rectangle</span><span class=special>&amp;</span> <span class=identifier>r</span><span class=special>)</span>
<span class=special>{</span>
<span class=keyword>return</span> <span class=special>(</span><span class=keyword>unsigned</span> <span class=keyword>long</span><span class=special>)(</span><span class=identifier>r</span><span class=special>.</span><span class=identifier>x1</span><span class=special>-</span><span class=identifier>r</span><span class=special>.</span><span class=identifier>x0</span><span class=special>)*(</span><span class=identifier>r</span><span class=special>.</span><span class=identifier>x1</span><span class=special>-</span><span class=identifier>r</span><span class=special>.</span><span class=identifier>x0</span><span class=special>)+</span>
<span class=special>(</span><span class=keyword>unsigned</span> <span class=keyword>long</span><span class=special>)(</span><span class=identifier>r</span><span class=special>.</span><span class=identifier>y1</span><span class=special>-</span><span class=identifier>r</span><span class=special>.</span><span class=identifier>y0</span><span class=special>)*(</span><span class=identifier>r</span><span class=special>.</span><span class=identifier>y1</span><span class=special>-</span><span class=identifier>r</span><span class=special>.</span><span class=identifier>y0</span><span class=special>);</span>
<span class=special>}</span>
<span class=keyword>typedef</span> <span class=identifier>multi_index_container</span><span class=special>&lt;</span>
<span class=identifier>rectangle</span><span class=special>,</span>
<span class=identifier>indexed_by</span><span class=special>&lt;</span>
<span class=comment>// sort by increasing area</span>
<span class=identifier>ordered_non_unique</span><span class=special>&lt;</span><span class=identifier>global_fun</span><span class=special>&lt;</span><span class=keyword>const</span> <span class=identifier>rectangle</span><span class=special>&amp;,</span><span class=keyword>unsigned</span> <span class=keyword>long</span><span class=special>,&amp;</span><span class=identifier>area</span><span class=special>&gt;</span> <span class=special>&gt;</span>
<span class=special>&gt;</span>
<span class=special>&gt;</span> <span class=identifier>rectangle_container</span><span class=special>;</span>
</pre></blockquote>
<p>
The specification of <code>global_fun</code> obeys the following syntax:
</p>
<blockquote><pre>
<span class=identifier>global_fun</span><span class=special>&lt;</span><span class=identifier><i>(argument type)</i></span><span class=special>,</span><span class=identifier><i>(key type)</i></span><span class=special>,</span><span class=identifier><i>(pointer to function)</i></span><span class=special>&gt;</span>
</pre></blockquote>
<p>
where the argument type and key type must match <i>exactly</i> those in the
signature of the function used; for instance, in the example above the argument
type is <code>const rectangle&amp;</code>, without omitting the "<code>const</code>"
and "<code>&amp;</code>" parts. So, although most of the time the base type will be
accepted by constant reference, <code>global_fun</code> is also prepared to take
functions accepting their argument by value or by non-constant reference: this
latter case cannot generally be used directly in the specification of
<code>multi_index_container</code>s as their elements are treated as constant,
but the section on <a href="#advanced_key_extractors">advanced features
of Boost.MultiIndex key extractors</a> describes valid use cases of
key extraction based on such functions with a non-constant reference argument.
</p>
<p><a href="../examples.html#example2">Example 2</a> in the examples section
uses <code>gobal_fun</code>.
<p>
<h2><a name="user_defined_key_extractors">User-defined key extractors</a></h2>
<p>
@@ -632,10 +695,12 @@ following final type:
<blockquote><pre>
<span class=keyword>struct</span> <span class=identifier>T</span>
<span class=special>{</span>
<span class=keyword>int</span> <span class=identifier>i</span><span class=special>;</span>
<span class=keyword>const</span> <span class=keyword>int</span> <span class=identifier>j</span><span class=special>;</span>
<span class=keyword>int</span> <span class=identifier>f</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=keyword>int</span> <span class=identifier>g</span><span class=special>();</span>
<span class=keyword>int</span> <span class=identifier>i</span><span class=special>;</span>
<span class=keyword>const</span> <span class=keyword>int</span> <span class=identifier>j</span><span class=special>;</span>
<span class=keyword>int</span> <span class=identifier>f</span><span class=special>()</span><span class=keyword>const</span><span class=special>;</span>
<span class=keyword>int</span> <span class=identifier>g</span><span class=special>();</span>
<span class=keyword>static</span> <span class=keyword>int</span> <span class=identifier>gf</span><span class=special>(</span><span class=keyword>const</span> <span class=identifier>T</span><span class=special>&amp;);</span>
<span class=keyword>static</span> <span class=keyword>int</span> <span class=identifier>gg</span><span class=special>(</span><span class=identifier>T</span><span class=special>&amp;);</span>
<span class=special>};</span>
</pre></blockquote>
@@ -656,7 +721,7 @@ each of its members.
<th>read/write?</th>
</tr>
<tr>
<td align="center" rowspan="4"><code>T</code></td>
<td align="center" rowspan="6"><code>T</code></td>
<td><code>i</code></td>
<td><code>member&lt;T,int,&amp;T::i></code></td>
<td align="center">yes</td>
@@ -680,9 +745,21 @@ each of its members.
<td align="center">no</td>
<td align="center">no</td>
</tr>
<tr>
<td><code>gf()</code></td>
<td><code>global_fun&lt;const T&amp;,int,&amp;T::gf></code></td>
<td align="center">yes</td>
<td align="center">no</td>
</tr>
<tr>
<td><code>gg()</code></td>
<td><code>global_fun&lt;T&amp;,int,&amp;T::gg></code></td>
<td align="center">no</td>
<td align="center">no</td>
</tr>
<tr class="odd_tr">
<td align="center" rowspan="4"><code>reference_wrapper&lt;T></code></td>
<td align="center" rowspan="6"><code>reference_wrapper&lt;T></code></td>
<td><code>i</code></td>
<td><code>member&lt;T,int,&amp;T::i></code></td>
<td align="center">yes</td>
@@ -706,9 +783,21 @@ each of its members.
<td align="center">yes</td>
<td align="center">no</td>
</tr>
<tr class="odd_tr">
<td><code>gf()</code></td>
<td><code>global_fun&lt;const T&amp;,int,&amp;T::gf></code></td>
<td align="center">yes</td>
<td align="center">no</td>
</tr>
<tr class="odd_tr">
<td><code>gg()</code></td>
<td><code>global_fun&lt;T&amp;,int,&amp;T::gg></code></td>
<td align="center">yes</td>
<td align="center">no</td>
</tr>
<tr>
<td align="center" rowspan="4"><code>reference_wrapper&lt;const T></code></td>
<td align="center" rowspan="6"><code>reference_wrapper&lt;const T></code></td>
<td><code>i</code></td>
<td><code>member&lt;T,const int,&amp;T::i></code></td>
<td align="center">yes</td>
@@ -730,9 +819,19 @@ each of its members.
<td><code>g()</code></td>
<td colspan="3">&nbsp;</td>
</tr>
<tr>
<td><code>gf()</code></td>
<td><code>global_fun&lt;const T&amp;,int,&amp;T::gf></code></td>
<td align="center">yes</td>
<td align="center">no</td>
</tr>
<tr>
<td><code>gg()</code></td>
<td colspan="3">&nbsp;</td>
</tr>
<tr class="odd_tr">
<td align="center" rowspan="4">chained pointer to <code>T</code><br>
<td align="center" rowspan="6">chained pointer to <code>T</code><br>
or to <code>reference_wrapper&lt;T></code></td>
<td><code>i</code></td>
<td><code>member&lt;T,int,&amp;T::i></code></td>
@@ -757,9 +856,21 @@ each of its members.
<td align="center">yes</td>
<td align="center">no</td>
</tr>
<tr class="odd_tr">
<td><code>gf()</code></td>
<td><code>global_fun&lt;const T&amp;,int,&amp;T::gf></code></td>
<td align="center">yes</td>
<td align="center">no</td>
</tr>
<tr class="odd_tr">
<td><code>gg()</code></td>
<td><code>global_fun&lt;T&amp;,int,&amp;T::gg></code></td>
<td align="center">yes</td>
<td align="center">no</td>
</tr>
<tr>
<td align="center" rowspan="4">chained pointer to <code>const T</code><br>
<td align="center" rowspan="6">chained pointer to <code>const T</code><br>
or to <code>reference_wrapper&lt;const T></code></td>
<td><code>i</code></td>
<td><code>member&lt;T,const int,&amp;T::i></code></td>
@@ -782,6 +893,16 @@ each of its members.
<td><code>g()</code></td>
<td colspan="3">&nbsp;</td>
</tr>
<tr>
<td><code>gf()</code></td>
<td><code>global_fun&lt;const T&amp;,int,&amp;T::gf></code></td>
<td align="center">yes</td>
<td align="center">no</td>
</tr>
<tr>
<td><code>gg()</code></td>
<td colspan="3">&nbsp;</td>
</tr>
</table>
</p>
@@ -790,10 +911,12 @@ each of its members.
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
<code>T</code> objects). The only negative cases are for <code>T::g</code> and
<code>T:gg</code> when the elements are raw <code>T</code> objects, which make sense
as we are dealing with a non-constant member function (<code>T::g</code>)
and a function taking <code>T</code> by
non-constant reference: this also implies that <code>multi_index_container</code>s
of elements of <code>T</code> cannot be sorted by <code>T::g</code> or <code>T::gg</code>, because
elements contained within a <code>multi_index_container</code> are treated as constant.
</p>
@@ -804,7 +927,7 @@ The column "read/write?" shows which combinations yield
<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>
specification of <code>member</code> key extractors: in some sense, the <code>const</code>
qualifier is carried along to the member part, even if that particular
member is not defined as <code>const</code>. For instance, if the elements
are of type <code>const T *</code>, sorting by <code>T::i</code> is <i>not</i>
@@ -832,9 +955,9 @@ Container creation
<br>
<p>Revised February 6th 2006</p>
<p>Revised June 11th 2007</p>
<p>&copy; Copyright 2003-2006 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
<p>&copy; Copyright 2003-2007 Joaqu&iacute;n M L&oacute;pez Mu&ntilde;oz.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
+9 -4
View File
@@ -1,6 +1,6 @@
# Boost.MultiIndex examples Jamfile
#
# Copyright 2003-2006 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)
@@ -27,14 +27,19 @@ exe composite_keys
: <include>$(BOOST_ROOT)
;
exe fun_key
: fun_key.cpp
: <include>$(BOOST_ROOT)
;
exe hashed
: hashed.cpp
: <include>$(BOOST_ROOT)
;
exe memfun_key
: memfun_key.cpp
: <include>$(BOOST_ROOT)
exe ip_allocator
: ip_allocator.cpp
: <include>$(BOOST_ROOT) <threading>multi
;
exe non_default_ctor
+3 -2
View File
@@ -1,6 +1,6 @@
/* Boost.MultiIndex example of composite keys.
*
* Copyright 2003-2005 Joaquín M López Muñoz.
* Copyright 2003-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)
@@ -18,6 +18,7 @@
#include <boost/multi_index/composite_key.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/next_prior.hpp>
#include <boost/tokenizer.hpp>
#include <functional>
#include <iostream>
@@ -287,7 +288,7 @@ int main()
continue;
}
it->second->execute(++tok.begin(),tok.end());
it->second->execute(boost::next(tok.begin()),tok.end());
}
return 0;
+24 -3
View File
@@ -1,6 +1,6 @@
/* Boost.MultiIndex example of member functions used as key extractors.
/* Boost.MultiIndex example of functions used as key extractors.
*
* Copyright 2003-2006 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)
@@ -14,6 +14,7 @@
#endif
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/global_fun.hpp>
#include <boost/multi_index/mem_fun.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <iostream>
@@ -46,7 +47,13 @@ private:
std::string family_name;
};
/* multi_index_container with only one index based on name_record::name().
std::string::size_type name_record_length(const name_record& r)
{
return r.name().size();
}
/* multi_index_container with indices based on name_record::name()
* and name_record_length().
* See Compiler specifics: Use of const_mem_fun_explicit and
* mem_fun_explicit for info on BOOST_MULTI_INDEX_CONST_MEM_FUN.
*/
@@ -56,6 +63,9 @@ typedef multi_index_container<
indexed_by<
ordered_unique<
BOOST_MULTI_INDEX_CONST_MEM_FUN(name_record,std::string,name)
>,
ordered_non_unique<
global_fun<const name_record&,std::string::size_type,name_record_length>
>
>
> name_record_set;
@@ -71,9 +81,20 @@ int main()
/* list the names in ns in phonebook order */
std::cout<<"Phonenook order\n"
<<"---------------"<<std::endl;
for(name_record_set::iterator it=ns.begin();it!=ns.end();++it){
std::cout<<it->name()<<std::endl;
}
/* list the names in ns according to their length*/
std::cout<<"\nLength order\n"
<< "------------"<<std::endl;
for(nth_index_iterator<name_record_set,1>::type it1=get<1>(ns).begin();
it1!=get<1>(ns).end();++it1){
std::cout<<it1->name()<<std::endl;
}
return 0;
}
+293
View File
@@ -0,0 +1,293 @@
/* Boost.MultiIndex example of use of Boost.Interprocess allocators.
*
* Copyright 2003-2007 Joaquín M López Muñoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/multi_index for library home page.
*/
#if !defined(NDEBUG)
#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING
#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <algorithm>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <boost/interprocess/managed_mapped_file.hpp>
#include <boost/interprocess/sync/named_mutex.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/member.hpp>
#include <iostream>
#include <iterator>
#include <sstream>
#include <string>
using boost::multi_index_container;
using namespace boost::multi_index;
namespace bip=boost::interprocess;
/* shared_string is a string type placeable in shared memory,
* courtesy of Boost.Interprocess.
*/
typedef bip::basic_string<
char,std::char_traits<char>,
bip::allocator<char,bip::managed_mapped_file::segment_manager>
> shared_string;
/* Book record. All its members can be placed in shared memory,
* hence the structure itself can too.
*/
struct book
{
shared_string name;
shared_string author;
unsigned pages;
unsigned prize;
book(const shared_string::allocator_type& al):
name(al),author(al),pages(0),prize(0)
{}
friend std::ostream& operator<<(std::ostream& os,const book& b)
{
os<<b.author<<": \""<<b.name<<"\", $"<<b.prize<<", "<<b.pages<<" pages\n";
return os;
}
};
/* partial_str_less allows for partial searches taking into account
* only the first n chars of the strings compared against. See
* Tutorial: Basics: Special lookup operations for more info on this
* type of comparison functors.
*/
/* partial_string is a mere string holder used to differentiate from
* a plain string.
*/
struct partial_string
{
partial_string(const shared_string& str):str(str){}
shared_string str;
};
struct partial_str_less
{
bool operator()(const shared_string& x,const shared_string& y)const
{
return x<y;
}
bool operator()(const shared_string& x,const partial_string& y)const
{
return x.substr(0,y.str.size())<y.str;
}
bool operator()(const partial_string& x,const shared_string& y)const
{
return x.str<y.substr(0,x.str.size());
}
};
/* Define a multi_index_container of book records with indices on
* author, name and prize. The index on names allows for partial
* searches. This container can be placed in shared memory because:
* * book can be placed in shared memory.
* * We are using a Boost.Interprocess specific allocator.
*/
/* see Compiler specifics: Use of member_offset for info on
* BOOST_MULTI_INDEX_MEMBER
*/
typedef multi_index_container<
book,
indexed_by<
ordered_non_unique<
BOOST_MULTI_INDEX_MEMBER(book,shared_string,author)
>,
ordered_non_unique<
BOOST_MULTI_INDEX_MEMBER(book,shared_string,name),
partial_str_less
>,
ordered_non_unique<
BOOST_MULTI_INDEX_MEMBER(book,unsigned,prize)
>
>,
bip::allocator<book,bip::managed_mapped_file::segment_manager>
> book_container;
/* A small utility to get data entered via std::cin */
template<typename T>
void enter(const char* msg,T& t)
{
std::cout<<msg;
std::string str;
std::getline(std::cin,str);
std::istringstream iss(str);
iss>>t;
}
void enter(const char* msg,std::string& str)
{
std::cout<<msg;
std::getline(std::cin,str);
}
void enter(const char* msg,shared_string& str)
{
std::cout<<msg;
std::string stdstr;
std::getline(std::cin,stdstr);
str=stdstr.c_str();
}
int main()
{
/* Create (or open) the memory mapped file where the book container
* is stored, along with a mutex for synchronized access.
*/
bip::managed_mapped_file seg(
bip::open_or_create,"./book_container.db",
65536);
bip::named_mutex mutex(
bip::open_or_create,"7FD6D7E8-320B-11DC-82CF-F0B655D89593");
/* create or open the book container in shared memory */
book_container* pbc=seg.find_or_construct<book_container>("book container")(
book_container::ctor_args_list(),
book_container::allocator_type(seg.get_segment_manager()));
std::string command_info=
"1. list books by author\n"
"2. list all books by prize\n"
"3. insert a book\n"
"4. delete a book\n"
"0. exit\n";
std::cout<<command_info;
/* main loop */
for(bool exit=false;!exit;){
int command=-1;
enter("command: ",command);
switch(command){
case 0:{ /* exit */
exit=true;
break;
}
case 1:{ /* list books by author */
std::string author;
enter("author (empty=all authors): ",author);
/* operations with the container must be mutex protected */
bip::scoped_lock<bip::named_mutex> lock(mutex);
std::pair<book_container::iterator,book_container::iterator> rng;
if(author.empty()){
rng=std::make_pair(pbc->begin(),pbc->end());
}
else{
rng=pbc->equal_range(
shared_string(
author.c_str(),
shared_string::allocator_type(seg.get_segment_manager())));
}
if(rng.first==rng.second){
std::cout<<"no entries\n";
}
else{
std::copy(
rng.first,rng.second,std::ostream_iterator<book>(std::cout));
}
break;
}
case 2:{ /* list all books by prize */
bip::scoped_lock<bip::named_mutex> lock(mutex);
std::copy(
get<2>(*pbc).begin(),get<2>(*pbc).end(),
std::ostream_iterator<book>(std::cout));
break;
}
case 3:{ /* insert a book */
book b(shared_string::allocator_type(seg.get_segment_manager()));
enter("author: ",b.author);
enter("name: " ,b.name);
enter("prize: " ,b.prize);
enter("pages: " ,b.pages);
std::cout<<"insert the following?\n"<<b<<"(y/n): ";
char yn='n';
enter("",yn);
if(yn=='y'||yn=='Y'){
bip::scoped_lock<bip::named_mutex> lock(mutex);
pbc->insert(b);
}
break;
}
case 4:{ /* delete a book */
shared_string name(
shared_string::allocator_type(seg.get_segment_manager()));
enter(
"name of the book (you can enter\nonly the first few characters): ",
name);
typedef nth_index<book_container,1>::type index_by_name;
index_by_name& idx=get<1>(*pbc);
index_by_name::iterator it;
book b(shared_string::allocator_type(seg.get_segment_manager()));
{
/* Look for a book whose title begins with name. Note that we
* are unlocking after doing the search so as to not leave the
* container blocked during user prompting. That is also why a
* local copy of the book is done.
*/
bip::scoped_lock<bip::named_mutex> lock(mutex);
it=idx.find(partial_string(name));
if(it==idx.end()){
std::cout<<"no such book found\n";
break;
}
b=*it;
}
std::cout<<"delete the following?\n"<<b<<"(y/n): ";
char yn='n';
enter("",yn);
if(yn=='y'||yn=='Y'){
bip::scoped_lock<bip::named_mutex> lock(mutex);
idx.erase(it);
}
break;
}
default:{
std::cout<<"select one option:\n"<<command_info;
break;
}
}
}
return 0;
}
+2 -2
View File
@@ -1,4 +1,4 @@
/* Copyright 2003-2006 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)
@@ -14,6 +14,7 @@
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/functional/hash_fwd.hpp>
#include <boost/multi_index/detail/access_specifier.hpp>
#include <boost/multi_index/detail/prevent_eti.hpp>
#include <boost/mpl/eval_if.hpp>
@@ -106,7 +107,6 @@
namespace boost{
template<class T> class reference_wrapper; /* fwd decl. */
template<class T> struct hash; /* fwd decl. */
namespace multi_index{
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
/* Copyright 2003-2007 Joaquín M López Muñoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
@@ -16,6 +16,7 @@
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <algorithm>
#include <boost/detail/allocator_utilities.hpp>
#include <boost/multi_index/detail/prevent_eti.hpp>
#include <boost/noncopyable.hpp>
#include <memory>
@@ -44,8 +45,15 @@ namespace detail{
template<typename T,typename Allocator=std::allocator<T> >
struct auto_space:private noncopyable
{
typedef typename prevent_eti<
Allocator,
typename boost::detail::allocator::rebind_to<
Allocator,T
>::type
>::type::pointer pointer;
explicit auto_space(const Allocator& al=Allocator(),std::size_t n=1):
al_(al),n_(n),data_(n_?al_.allocate(n_):0)
al_(al),n_(n),data_(n_?al_.allocate(n_):pointer(0))
{}
~auto_space()
@@ -55,10 +63,20 @@ struct auto_space:private noncopyable
Allocator get_allocator()const{return al_;}
T* data()const{return data_;}
pointer data()const{return data_;}
void swap(auto_space& x)
{
if(al_!=x.al_){
#if defined(BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL)
std::swap(al_,x.al_);
#else
using std::swap;
swap(al_,x.al_);
#endif
}
std::swap(n_,x.n_);
std::swap(data_,x.data_);
}
@@ -67,7 +85,7 @@ private:
typename boost::detail::allocator::rebind_to<
Allocator,T>::type al_;
std::size_t n_;
T* data_;
pointer data_;
};
template<typename T,typename Allocator>
@@ -1,4 +1,4 @@
/* Copyright 2003-2006 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)
@@ -49,12 +49,6 @@ public:
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);
@@ -102,6 +96,14 @@ private:
Node* node;
};
template<typename Node,typename Derived>
bool operator==(
const bidir_node_iterator<Node,Derived>& x,
const bidir_node_iterator<Node,Derived>& y)
{
return x.get_node()==y.get_node();
}
} /* namespace multi_index::detail */
} /* namespace multi_index */
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
/* Copyright 2003-2007 Joaquín M López Muñoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
@@ -17,6 +17,7 @@
#include <algorithm>
#include <boost/multi_index/detail/auto_space.hpp>
#include <boost/multi_index/detail/hash_index_node.hpp>
#include <boost/multi_index/detail/prevent_eti.hpp>
#include <boost/noncopyable.hpp>
#include <cstddef>
#include <limits.h>
@@ -84,8 +85,20 @@ protected:
template<typename Allocator>
class bucket_array:public bucket_array_base
{
typedef typename prevent_eti<
Allocator,
hashed_index_node_impl<
typename boost::detail::allocator::rebind_to<
Allocator,
void
>::type
>
>::type node_impl_type;
public:
bucket_array(const Allocator& al,hashed_index_node_impl* end_,std::size_t size):
typedef typename node_impl_type::pointer pointer;
bucket_array(const Allocator& al,pointer end_,std::size_t size):
size_(bucket_array_base::next_prime(size)),
spc(al,size_+1)
{
@@ -104,21 +117,21 @@ public:
return hash%size_;
}
hashed_index_node_impl* begin()const{return &buckets()[0];}
hashed_index_node_impl* end()const{return &buckets()[size_];}
hashed_index_node_impl* at(std::size_t n)const{return &buckets()[n];}
pointer begin()const{return buckets();}
pointer end()const{return buckets()+size_;}
pointer at(std::size_t n)const{return buckets()+n;}
std::size_t first_nonempty(std::size_t n)const
{
for(;;++n){
hashed_index_node_impl* x=at(n);
pointer x=at(n);
if(x->next()!=x)return n;
}
}
void clear()
{
for(hashed_index_node_impl* x=begin(),*y=end();x!=y;++x)x->next()=x;
for(pointer x=begin(),y=end();x!=y;++x)x->next()=x;
}
void swap(bucket_array& x)
@@ -128,10 +141,10 @@ public:
}
private:
std::size_t size_;
auto_space<hashed_index_node_impl,Allocator> spc;
std::size_t size_;
auto_space<node_impl_type,Allocator> spc;
hashed_index_node_impl* buckets()const
pointer buckets()const
{
return spc.data();
}
+26 -19
View File
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
/* Copyright 2003-2007 Joaquín M López Muñoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
@@ -17,6 +17,7 @@
#include <algorithm>
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/multi_index/detail/auto_space.hpp>
#include <boost/multi_index/detail/prevent_eti.hpp>
#include <boost/noncopyable.hpp>
#include <cstddef>
#include <functional>
@@ -69,31 +70,31 @@ public:
{
if(!released){
for(std::size_t i=0;i<n;++i){
boost::detail::allocator::destroy(&spc.data()[i].second->value());
deallocate(spc.data()[i].second);
boost::detail::allocator::destroy(&(spc.data()+i)->second->value());
deallocate((spc.data()+i)->second);
}
}
}
const_iterator begin()const{return spc.data();}
const_iterator end()const{return spc.data()+n;}
const_iterator begin()const{return &*spc.data();}
const_iterator end()const{return &*(spc.data()+n);}
void clone(Node* node)
{
spc.data()[n].first=node;
spc.data()[n].second=al_.allocate(1);
(spc.data()+n)->first=node;
(spc.data()+n)->second=&*al_.allocate(1);
BOOST_TRY{
boost::detail::allocator::construct(
&spc.data()[n].second->value(),node->value());
&(spc.data()+n)->second->value(),node->value());
}
BOOST_CATCH(...){
deallocate(spc.data()[n].second);
deallocate((spc.data()+n)->second);
BOOST_RETHROW;
}
BOOST_CATCH_END
++n;
if(n==size_)std::sort(spc.data(),spc.data()+size_);
if(n==size_)std::sort(&*spc.data(),&*spc.data()+size_);
}
Node* find(Node* node)const
@@ -109,18 +110,24 @@ public:
}
private:
typename boost::detail::allocator::rebind_to<
Allocator,Node>::type al_;
std::size_t size_;
auto_space<copy_map_entry<Node>,Allocator> spc;
std::size_t n;
Node* header_org_;
Node* header_cpy_;
bool released;
typedef typename prevent_eti<
Allocator,
typename boost::detail::allocator::rebind_to<
Allocator,Node>::type
>::type allocator_type;
typedef typename allocator_type::pointer allocator_pointer;
allocator_type al_;
std::size_t size_;
auto_space<copy_map_entry<Node>,Allocator> spc;
std::size_t n;
Node* header_org_;
Node* header_cpy_;
bool released;
void deallocate(Node* node)
{
al_.deallocate(node,1);
al_.deallocate(static_cast<allocator_pointer>(node),1);
}
};
@@ -1,59 +0,0 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/multi_index for library home page.
*/
#ifndef BOOST_MULTI_INDEX_DETAIL_DEF_CTOR_TUPLE_CONS_HPP
#define BOOST_MULTI_INDEX_DETAIL_DEF_CTOR_TUPLE_CONS_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/config.hpp>
#if defined(BOOST_MSVC)
/* In MSVC, tuples::cons is not default constructible. We provide a
* tiny wrapper around tuple::cons filling that hole.
*/
#include <boost/tuple/tuple.hpp>
namespace boost{
namespace multi_index{
namespace detail{
template<typename Cons>
struct default_constructible_tuple_cons:Cons
{
default_constructible_tuple_cons():
Cons(
Cons::head_type(),
static_cast<const Cons::tail_type&>(
default_constructible_tuple_cons<Cons::tail_type>()))
{}
default_constructible_tuple_cons(const Cons& cons):Cons(cons){}
};
template<>
struct default_constructible_tuple_cons<tuples::null_type>:tuples::null_type
{
default_constructible_tuple_cons(){}
default_constructible_tuple_cons(const tuples::null_type&){}
};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif /* BOOST_MSVC */
#endif
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
/* Copyright 2003-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)
@@ -14,7 +14,7 @@
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/functional/hash/hash.hpp>
#include <boost/functional/hash.hpp>
#include <boost/mpl/aux_/na.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/identity.hpp>
@@ -26,8 +26,6 @@
namespace boost{
template<class T> struct hash; /* fwd decl. */
namespace multi_index{
namespace detail{
@@ -1,4 +1,4 @@
/* Copyright 2003-2006 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)
@@ -50,12 +50,6 @@ public:
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());
@@ -100,6 +94,14 @@ private:
BucketArray* buckets;
};
template<typename Node,typename BucketArray,typename Derived>
bool operator==(
const hashed_index_iterator<Node,BucketArray,Derived>& x,
const hashed_index_iterator<Node,BucketArray,Derived>& y)
{
return x.get_node()==y.get_node();
}
} /* namespace multi_index::detail */
} /* namespace multi_index */
@@ -1,4 +1,4 @@
/* Copyright 2003-2006 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)
@@ -14,6 +14,8 @@
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/detail/allocator_utilities.hpp>
#include <boost/multi_index/detail/prevent_eti.hpp>
#include <functional>
namespace boost{
@@ -24,18 +26,30 @@ namespace detail{
/* singly-linked node for use by hashed_index */
template<typename Allocator>
struct hashed_index_node_impl
{
hashed_index_node_impl*& next(){return next_;}
hashed_index_node_impl* next()const{return next_;}
typedef typename prevent_eti<
Allocator,
typename boost::detail::allocator::rebind_to<
Allocator,hashed_index_node_impl
>::type
>::type::pointer pointer;
typedef typename prevent_eti<
Allocator,
typename boost::detail::allocator::rebind_to<
Allocator,hashed_index_node_impl
>::type
>::type::const_pointer const_pointer;
pointer& next(){return next_;}
pointer next()const{return next_;}
/* algorithmic stuff */
static void increment(
hashed_index_node_impl*& x,
hashed_index_node_impl* bbegin,hashed_index_node_impl* bbend)
static void increment(pointer& x,pointer bbegin,pointer bbend)
{
std::less_equal<hashed_index_node_impl*> leq;
std::less_equal<pointer> leq;
x=x->next();
if(leq(bbegin,x)&&leq(x,bbend)){ /* bucket node */
@@ -46,66 +60,100 @@ struct hashed_index_node_impl
}
}
static void link(
hashed_index_node_impl* x,hashed_index_node_impl* pos)
static void link(pointer x,pointer pos)
{
x->next()=pos->next();
pos->next()=x;
};
static void unlink(hashed_index_node_impl* x)
static void unlink(pointer x)
{
hashed_index_node_impl* y=x->next();
pointer y=x->next();
while(y->next()!=x){y=y->next();}
y->next()=x->next();
}
static hashed_index_node_impl* prev(hashed_index_node_impl* x)
static pointer prev(pointer x)
{
hashed_index_node_impl* y=x->next();
pointer y=x->next();
while(y->next()!=x){y=y->next();}
return y;
}
static void unlink_next(hashed_index_node_impl* x)
static void unlink_next(pointer x)
{
x->next()=x->next()->next();
}
private:
hashed_index_node_impl* next_;
pointer next_;
};
template<typename Super>
struct hashed_index_node_trampoline:hashed_index_node_impl{};
struct hashed_index_node_trampoline:
prevent_eti<
Super,
hashed_index_node_impl<
typename boost::detail::allocator::rebind_to<
typename Super::allocator_type,
void
>::type
>
>::type
{
typedef typename prevent_eti<
Super,
hashed_index_node_impl<
typename boost::detail::allocator::rebind_to<
typename Super::allocator_type,
void
>::type
>
>::type impl_type;
};
template<typename Super>
struct hashed_index_node:Super,hashed_index_node_trampoline<Super>
{
hashed_index_node_impl* impl()
{return static_cast<impl_type*>(this);}
const hashed_index_node_impl* impl()const
{return static_cast<const impl_type*>(this);}
private:
typedef hashed_index_node_trampoline<Super> trampoline;
static hashed_index_node* from_impl(hashed_index_node_impl *x)
{return static_cast<hashed_index_node*>(static_cast<impl_type*>(x));}
static const hashed_index_node* from_impl(const hashed_index_node_impl* x)
public:
typedef typename trampoline::impl_type impl_type;
typedef typename trampoline::pointer impl_pointer;
typedef typename trampoline::const_pointer const_impl_pointer;
impl_pointer impl()
{
return static_cast<impl_pointer>(
static_cast<impl_type*>(static_cast<trampoline*>(this)));
}
const_impl_pointer impl()const
{
return static_cast<const_impl_pointer>(
static_cast<const impl_type*>(static_cast<const trampoline*>(this)));
}
static hashed_index_node* from_impl(impl_pointer x)
{
return static_cast<hashed_index_node*>(
static_cast<trampoline*>(&*x));
}
static const hashed_index_node* from_impl(const_impl_pointer x)
{
return static_cast<const hashed_index_node*>(
static_cast<const impl_type*>(x));
static_cast<const trampoline*>(&*x));
}
static void increment(
hashed_index_node*& x,
hashed_index_node_impl* bbegin,hashed_index_node_impl* bend)
hashed_index_node*& x,impl_pointer bbegin,impl_pointer bend)
{
hashed_index_node_impl* xi=x->impl();
impl_type::increment(xi,bbegin,bend);
impl_pointer xi=x->impl();
trampoline::increment(xi,bbegin,bend);
x=from_impl(xi);
}
private:
typedef hashed_index_node_trampoline<Super> impl_type;
};
} /* namespace multi_index::detail */
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
/* Copyright 2003-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)
@@ -29,13 +29,13 @@ namespace detail{
* to the base from member trick.
*/
template<typename NodeType,typename Final>
template<typename NodeTypePtr,typename Final>
struct header_holder:private noncopyable
{
header_holder():member(final().allocate_node()){}
~header_holder(){final().deallocate_node(member);}
~header_holder(){final().deallocate_node(&*member);}
NodeType* member;
NodeTypePtr member;
private:
Final& final(){return *static_cast<Final*>(this);}
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
/* Copyright 2003-2007 Joaquín M López Muñoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
@@ -46,7 +46,7 @@ template<typename Value,typename IndexSpecifierList,typename Allocator>
class index_base
{
protected:
typedef index_node_base<Value> node_type;
typedef index_node_base<Value,Allocator> node_type;
typedef typename multi_index_node_type<
Value,IndexSpecifierList,Allocator>::type final_node_type;
typedef multi_index_container<
@@ -117,6 +117,8 @@ protected:
bool modify_(node_type*){return true;}
bool modify_rollback_(node_type*){return true;}
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
/* serialization */
@@ -162,9 +164,13 @@ protected:
{return final().replace_(k,x);}
template<typename Modifier>
bool final_modify_(Modifier mod,final_node_type* x)
bool final_modify_(Modifier& mod,final_node_type* x)
{return final().modify_(mod,x);}
template<typename Modifier,typename Rollback>
bool final_modify_(Modifier& mod,Rollback& back,final_node_type* x)
{return final().modify_(mod,back,x);}
#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
void final_check_invariant_()const{final().check_invariant_();}
#endif
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
/* Copyright 2003-2007 Joaquín M López Muñoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
@@ -91,7 +91,7 @@ public:
}
private:
Node** entries()const{return spc.data();}
Node** entries()const{return &*spc.data();}
/* We try to delay sorting as much as possible just in case it
* is not necessary, hence this version of load_node.
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
/* Copyright 2003-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)
@@ -179,7 +179,7 @@ protected:
}
private:
entry* entries()const{return spc.data();}
entry* entries()const{return &*spc.data();}
auto_space<entry,Allocator> spc;
std::size_t size_;
@@ -1,4 +1,4 @@
/* Copyright 2003-2006 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)
@@ -42,11 +42,12 @@ struct pod_value_holder
>::type space;
};
template<typename Value>
template<typename Value,typename Allocator>
struct index_node_base:private pod_value_holder<Value>
{
typedef index_node_base base_type; /* used for serialization purposes */
typedef Value value_type;
typedef Allocator allocator_type;
value_type& value()
{
@@ -88,7 +89,9 @@ Node* node_from_value(
const Value* p
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Node))
{
return static_cast<Node*>(index_node_base<Value>::from_value(p));
typedef typename Node::allocator_type allocator_type;
return static_cast<Node*>(
index_node_base<Value,allocator_type>::from_value(p));
}
} /* namespace multi_index::detail */
@@ -109,9 +112,9 @@ namespace multi_index{
namespace detail{
#endif
template<class Archive,typename Value>
template<class Archive,typename Value,typename Allocator>
inline void load_construct_data(
Archive&,boost::multi_index::detail::index_node_base<Value>*,
Archive&,boost::multi_index::detail::index_node_base<Value,Allocator>*,
const unsigned int)
{
throw_exception(
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaqu M Lez Muz.
/* 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)
@@ -30,6 +30,12 @@ namespace detail{
* for internal consumption.
*/
/* NB. The purpose of the (non-inclass) global operators ==, < and - defined
* above is to partially alleviate a problem of MSVC++ 6.0 by * which
* friend-injected operators on T are not visible if T is instantiated only
* in template code where T is a dependent type.
*/
class iter_adaptor_access
{
public:
@@ -107,6 +113,15 @@ private:
const Derived& final()const{return *static_cast<const Derived*>(this);}
};
template<class Derived,class Base>
bool operator==(
const forward_iter_adaptor_base<Derived,Base>& x,
const forward_iter_adaptor_base<Derived,Base>& y)
{
return iter_adaptor_access::equal(
static_cast<const Derived&>(x),static_cast<const Derived&>(y));
}
template<>
struct iter_adaptor_selector<std::forward_iterator_tag>
{
@@ -156,6 +171,15 @@ private:
const Derived& final()const{return *static_cast<const Derived*>(this);}
};
template<class Derived,class Base>
bool operator==(
const bidirectional_iter_adaptor_base<Derived,Base>& x,
const bidirectional_iter_adaptor_base<Derived,Base>& y)
{
return iter_adaptor_access::equal(
static_cast<const Derived&>(x),static_cast<const Derived&>(y));
}
template<>
struct iter_adaptor_selector<std::bidirectional_iterator_tag>
{
@@ -228,6 +252,34 @@ private:
const Derived& final()const{return *static_cast<const Derived*>(this);}
};
template<class Derived,class Base>
bool operator==(
const random_access_iter_adaptor_base<Derived,Base>& x,
const random_access_iter_adaptor_base<Derived,Base>& y)
{
return iter_adaptor_access::equal(
static_cast<const Derived&>(x),static_cast<const Derived&>(y));
}
template<class Derived,class Base>
bool operator<(
const random_access_iter_adaptor_base<Derived,Base>& x,
const random_access_iter_adaptor_base<Derived,Base>& y)
{
return iter_adaptor_access::distance_to(
static_cast<const Derived&>(x),static_cast<const Derived&>(y))>0;
}
template<class Derived,class Base>
typename random_access_iter_adaptor_base<Derived,Base>::difference_type
operator-(
const random_access_iter_adaptor_base<Derived,Base>& x,
const random_access_iter_adaptor_base<Derived,Base>& y)
{
return iter_adaptor_access::distance_to(
static_cast<const Derived&>(y),static_cast<const Derived&>(x));
}
template<>
struct iter_adaptor_selector<std::random_access_iterator_tag>
{
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
/* Copyright 2003-2007 Joaquín M López Muńoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
@@ -24,19 +24,19 @@ namespace detail{
* with references to references, dealing with function pointers, etc.
*/
template<typename Modifier,typename Value,typename KeyFromValue>
template<typename Fun,typename Value,typename KeyFromValue>
struct modify_key_adaptor
{
modify_key_adaptor(Modifier mod_,KeyFromValue kfv_):mod(mod_),kfv(kfv_){}
modify_key_adaptor(Fun f_,KeyFromValue kfv_):f(f_),kfv(kfv_){}
void operator()(Value& x)
{
mod(kfv(x));
f(kfv(x));
}
private:
Modifier mod;
Fun f;
KeyFromValue kfv;
};
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaquí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)
@@ -65,7 +65,7 @@ struct multi_index_node_type
typedef typename mpl::reverse_iter_fold<
IndexSpecifierList,
index_node_base<Value>,
index_node_base<Value,Allocator>,
mpl::bind2<index_node_applier,mpl::_2,mpl::_1>
>::type type;
};
@@ -42,12 +42,15 @@
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <cstddef>
#include <boost/detail/allocator_utilities.hpp>
#include <boost/multi_index/detail/prevent_eti.hpp>
#if !defined(BOOST_MULTI_INDEX_DISABLE_COMPRESSED_ORDERED_INDEX_NODES)
#include <boost/mpl/and.hpp>
#include <boost/mpl/if.hpp>
#include <boost/multi_index/detail/uintptr_type.hpp>
#include <boost/type_traits/alignment_of.hpp>
#include <boost/type_traits/is_same.hpp>
#endif
namespace boost{
@@ -61,27 +64,43 @@ namespace detail{
enum ordered_index_color{red=false,black=true};
enum ordered_index_side{to_left=false,to_right=true};
template<typename Allocator>
struct ordered_index_node_impl; /* fwd decl. */
template<typename Allocator>
struct ordered_index_node_std_base
{
typedef ordered_index_color& color_ref;
typedef ordered_index_node_impl*& parent_ref;
typedef typename prevent_eti<
Allocator,
typename boost::detail::allocator::rebind_to<
Allocator,
ordered_index_node_impl<Allocator>
>::type
>::type::pointer pointer;
typedef typename prevent_eti<
Allocator,
typename boost::detail::allocator::rebind_to<
Allocator,
ordered_index_node_impl<Allocator>
>::type
>::type::const_pointer const_pointer;
typedef ordered_index_color& color_ref;
typedef pointer& parent_ref;
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_;}
ordered_index_color& color(){return color_;}
ordered_index_color color()const{return color_;}
pointer& parent(){return parent_;}
pointer parent()const{return parent_;}
pointer& left(){return left_;}
pointer left()const{return left_;}
pointer& right(){return right_;}
pointer right()const{return right_;}
private:
ordered_index_color color_;
ordered_index_node_impl* parent_;
ordered_index_node_impl* left_;
ordered_index_node_impl* right_;
ordered_index_color color_;
pointer parent_;
pointer left_;
pointer right_;
};
#if !defined(BOOST_MULTI_INDEX_DISABLE_COMPRESSED_ORDERED_INDEX_NODES)
@@ -102,8 +121,12 @@ private:
#pragma warning(disable:4312 4311)
#endif
template<typename Allocator>
struct ordered_index_node_compressed_base
{
typedef ordered_index_node_impl<Allocator>* pointer;
typedef const ordered_index_node_impl<Allocator>* const_pointer;
struct color_ref
{
color_ref(uintptr_type* r_):r(r_){}
@@ -133,12 +156,12 @@ struct ordered_index_node_compressed_base
{
parent_ref(uintptr_type* r_):r(r_){}
operator ordered_index_node_impl*()const
operator pointer()const
{
return (ordered_index_node_impl*)(void*)(*r&~uintptr_type(1));
return (pointer)(void*)(*r&~uintptr_type(1));
}
parent_ref& operator=(ordered_index_node_impl* p)
parent_ref& operator=(pointer p)
{
*r=((uintptr_type)(void*)p)|(*r&uintptr_type(1));
return *this;
@@ -146,69 +169,92 @@ struct ordered_index_node_compressed_base
parent_ref& operator=(const parent_ref& x)
{
return operator=(x.operator ordered_index_node_impl*());
return operator=(x.operator pointer());
}
ordered_index_node_impl* operator->()const
pointer operator->()const
{
return operator ordered_index_node_impl*();
return operator pointer();
}
private:
uintptr_type* r;
};
color_ref color(){return color_ref(&parentcolor_);}
ordered_index_color color()const
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
parent_ref parent(){return parent_ref(&parentcolor_);}
pointer parent()const
{
return (ordered_index_node_impl*)(void*)(parentcolor_&~uintptr_type(1));
return (pointer)(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_;}
pointer& left(){return left_;}
pointer left()const{return left_;}
pointer& right(){return right_;}
pointer right()const{return right_;}
private:
uintptr_type parentcolor_;
ordered_index_node_impl* left_;
ordered_index_node_impl* right_;
uintptr_type parentcolor_;
pointer left_;
pointer right_;
};
#if defined(BOOST_MSVC)
#pragma warning(pop)
#endif
#endif
struct ordered_index_node_impl:
template<typename Allocator>
struct ordered_index_node_impl_base:
#if !defined(BOOST_MULTI_INDEX_DISABLE_COMPRESSED_ORDERED_INDEX_NODES)
mpl::if_c<
!(has_uintptr_type::value)||
(alignment_of<ordered_index_node_compressed_base>::value%2),
ordered_index_node_std_base,
ordered_index_node_compressed_base
(alignment_of<ordered_index_node_compressed_base<Allocator> >::value%2)||
!(is_same<
typename prevent_eti<
Allocator,
typename boost::detail::allocator::rebind_to<
Allocator,
ordered_index_node_impl<Allocator>
>::type
>::type::pointer,
ordered_index_node_impl<Allocator>*>::value),
ordered_index_node_std_base<Allocator>,
ordered_index_node_compressed_base<Allocator>
>::type
#else
ordered_index_node_std_base
ordered_index_node_std_base<Allocator>
#endif
{};
template<typename Allocator>
struct ordered_index_node_impl:ordered_index_node_impl_base<Allocator>
{
private:
typedef ordered_index_node_impl_base<Allocator> super;
public:
typedef typename super::color_ref color_ref;
typedef typename super::parent_ref parent_ref;
typedef typename super::pointer pointer;
typedef typename super::const_pointer const_pointer;
/* interoperability with bidir_node_iterator */
static void increment(ordered_index_node_impl*& x)
static void increment(pointer& x)
{
if(x->right()){
if(x->right()!=pointer(0)){
x=x->right();
while(x->left())x=x->left();
while(x->left()!=pointer(0))x=x->left();
}
else{
ordered_index_node_impl* y=x->parent();
pointer y=x->parent();
while(x==y->right()){
x=y;
y=y->parent();
@@ -217,17 +263,17 @@ struct ordered_index_node_impl:
}
}
static void decrement(ordered_index_node_impl*& x)
static void decrement(pointer& x)
{
if(x->color()==red&&x->parent()->parent()==x){
x=x->right();
}
else if(x->left()){
ordered_index_node_impl* y=x->left();
while(y->right())y=y->right();
else if(x->left()!=pointer(0)){
pointer y=x->left();
while(y->right()!=pointer(0))y=y->right();
x=y;
}else{
ordered_index_node_impl* y=x->parent();
pointer y=x->parent();
while(x==y->left()){
x=y;
y=y->parent();
@@ -238,12 +284,11 @@ struct ordered_index_node_impl:
/* algorithmic stuff */
static void rotate_left(
ordered_index_node_impl* x,parent_ref root)
static void rotate_left(pointer x,parent_ref root)
{
ordered_index_node_impl* y=x->right();
pointer y=x->right();
x->right()=y->left();
if(y->left())y->left()->parent()=x;
if(y->left()!=pointer(0))y->left()->parent()=x;
y->parent()=x->parent();
if(x==root) root=y;
@@ -253,24 +298,23 @@ struct ordered_index_node_impl:
x->parent()=y;
}
static ordered_index_node_impl* minimum(ordered_index_node_impl* x)
static pointer minimum(pointer x)
{
while(x->left())x=x->left();
while(x->left()!=pointer(0))x=x->left();
return x;
}
static ordered_index_node_impl* maximum(ordered_index_node_impl* x)
static pointer maximum(pointer x)
{
while(x->right())x=x->right();
while(x->right()!=pointer(0))x=x->right();
return x;
}
static void rotate_right(
ordered_index_node_impl* x,parent_ref root)
static void rotate_right(pointer x,parent_ref root)
{
ordered_index_node_impl* y=x->left();
pointer y=x->left();
x->left()=y->right();
if(y->right())y->right()->parent()=x;
if(y->right()!=pointer(0))y->right()->parent()=x;
y->parent()=x->parent();
if(x==root) root=y;
@@ -280,14 +324,13 @@ struct ordered_index_node_impl:
x->parent()=y;
}
static void rebalance(
ordered_index_node_impl* x,parent_ref root)
static void rebalance(pointer x,parent_ref root)
{
x->color()=red;
while(x!=root&&x->parent()->color()==red){
if(x->parent()==x->parent()->parent()->left()){
ordered_index_node_impl* y=x->parent()->parent()->right();
if(y&&y->color()==red){
pointer y=x->parent()->parent()->right();
if(y!=pointer(0)&&y->color()==red){
x->parent()->color()=black;
y->color()=black;
x->parent()->parent()->color()=red;
@@ -304,8 +347,8 @@ struct ordered_index_node_impl:
}
}
else{
ordered_index_node_impl* y=x->parent()->parent()->left();
if(y&&y->color()==red){
pointer y=x->parent()->parent()->left();
if(y!=pointer(0)&&y->color()==red){
x->parent()->color()=black;
y->color()=black;
x->parent()->parent()->color()=red;
@@ -326,9 +369,7 @@ struct ordered_index_node_impl:
}
static void link(
ordered_index_node_impl* x,
ordered_index_side side,ordered_index_node_impl* position,
ordered_index_node_impl* header)
pointer x,ordered_index_side side,pointer position,pointer header)
{
if(side==to_left){
position->left()=x; /* also makes leftmost=x when parent==header */
@@ -347,28 +388,27 @@ struct ordered_index_node_impl:
}
}
x->parent()=position;
x->left()=0;
x->right()=0;
x->left()=pointer(0);
x->right()=pointer(0);
ordered_index_node_impl::rebalance(x,header->parent());
}
static ordered_index_node_impl* rebalance_for_erase(
ordered_index_node_impl* z,parent_ref root,
ordered_index_node_impl*& leftmost,ordered_index_node_impl*& rightmost)
static pointer rebalance_for_erase(
pointer z,parent_ref root,pointer& leftmost,pointer& rightmost)
{
ordered_index_node_impl* y=z;
ordered_index_node_impl* x=0;
ordered_index_node_impl* x_parent=0;
if(y->left()==0){ /* z has at most one non-null child. y==z. */
x=y->right(); /* x might be null */
pointer y=z;
pointer x=pointer(0);
pointer x_parent=pointer(0);
if(y->left()==pointer(0)){ /* z has at most one non-null child. y==z. */
x=y->right(); /* x might be null */
}
else{
if(y->right()==0) { /* z has exactly one non-null child. y==z. */
x=y->left(); /* x is not null */
if(y->right()==pointer(0)){ /* z has exactly one non-null child. y==z. */
x=y->left(); /* x is not null */
}
else{ /* z has two non-null children. Set y to */
y=y->right(); /* z's successor. x might be null. */
while(y->left())y=y->left();
else{ /* z has two non-null children. Set y to */
y=y->right(); /* z's successor. x might be null. */
while(y->left()!=pointer(0))y=y->left();
x=y->right();
}
}
@@ -377,7 +417,7 @@ struct ordered_index_node_impl:
y->left()=z->left();
if(y!=z->right()){
x_parent=y->parent();
if(x) x->parent()=y->parent();
if(x!=pointer(0))x->parent()=y->parent();
y->parent()->left()=x; /* y must be a child of left */
y->right()=z->right();
z->right()->parent()=y;
@@ -397,7 +437,7 @@ struct ordered_index_node_impl:
}
else{ /* y==z */
x_parent=y->parent();
if(x)x->parent()=y->parent();
if(x!=pointer(0))x->parent()=y->parent();
if(root==z){
root=x;
}
@@ -406,15 +446,15 @@ struct ordered_index_node_impl:
else z->parent()->right()=x;
}
if(leftmost==z){
if(z->right()==0){ /* z->left() must be null also */
if(z->right()==pointer(0)){ /* z->left() must be null also */
leftmost=z->parent();
}
else{
leftmost=minimum(x); /* makes leftmost==header if z==root */
leftmost=minimum(x); /* makes leftmost==header if z==root */
}
}
if(rightmost==z){
if(z->left()==0){ /* z->right() must be null also */
if(z->left()==pointer(0)){ /* z->right() must be null also */
rightmost=z->parent();
}
else{ /* x==z->left() */
@@ -423,75 +463,73 @@ struct ordered_index_node_impl:
}
}
if(y->color()!=red){
while(x!=root&&(x==0 || x->color()==black)){
while(x!=root&&(x==pointer(0)|| x->color()==black)){
if(x==x_parent->left()){
ordered_index_node_impl* w=x_parent->right();
pointer w=x_parent->right();
if(w->color()==red){
w->color()=black;
x_parent->color()=red;
rotate_left(x_parent,root);
w=x_parent->right();
}
if((w->left()==0||w->left()->color()==black) &&
(w->right()==0||w->right()->color()==black)){
if((w->left()==pointer(0)||w->left()->color()==black) &&
(w->right()==pointer(0)||w->right()->color()==black)){
w->color()=red;
x=x_parent;
x_parent=x_parent->parent();
}
else{
if(w->right()==0
if(w->right()==pointer(0 )
|| w->right()->color()==black){
if(w->left()) w->left()->color()=black;
if(w->left()!=pointer(0)) w->left()->color()=black;
w->color()=red;
rotate_right(w,root);
w=x_parent->right();
}
w->color()=x_parent->color();
x_parent->color()=black;
if(w->right())w->right()->color()=black;
if(w->right()!=pointer(0))w->right()->color()=black;
rotate_left(x_parent,root);
break;
}
}
else{ /* same as above,with right <-> left */
ordered_index_node_impl* w=x_parent->left();
pointer w=x_parent->left();
if(w->color()==red){
w->color()=black;
x_parent->color()=red;
rotate_right(x_parent,root);
w=x_parent->left();
}
if((w->right()==0||w->right()->color()==black) &&
(w->left()==0||w->left()->color()==black)){
if((w->right()==pointer(0)||w->right()->color()==black) &&
(w->left()==pointer(0)||w->left()->color()==black)){
w->color()=red;
x=x_parent;
x_parent=x_parent->parent();
}
else{
if(w->left()==0||w->left()->color()==black){
if(w->right())w->right()->color()=black;
if(w->left()==pointer(0)||w->left()->color()==black){
if(w->right()!=pointer(0))w->right()->color()=black;
w->color()=red;
rotate_left(w,root);
w=x_parent->left();
}
w->color()=x_parent->color();
x_parent->color()=black;
if(w->left())w->left()->color()=black;
if(w->left()!=pointer(0))w->left()->color()=black;
rotate_right(x_parent,root);
break;
}
}
}
if(x)x->color()=black;
if(x!=pointer(0))x->color()=black;
}
return y;
}
static void restore(
ordered_index_node_impl* x,ordered_index_node_impl* position,
ordered_index_node_impl* header)
static void restore(pointer x,pointer position,pointer header)
{
if(position->left()==0||position->left()==header){
if(position->left()==pointer(0)||position->left()==header){
link(x,to_left,position,header);
}
else{
@@ -503,10 +541,9 @@ struct ordered_index_node_impl:
#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
/* invariant stuff */
static std::size_t black_count(
ordered_index_node_impl* node,ordered_index_node_impl* root)
static std::size_t black_count(pointer node,pointer root)
{
if(!node)return 0;
if(node==pointer(0))return 0;
std::size_t sum=0;
for(;;){
if(node->color()==black)++sum;
@@ -519,54 +556,87 @@ struct ordered_index_node_impl:
};
template<typename Super>
struct ordered_index_node_trampoline:ordered_index_node_impl{};
struct ordered_index_node_trampoline:
prevent_eti<
Super,
ordered_index_node_impl<
typename boost::detail::allocator::rebind_to<
typename Super::allocator_type,
void
>::type
>
>::type
{
typedef typename prevent_eti<
Super,
ordered_index_node_impl<
typename boost::detail::allocator::rebind_to<
typename Super::allocator_type,
void
>::type
>
>::type impl_type;
};
template<typename Super>
struct ordered_index_node:Super,ordered_index_node_trampoline<Super>
{
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;
typedef ordered_index_node_trampoline<Super> trampoline;
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();}
typedef typename trampoline::impl_type impl_type;
typedef typename trampoline::color_ref impl_color_ref;
typedef typename trampoline::parent_ref impl_parent_ref;
typedef typename trampoline::pointer impl_pointer;
typedef typename trampoline::const_pointer const_impl_pointer;
ordered_index_node_impl* impl(){return static_cast<impl_type*>(this);}
const ordered_index_node_impl* impl()const
{return static_cast<const impl_type*>(this);}
impl_color_ref color(){return trampoline::color();}
ordered_index_color color()const{return trampoline::color();}
impl_parent_ref parent(){return trampoline::parent();}
impl_pointer parent()const{return trampoline::parent();}
impl_pointer& left(){return trampoline::left();}
impl_pointer left()const{return trampoline::left();}
impl_pointer& right(){return trampoline::right();}
impl_pointer right()const{return trampoline::right();}
static ordered_index_node* from_impl(ordered_index_node_impl *x)
impl_pointer impl()
{
return static_cast<ordered_index_node*>(static_cast<impl_type*>(x));
return static_cast<impl_pointer>(
static_cast<impl_type*>(static_cast<trampoline*>(this)));
}
static const ordered_index_node* from_impl(const ordered_index_node_impl* x)
const_impl_pointer impl()const
{
return static_cast<const_impl_pointer>(
static_cast<const impl_type*>(static_cast<const trampoline*>(this)));
}
static ordered_index_node* from_impl(impl_pointer x)
{
return static_cast<ordered_index_node*>(
static_cast<trampoline*>(&*x));
}
static const ordered_index_node* from_impl(const_impl_pointer x)
{
return static_cast<const ordered_index_node*>(
static_cast<const impl_type*>(x));
static_cast<const trampoline*>(&*x));
}
/* interoperability with bidir_node_iterator */
static void increment(ordered_index_node*& x)
{
ordered_index_node_impl* xi=x->impl();
impl_type::increment(xi);
impl_pointer xi=x->impl();
trampoline::increment(xi);
x=from_impl(xi);
}
static void decrement(ordered_index_node*& x)
{
ordered_index_node_impl* xi=x->impl();
impl_type::decrement(xi);
impl_pointer xi=x->impl();
trampoline::decrement(xi);
x=from_impl(xi);
}
};
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
/* Copyright 2003-2007 Joaquín M López Muñoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
@@ -40,6 +40,9 @@
#pragma once
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <utility>
namespace boost{
namespace multi_index{
@@ -55,21 +58,20 @@ template<
typename CompatibleKey,typename CompatibleCompare
>
inline Node* ordered_index_find(
Node* header,const KeyFromValue& key,const CompatibleKey& x,
Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
const CompatibleCompare& comp)
{
Node* y=header;
Node* z=Node::from_impl(header->parent());
while (z){
if(!comp(key(z->value()),x)){
y=z;
z=Node::from_impl(z->left());
Node* y0=y;
while (top){
if(!comp(key(top->value()),x)){
y=top;
top=Node::from_impl(top->left());
}
else z=Node::from_impl(z->right());
else top=Node::from_impl(top->right());
}
return (y==header||comp(x,key(y->value())))?header:y;
return (y==y0||comp(x,key(y->value())))?y0:y;
}
template<
@@ -77,18 +79,15 @@ template<
typename CompatibleKey,typename CompatibleCompare
>
inline Node* ordered_index_lower_bound(
Node* header,const KeyFromValue& key,const CompatibleKey& x,
Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
const CompatibleCompare& comp)
{
Node* y=header;
Node* z=Node::from_impl(header->parent());
while(z){
if(!comp(key(z->value()),x)){
y=z;
z=Node::from_impl(z->left());
while(top){
if(!comp(key(top->value()),x)){
y=top;
top=Node::from_impl(top->left());
}
else z=Node::from_impl(z->right());
else top=Node::from_impl(top->right());
}
return y;
@@ -99,23 +98,46 @@ template<
typename CompatibleKey,typename CompatibleCompare
>
inline Node* ordered_index_upper_bound(
Node* header,const KeyFromValue& key,const CompatibleKey& x,
Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
const CompatibleCompare& comp)
{
Node* y=header;
Node* z=Node::from_impl(header->parent());
while(z){
if(comp(x,key(z->value()))){
y=z;
z=Node::from_impl(z->left());
while(top){
if(comp(x,key(top->value()))){
y=top;
top=Node::from_impl(top->left());
}
else z=Node::from_impl(z->right());
else top=Node::from_impl(top->right());
}
return y;
}
template<
typename Node,typename KeyFromValue,
typename CompatibleKey,typename CompatibleCompare
>
inline std::pair<Node*,Node*> ordered_index_equal_range(
Node* top,Node* y,const KeyFromValue& key,const CompatibleKey& x,
const CompatibleCompare& comp)
{
while(top){
if(comp(key(top->value()),x)){
top=Node::from_impl(top->right());
}
else if(comp(x,key(top->value()))){
y=top;
top=Node::from_impl(top->left());
}
else{
return std::pair<Node*,Node*>(
ordered_index_lower_bound(Node::from_impl(top->left()),top,key,x,comp),
ordered_index_upper_bound(Node::from_impl(top->right()),y,key,x,comp));
}
}
return std::pair<Node*,Node*>(y,y);
}
} /* namespace multi_index::detail */
} /* namespace multi_index */
@@ -1,4 +1,4 @@
/* Copyright 2003-2006 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)
@@ -15,7 +15,9 @@
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <algorithm>
#include <boost/detail/allocator_utilities.hpp>
#include <boost/multi_index/detail/auto_space.hpp>
#include <boost/multi_index/detail/prevent_eti.hpp>
#include <boost/multi_index/detail/rnd_index_ptr_array.hpp>
#include <boost/noncopyable.hpp>
#include <cstddef>
@@ -43,10 +45,19 @@ 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;
typedef typename prevent_eti<
Allocator,
random_access_index_node_impl<
typename boost::detail::allocator::rebind_to<
Allocator,
void
>::type
>
>::type node_impl_type;
typedef typename node_impl_type::pointer node_impl_pointer;
typedef random_access_index_ptr_array<Allocator> ptr_array;
random_access_index_loader_base(const Allocator& al_,ptr_array_type& ptrs_):
random_access_index_loader_base(const Allocator& al_,ptr_array& ptrs_):
al(al_),
ptrs(ptrs_),
header(*ptrs.end()),
@@ -58,14 +69,14 @@ protected:
{
if(preprocessed)
{
node_type* n=header;
node_impl_pointer n=header;
next(n)=n;
for(std::size_t i=ptrs.size();i--;){
n=prev(n);
std::size_t d=position(n);
if(d!=i){
node_type* m=prev(next_at(i));
node_impl_pointer m=prev(next_at(i));
std::swap(m->up(),n->up());
next_at(d)=next_at(i);
std::swap(prev_at(d),prev_at(i));
@@ -75,10 +86,10 @@ protected:
}
}
void rearrange(node_type* position,node_type *x)
void rearrange(node_impl_pointer position,node_impl_pointer x)
{
preprocess(); /* only incur this penalty if rearrange() is ever called */
if(!position)position=header;
if(position==node_impl_pointer(0))position=header;
next(prev(x))=next(x);
prev(next(x))=prev(x);
prev(x)=position;
@@ -91,49 +102,50 @@ private:
{
if(!preprocessed){
/* get space for the auxiliary prev array */
auto_space<node_type*,Allocator> tmp(al,ptrs.size()+1);
auto_space<node_impl_pointer,Allocator> tmp(al,ptrs.size()+1);
prev_spc.swap(tmp);
/* prev_spc elements point to the prev nodes */
std::rotate_copy(ptrs.begin(),ptrs.end(),ptrs.end()+1,prev_spc.data());
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);
std::rotate(&*ptrs.begin(),&*ptrs.begin()+1,&*ptrs.end()+1);
preprocessed=true;
}
}
std::size_t position(node_type* x)const
std::size_t position(node_impl_pointer x)const
{
return (std::size_t)(x->up()-ptrs.begin());
}
node_type*& next_at(std::size_t n)const
node_impl_pointer& next_at(std::size_t n)const
{
return *ptrs.at(n);
}
node_type*& prev_at(std::size_t n)const
node_impl_pointer& prev_at(std::size_t n)const
{
return prev_spc.data()[n];
return *(prev_spc.data()+n);
}
node_type*& next(node_type* x)const
node_impl_pointer& next(node_impl_pointer x)const
{
return *(x->up());
}
node_type*& prev(node_type* x)const
node_impl_pointer& prev(node_impl_pointer 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;
Allocator al;
ptr_array& ptrs;
node_impl_pointer header;
auto_space<node_impl_pointer,Allocator> prev_spc;
bool preprocessed;
};
template<typename Node,typename Allocator>
@@ -141,16 +153,17 @@ 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;
typedef typename super::node_impl_pointer node_impl_pointer;
typedef typename super::ptr_array ptr_array;
public:
random_access_index_loader(const Allocator& al_,ptr_array_type& ptrs_):
random_access_index_loader(const Allocator& al_,ptr_array& ptrs_):
super(al_,ptrs_)
{}
void rearrange(Node* position,Node *x)
{
super::rearrange(position?position->impl():0,x->impl());
super::rearrange(position?position->impl():node_impl_pointer(0),x->impl());
}
};
@@ -1,4 +1,4 @@
/* Copyright 2003-2006 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)
@@ -15,7 +15,9 @@
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <algorithm>
#include <boost/detail/allocator_utilities.hpp>
#include <boost/math/common_factor_rt.hpp>
#include <boost/multi_index/detail/prevent_eti.hpp>
#include <cstddef>
#include <functional>
@@ -25,42 +27,58 @@ namespace multi_index{
namespace detail{
template<typename Allocator>
struct random_access_index_node_impl
{
random_access_index_node_impl**& up(){return up_;}
random_access_index_node_impl** up()const{return up_;}
typedef typename prevent_eti<
Allocator,
typename boost::detail::allocator::rebind_to<
Allocator,random_access_index_node_impl
>::type
>::type::pointer pointer;
typedef typename prevent_eti<
Allocator,
typename boost::detail::allocator::rebind_to<
Allocator,random_access_index_node_impl
>::type
>::type::const_pointer const_pointer;
typedef typename prevent_eti<
Allocator,
typename boost::detail::allocator::rebind_to<
Allocator,pointer
>::type
>::type::pointer ptr_pointer;
ptr_pointer& up(){return up_;}
ptr_pointer up()const{return up_;}
/* interoperability with rnd_node_iterator */
static void increment(random_access_index_node_impl*& x)
static void increment(pointer& x)
{
x=*(x->up()+1);
}
static void decrement(random_access_index_node_impl*& x)
static void decrement(pointer& x)
{
x=*(x->up()-1);
}
static void advance(
random_access_index_node_impl*& x,std::ptrdiff_t n)
static void advance(pointer& 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)
static std::ptrdiff_t distance(pointer x,pointer y)
{
return y->up()-x->up();
}
/* algorithmic stuff */
static void relocate(
random_access_index_node_impl** pos,
random_access_index_node_impl** x)
static void relocate(ptr_pointer pos,ptr_pointer x)
{
random_access_index_node_impl* n=*x;
pointer n=*x;
if(x<pos){
extract(x,pos);
*(pos-1)=n;
@@ -77,12 +95,9 @@ struct random_access_index_node_impl
}
};
static void relocate(
random_access_index_node_impl** pos,
random_access_index_node_impl** first,
random_access_index_node_impl** last)
static void relocate(ptr_pointer pos,ptr_pointer first,ptr_pointer last)
{
random_access_index_node_impl** begin,**middle,**end;
ptr_pointer begin,middle,end;
if(pos<first){
begin=pos;
middle=first;
@@ -100,38 +115,36 @@ struct random_access_index_node_impl
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];
pointer tmp=begin[i];
for(std::ptrdiff_t j=i,k;;){
if(j<n_m)k=j+m;
else k=j-n_m;
if(k==i){
begin[j]=tmp;
begin[j]->up()=&begin[j];
*(begin+j)=tmp;
(*(begin+j))->up()=begin+j;
break;
}
else{
begin[j]=begin[k];
begin[j]->up()=&begin[j];
*(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];
*(begin+k)=tmp;
(*(begin+k))->up()=begin+k;
break;
}
else{
begin[k]=begin[j];
begin[k]->up()=&begin[k];
*(begin+k)=*(begin+j);
(*(begin+k))->up()=begin+k;
}
}
}
};
static void extract(
random_access_index_node_impl** x,
random_access_index_node_impl** pend)
static void extract(ptr_pointer x,ptr_pointer pend)
{
--pend;
while(x!=pend){
@@ -142,9 +155,7 @@ struct random_access_index_node_impl
}
static void transfer(
random_access_index_node_impl** pbegin0,
random_access_index_node_impl** pend0,
random_access_index_node_impl** pbegin1)
ptr_pointer pbegin0,ptr_pointer pend0,ptr_pointer pbegin1)
{
while(pbegin0!=pend0){
*pbegin1=*pbegin0++;
@@ -153,9 +164,7 @@ struct random_access_index_node_impl
}
}
static void reverse(
random_access_index_node_impl** pbegin,
random_access_index_node_impl** pend)
static void reverse(ptr_pointer pbegin,ptr_pointer pend)
{
std::ptrdiff_t d=(pend-pbegin)/2;
for(std::ptrdiff_t i=0;i<d;++i){
@@ -167,68 +176,100 @@ struct random_access_index_node_impl
}
private:
random_access_index_node_impl** up_;
ptr_pointer up_;
};
template<typename Super>
struct random_access_index_node_trampoline:random_access_index_node_impl{};
struct random_access_index_node_trampoline:
prevent_eti<
Super,
random_access_index_node_impl<
typename boost::detail::allocator::rebind_to<
typename Super::allocator_type,
void
>::type
>
>::type
{
typedef typename prevent_eti<
Super,
random_access_index_node_impl<
typename boost::detail::allocator::rebind_to<
typename Super::allocator_type,
void
>::type
>
>::type impl_type;
};
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();}
private:
typedef random_access_index_node_trampoline<Super> trampoline;
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);}
public:
typedef typename trampoline::impl_type impl_type;
typedef typename trampoline::pointer impl_pointer;
typedef typename trampoline::const_pointer const_impl_pointer;
typedef typename trampoline::ptr_pointer impl_ptr_pointer;
static random_access_index_node* from_impl(random_access_index_node_impl *x)
impl_ptr_pointer& up(){return trampoline::up();}
impl_ptr_pointer up()const{return trampoline::up();}
impl_pointer impl()
{
return static_cast<random_access_index_node*>(
static_cast<impl_type*>(x));
return static_cast<impl_pointer>(
static_cast<impl_type*>(static_cast<trampoline*>(this)));
}
static const random_access_index_node* from_impl(
const random_access_index_node_impl* x)
const_impl_pointer impl()const
{
return static_cast<const_impl_pointer>(
static_cast<const impl_type*>(static_cast<const trampoline*>(this)));
}
static random_access_index_node* from_impl(impl_pointer x)
{
return static_cast<random_access_index_node*>(
static_cast<trampoline*>(&*x));
}
static const random_access_index_node* from_impl(const_impl_pointer x)
{
return static_cast<const random_access_index_node*>(
static_cast<const impl_type*>(x));
static_cast<const trampoline*>(&*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);
impl_pointer xi=x->impl();
trampoline::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);
impl_pointer xi=x->impl();
trampoline::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);
impl_pointer xi=x->impl();
trampoline::advance(xi,n);
x=from_impl(xi);
}
static std::ptrdiff_t distance(
random_access_index_node* x,random_access_index_node* y)
{
return impl_type::distance(x->impl(),y->impl());
return trampoline::distance(x->impl(),y->impl());
}
private:
typedef random_access_index_node_trampoline<Super> impl_type;
};
} /* namespace multi_index::detail */
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
/* Copyright 2003-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)
@@ -34,10 +34,11 @@ Node* random_access_index_remove(
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Node))
{
typedef typename Node::value_type value_type;
typedef typename Node::impl_ptr_pointer impl_ptr_pointer;
random_access_index_node_impl** first=ptrs.begin(),
** res=first,
** last=ptrs.end();
impl_ptr_pointer first=ptrs.begin(),
res=first,
last=ptrs.end();
for(;first!=last;++first){
if(!pred(
const_cast<const value_type&>(Node::from_impl(*first)->value()))){
@@ -57,11 +58,12 @@ Node* random_access_index_unique(
random_access_index_ptr_array<Allocator>& ptrs,BinaryPredicate binary_pred
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Node))
{
typedef typename Node::value_type value_type;
typedef typename Node::value_type value_type;
typedef typename Node::impl_ptr_pointer impl_ptr_pointer;
random_access_index_node_impl** first=ptrs.begin(),
** res=first,
** last=ptrs.end();
impl_ptr_pointer first=ptrs.begin(),
res=first,
last=ptrs.end();
if(first!=last){
for(;++first!=last;){
if(!binary_pred(
@@ -84,17 +86,19 @@ 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_DEDUCED_TYPENAME Node::impl_ptr_pointer first1,Compare comp
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Node))
{
typedef typename Node::value_type value_type;
typedef typename Node::value_type value_type;
typedef typename Node::impl_pointer impl_pointer;
typedef typename Node::impl_ptr_pointer impl_ptr_pointer;
auto_space<random_access_index_node_impl*,Allocator> spc(al,ptrs.size());
auto_space<impl_pointer,Allocator> spc(al,ptrs.size());
random_access_index_node_impl** first0=ptrs.begin(),
** last0=first1,
** last1=ptrs.end(),
** out=spc.data();
impl_ptr_pointer first0=ptrs.begin(),
last0=first1,
last1=ptrs.end(),
out=spc.data();
while(first0!=last0&&first1!=last1){
if(comp(
const_cast<const value_type&>(Node::from_impl(*first1)->value()),
@@ -105,8 +109,8 @@ void random_access_index_inplace_merge(
*out++=*first0++;
}
}
std::copy(first0,last0,out);
std::copy(first1,last1,out);
std::copy(&*first0,&*last0,&*out);
std::copy(&*first1,&*last1,&*out);
first1=ptrs.begin();
out=spc.data();
@@ -124,13 +128,13 @@ void random_access_index_inplace_merge(
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>
typename Node::impl_pointer,
typename Node::impl_pointer,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
typename Node::impl_pointer x,typename Node::impl_pointer y)const
{
typedef typename Node::value_type value_type;
@@ -171,18 +175,20 @@ void random_access_index_sort(
*/
typedef typename Node::value_type value_type;
typedef typename Node::impl_pointer impl_pointer;
typedef typename Node::impl_ptr_pointer impl_ptr_pointer;
typedef random_access_index_sort_compare<
Node,Compare> ptr_compare;
random_access_index_node_impl** first=ptrs.begin();
random_access_index_node_impl** last=ptrs.end();
impl_ptr_pointer first=ptrs.begin();
impl_ptr_pointer last=ptrs.end();
auto_space<
random_access_index_node_impl*,
Allocator> spc(al,ptrs.size());
random_access_index_node_impl** buf=spc.data();
impl_pointer,
Allocator> spc(al,ptrs.size());
impl_ptr_pointer buf=spc.data();
std::copy(first,last,buf);
std::stable_sort(buf,buf+ptrs.size(),ptr_compare(comp));
std::copy(&*first,&*last,&*buf);
std::stable_sort(&*buf,&*buf+ptrs.size(),ptr_compare(comp));
while(first!=last){
*first=*buf++;
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
/* Copyright 2003-2007 Joaquín M López Muñoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
@@ -15,7 +15,9 @@
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <algorithm>
#include <boost/detail/allocator_utilities.hpp>
#include <boost/multi_index/detail/auto_space.hpp>
#include <boost/multi_index/detail/prevent_eti.hpp>
#include <boost/multi_index/detail/rnd_index_node.hpp>
#include <boost/noncopyable.hpp>
#include <cstddef>
@@ -31,8 +33,24 @@ namespace detail{
template<typename Allocator>
class random_access_index_ptr_array:private noncopyable
{
typedef typename prevent_eti<
Allocator,
random_access_index_node_impl<
typename boost::detail::allocator::rebind_to<
Allocator,
void
>::type
>
>::type node_impl_type;
public:
typedef random_access_index_node_impl* value_type;
typedef typename node_impl_type::pointer value_type;
typedef typename prevent_eti<
Allocator,
typename boost::detail::allocator::rebind_to<
Allocator,value_type
>::type
>::type::pointer pointer;
random_access_index_ptr_array(
const Allocator& al,value_type end_,std::size_t size):
@@ -58,15 +76,15 @@ public:
{
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());
node_impl_type::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];}
pointer begin()const{return ptrs();}
pointer end()const{return ptrs()+size_;}
pointer at(std::size_t n)const{return ptrs()+n;}
void push_back(value_type x)
{
@@ -79,7 +97,7 @@ public:
void erase(value_type x)
{
random_access_index_node_impl::extract(x->up(),end()+1);
node_impl_type::extract(x->up(),end()+1);
--size_;
}
@@ -102,7 +120,7 @@ private:
std::size_t capacity_;
auto_space<value_type,Allocator> spc;
value_type* ptrs()const
pointer ptrs()const
{
return spc.data();
}
@@ -1,4 +1,4 @@
/* Copyright 2003-2006 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)
@@ -47,18 +47,6 @@ public:
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);
@@ -83,12 +71,6 @@ public:
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.
@@ -124,6 +106,30 @@ private:
Node* node;
};
template<typename Node,typename Derived>
bool operator==(
const rnd_node_iterator<Node,Derived>& x,
const rnd_node_iterator<Node,Derived>& y)
{
return x.get_node()==y.get_node();
}
template<typename Node,typename Derived>
bool operator<(
const rnd_node_iterator<Node,Derived>& x,
const rnd_node_iterator<Node,Derived>& y)
{
return Node::distance(x.get_node(),y.get_node())>0;
}
template<typename Node,typename Derived>
std::ptrdiff_t operator-(
const rnd_node_iterator<Node,Derived>& x,
const rnd_node_iterator<Node,Derived>& y)
{
return Node::distance(y.get_node(),x.get_node());
}
} /* namespace multi_index::detail */
} /* namespace multi_index */
@@ -1,4 +1,4 @@
/* Copyright 2003-2006 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)
@@ -13,7 +13,10 @@
#pragma once
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <algorithm>
#include <boost/detail/allocator_utilities.hpp>
#include <boost/multi_index/detail/prevent_eti.hpp>
namespace boost{
@@ -23,36 +26,48 @@ namespace detail{
/* doubly-linked node for use by sequenced_index */
template<typename Allocator>
struct sequenced_index_node_impl
{
sequenced_index_node_impl*& prior(){return prior_;}
sequenced_index_node_impl* prior()const{return prior_;}
sequenced_index_node_impl*& next(){return next_;}
sequenced_index_node_impl* next()const{return next_;}
typedef typename prevent_eti<
Allocator,
typename boost::detail::allocator::rebind_to<
Allocator,sequenced_index_node_impl
>::type
>::type::pointer pointer;
typedef typename prevent_eti<
Allocator,
typename boost::detail::allocator::rebind_to<
Allocator,sequenced_index_node_impl
>::type
>::type::const_pointer const_pointer;
pointer& prior(){return prior_;}
pointer prior()const{return prior_;}
pointer& next(){return next_;}
pointer next()const{return next_;}
/* 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();}
static void increment(pointer& x){x=x->next();}
static void decrement(pointer& x){x=x->prior();}
/* algorithmic stuff */
static void link(
sequenced_index_node_impl* x,sequenced_index_node_impl* header)
static void link(pointer x,pointer header)
{
x->prior()=header->prior();
x->next()=header;
x->prior()->next()=x->next()->prior()=x;
};
static void unlink(sequenced_index_node_impl* x)
static void unlink(pointer x)
{
x->prior()->next()=x->next();
x->next()->prior()=x->prior();
}
static void relink(
sequenced_index_node_impl* position,sequenced_index_node_impl* x)
static void relink(pointer position,pointer x)
{
unlink(x);
x->prior()=position->prior();
@@ -60,14 +75,12 @@ struct sequenced_index_node_impl
x->prior()->next()=x->next()->prior()=x;
}
static void relink(
sequenced_index_node_impl* position,
sequenced_index_node_impl* x,sequenced_index_node_impl* y)
static void relink(pointer position,pointer x,pointer y)
{
/* position is assumed not to be in [x,y) */
if(x!=y){
sequenced_index_node_impl* z=y->prior();
pointer z=y->prior();
x->prior()->next()=y;
y->prior()=x->prior();
x->prior()=position->prior();
@@ -77,17 +90,17 @@ struct sequenced_index_node_impl
}
}
static void reverse(sequenced_index_node_impl* header)
static void reverse(pointer header)
{
sequenced_index_node_impl* x=header;
pointer x=header;
do{
sequenced_index_node_impl* y=x->next();
pointer y=x->next();
std::swap(x->prior(),x->next());
x=y;
}while(x!=header);
}
static void swap(sequenced_index_node_impl* x,sequenced_index_node_impl* y)
static void swap(pointer x,pointer y)
{
/* This swap function does not exchange the header nodes,
* but rather their pointers. This is *not* used for implementing
@@ -117,53 +130,88 @@ struct sequenced_index_node_impl
}
private:
sequenced_index_node_impl* prior_;
sequenced_index_node_impl* next_;
pointer prior_;
pointer next_;
};
template<typename Super>
struct sequenced_index_node_trampoline:sequenced_index_node_impl{};
struct sequenced_index_node_trampoline:
prevent_eti<
Super,
sequenced_index_node_impl<
typename boost::detail::allocator::rebind_to<
typename Super::allocator_type,
void
>::type
>
>::type
{
typedef typename prevent_eti<
Super,
sequenced_index_node_impl<
typename boost::detail::allocator::rebind_to<
typename Super::allocator_type,
void
>::type
>
>::type impl_type;
};
template<typename Super>
struct sequenced_index_node:Super,sequenced_index_node_trampoline<Super>
{
sequenced_index_node_impl*& prior(){return impl_type::prior();}
sequenced_index_node_impl* 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();}
private:
typedef sequenced_index_node_trampoline<Super> trampoline;
sequenced_index_node_impl* impl()
{return static_cast<impl_type*>(this);}
const sequenced_index_node_impl* impl()const
{return static_cast<const impl_type*>(this);}
public:
typedef typename trampoline::impl_type impl_type;
typedef typename trampoline::pointer impl_pointer;
typedef typename trampoline::const_pointer const_impl_pointer;
static sequenced_index_node* from_impl(sequenced_index_node_impl *x)
{return static_cast<sequenced_index_node*>(static_cast<impl_type*>(x));}
static const sequenced_index_node* from_impl(
const sequenced_index_node_impl* x)
impl_pointer& prior(){return trampoline::prior();}
impl_pointer prior()const{return trampoline::prior();}
impl_pointer& next(){return trampoline::next();}
impl_pointer next()const{return trampoline::next();}
impl_pointer impl()
{
return static_cast<impl_pointer>(
static_cast<impl_type*>(static_cast<trampoline*>(this)));
}
const_impl_pointer impl()const
{
return static_cast<const_impl_pointer>(
static_cast<const impl_type*>(static_cast<const trampoline*>(this)));
}
static sequenced_index_node* from_impl(impl_pointer x)
{
return static_cast<sequenced_index_node*>(
static_cast<trampoline*>(&*x));
}
static const sequenced_index_node* from_impl(const_impl_pointer x)
{
return static_cast<const sequenced_index_node*>(
static_cast<const impl_type*>(x));
static_cast<const trampoline*>(&*x));
}
/* interoperability with bidir_node_iterator */
static void increment(sequenced_index_node*& x)
{
sequenced_index_node_impl* xi=x->impl();
impl_type::increment(xi);
impl_pointer xi=x->impl();
trampoline::increment(xi);
x=from_impl(xi);
}
static void decrement(sequenced_index_node*& x)
{
sequenced_index_node_impl* xi=x->impl();
impl_type::decrement(xi);
impl_pointer xi=x->impl();
trampoline::decrement(xi);
x=from_impl(xi);
}
private:
typedef sequenced_index_node_trampoline<Super> impl_type;
};
} /* namespace multi_index::detail */
@@ -1,4 +1,4 @@
/* Copyright 2003-2006 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)
@@ -77,23 +77,28 @@ void sequenced_index_merge(SequencedIndex& x,SequencedIndex& y,Compare comp)
template<typename Node,typename Compare>
void sequenced_index_collate(
sequenced_index_node_impl* x,sequenced_index_node_impl* y,Compare comp
BOOST_DEDUCED_TYPENAME Node::impl_type* x,
BOOST_DEDUCED_TYPENAME Node::impl_type* y,
Compare comp
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Node))
{
sequenced_index_node_impl* first0=x->next();
sequenced_index_node_impl* last0=x;
sequenced_index_node_impl* first1=y->next();
sequenced_index_node_impl* last1=y;
typedef typename Node::impl_type impl_type;
typedef typename Node::impl_pointer impl_pointer;
impl_pointer first0=x->next();
impl_pointer last0=x;
impl_pointer first1=y->next();
impl_pointer last1=y;
while(first0!=last0&&first1!=last1){
if(comp(
Node::from_impl(first1)->value(),Node::from_impl(first0)->value())){
sequenced_index_node_impl* tmp=first1->next();
sequenced_index_node_impl::relink(first0,first1);
impl_pointer tmp=first1->next();
impl_type::relink(first0,first1);
first1=tmp;
}
else first0=first0->next();
}
sequenced_index_node_impl::relink(last0,first1,last1);
impl_type::relink(last0,first1,last1);
}
/* Some versions of CGG require a bogus typename in counter_spc
@@ -122,54 +127,64 @@ void sequenced_index_sort(Node* header,Compare comp)
if(header->next()==header->impl()||
header->next()->next()==header->impl())return;
aligned_storage<
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*>(static_cast<void*>(&carry_spc));
aligned_storage<
typedef typename Node::impl_type impl_type;
typedef typename Node::impl_pointer impl_pointer;
typedef typename aligned_storage<
sizeof(impl_type),
alignment_of<impl_type>::value
>::type carry_spc_type;
carry_spc_type carry_spc;
impl_type& carry=
*static_cast<impl_type*>(static_cast<void*>(&carry_spc));
typedef typename aligned_storage<
sizeof(
sequenced_index_node_impl
impl_type
[sequenced_index_sort_max_fill]),
alignment_of<
sequenced_index_node_impl
impl_type
[sequenced_index_sort_max_fill]
>::value
>::type counter_spc;
sequenced_index_node_impl* counter=
static_cast<sequenced_index_node_impl*>(static_cast<void*>(&counter_spc));
std::size_t fill=0;
>::type counter_spc_type;
counter_spc_type counter_spc;
impl_type* counter=
static_cast<impl_type*>(static_cast<void*>(&counter_spc));
std::size_t fill=0;
carry.prior()=carry.next()=&carry;
counter[0].prior()=counter[0].next()=&counter[0];
carry.prior()=carry.next()=static_cast<impl_pointer>(&carry);
counter[0].prior()=counter[0].next()=static_cast<impl_pointer>(&counter[0]);
BOOST_TRY{
while(header->next()!=header->impl()){
sequenced_index_node_impl::relink(carry.next(),header->next());
impl_type::relink(carry.next(),header->next());
std::size_t i=0;
while(i<fill&&counter[i].next()!=&counter[i]){
while(i<fill&&counter[i].next()!=static_cast<impl_pointer>(&counter[i])){
sequenced_index_collate<Node>(&carry,&counter[i++],comp);
}
sequenced_index_node_impl::swap(&carry,&counter[i]);
impl_type::swap(
static_cast<impl_pointer>(&carry),
static_cast<impl_pointer>(&counter[i]));
if(i==fill){
++fill;
counter[fill].prior()=counter[fill].next()=&counter[fill];
counter[fill].prior()=counter[fill].next()=
static_cast<impl_pointer>(&counter[fill]);
}
}
for(std::size_t i=1;i<fill;++i){
sequenced_index_collate<Node>(&counter[i],&counter[i-1],comp);
}
sequenced_index_node_impl::swap(header->impl(),&counter[fill-1]);
impl_type::swap(
header->impl(),static_cast<impl_pointer>(&counter[fill-1]));
}
BOOST_CATCH(...)
{
sequenced_index_node_impl::relink(header->impl(),carry.next(),&carry);
impl_type::relink(
header->impl(),carry.next(),static_cast<impl_pointer>(&carry));
for(std::size_t i=0;i<=fill;++i){
sequenced_index_node_impl::relink(
header->impl(),counter[i].next(),&counter[i]);
impl_type::relink(
header->impl(),counter[i].next(),
static_cast<impl_pointer>(&counter[i]));
}
BOOST_RETHROW;
}
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
/* Copyright 2003-2007 Joaquín M López Muñoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
@@ -44,13 +44,20 @@ template<>struct uintptr_candidates<3> {typedef unsigned long long type;};
template<>struct uintptr_candidates<3> {typedef unsigned int type;};
#endif
#if defined(BOOST_HAS_MS_INT64)
template<>struct uintptr_candidates<4> {typedef unsigned __int64 type;};
#else
template<>struct uintptr_candidates<4> {typedef unsigned int type;};
#endif
struct uintptr_aux
{
BOOST_STATIC_CONSTANT(int,index=
sizeof(void*)==sizeof(uintptr_candidates<0>::type)?0:
sizeof(void*)==sizeof(uintptr_candidates<1>::type)?1:
sizeof(void*)==sizeof(uintptr_candidates<2>::type)?2:
sizeof(void*)==sizeof(uintptr_candidates<3>::type)?3:-1);
sizeof(void*)==sizeof(uintptr_candidates<3>::type)?3:
sizeof(void*)==sizeof(uintptr_candidates<4>::type)?4:-1);
BOOST_STATIC_CONSTANT(bool,has_uintptr_type=(index>=0));
+46 -15
View File
@@ -1,4 +1,4 @@
/* Copyright 2003-2006 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)
@@ -22,28 +22,59 @@ namespace multi_index{
/* dummy type and variable for use in ordered_index::range() */
namespace detail{
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
/* The default branch actually works for MSVC 6.0, but seems like
* this implementation of unbounded improves the performance of ordered
* indices! This behavior is hard to explain and probably a test artifact,
* but it does not hurt to have the workaround anyway.
*/
struct unbounded_type{};
} /* namespace multi_index::detail */
namespace detail{struct unbounded_type{};}
namespace{
#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 */
#else
/* ODR-abiding technique shown at the example attached to
* http://lists.boost.org/Archives/boost/2006/07/108355.php
*/
namespace detail{class unbounded_helper;}
detail::unbounded_helper unbounded(detail::unbounded_helper);
namespace detail{
class unbounded_helper
{
unbounded_helper(){}
unbounded_helper(const unbounded_helper&){}
friend unbounded_helper multi_index::unbounded(unbounded_helper);
};
typedef unbounded_helper (*unbounded_type)(unbounded_helper);
} /* namespace multi_index::detail */
inline detail::unbounded_helper unbounded(detail::unbounded_helper)
{
return detail::unbounded_helper();
}
#endif
/* tags used in the implementation of range */
namespace detail{
struct none_unbounded_tag{};
struct lower_unbounded_tag{};
struct upper_unbounded_tag{};
struct both_unbounded_tag{};
} /* namespace multi_index::detail */
} /* namespace multi_index */
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
/* Copyright 2003-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)
@@ -26,7 +26,8 @@ namespace detail{
template<typename Value,typename KeyFromValue,typename Compare>
struct value_comparison:std::binary_function<Value,Value,bool>
{
value_comparison(KeyFromValue key_=KeyFromValue(),Compare comp_=Compare()):
value_comparison(
const KeyFromValue& key_=KeyFromValue(),const Compare& comp_=Compare()):
key(key_),comp(comp_)
{
}
+188
View File
@@ -0,0 +1,188 @@
/* Copyright 2003-2007 Joaquín M López Muñoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/multi_index for library home page.
*/
#ifndef BOOST_MULTI_INDEX_GLOBAL_FUN_HPP
#define BOOST_MULTI_INDEX_GLOBAL_FUN_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/mpl/if.hpp>
#include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/is_reference.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/utility/enable_if.hpp>
#if !defined(BOOST_NO_SFINAE)
#include <boost/type_traits/is_convertible.hpp>
#endif
namespace boost{
template<class T> class reference_wrapper; /* fwd decl. */
namespace multi_index{
namespace detail{
/* global_fun is a read-only key extractor from Value based on a given global
* (or static member) function with signature:
*
* Type f([const] Value [&]);
*
* Additionally, global_fun and const_global_fun are overloaded to support
* referece_wrappers of Value and "chained pointers" to Value's. By chained
* pointer to T we mean a type P such that, given a p of Type P
* *...n...*x is convertible to T&, for some n>=1.
* Examples of chained pointers are raw and smart pointers, iterators and
* arbitrary combinations of these (vg. T** or auto_ptr<T*>.)
*/
/* NB. Some overloads of operator() have an extra dummy parameter int=0.
* This disambiguator serves several purposes:
* - Without it, MSVC++ 6.0 incorrectly regards some overloads as
* specializations of a previous member function template.
* - MSVC++ 6.0/7.0 seem to incorrectly treat some different memfuns
* as if they have the same signature.
* - If remove_const is broken due to lack of PTS, int=0 avoids the
* declaration of memfuns with identical signature.
*/
template<class Value,typename Type,Type (*PtrToFunction)(Value)>
struct const_ref_global_fun_base
{
typedef typename remove_reference<Type>::type result_type;
template<typename ChainedPtr>
#if !defined(BOOST_NO_SFINAE)
typename disable_if<
is_convertible<const ChainedPtr&,Value>,Type>::type
#else
Type
#endif
operator()(const ChainedPtr& x)const
{
return operator()(*x);
}
Type operator()(Value x)const
{
return PtrToFunction(x);
}
Type operator()(
const reference_wrapper<
typename remove_reference<Value>::type>& x)const
{
return operator()(x.get());
}
Type operator()(
const reference_wrapper<
typename remove_const<
typename remove_reference<Value>::type>::type>& x,int=0)const
{
return operator()(x.get());
}
};
template<class Value,typename Type,Type (*PtrToFunction)(Value)>
struct non_const_ref_global_fun_base
{
typedef typename remove_reference<Type>::type result_type;
template<typename ChainedPtr>
#if !defined(BOOST_NO_SFINAE)
typename disable_if<
is_convertible<ChainedPtr&,Value>,Type>::type
#else
Type
#endif
operator()(const ChainedPtr& x)const
{
return operator()(*x);
}
Type operator()(Value x)const
{
return PtrToFunction(x);
}
Type operator()(
const reference_wrapper<
typename remove_reference<Value>::type>& x)const
{
return operator()(x.get());
}
};
template<class Value,typename Type,Type (*PtrToFunction)(Value)>
struct non_ref_global_fun_base
{
typedef typename remove_reference<Type>::type result_type;
template<typename ChainedPtr>
#if !defined(BOOST_NO_SFINAE)
typename disable_if<
is_convertible<const ChainedPtr&,const Value&>,Type>::type
#else
Type
#endif
operator()(const ChainedPtr& x)const
{
return operator()(*x);
}
Type operator()(const Value& x)const
{
return PtrToFunction(x);
}
Type operator()(const reference_wrapper<const Value>& x)const
{
return operator()(x.get());
}
Type operator()(
const reference_wrapper<
typename remove_const<Value>::type>& x,int=0)const
{
return operator()(x.get());
}
};
} /* namespace multi_index::detail */
template<class Value,typename Type,Type (*PtrToFunction)(Value)>
struct global_fun:
mpl::if_c<
is_reference<Value>::value,
typename mpl::if_c<
is_const<typename remove_reference<Value>::type>::value,
detail::const_ref_global_fun_base<Value,Type,PtrToFunction>,
detail::non_const_ref_global_fun_base<Value,Type,PtrToFunction>
>::type,
detail::non_ref_global_fun_base<Value,Type,PtrToFunction>
>::type
{
};
} /* namespace multi_index */
} /* namespace boost */
#endif
+155 -63
View File
@@ -25,6 +25,7 @@
#include <boost/multi_index/detail/auto_space.hpp>
#include <boost/multi_index/detail/bucket_array.hpp>
#include <boost/multi_index/detail/hash_index_iterator.hpp>
#include <boost/multi_index/detail/index_node_base.hpp>
#include <boost/multi_index/detail/modify_key_adaptor.hpp>
#include <boost/multi_index/detail/safe_ctr_proxy.hpp>
#include <boost/multi_index/detail/safe_mode.hpp>
@@ -100,6 +101,10 @@ class hashed_index:
protected:
typedef hashed_index_node<
typename super::node_type> node_type;
private:
typedef typename node_type::impl_type node_impl_type;
typedef typename node_impl_type::pointer node_impl_pointer;
typedef bucket_array<
typename super::final_allocator_type> bucket_array_type;
@@ -172,8 +177,7 @@ private:
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
typedef safe_ctr_proxy_impl<
hashed_index_iterator<
node_type,
bucket_array_type>,
node_type,bucket_array_type>,
hashed_index> safe_super;
#else
typedef safe_mode::safe_container<
@@ -227,6 +231,19 @@ public:
iterator end(){return make_iterator(header());}
const_iterator end()const{return make_iterator(header());}
const_iterator cbegin()const{return begin();}
const_iterator cend()const{return end();}
iterator iterator_to(const value_type& x)
{
return make_iterator(node_from_value<node_type>(&x));
}
const_iterator iterator_to(const value_type& x)const
{
return make_iterator(node_from_value<node_type>(&x));
}
/* modifiers */
std::pair<iterator,bool> insert(value_param_type x)
@@ -268,15 +285,15 @@ public:
{
BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
size_type s=0;
std::size_t buc=buckets.position(hash(k));
hashed_index_node_impl* x=buckets.at(buc);
hashed_index_node_impl* y=x->next();
size_type s=0;
std::size_t buc=buckets.position(hash(k));
node_impl_pointer x=buckets.at(buc);
node_impl_pointer y=x->next();
while(y!=x){
if(eq(k,key(node_type::from_impl(y)->value()))){
bool b;
do{
hashed_index_node_impl* z=y->next();
node_impl_pointer z=y->next();
b=z!=x&&eq(
key(node_type::from_impl(y)->value()),
key(node_type::from_impl(z)->value()));
@@ -337,6 +354,27 @@ public:
mod,static_cast<final_node_type*>(position.get_node()));
}
template<typename Modifier,typename Rollback>
bool modify(iterator position,Modifier mod,Rollback back)
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
/* MSVC++ 6.0 optimizer on safe mode code chokes if this
* this is not added. Left it for all compilers as it does no
* harm.
*/
position.detach();
#endif
return this->final_modify_(
mod,back,static_cast<final_node_type*>(position.get_node()));
}
template<typename Modifier>
bool modify_key(iterator position,Modifier mod)
{
@@ -348,6 +386,19 @@ public:
position,modify_key_adaptor<Modifier,value_type,KeyFromValue>(mod,key));
}
template<typename Modifier,typename Rollback>
bool modify_key(iterator position,Modifier mod,Rollback back)
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
return modify(
position,
modify_key_adaptor<Modifier,value_type,KeyFromValue>(mod,key),
modify_key_adaptor<Modifier,value_type,KeyFromValue>(back,key));
}
void clear()
{
BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
@@ -385,9 +436,9 @@ public:
const CompatibleKey& k,
const CompatibleHash& hash,const CompatiblePred& eq)const
{
std::size_t buc=buckets.position(hash(k));
hashed_index_node_impl* x=buckets.at(buc);
hashed_index_node_impl* y=x->next();
std::size_t buc=buckets.position(hash(k));
node_impl_pointer x=buckets.at(buc);
node_impl_pointer y=x->next();
while(y!=x){
if(eq(k,key(node_type::from_impl(y)->value()))){
return make_iterator(node_type::from_impl(y));
@@ -410,10 +461,10 @@ public:
const CompatibleKey& k,
const CompatibleHash& hash,const CompatiblePred& eq)const
{
size_type res=0;
std::size_t buc=buckets.position(hash(k));
hashed_index_node_impl* x=buckets.at(buc);
hashed_index_node_impl* y=x->next();
size_type res=0;
std::size_t buc=buckets.position(hash(k));
node_impl_pointer x=buckets.at(buc);
node_impl_pointer y=x->next();
while(y!=x){
if(eq(k,key(node_type::from_impl(y)->value()))){
do{
@@ -440,12 +491,12 @@ public:
const CompatibleKey& k,
const CompatibleHash& hash,const CompatiblePred& eq)const
{
std::size_t buc=buckets.position(hash(k));
hashed_index_node_impl* x=buckets.at(buc);
hashed_index_node_impl* y=x->next();
std::size_t buc=buckets.position(hash(k));
node_impl_pointer x=buckets.at(buc);
node_impl_pointer y=x->next();
while(y!=x){
if(eq(k,key(node_type::from_impl(y)->value()))){
hashed_index_node_impl* y0=y;
node_impl_pointer y0=y;
do{
y=y->next();
}while(y!=x&&eq(k,key(node_type::from_impl(y)->value())));
@@ -471,9 +522,9 @@ public:
size_type bucket_size(size_type n)const
{
size_type res=0;
hashed_index_node_impl* x=buckets.at(n);
hashed_index_node_impl* y=x->next();
size_type res=0;
node_impl_pointer x=buckets.at(n);
node_impl_pointer y=x->next();
while(y!=x){
++res;
y=y->next();
@@ -493,8 +544,8 @@ public:
const_local_iterator begin(size_type n)const
{
hashed_index_node_impl* x=buckets.at(n);
hashed_index_node_impl* y=x->next();
node_impl_pointer x=buckets.at(n);
node_impl_pointer y=x->next();
if(y==x)return end();
return make_iterator(node_type::from_impl(y));
}
@@ -506,7 +557,7 @@ public:
const_local_iterator end(size_type n)const
{
hashed_index_node_impl* x=buckets.at(n);
node_impl_pointer x=buckets.at(n);
if(x==x->next())return end();
do{
++x;
@@ -514,6 +565,19 @@ public:
return make_iterator(node_type::from_impl(x->next()));
}
const_local_iterator cbegin(size_type n)const{return begin(n);}
const_local_iterator cend(size_type n)const{return end(n);}
local_iterator local_iterator_to(const value_type& x)
{
return make_iterator(node_from_value<node_type>(&x));
}
const_local_iterator local_iterator_to(const value_type& x)const
{
return make_iterator(node_from_value<node_type>(&x));
}
/* hash policy */
float load_factor()const{return static_cast<float>(size())/bucket_count();}
@@ -602,13 +666,13 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,
const copy_map_type& map)
{
for(hashed_index_node_impl* begin_org=x.buckets.begin(),
* begin_cpy=buckets.begin(),
* end_org=x.buckets.end();
for(node_impl_pointer begin_org=x.buckets.begin(),
begin_cpy=buckets.begin(),
end_org=x.buckets.end();
begin_org!=end_org;++begin_org,++begin_cpy){
hashed_index_node_impl* next_org=begin_org->next();
hashed_index_node_impl* cpy=begin_cpy;
node_impl_pointer next_org=begin_org->next();
node_impl_pointer cpy=begin_cpy;
while(next_org!=begin_org){
cpy->next()=
static_cast<node_type*>(
@@ -628,8 +692,8 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
{
reserve(size()+1);
std::size_t buc=find_bucket(v);
hashed_index_node_impl* pos=buckets.at(buc);
std::size_t buc=find_bucket(v);
node_impl_pointer pos=buckets.at(buc);
if(!link_point(v,pos,Category()))return node_type::from_impl(pos);
node_type* res=static_cast<node_type*>(super::insert_(v,x));
@@ -644,8 +708,8 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
{
reserve(size()+1);
std::size_t buc=find_bucket(v);
hashed_index_node_impl* pos=buckets.at(buc);
std::size_t buc=find_bucket(v);
node_impl_pointer pos=buckets.at(buc);
if(!link_point(v,pos,Category()))return node_type::from_impl(pos);
node_type* res=static_cast<node_type*>(super::insert_(v,position,x));
@@ -669,11 +733,11 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
void delete_all_nodes_()
{
for(hashed_index_node_impl* x=buckets.begin(),*x_end=buckets.end();
for(node_impl_pointer x=buckets.begin(),x_end=buckets.end();
x!=x_end;++x){
hashed_index_node_impl* y=x->next();
node_impl_pointer y=x->next();
while(y!=x){
hashed_index_node_impl* z=y->next();
node_impl_pointer z=y->next();
this->final_delete_node_(
static_cast<final_node_type*>(node_type::from_impl(y)));
y=z;
@@ -716,12 +780,12 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
return super::replace_(v,x);
}
hashed_index_node_impl* y=prev(x);
node_impl_pointer y=prev(x);
unlink_next(y);
BOOST_TRY{
std::size_t buc=find_bucket(v);
hashed_index_node_impl* pos=buckets.at(buc);
std::size_t buc=find_bucket(v);
node_impl_pointer pos=buckets.at(buc);
if(link_point(v,pos,Category())&&super::replace_(v,x)){
link(x,pos);
if(first_bucket>buc){
@@ -746,8 +810,8 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
{
unlink(x);
std::size_t buc;
hashed_index_node_impl* pos;
std::size_t buc;
node_impl_pointer pos;
BOOST_TRY
{
buc=find_bucket(x->value());
@@ -806,6 +870,34 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
BOOST_CATCH_END
}
bool modify_rollback_(node_type* x)
{
node_impl_pointer y=prev(x);
unlink_next(y);
BOOST_TRY{
std::size_t buc=find_bucket(x->value());
node_impl_pointer pos=buckets.at(buc);
if(link_point(x->value(),pos,Category())&&super::modify_rollback_(x)){
link(x,pos);
if(first_bucket>buc){
first_bucket=buc;
}
else if(first_bucket<buc){
first_bucket=buckets.first_nonempty(first_bucket);
}
return true;
}
link(x,y);
return false;
}
BOOST_CATCH(...){
link(x,y);
BOOST_RETHROW;
}
BOOST_CATCH_END
}
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
/* serialization */
@@ -872,9 +964,9 @@ private:
}
bool link_point(
value_param_type v,hashed_index_node_impl*& pos,hashed_unique_tag)
value_param_type v,node_impl_pointer& pos,hashed_unique_tag)
{
hashed_index_node_impl* x=pos->next();
node_impl_pointer x=pos->next();
while(x!=pos){
if(eq(key(v),key(node_type::from_impl(x)->value()))){
pos=x;
@@ -886,10 +978,10 @@ private:
}
bool link_point(
value_param_type v,hashed_index_node_impl*& pos,hashed_non_unique_tag)
value_param_type v,node_impl_pointer& pos,hashed_non_unique_tag)
{
hashed_index_node_impl* prev=pos;
hashed_index_node_impl* x=pos->next();
node_impl_pointer prev=pos;
node_impl_pointer x=pos->next();
while(x!=pos){
if(eq(key(v),key(node_type::from_impl(x)->value()))){
pos=prev;
@@ -901,29 +993,29 @@ private:
return true;
}
void link(node_type* x,hashed_index_node_impl* pos)
void link(node_type* x,node_impl_pointer pos)
{
hashed_index_node_impl::link(x->impl(),pos);
node_impl_type::link(x->impl(),pos);
};
void link(hashed_index_node_impl* x,hashed_index_node_impl* pos)
void link(node_impl_pointer x,node_impl_pointer pos)
{
hashed_index_node_impl::link(x,pos);
node_impl_type::link(x,pos);
};
void unlink(node_type* x)
{
hashed_index_node_impl::unlink(x->impl());
node_impl_type::unlink(x->impl());
};
static hashed_index_node_impl* prev(node_type* x)
static node_impl_pointer prev(node_type* x)
{
return hashed_index_node_impl::prev(x->impl());
return node_impl_type::prev(x->impl());
}
static void unlink_next(hashed_index_node_impl* x)
static void unlink_next(node_impl_pointer x)
{
hashed_index_node_impl::unlink_next(x);
node_impl_type::unlink_next(x);
}
void calculate_max_load()
@@ -949,10 +1041,10 @@ private:
auto_space<std::size_t,allocator_type> hashes(get_allocator(),size());
std::size_t i=0;
hashed_index_node_impl* x=buckets.begin();
hashed_index_node_impl* x_end=buckets.end();
node_impl_pointer x=buckets.begin();
node_impl_pointer x_end=buckets.end();
for(;x!=x_end;++x){
hashed_index_node_impl* y=x->next();
node_impl_pointer y=x->next();
while(y!=x){
hashes.data()[i++]=hash(key(node_type::from_impl(y)->value()));
y=y->next();
@@ -962,11 +1054,11 @@ private:
i=0;
x=buckets.begin();
for(;x!=x_end;++x){
hashed_index_node_impl* y=x->next();
node_impl_pointer y=x->next();
while(y!=x){
hashed_index_node_impl* z=y->next();
std::size_t buc1=buckets1.position(hashes.data()[i++]);
hashed_index_node_impl* x1=buckets1.at(buc1);
node_impl_pointer z=y->next();
std::size_t buc1=buckets1.position(hashes.data()[i++]);
node_impl_pointer x1=buckets1.at(buc1);
link(y,x1);
y=z;
}
@@ -1014,7 +1106,7 @@ void swap(
} /* namespace multi_index::detail */
/* sequenced index specifiers */
/* hashed index specifiers */
template<typename Arg1,typename Arg2,typename Arg3,typename Arg4>
struct hashed_unique
+3 -3
View File
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaquín M López Muñoz.
/* Copyright 2003-2007 Joaquín M López Muñoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
@@ -6,8 +6,8 @@
* See http://www.boost.org/libs/multi_index for library home page.
*/
#ifndef BOOST_MULTI_INDEX_IDENTITY_HPP
#define BOOST_MULTI_INDEX_IDENTITY_HPP
#ifndef BOOST_MULTI_INDEX_IDENTITY_FWD_HPP
#define BOOST_MULTI_INDEX_IDENTITY_FWD_HPP
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
#pragma once
+2 -1
View File
@@ -1,4 +1,4 @@
/* Copyright 2003-2005 Joaqu M Lez Muz.
/* 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)
@@ -15,6 +15,7 @@
#include <boost/multi_index/composite_key.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/global_fun.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/mem_fun.hpp>
+7 -17
View File
@@ -1,4 +1,4 @@
/* Copyright 2003-2006 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)
@@ -39,16 +39,6 @@ namespace multi_index{
* arbitrary combinations of these (vg. T** or auto_ptr<T*>.)
*/
/* NB. Some overloads of operator() have an extra dummy parameter int=0.
* This disambiguator serves several purposes:
* - Without it, MSVC++ 6.0 incorrectly regards some overloads as
* specializations of a previous member function template.
* - MSVC++ 6.0/7.0 seem to incorrectly treat some different memfuns
* as if they have the same signature.
* - If remove_const is broken due to lack of PTS, int=0 avoids the
* declaration of memfuns with identical signature.
*/
template<class Class,typename Type,Type (Class::*PtrToMemberFunction)()const>
struct const_mem_fun
{
@@ -78,7 +68,7 @@ struct const_mem_fun
return operator()(x.get());
}
Type operator()(const reference_wrapper<Class>& x,int=0)const
Type operator()(const reference_wrapper<Class>& x)const
{
return operator()(x.get());
}
@@ -115,9 +105,9 @@ struct mem_fun
};
/* MSVC++ 6.0 has problems with const member functions as non-type template
* parameters, somehow it takes them as non-const. mem_fun_explicit workarounds
* this defficiency by accepting an extra type parameter that specifies the
* signature of he member function. The workaround was found at:
* parameters, somehow it takes them as non-const. const_mem_fun_explicit
* workarounds this deficiency by accepting an extra type parameter that
* specifies the signature of the member function. The workaround was found at:
* Daniel, C.:"Re: weird typedef problem in VC",
* news:microsoft.public.vc.language, 21st nov 2002,
* http://groups.google.com/groups?
@@ -155,7 +145,7 @@ struct const_mem_fun_explicit
return operator()(x.get());
}
Type operator()(const reference_wrapper<Class>& x,int=0)const
Type operator()(const reference_wrapper<Class>& x)const
{
return operator()(x.get());
}
@@ -194,7 +184,7 @@ struct mem_fun_explicit
};
/* BOOST_MULTI_INDEX_CONST_MEM_FUN and BOOST_MULTI_INDEX_MEM_FUN resolve to
* mem_fun_explicit for MSVC++ 6.0 and to [const_]mem_fun otherwise.
* [const_]mem_fun_explicit for MSVC++ 6.0 and to [const_]mem_fun otherwise.
*/
#if defined(BOOST_MSVC)&&(BOOST_MSVC<1300)
+232 -81
View File
@@ -46,9 +46,11 @@
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/iterator/reverse_iterator.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/push_front.hpp>
#include <boost/multi_index/detail/access_specifier.hpp>
#include <boost/multi_index/detail/bidir_node_iterator.hpp>
#include <boost/multi_index/detail/index_node_base.hpp>
#include <boost/multi_index/detail/modify_key_adaptor.hpp>
#include <boost/multi_index/detail/ord_index_node.hpp>
#include <boost/multi_index/detail/ord_index_ops.hpp>
@@ -60,6 +62,7 @@
#include <boost/multi_index/ordered_index_fwd.hpp>
#include <boost/ref.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/type_traits/is_same.hpp>
#include <utility>
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
@@ -130,6 +133,10 @@ protected:
typedef ordered_index_node<
typename super::node_type> node_type;
private:
typedef typename node_type::impl_type node_impl_type;
typedef typename node_impl_type::pointer node_impl_pointer;
public:
/* types */
@@ -237,7 +244,21 @@ public:
const_reverse_iterator rbegin()const{return make_reverse_iterator(end());}
reverse_iterator rend(){return make_reverse_iterator(begin());}
const_reverse_iterator rend()const{return make_reverse_iterator(begin());}
const_iterator cbegin()const{return begin();}
const_iterator cend()const{return end();}
const_reverse_iterator crbegin()const{return rbegin();}
const_reverse_iterator crend()const{return rend();}
iterator iterator_to(const value_type& x)
{
return make_iterator(node_from_value<node_type>(&x));
}
const_iterator iterator_to(const value_type& x)const
{
return make_iterator(node_from_value<node_type>(&x));
}
/* capacity */
bool empty()const{return this->final_empty_();}
@@ -338,6 +359,27 @@ public:
mod,static_cast<final_node_type*>(position.get_node()));
}
template<typename Modifier,typename Rollback>
bool modify(iterator position,Modifier mod,Rollback back)
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
/* MSVC++ 6.0 optimizer on safe mode code chokes if this
* this is not added. Left it for all compilers as it does no
* harm.
*/
position.detach();
#endif
return this->final_modify_(
mod,back,static_cast<final_node_type*>(position.get_node()));
}
template<typename Modifier>
bool modify_key(iterator position,Modifier mod)
{
@@ -349,6 +391,19 @@ public:
position,modify_key_adaptor<Modifier,value_type,KeyFromValue>(mod,key));
}
template<typename Modifier,typename Rollback>
bool modify_key(iterator position,Modifier mod,Rollback back)
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
return modify(
position,
modify_key_adaptor<Modifier,value_type,KeyFromValue>(mod,key),
modify_key_adaptor<Modifier,value_type,KeyFromValue>(back,key));
}
void swap(ordered_index<KeyFromValue,Compare,SuperMeta,TagList,Category>& x)
{
BOOST_MULTI_INDEX_ORD_INDEX_CHECK_INVARIANT;
@@ -376,14 +431,14 @@ public:
template<typename CompatibleKey>
iterator find(const CompatibleKey& x)const
{
return make_iterator(ordered_index_find(header(),key,x,comp));
return make_iterator(ordered_index_find(root(),header(),key,x,comp));
}
template<typename CompatibleKey,typename CompatibleCompare>
iterator find(
const CompatibleKey& x,const CompatibleCompare& comp)const
{
return make_iterator(ordered_index_find(header(),key,x,comp));
return make_iterator(ordered_index_find(root(),header(),key,x,comp));
}
template<typename CompatibleKey>
@@ -403,42 +458,51 @@ public:
template<typename CompatibleKey>
iterator lower_bound(const CompatibleKey& x)const
{
return make_iterator(ordered_index_lower_bound(header(),key,x,comp));
return make_iterator(
ordered_index_lower_bound(root(),header(),key,x,comp));
}
template<typename CompatibleKey,typename CompatibleCompare>
iterator lower_bound(
const CompatibleKey& x,const CompatibleCompare& comp)const
{
return make_iterator(ordered_index_lower_bound(header(),key,x,comp));
return make_iterator(
ordered_index_lower_bound(root(),header(),key,x,comp));
}
template<typename CompatibleKey>
iterator upper_bound(const CompatibleKey& x)const
{
return make_iterator(ordered_index_upper_bound(header(),key,x,comp));
return make_iterator(
ordered_index_upper_bound(root(),header(),key,x,comp));
}
template<typename CompatibleKey,typename CompatibleCompare>
iterator upper_bound(
const CompatibleKey& x,const CompatibleCompare& comp)const
{
return make_iterator(ordered_index_upper_bound(header(),key,x,comp));
return make_iterator(
ordered_index_upper_bound(root(),header(),key,x,comp));
}
template<typename CompatibleKey>
std::pair<iterator,iterator> equal_range(
const CompatibleKey& x)const
{
return equal_range(x,comp);
std::pair<node_type*,node_type*> p=
ordered_index_equal_range(root(),header(),key,x,comp);
return std::pair<iterator,iterator>(
make_iterator(p.first),make_iterator(p.second));
}
template<typename CompatibleKey,typename CompatibleCompare>
std::pair<iterator,iterator> equal_range(
const CompatibleKey& x,const CompatibleCompare& comp)const
{
std::pair<node_type*,node_type*> p=
ordered_index_equal_range(root(),header(),key,x,comp);
return std::pair<iterator,iterator>(
lower_bound(x,comp),upper_bound(x,comp));
make_iterator(p.first),make_iterator(p.second));
}
/* range */
@@ -447,12 +511,21 @@ public:
std::pair<iterator,iterator>
range(LowerBounder lower,UpperBounder upper)const
{
std::pair<iterator,iterator> p(
lower_range(lower),upper_range(upper));
if(p.second!=end()&&(p.first==end()||comp(key(*p.second),key(*p.first)))){
p.second=p.first;
}
return p;
typedef typename mpl::if_<
is_same<LowerBounder,unbounded_type>,
BOOST_DEDUCED_TYPENAME mpl::if_<
is_same<UpperBounder,unbounded_type>,
both_unbounded_tag,
lower_unbounded_tag
>::type,
BOOST_DEDUCED_TYPENAME mpl::if_<
is_same<UpperBounder,unbounded_type>,
upper_unbounded_tag,
none_unbounded_tag
>::type
>::type dispatch;
return range(lower,upper,dispatch());
}
BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
@@ -523,8 +596,8 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
cpy->color()=org->color();
ordered_index_node_impl* parent_org=org->parent();
if(!parent_org)cpy->parent()=0;
node_impl_pointer parent_org=org->parent();
if(parent_org==node_impl_pointer(0))cpy->parent()=node_impl_pointer(0);
else{
node_type* parent_cpy=map.find(
static_cast<final_node_type*>(node_type::from_impl(parent_org)));
@@ -538,8 +611,10 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
}
}
if(!org->left())cpy->left()=0;
if(!org->right())cpy->right()=0;
if(org->left()==node_impl_pointer(0))
cpy->left()=node_impl_pointer(0);
if(org->right()==node_impl_pointer(0))
cpy->right()=node_impl_pointer(0);
}
}
@@ -555,8 +630,7 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
node_type* res=static_cast<node_type*>(super::insert_(v,x));
if(res==x){
ordered_index_node_impl::link(
x->impl(),inf.side,inf.pos,header()->impl());
node_impl_type::link(x->impl(),inf.side,inf.pos,header()->impl());
}
return res;
}
@@ -570,15 +644,14 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
node_type* res=static_cast<node_type*>(super::insert_(v,position,x));
if(res==x){
ordered_index_node_impl::link(
x->impl(),inf.side,inf.pos,header()->impl());
node_impl_type::link(x->impl(),inf.side,inf.pos,header()->impl());
}
return res;
}
void erase_(node_type* x)
{
ordered_index_node_impl::rebalance_for_erase(
node_impl_type::rebalance_for_erase(
x->impl(),header()->parent(),header()->left(),header()->right());
super::erase_(x);
@@ -623,23 +696,20 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
node_type* next=x;
node_type::increment(next);
ordered_index_node_impl::rebalance_for_erase(
node_impl_type::rebalance_for_erase(
x->impl(),header()->parent(),header()->left(),header()->right());
BOOST_TRY{
link_info inf;
if(link_point(key(v),inf,Category())&&super::replace_(v,x)){
ordered_index_node_impl::link(
x->impl(),inf.side,inf.pos,header()->impl());
node_impl_type::link(x->impl(),inf.side,inf.pos,header()->impl());
return true;
}
ordered_index_node_impl::restore(
x->impl(),next->impl(),header()->impl());
node_impl_type::restore(x->impl(),next->impl(),header()->impl());
return false;
}
BOOST_CATCH(...){
ordered_index_node_impl::restore(
x->impl(),next->impl(),header()->impl());
node_impl_type::restore(x->impl(),next->impl(),header()->impl());
BOOST_RETHROW;
}
BOOST_CATCH_END
@@ -657,7 +727,7 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
}
BOOST_CATCH_END
if(!b){
ordered_index_node_impl::rebalance_for_erase(
node_impl_type::rebalance_for_erase(
x->impl(),header()->parent(),header()->left(),header()->right());
BOOST_TRY{
link_info inf;
@@ -669,8 +739,7 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
#endif
return false;
}
ordered_index_node_impl::link(
x->impl(),inf.side,inf.pos,header()->impl());
node_impl_type::link(x->impl(),inf.side,inf.pos,header()->impl());
}
BOOST_CATCH(...){
super::erase_(x);
@@ -686,7 +755,7 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
BOOST_TRY{
if(!super::modify_(x)){
ordered_index_node_impl::rebalance_for_erase(
node_impl_type::rebalance_for_erase(
x->impl(),header()->parent(),header()->left(),header()->right());
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
@@ -698,7 +767,7 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
else return true;
}
BOOST_CATCH(...){
ordered_index_node_impl::rebalance_for_erase(
node_impl_type::rebalance_for_erase(
x->impl(),header()->parent(),header()->left(),header()->right());
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
@@ -710,6 +779,35 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
BOOST_CATCH_END
}
bool modify_rollback_(node_type* x)
{
if(in_place(x->value(),x,Category())){
return super::modify_rollback_(x);
}
node_type* next=x;
node_type::increment(next);
node_impl_type::rebalance_for_erase(
x->impl(),header()->parent(),header()->left(),header()->right());
BOOST_TRY{
link_info inf;
if(link_point(key(x->value()),inf,Category())&&
super::modify_rollback_(x)){
node_impl_type::link(x->impl(),inf.side,inf.pos,header()->impl());
return true;
}
node_impl_type::restore(x->impl(),next->impl(),header()->impl());
return false;
}
BOOST_CATCH(...){
node_impl_type::restore(x->impl(),next->impl(),header()->impl());
BOOST_RETHROW;
}
BOOST_CATCH_END
}
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
/* serialization */
@@ -740,7 +838,7 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
else{
if((size_type)std::distance(begin(),end())!=size())return false;
std::size_t len=ordered_index_node_impl::black_count(
std::size_t len=node_impl_type::black_count(
leftmost()->impl(),root()->impl());
for(const_iterator it=begin(),it_end=end();it!=it_end;++it){
node_type* x=it.get_node();
@@ -754,16 +852,13 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
if(left_x&&comp(key(x->value()),key(left_x->value())))return false;
if(right_x&&comp(key(right_x->value()),key(x->value())))return false;
if(!left_x&&!right_x&&
ordered_index_node_impl::black_count(
x->impl(),root()->impl())!=len)
node_impl_type::black_count(x->impl(),root()->impl())!=len)
return false;
}
if(leftmost()->impl()!=
ordered_index_node_impl::minimum(root()->impl()))
if(leftmost()->impl()!=node_impl_type::minimum(root()->impl()))
return false;
if(rightmost()->impl()!=
ordered_index_node_impl::maximum(root()->impl()))
if(rightmost()->impl()!=node_impl_type::maximum(root()->impl()))
return false;
}
@@ -790,15 +885,17 @@ private:
header()->color()=red;
/* used to distinguish header() from root, in iterator.operator++ */
header()->parent()=0;
header()->parent()=node_impl_pointer(0);
header()->left()=header()->impl();
header()->right()=header()->impl();
}
struct link_info
{
ordered_index_side side;
ordered_index_node_impl* pos;
link_info():side(to_left){}
ordered_index_side side;
node_impl_pointer pos;
};
bool link_point(key_param_type k,link_info& inf,ordered_unique_tag)
@@ -847,6 +944,21 @@ private:
return true;
}
bool lower_link_point(key_param_type k,link_info& inf,ordered_non_unique_tag)
{
node_type* y=header();
node_type* x=root();
bool c=false;
while (x){
y=x;
c=comp(key(x->value()),k);
x=node_type::from_impl(c?x->right():x->left());
}
inf.side=c?to_right:to_left;
inf.pos=y->impl();
return true;
}
bool hinted_link_point(
key_param_type k,node_type* position,link_info& inf,ordered_unique_tag)
{
@@ -870,7 +982,7 @@ private:
node_type* before=position;
node_type::decrement(before);
if(comp(key(before->value()),k)&&comp(k,key(position->value()))){
if(before->right()==0){
if(before->right()==node_impl_pointer(0)){
inf.side=to_right;
inf.pos=before->impl();
return true;
@@ -894,7 +1006,7 @@ private:
inf.pos=position->impl();
return true;
}
else return link_point(k,inf,ordered_non_unique_tag());
else return lower_link_point(k,inf,ordered_non_unique_tag());
}
else if(position==header()){
if(!comp(k,key(rightmost()->value()))){
@@ -907,17 +1019,20 @@ private:
else{
node_type* before=position;
node_type::decrement(before);
if (!comp(k,key(before->value()))&&!comp(key(position->value()),k)){
if(before->right()==0){
inf.side=to_right;
inf.pos=before->impl();
return true;
}
else{
inf.side=to_left;
inf.pos=position->impl();
return true;
if(!comp(k,key(before->value()))){
if(!comp(key(position->value()),k)){
if(before->right()==node_impl_pointer(0)){
inf.side=to_right;
inf.pos=before->impl();
return true;
}
else{
inf.side=to_left;
inf.pos=position->impl();
return true;
}
}
else return lower_link_point(k,inf,ordered_non_unique_tag());
}
else return link_point(k,inf,ordered_non_unique_tag());
}
@@ -968,48 +1083,84 @@ private:
}
#endif
template<typename LowerBounder>
iterator lower_range(LowerBounder lower)const
template<typename LowerBounder,typename UpperBounder>
std::pair<iterator,iterator>
range(LowerBounder lower,UpperBounder upper,none_unbounded_tag)const
{
node_type* y=header();
node_type* z=root();
while(z){
if(lower(key(z->value()))){
if(!lower(key(z->value()))){
z=node_type::from_impl(z->right());
}
else if(!upper(key(z->value()))){
y=z;
z=node_type::from_impl(z->left());
}
else z=node_type::from_impl(z->right());
else{
return std::pair<iterator,iterator>(
make_iterator(
lower_range(node_type::from_impl(z->left()),z,lower)),
make_iterator(
upper_range(node_type::from_impl(z->right()),y,upper)));
}
}
return make_iterator(y);
return std::pair<iterator,iterator>(make_iterator(y),make_iterator(y));
}
iterator lower_range(unbounded_type)const
template<typename LowerBounder,typename UpperBounder>
std::pair<iterator,iterator>
range(LowerBounder,UpperBounder upper,lower_unbounded_tag)const
{
return begin();
return std::pair<iterator,iterator>(
begin(),
make_iterator(upper_range(root(),header(),upper)));
}
template<typename LowerBounder,typename UpperBounder>
std::pair<iterator,iterator>
range(LowerBounder lower,UpperBounder,upper_unbounded_tag)const
{
return std::pair<iterator,iterator>(
make_iterator(lower_range(root(),header(),lower)),
end());
}
template<typename LowerBounder,typename UpperBounder>
std::pair<iterator,iterator>
range(LowerBounder,UpperBounder,both_unbounded_tag)const
{
return std::pair<iterator,iterator>(begin(),end());
}
template<typename LowerBounder>
node_type * lower_range(node_type* top,node_type* y,LowerBounder lower)const
{
while(top){
if(lower(key(top->value()))){
y=top;
top=node_type::from_impl(top->left());
}
else top=node_type::from_impl(top->right());
}
return y;
}
template<typename UpperBounder>
iterator upper_range(UpperBounder upper)const
node_type * upper_range(node_type* top,node_type* y,UpperBounder upper)const
{
node_type* y=header();
node_type* z=root();
while(z){
if(!upper(key(z->value()))){
y=z;
z=node_type::from_impl(z->left());
while(top){
if(!upper(key(top->value()))){
y=top;
top=node_type::from_impl(top->left());
}
else z=node_type::from_impl(z->right());
else top=node_type::from_impl(top->right());
}
return make_iterator(y);
}
iterator upper_range(unbounded_type)const
{
return end();
return y;
}
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
@@ -1068,9 +1219,9 @@ private:
else node_type::increment(position);
if(position!=x){
ordered_index_node_impl::rebalance_for_erase(
node_impl_type::rebalance_for_erase(
x->impl(),header()->parent(),header()->left(),header()->right());
ordered_index_node_impl::restore(
node_impl_type::restore(
x->impl(),position->impl(),header()->impl());
}
}
+116 -28
View File
@@ -19,6 +19,8 @@
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/iterator/reverse_iterator.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/not.hpp>
#include <boost/mpl/push_front.hpp>
#include <boost/multi_index/detail/access_specifier.hpp>
#include <boost/multi_index/detail/index_node_base.hpp>
@@ -32,6 +34,7 @@
#include <boost/multi_index/random_access_index_fwd.hpp>
#include <boost/throw_exception.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <cstddef>
#include <functional>
#include <stdexcept>
@@ -94,6 +97,12 @@ protected:
typedef random_access_index_node<
typename super::node_type> node_type;
private:
typedef typename node_type::impl_type node_impl_type;
typedef random_access_index_ptr_array<
typename super::final_allocator_type> ptr_array;
typedef typename ptr_array::pointer node_impl_ptr_pointer;
public:
/* types */
@@ -183,9 +192,7 @@ public:
template <class InputIterator>
void assign(InputIterator first,InputIterator last)
{
BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
clear();
for(;first!=last;++first)push_back(*first);
assign_iter(first,last,mpl::not_<is_integral<InputIterator> >());
}
void assign(size_type n,value_param_type value)
@@ -212,6 +219,20 @@ public:
const_reverse_iterator rbegin()const{return make_reverse_iterator(end());}
reverse_iterator rend(){return make_reverse_iterator(begin());}
const_reverse_iterator rend()const{return make_reverse_iterator(begin());}
const_iterator cbegin()const{return begin();}
const_iterator cend()const{return end();}
const_reverse_iterator crbegin()const{return rbegin();}
const_reverse_iterator crend()const{return rend();}
iterator iterator_to(const value_type& x)
{
return make_iterator(node_from_value<node_type>(&x));
}
const_iterator iterator_to(const value_type& x)const
{
return make_iterator(node_from_value<node_type>(&x));
}
/* capacity */
@@ -290,19 +311,7 @@ public:
template<typename InputIterator>
void insert(iterator position,InputIterator first,InputIterator last)
{
BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
size_type s=0;
BOOST_TRY{
for(;first!=last;++first){
if(push_back(*first).second)++s;
}
}
BOOST_CATCH(...){
relocate(position,end()-s,end());
BOOST_RETHROW;
}
BOOST_CATCH_END
relocate(position,end()-s,end());
insert_iter(position,first,last,mpl::not_<is_integral<InputIterator> >());
}
iterator erase(iterator position)
@@ -360,6 +369,27 @@ public:
mod,static_cast<final_node_type*>(position.get_node()));
}
template<typename Modifier,typename Rollback>
bool modify(iterator position,Modifier mod,Rollback back)
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
/* MSVC++ 6.0 optimizer on safe mode code chokes if this
* this is not added. Left it for all compilers as it does no
* harm.
*/
position.detach();
#endif
return this->final_modify_(
mod,back,static_cast<final_node_type*>(position.get_node()));
}
void swap(random_access_index<SuperMeta,TagList>& x)
{
BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
@@ -540,7 +570,7 @@ public:
void reverse()
{
BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
random_access_index_node_impl::reverse(ptrs.begin(),ptrs.end());
node_impl_type::reverse(ptrs.begin(),ptrs.end());
}
/* rearrange operations */
@@ -575,10 +605,10 @@ public:
void rearrange(InputIterator first)
{
BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
for(random_access_index_node_impl** p0=ptrs.begin(),** p0_end=ptrs.end();
for(node_impl_ptr_pointer p0=ptrs.begin(),p0_end=ptrs.end();
p0!=p0_end;++first,++p0){
const value_type& v1=*first;
random_access_index_node_impl** p1=node_from_value<node_type>(&v1)->up();
const value_type& v1=*first;
node_impl_ptr_pointer p1=node_from_value<node_type>(&v1)->up();
std::swap(*p0,*p1);
(*p0)->up()=p0;
@@ -625,9 +655,9 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
void copy_(
const random_access_index<SuperMeta,TagList>& x,const copy_map_type& map)
{
for(random_access_index_node_impl** begin_org=x.ptrs.begin(),
** begin_cpy=ptrs.begin(),
** end_org=x.ptrs.end();
for(node_impl_ptr_pointer begin_org=x.ptrs.begin(),
begin_cpy=ptrs.begin(),
end_org=x.ptrs.end();
begin_org!=end_org;++begin_org,++begin_cpy){
*begin_cpy=
static_cast<node_type*>(
@@ -668,8 +698,7 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
void delete_all_nodes_()
{
for(random_access_index_node_impl** x=ptrs.begin(),**x_end=ptrs.end();
x!=x_end;++x){
for(node_impl_ptr_pointer x=ptrs.begin(),x_end=ptrs.end();x!=x_end;++x){
this->final_delete_node_(
static_cast<final_node_type*>(node_type::from_impl(*x)));
}
@@ -727,6 +756,11 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
BOOST_CATCH_END
}
bool modify_rollback_(node_type* x)
{
return super::modify_rollback_(x);
}
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
/* serialization */
@@ -785,12 +819,12 @@ private:
static void relocate(node_type* position,node_type* x)
{
random_access_index_node_impl::relocate(position->up(),x->up());
node_impl_type::relocate(position->up(),x->up());
}
static void relocate(node_type* position,node_type* first,node_type* last)
{
random_access_index_node_impl::relocate(
node_impl_type::relocate(
position->up(),first->up(),last->up());
}
@@ -802,7 +836,61 @@ private:
}
#endif
random_access_index_ptr_array<typename super::final_allocator_type> ptrs;
template <class InputIterator>
void assign_iter(InputIterator first,InputIterator last,mpl::true_)
{
BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
clear();
for(;first!=last;++first)push_back(*first);
}
void assign_iter(size_type n,value_param_type value,mpl::false_)
{
BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
clear();
for(size_type i=0;i<n;++i)push_back(value);
}
template<typename InputIterator>
void insert_iter(
iterator position,InputIterator first,InputIterator last,mpl::true_)
{
BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
size_type s=0;
BOOST_TRY{
for(;first!=last;++first){
if(push_back(*first).second)++s;
}
}
BOOST_CATCH(...){
relocate(position,end()-s,end());
BOOST_RETHROW;
}
BOOST_CATCH_END
relocate(position,end()-s,end());
}
void insert_iter(
iterator position,size_type n,value_param_type x,mpl::false_)
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
size_type s=0;
BOOST_TRY{
while(n--){
if(push_back(x).second)++s;
}
}
BOOST_CATCH(...){
relocate(position,end()-s,end());
BOOST_RETHROW;
}
BOOST_CATCH_END
relocate(position,end()-s,end());
}
ptr_array ptrs;
#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
BOOST_WORKAROUND(__MWERKS__,<=0x3003)
+113 -30
View File
@@ -15,9 +15,12 @@
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/call_traits.hpp>
#include <boost/detail/allocator_utilities.hpp>
#include <boost/detail/no_exceptions_support.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/iterator/reverse_iterator.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/not.hpp>
#include <boost/mpl/push_front.hpp>
#include <boost/multi_index/detail/access_specifier.hpp>
#include <boost/multi_index/detail/bidir_node_iterator.hpp>
@@ -29,6 +32,7 @@
#include <boost/multi_index/detail/seq_index_ops.hpp>
#include <boost/multi_index/sequenced_index_fwd.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <cstddef>
#include <functional>
#include <utility>
@@ -81,47 +85,50 @@ class sequenced_index:
#pragma parse_mfunc_templ off
#endif
typedef typename SuperMeta::type super;
typedef typename SuperMeta::type super;
protected:
typedef sequenced_index_node<
typename super::node_type> node_type;
typename super::node_type> node_type;
private:
typedef typename node_type::impl_type node_impl_type;
public:
/* types */
typedef typename node_type::value_type value_type;
typedef tuples::null_type ctor_args;
typedef typename super::final_allocator_type allocator_type;
typedef typename allocator_type::reference reference;
typedef typename allocator_type::const_reference const_reference;
typedef typename node_type::value_type value_type;
typedef tuples::null_type ctor_args;
typedef typename super::final_allocator_type allocator_type;
typedef typename allocator_type::reference reference;
typedef typename allocator_type::const_reference const_reference;
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
typedef safe_mode::safe_iterator<
bidir_node_iterator<node_type>,
safe_ctr_proxy<
bidir_node_iterator<node_type> > > iterator;
bidir_node_iterator<node_type> > > iterator;
#else
typedef safe_mode::safe_iterator<
bidir_node_iterator<node_type>,
sequenced_index> iterator;
sequenced_index> iterator;
#endif
#else
typedef bidir_node_iterator<node_type> iterator;
typedef bidir_node_iterator<node_type> iterator;
#endif
typedef iterator const_iterator;
typedef iterator const_iterator;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef typename allocator_type::pointer pointer;
typedef typename allocator_type::const_pointer const_pointer;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef typename allocator_type::pointer pointer;
typedef typename allocator_type::const_pointer const_pointer;
typedef typename
boost::reverse_iterator<iterator> reverse_iterator;
boost::reverse_iterator<iterator> reverse_iterator;
typedef typename
boost::reverse_iterator<const_iterator> const_reverse_iterator;
typedef TagList tag_list;
boost::reverse_iterator<const_iterator> const_reverse_iterator;
typedef TagList tag_list;
protected:
typedef typename super::final_node_type final_node_type;
@@ -175,9 +182,7 @@ public:
template <class InputIterator>
void assign(InputIterator first,InputIterator last)
{
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
clear();
for(;first!=last;++first)push_back(*first);
assign_iter(first,last,mpl::not_<is_integral<InputIterator> >());
}
void assign(size_type n,value_param_type value)
@@ -204,6 +209,20 @@ public:
const_reverse_iterator rbegin()const{return make_reverse_iterator(end());}
reverse_iterator rend(){return make_reverse_iterator(begin());}
const_reverse_iterator rend()const{return make_reverse_iterator(begin());}
const_iterator cbegin()const{return begin();}
const_iterator cend()const{return end();}
const_reverse_iterator crbegin()const{return rbegin();}
const_reverse_iterator crend()const{return rend();}
iterator iterator_to(const value_type& x)
{
return make_iterator(node_from_value<node_type>(&x));
}
const_iterator iterator_to(const value_type& x)const
{
return make_iterator(node_from_value<node_type>(&x));
}
/* capacity */
@@ -216,8 +235,15 @@ public:
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
if(n>size())insert(end(),n-size(),x);
else if(n<size()){
iterator it=begin();
std::advance(it,n);
iterator it;
if(n<=size()/2){
it=begin();
std::advance(it,n);
}
else{
it=end();
for(size_type m=size()-n;m--;--it){}
}
erase(it,end());
}
}
@@ -261,8 +287,7 @@ public:
template<typename InputIterator>
void insert(iterator position,InputIterator first,InputIterator last)
{
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
for(;first!=last;++first)insert(position,*first);
insert_iter(position,first,last,mpl::not_<is_integral<InputIterator> >());
}
iterator erase(iterator position)
@@ -320,6 +345,27 @@ public:
mod,static_cast<final_node_type*>(position.get_node()));
}
template<typename Modifier,typename Rollback>
bool modify(iterator position,Modifier mod,Rollback back)
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
/* MSVC++ 6.0 optimizer on safe mode code chokes if this
* this is not added. Left it for all compilers as it does no
* harm.
*/
position.detach();
#endif
return this->final_modify_(
mod,back,static_cast<final_node_type*>(position.get_node()));
}
void swap(sequenced_index<SuperMeta,TagList>& x)
{
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
@@ -451,7 +497,7 @@ public:
void reverse()
{
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
sequenced_index_node_impl::reverse(header()->impl());
node_impl_type::reverse(header()->impl());
}
/* rearrange operations */
@@ -627,6 +673,11 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
BOOST_CATCH_END
}
bool modify_rollback_(node_type* x)
{
return super::modify_rollback_(x);
}
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
/* serialization */
@@ -688,22 +739,22 @@ private:
void link(node_type* x)
{
sequenced_index_node_impl::link(x->impl(),header()->impl());
node_impl_type::link(x->impl(),header()->impl());
};
static void unlink(node_type* x)
{
sequenced_index_node_impl::unlink(x->impl());
node_impl_type::unlink(x->impl());
}
static void relink(node_type* position,node_type* x)
{
sequenced_index_node_impl::relink(position->impl(),x->impl());
node_impl_type::relink(position->impl(),x->impl());
}
static void relink(node_type* position,node_type* first,node_type* last)
{
sequenced_index_node_impl::relink(
node_impl_type::relink(
position->impl(),first->impl(),last->impl());
}
@@ -724,6 +775,38 @@ private:
}
#endif
template <class InputIterator>
void assign_iter(InputIterator first,InputIterator last,mpl::true_)
{
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
clear();
for(;first!=last;++first)push_back(*first);
}
void assign_iter(size_type n,value_param_type value,mpl::false_)
{
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
clear();
for(size_type i=0;i<n;++i)push_back(value);
}
template<typename InputIterator>
void insert_iter(
iterator position,InputIterator first,InputIterator last,mpl::true_)
{
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
for(;first!=last;++first)insert(position,*first);
}
void insert_iter(
iterator position,size_type n,value_param_type x,mpl::false_)
{
BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
BOOST_MULTI_INDEX_SEQ_INDEX_CHECK_INVARIANT;
for(size_type i=0;i<n;++i)insert(position,x);
}
#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
BOOST_WORKAROUND(__MWERKS__,<=0x3003)
#pragma parse_mfunc_templ reset
+70 -20
View File
@@ -31,7 +31,6 @@
#include <boost/multi_index/detail/access_specifier.hpp>
#include <boost/multi_index/detail/base_type.hpp>
#include <boost/multi_index/detail/converter.hpp>
#include <boost/multi_index/detail/def_ctor_tuple_cons.hpp>
#include <boost/multi_index/detail/header_holder.hpp>
#include <boost/multi_index/detail/has_tag.hpp>
#include <boost/multi_index/detail/no_duplicate_tags.hpp>
@@ -72,8 +71,14 @@ class multi_index_container:
Value,IndexSpecifierList,Allocator>::type
>::type>,
BOOST_MULTI_INDEX_PRIVATE_IF_MEMBER_TEMPLATE_FRIENDS detail::header_holder<
typename detail::multi_index_node_type<
Value,IndexSpecifierList,Allocator>::type,
typename detail::prevent_eti<
Allocator,
typename boost::detail::allocator::rebind_to<
Allocator,
typename detail::multi_index_node_type<
Value,IndexSpecifierList,Allocator>::type
>::type
>::type::pointer,
multi_index_container<Value,IndexSpecifierList,Allocator> >,
public detail::multi_index_base_type<
Value,IndexSpecifierList,Allocator>::type
@@ -97,13 +102,18 @@ private:
typedef typename detail::multi_index_base_type<
Value,IndexSpecifierList,Allocator>::type super;
typedef ::boost::base_from_member<
typename boost::detail::allocator::rebind_to<
typedef typename
boost::detail::allocator::rebind_to<
Allocator,
typename super::node_type
>::type> bfm_allocator;
>::type node_allocator;
typedef ::boost::base_from_member<
node_allocator> bfm_allocator;
typedef detail::header_holder<
typename super::node_type,
typename detail::prevent_eti<
Allocator,
node_allocator
>::type::pointer,
multi_index_container> bfm_header;
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
@@ -116,15 +126,8 @@ public:
* brought forward here to save us some typename's.
*/
#if defined(BOOST_MSVC)
typedef
detail::default_constructible_tuple_cons<
typename super::ctor_args_list> ctor_args_list;
#else
typedef typename super::ctor_args_list ctor_args_list;
#endif
typedef IndexSpecifierList index_specifier_type_list;
typedef typename super::ctor_args_list ctor_args_list;
typedef IndexSpecifierList index_specifier_type_list;
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
/* MSVC++ 6.0 chokes on moderately long index lists (around 6 indices
@@ -430,17 +433,18 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
node_type* header()const
{
return bfm_header::member;
return &*bfm_header::member;
}
node_type* allocate_node()
{
return bfm_allocator::member.allocate(1);
return &*bfm_allocator::member.allocate(1);
}
void deallocate_node(node_type* x)
{
bfm_allocator::member.deallocate(x,1);
typedef typename node_allocator::pointer node_pointer;
bfm_allocator::member.deallocate(static_cast<node_pointer>(x),1);
}
bool empty_()const
@@ -527,6 +531,16 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
void swap_(multi_index_container<Value,IndexSpecifierList,Allocator>& x)
{
if(bfm_allocator::member!=x.bfm_allocator::member){
#if defined(BOOST_FUNCTION_SCOPE_USING_DECLARATION_BREAKS_ADL)
std::swap(bfm_allocator::member,x.bfm_allocator::member);
#else
using std::swap;
swap(bfm_allocator::member,x.bfm_allocator::member);
#endif
}
std::swap(bfm_header::member,x.bfm_header::member);
super::swap_(x);
std::swap(node_count,x.node_count);
@@ -538,7 +552,7 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
}
template<typename Modifier>
bool modify_(Modifier mod,node_type* x)
bool modify_(Modifier& mod,node_type* x)
{
mod(const_cast<value_type&>(x->value()));
@@ -558,6 +572,42 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
BOOST_CATCH_END
}
template<typename Modifier,typename Rollback>
bool modify_(Modifier& mod,Rollback& back,node_type* x)
{
mod(const_cast<value_type&>(x->value()));
bool b;
BOOST_TRY{
b=super::modify_rollback_(x);
}
BOOST_CATCH(...){
BOOST_TRY{
back(const_cast<value_type&>(x->value()));
BOOST_RETHROW;
}
BOOST_CATCH(...){
this->erase_(x);
BOOST_RETHROW;
}
BOOST_CATCH_END
}
BOOST_CATCH_END
BOOST_TRY{
if(!b){
back(const_cast<value_type&>(x->value()));
return false;
}
else return true;
}
BOOST_CATCH(...){
this->erase_(x);
BOOST_RETHROW;
}
BOOST_CATCH_END
}
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
/* serialization */
+3 -2
View File
@@ -1,6 +1,6 @@
/* Boost.MultiIndex performance test.
*
* Copyright 2003-2006 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)
@@ -16,6 +16,7 @@
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/next_prior.hpp>
#include <climits>
#include <ctime>
#include <iomanip>
@@ -163,7 +164,7 @@ struct list_wrapper:List
pair<iterator,bool> insert(const value_type& v)
{
List::push_back(v);
return pair<iterator,bool>(--List::end(),true);
return pair<iterator,bool>(boost::prior(List::end()),true);
}
};
+3 -2
View File
@@ -1,6 +1,6 @@
# Boost.MultiIndex tests Jamfile
#
# Copyright 2003-2006 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)
@@ -26,7 +26,8 @@ test-suite "multi_index" :
[ run test_rearrange.cpp test_rearrange_main.cpp ]
[ run test_safe_mode.cpp test_safe_mode_main.cpp ]
[ run test_serialization.cpp test_serialization1.cpp
test_serialization2.cpp test_serialization_main.cpp
test_serialization2.cpp test_serialization3.cpp
test_serialization_main.cpp
/boost/serialization//boost_serialization ]
[ run test_set_ops.cpp test_set_ops_main.cpp ]
[ run test_special_set_ops.cpp test_special_set_ops_main.cpp ]
+4 -2
View File
@@ -1,6 +1,6 @@
/* Used in Boost.MultiIndex tests.
*
* Copyright 2003-2006 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)
@@ -23,6 +23,7 @@
#include <cstddef>
#include <ostream>
#include <string>
#include "non_std_allocator.hpp"
struct employee
{
@@ -92,7 +93,8 @@ struct employee_set_indices:
typedef
boost::multi_index::multi_index_container<
employee,
employee_set_indices> employee_set;
employee_set_indices,
non_std_allocator<employee> > employee_set;
#if defined(BOOST_NO_MEMBER_TEMPLATES)
typedef boost::multi_index::nth_index<
+136
View File
@@ -0,0 +1,136 @@
/* Used in Boost.MultiIndex tests.
*
* Copyright 2003-2007 Joaquín M López Muñoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/multi_index for library home page.
*/
#ifndef BOOST_MULTI_INDEX_TEST_NON_STD_ALLOCATOR_HPP
#define BOOST_MULTI_INDEX_TEST_NON_STD_ALLOCATOR_HPP
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <iterator>
#include <cstddef>
template<typename T>
class non_raw_pointer
{
public:
typedef std::ptrdiff_t difference_type;
typedef T value_type;
typedef T* pointer;
typedef T& reference;
typedef std::random_access_iterator_tag iterator_category;
non_raw_pointer(){}
explicit non_raw_pointer(T* p_):p(p_){}
T& operator*()const{return *p;}
T* operator->()const{return p;}
non_raw_pointer& operator++(){++p;return *this;}
non_raw_pointer operator++(int){non_raw_pointer t(*this);++p;return t;}
non_raw_pointer& operator--(){--p;return *this;}
non_raw_pointer operator--(int){non_raw_pointer t(*this);--p;return t;}
non_raw_pointer& operator+=(std::ptrdiff_t n){p+=n;return *this;}
non_raw_pointer& operator-=(std::ptrdiff_t n){p-=n;return *this;}
T& operator[](std::ptrdiff_t n)const{return p[n];}
private:
T* p;
};
template<typename T>
non_raw_pointer<T> operator+(const non_raw_pointer<T>& x,std::ptrdiff_t n)
{return non_raw_pointer<T>((&*x)+n);}
template<typename T>
non_raw_pointer<T> operator+(std::ptrdiff_t n,const non_raw_pointer<T>& x)
{return non_raw_pointer<T>(n+(&*x));}
template<typename T>
non_raw_pointer<T> operator-(const non_raw_pointer<T>& x,std::ptrdiff_t n)
{return non_raw_pointer<T>((&*x)-n);}
template<typename T>
std::ptrdiff_t operator-(
const non_raw_pointer<T>& x,const non_raw_pointer<T>& y)
{return (&*x)-(&*y);}
template<typename T>
bool operator==(const non_raw_pointer<T>& x,const non_raw_pointer<T>& y)
{return (&*x)==(&*y);}
template<typename T>
bool operator!=(const non_raw_pointer<T>& x,const non_raw_pointer<T>& y)
{return (&*x)!=(&*y);}
template<typename T>
bool operator<(const non_raw_pointer<T>& x,const non_raw_pointer<T>& y)
{return (&*x)<(&*y);}
template<typename T>
bool operator>(const non_raw_pointer<T>& x,const non_raw_pointer<T>& y)
{return (&*x)>(&*y);}
template<typename T>
bool operator>=(const non_raw_pointer<T>& x,const non_raw_pointer<T>& y)
{return (&*x)>=(&*y);}
template<typename T>
bool operator<=(const non_raw_pointer<T>& x,const non_raw_pointer<T>& y)
{return (&*x)<=(&*y);}
template<typename T>
class non_std_allocator
{
public:
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef non_raw_pointer<T> pointer;
typedef non_raw_pointer<const T> const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;
template<class U>struct rebind{typedef non_std_allocator<U> other;};
non_std_allocator(){}
non_std_allocator(const non_std_allocator<T>&){}
template<class U>non_std_allocator(const non_std_allocator<U>&,int=0){}
pointer allocate(size_type n)
{
return pointer((T*)(new char[n*sizeof(T)]));
}
void deallocate(pointer p,size_type)
{
delete[](char *)&*p;
}
size_type max_size() const{return (size_type )(-1);}
friend bool operator==(const non_std_allocator&,const non_std_allocator&)
{
return true;
}
friend bool operator!=(const non_std_allocator&,const non_std_allocator&)
{
return false;
}
};
template<>
class non_std_allocator<void>
{
public:
typedef non_raw_pointer<void> pointer;
typedef non_raw_pointer<const void> const_pointer;
typedef void value_type;
template<class U>struct rebind{typedef non_std_allocator<U> other;};
};
#endif
+16 -1
View File
@@ -1,6 +1,6 @@
/* Used in Boost.MultiIndex tests.
*
* Copyright 2003-2004 Joaqu M Lez Muz.
* 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)
@@ -32,6 +32,21 @@ inline void increment_int(int& x)
++x;
}
inline void decrement_first(pair_of_ints& p)
{
--p.first;
}
inline void decrement_second(pair_of_ints& p)
{
--p.second;
}
inline void decrement_int(int& x)
{
--x;
}
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
namespace boost{
namespace serialization{
+4 -1
View File
@@ -1,6 +1,6 @@
/* Boost.MultiIndex test for capacity memfuns.
*
* Copyright 2003-2006 Joaqu M Lez Muz.
* 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)
@@ -53,6 +53,9 @@ void test_capacity()
ss.resize(5);
BOOST_CHECK(ss.size()==5);
ss.resize(4);
BOOST_CHECK(ss.size()==4);
multi_index_container<int,indexed_by<random_access<> > > rs;
rs.resize(10);
+26 -1
View File
@@ -1,6 +1,6 @@
/* Boost.MultiIndex test for copying and assignment.
*
* Copyright 2003-2006 Joaqu M Lez Muz.
* 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)
@@ -57,6 +57,27 @@ static void test_assign(BOOST_EXPLICIT_TEMPLATE_TYPE(Sequence))
#pragma parse_func_templ reset
#endif
template<typename Sequence>
static void test_integral_assign(BOOST_EXPLICIT_TEMPLATE_TYPE(Sequence))
{
/* Special cases described in 23.1.1/9: integral types must not
* be taken as iterators in assign(f,l) and insert(p,f,l).
*/
Sequence s;
s.assign(5,10);
BOOST_CHECK(s.size()==5&&std::accumulate(s.begin(),s.end(),0)==50);
s.assign(2u,5u);
BOOST_CHECK(s.size()==2&&std::accumulate(s.begin(),s.end(),0)==10);
s.clear();
s.insert(s.begin(),5,10);
BOOST_CHECK(s.size()==5&&std::accumulate(s.begin(),s.end(),0)==50);
s.insert(s.begin(),2u,5u);
BOOST_CHECK(s.size()==7&&std::accumulate(s.begin(),s.end(),0)==60);
}
void test_copy_assignment()
{
employee_set es;
@@ -130,7 +151,11 @@ void test_copy_assignment()
/* MSVC++ 6.0 chokes on test_assign without this explicit instantiation */
multi_index_container<int,indexed_by<sequenced<> > > s1;
test_assign<multi_index_container<int,indexed_by<sequenced<> > > >();
test_integral_assign<
multi_index_container<int,indexed_by<sequenced<> > > >();
multi_index_container<int,indexed_by<random_access<> > > s2;
test_assign<multi_index_container<int,indexed_by<random_access<> > > >();
test_integral_assign<
multi_index_container<int,indexed_by<random_access<> > > >();
}
+29 -5
View File
@@ -1,6 +1,6 @@
/* Boost.MultiIndex test for iterators.
*
* Copyright 2003-2006 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)
@@ -13,6 +13,7 @@
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include "pre_multi_index.hpp"
#include "employee.hpp"
#include <boost/next_prior.hpp>
#include <boost/test/test_tools.hpp>
using namespace boost::multi_index;
@@ -25,6 +26,7 @@ void test_non_const_iterators(Index& i,int target)
int n=0;
for(iterator it=i.begin();it!=i.end();++it){
BOOST_CHECK(i.iterator_to(*it)==it);
n+=it->id;
}
int m=0;
@@ -51,8 +53,14 @@ void test_const_iterators(const Index& i,int target)
typedef typename Index::const_iterator const_iterator;
typedef typename Index::const_reverse_iterator const_reverse_iterator;
BOOST_CHECK(i.cbegin()==i.begin());
BOOST_CHECK(i.cend()==i.end());
BOOST_CHECK(i.crbegin()==i.rbegin());
BOOST_CHECK(i.crend()==i.rend());
int n=0;
for(const_iterator it=i.begin();it!=i.end();++it){
BOOST_CHECK(i.iterator_to(*it)==it);
n+=it->id;
}
int m=0;
@@ -82,11 +90,13 @@ void test_non_const_hashed_iterators(Index& i,int target)
int n=0;
for(iterator it=i.begin();it!=i.end();++it){
BOOST_CHECK(i.iterator_to(*it)==it);
n+=it->id;
}
int m=0;
for(size_type buc=0;buc<i.bucket_count();++buc){
for(local_iterator it=i.begin(buc);it!=i.end(buc);++it){
BOOST_CHECK(i.local_iterator_to(*it)==it);
m+=it->id;
}
}
@@ -101,13 +111,20 @@ void test_const_hashed_iterators(const Index& i,int target)
typedef typename Index::const_local_iterator const_local_iterator;
typedef typename Index::size_type size_type;
BOOST_CHECK(i.cbegin()==i.begin());
BOOST_CHECK(i.cend()==i.end());
int n=0;
for(const_iterator it=i.begin();it!=i.end();++it){
BOOST_CHECK(i.iterator_to(*it)==it);
n+=it->id;
}
int m=0;
for(size_type buc=0;buc<i.bucket_count();++buc){
BOOST_CHECK(i.cbegin(buc)==i.begin(buc));
BOOST_CHECK(i.cend(buc)==i.end(buc));
for(const_local_iterator it=i.begin(buc);it!=i.end(buc);++it){
BOOST_CHECK(i.local_iterator_to(*it)==it);
m+=it->id;
}
}
@@ -129,16 +146,17 @@ void test_non_const_rnd_iterators(Index& i,int target)
int n=0;
for(iterator it=i.begin();it!=middle;++it){
BOOST_CHECK(i.iterator_to(*it)==it);
n+=it->id;
n+=it[off].id;
}
if(odd)n+=(--i.end())->id;
if(odd)n+=(boost::prior(i.end()))->id;
int m=0;
for(reverse_iterator rit=i.rbegin();rit!=rmiddle;++rit){
m+=rit->id;
m+=(rit+off)->id;
}
if(odd)m+=(--i.rend())->id;
if(odd)m+=(boost::prior(i.rend()))->id;
int p=0;
for(iterator it2=i.end();it2!=middle;){
--it2;
@@ -164,6 +182,11 @@ void test_const_rnd_iterators(const Index& i,int target)
typedef typename Index::const_reverse_iterator const_reverse_iterator;
typedef typename Index::difference_type difference_type;
BOOST_CHECK(i.cbegin()==i.begin());
BOOST_CHECK(i.cend()==i.end());
BOOST_CHECK(i.crbegin()==i.rbegin());
BOOST_CHECK(i.crend()==i.rend());
const_iterator middle=i.begin()+(i.end()-i.begin())/2;
difference_type off=middle-i.begin();
const_reverse_iterator rmiddle=i.rbegin()+off;
@@ -171,16 +194,17 @@ void test_const_rnd_iterators(const Index& i,int target)
int n=0;
for(const_iterator it=i.begin();it!=middle;++it){
BOOST_CHECK(i.iterator_to(*it)==it);
n+=it->id;
n+=it[off].id;
}
if(odd)n+=(--i.end())->id;
if(odd)n+=(boost::prior(i.end()))->id;
int m=0;
for(const_reverse_iterator rit=i.rbegin();rit!=rmiddle;++rit){
m+=rit->id;
m+=(rit+off)->id;
}
if(odd)m+=(--i.rend())->id;
if(odd)m+=(boost::prior(i.rend()))->id;
int p=0;
for(const_iterator it2=i.end();it2!=middle;){
--it2;
+102 -2
View File
@@ -1,6 +1,6 @@
/* Boost.MultiIndex test for key extractors.
*
* Copyright 2003-2006 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)
@@ -30,6 +30,10 @@ struct test_class
bool bool_mem_fun_const()const{return true;}
bool bool_mem_fun(){return false;}
static bool bool_global_fun(test_class){return true;}
static bool bool_global_fun_const_ref(const test_class&){return false;}
static bool bool_global_fun_ref(test_class&){return true;}
test_class(int i=0):int_member(i),int_cmember(i){}
test_class(int i,int j):int_member(i),int_cmember(j){}
@@ -69,6 +73,15 @@ typedef BOOST_MULTI_INDEX_MEMBER(test_class,const int,int_cmember) key_cm;
typedef BOOST_MULTI_INDEX_CONST_MEM_FUN(
test_class,bool,bool_mem_fun_const) key_cmf;
typedef BOOST_MULTI_INDEX_MEM_FUN(test_class,bool,bool_mem_fun) key_mf;
typedef global_fun<test_class,bool,&test_class::bool_global_fun> key_gf;
typedef global_fun<
const test_class&,bool,
&test_class::bool_global_fun_const_ref
> key_gcrf;
typedef global_fun<
test_class&,bool,
&test_class::bool_global_fun_ref
> key_grf;
typedef composite_key<
test_class,
idn,
@@ -84,7 +97,7 @@ typedef composite_key<
typedef composite_key<
boost::reference_wrapper<test_class>,
key_mf
> ccompw_key;
> ccompw_key;
#if !defined(BOOST_NO_SFINAE)
/* testcases for problems with non-copyable classes reported at
@@ -99,6 +112,9 @@ struct test_nc_class
bool bool_mem_fun_const()const{return true;}
bool bool_mem_fun(){return false;}
static bool bool_global_fun_const_ref(const test_nc_class&){return false;}
static bool bool_global_fun_ref(test_nc_class&){return true;}
test_nc_class(int i=0):int_member(i),int_cmember(i){}
test_nc_class(int i,int j):int_member(i),int_cmember(j){}
@@ -129,6 +145,14 @@ typedef BOOST_MULTI_INDEX_CONST_MEM_FUN(
test_nc_class,bool,bool_mem_fun_const) nc_key_cmf;
typedef BOOST_MULTI_INDEX_MEM_FUN(
test_nc_class,bool,bool_mem_fun) nc_key_mf;
typedef global_fun<
const test_nc_class&,bool,
&test_nc_class::bool_global_fun_const_ref
> nc_key_gcrf;
typedef global_fun<
test_nc_class&,bool,
&test_nc_class::bool_global_fun_ref
> nc_key_grf;
typedef composite_key<
test_nc_class,
nc_idn,
@@ -147,6 +171,9 @@ void test_key_extractors()
key_cm k_cm;
key_cmf k_cmf;
key_mf k_mf;
key_gf k_gf;
key_gcrf k_gcrf;
key_grf k_grf;
compkey cmpk;
ccompkey ccmpk;
ccompw_key ccmpk_w;
@@ -329,6 +356,71 @@ void test_key_extractors()
BOOST_CHECK(!k_mf(tpp));
BOOST_CHECK(!k_mf(tap));
BOOST_CHECK(!k_mf(tw));
BOOST_CHECK(k_gf(tr));
BOOST_CHECK(k_gf(ctr));
#if !defined(BOOST_NO_SFINAE)
BOOST_CHECK(k_gf(td));
BOOST_CHECK(k_gf(ctdr));
#endif
BOOST_CHECK(k_gf(tp));
BOOST_CHECK(k_gf(ctp));
#if !defined(BOOST_NO_SFINAE)
BOOST_CHECK(k_gf(tdp));
BOOST_CHECK(k_gf(ctdp));
#endif
BOOST_CHECK(k_gf(tpp));
BOOST_CHECK(k_gf(ctpp));
BOOST_CHECK(k_gf(tap));
BOOST_CHECK(k_gf(ctap));
BOOST_CHECK(k_gf(tw));
BOOST_CHECK(k_gf(ctw));
BOOST_CHECK(!k_gcrf(tr));
BOOST_CHECK(!k_gcrf(ctr));
#if !defined(BOOST_NO_SFINAE)
BOOST_CHECK(!k_gcrf(td));
BOOST_CHECK(!k_gcrf(ctdr));
#endif
BOOST_CHECK(!k_gcrf(tp));
BOOST_CHECK(!k_gcrf(ctp));
#if !defined(BOOST_NO_SFINAE)
BOOST_CHECK(!k_gcrf(tdp));
BOOST_CHECK(!k_gcrf(ctdp));
#endif
BOOST_CHECK(!k_gcrf(tpp));
BOOST_CHECK(!k_gcrf(ctpp));
BOOST_CHECK(!k_gcrf(tap));
BOOST_CHECK(!k_gcrf(ctap));
BOOST_CHECK(!k_gcrf(tw));
BOOST_CHECK(!k_gcrf(ctw));
BOOST_CHECK(k_grf(tr));
#if !defined(BOOST_NO_SFINAE)
BOOST_CHECK(k_grf(td));
#endif
BOOST_CHECK(k_grf(tp));
#if !defined(BOOST_NO_SFINAE)
BOOST_CHECK(k_grf(tdp));
#endif
BOOST_CHECK(k_grf(tpp));
BOOST_CHECK(k_grf(tap));
BOOST_CHECK(k_grf(tw));
BOOST_CHECK(ccmpk_w(tw)==make_tuple(false));
#if !defined(BOOST_NO_SFINAE)
@@ -342,6 +434,8 @@ void test_key_extractors()
nc_ckey_m nc_ck_m;
nc_key_cmf nc_k_cmf;
nc_key_mf nc_k_mf;
nc_key_gcrf nc_k_gcrf;
nc_key_grf nc_k_grf;
nc_compkey nc_cmpk;
test_nc_derived_class nc_td(-1,0);
@@ -357,6 +451,9 @@ void test_key_extractors()
BOOST_CHECK(nc_k_cmf(nc_td));
BOOST_CHECK(!nc_k_mf(nc_td));
BOOST_CHECK(!nc_k_gcrf(nc_td));
BOOST_CHECK(nc_k_grf(nc_td));
test_nc_class nc_t(1,0);
BOOST_CHECK(nc_cmpk(nc_td)==make_tuple(boost::cref(nc_t),1,1,true));
#endif
@@ -370,6 +467,9 @@ void test_key_extractors()
BOOST_CHECK(k_cm(it)==j);
BOOST_CHECK(k_cmf(it));
BOOST_CHECK(!k_mf(it));
BOOST_CHECK(k_gf(it));
BOOST_CHECK(!k_gcrf(it));
BOOST_CHECK(k_grf(it));
BOOST_CHECK(cmpk(it)==make_tuple(test_class(j),j,j,true));
BOOST_CHECK(ccmpk(it)==make_tuple(test_class(j),j));
++j;
+31 -1
View File
@@ -1,6 +1,6 @@
/* Boost.MultiIndex test for modifier memfuns.
*
* Copyright 2003-2006 Joaqu M Lez Muz.
* 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)
@@ -11,9 +11,12 @@
#include "test_modifiers.hpp"
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/next_prior.hpp>
#include <iterator>
#include <vector>
#include "pre_multi_index.hpp"
#include "employee.hpp"
#include <boost/next_prior.hpp>
#include <boost/test/test_tools.hpp>
class always_one
@@ -283,4 +286,31 @@ void test_modifiers()
aoc.insert(always_one());
aoc.erase(*(aoc.begin()));
BOOST_CHECK(aoc.empty());
/* Testcases for compliance with "as close to hint as possible"
* proposed behavior for associative containers:
* http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#233
* http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1780.html
*/
typedef multi_index_container<
int,
indexed_by<
ordered_non_unique<identity<int> >
>
> int_non_unique_container;
int_non_unique_container c;
c.insert(0);c.insert(0);
c.insert(1);c.insert(1);
c.insert(2);c.insert(2);
BOOST_CHECK(std::distance(c.begin(),c.insert(c.begin(),1))==2);
BOOST_CHECK(std::distance(c.begin(),c.insert(boost::next(c.begin()),1))==2);
BOOST_CHECK(std::distance(c.begin(),c.insert(c.lower_bound(1),1))==2);
BOOST_CHECK(
std::distance(c.begin(),c.insert(boost::next(c.lower_bound(1)),1))==3);
BOOST_CHECK(std::distance(c.begin(),c.insert(c.upper_bound(1),1))==8);
BOOST_CHECK(std::distance(c.begin(),c.insert(boost::prior(c.end()),1))==9);
BOOST_CHECK(std::distance(c.begin(),c.insert(c.end(),1))==10);
}
+3 -1
View File
@@ -104,15 +104,17 @@ void test_range()
std::bind1st(std::less<int>(),7), /* 7 < x */
std::bind2nd(std::less_equal<int>(),7)); /* x <= 7 */
CHECK_VOID_RANGE(p);
BOOST_CHECK(p.first==is.upper_bound(7));
p=is.range(
std::bind1st(std::less_equal<int>(),8), /* 8 <= x */
std::bind2nd(std::less<int>(),2)); /* x < 2 */
CHECK_VOID_RANGE(p);
BOOST_CHECK(p.first==is.lower_bound(8));
p=is.range(
std::bind1st(std::less<int>(),4), /* 4 < x */
std::bind2nd(std::less<int>(),5)); /* x < 5 */
CHECK_VOID_RANGE(p);
BOOST_CHECK(p.first!=is.end()&&p.second!=is.end());
BOOST_CHECK(p.first!=is.end());
}
+2 -1
View File
@@ -17,6 +17,7 @@
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/multi_index/random_access_index.hpp>
#include <boost/next_prior.hpp>
#include <boost/ref.hpp>
#include <boost/test/test_tools.hpp>
#include <vector>
@@ -87,7 +88,7 @@ static void local_test_rearrange(BOOST_EXPLICIT_TEMPLATE_TYPE(Sequence))
CHECK_EQUAL(sc,{3 _ 2 _ 4 _ 5 _ 0 _ 1});
BOOST_CHECK(std::distance(it,it2)==3);
sc.relocate(--(sc.end()),it,it2);
sc.relocate(boost::prior(sc.end()),it,it2);
CHECK_EQUAL(sc,{3 _ 0 _ 2 _ 4 _ 5 _ 1});
std::vector<boost::reference_wrapper<const value_type> > v;
+3 -1
View File
@@ -1,6 +1,6 @@
/* Boost.MultiIndex test for serialization.
*
* Copyright 2003-2006 Joaqu M Lez Muz.
* 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)
@@ -11,9 +11,11 @@
#include "test_serialization.hpp"
#include "test_serialization1.hpp"
#include "test_serialization2.hpp"
#include "test_serialization3.hpp"
void test_serialization()
{
test_serialization1();
test_serialization2();
test_serialization3();
}
+5 -3
View File
@@ -1,6 +1,6 @@
/* Boost.MultiIndex test for serialization, part 1.
*
* Copyright 2003-2006 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)
@@ -8,7 +8,7 @@
* See http://www.boost.org/libs/multi_index for library home page.
*/
#include "test_serialization.hpp"
#include "test_serialization1.hpp"
#include "test_serialization_template.hpp"
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
@@ -16,6 +16,7 @@
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/multi_index/random_access_index.hpp>
#include <boost/multi_index/key_extractors.hpp>
#include "non_std_allocator.hpp"
using namespace boost::multi_index;
@@ -49,7 +50,8 @@ void test_serialization1()
random_access<>,
sequenced<>,
ordered_non_unique<identity<int> >
>
>,
non_std_allocator<int>
> multi_index_t;
multi_index_t m;
+5 -84
View File
@@ -1,6 +1,6 @@
/* Boost.MultiIndex test for serialization, part 2.
*
* Copyright 2003-2006 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)
@@ -8,97 +8,18 @@
* See http://www.boost.org/libs/multi_index for library home page.
*/
#include "test_serialization.hpp"
#include "test_serialization2.hpp"
#include "test_serialization_template.hpp"
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/multi_index/random_access_index.hpp>
#include <boost/multi_index/key_extractors.hpp>
#include "non_std_allocator.hpp"
#include "pair_of_ints.hpp"
using namespace boost::multi_index;
void test_hashed_index_serialization()
{
const int N=100;
const int SHUFFLE=10232;
typedef multi_index_container<
int,
indexed_by<
hashed_unique<identity<int> >,
sequenced<>
>
> hashed_set;
typedef hashed_set::iterator iterator;
typedef hashed_set::local_iterator local_iterator;
hashed_set hs;
for(int i=0;i<N;++i){
hs.insert(i*SHUFFLE);
}
std::ostringstream oss;
{
boost::archive::text_oarchive oa(oss);
oa<<const_cast<const hashed_set&>(hs);
std::vector<iterator> its(N);
for(int i=0;i<N;++i){
iterator it=hs.find(i*SHUFFLE);
its.push_back(it);
oa<<const_cast<const iterator&>(its.back());
}
iterator it=hs.end();
oa<<const_cast<const iterator&>(it);
std::vector<local_iterator> lits(2*N);
for(std::size_t buc=0;buc<hs.bucket_count();++buc){
for(local_iterator lit=hs.begin(buc),lit_end=hs.end(buc);
lit!=lit_end;++lit){
oa<<*lit;
lits.push_back(lit);
oa<<const_cast<const local_iterator&>(lits.back());
}
local_iterator lit2=hs.end(buc);
lits.push_back(lit2);
oa<<const_cast<const local_iterator&>(lits.back());
}
}
hashed_set hs2;
std::istringstream iss(oss.str());
boost::archive::text_iarchive ia(iss);
ia>>hs2;
BOOST_CHECK(get<1>(hs)==get<1>(hs2));
for(int j=0;j<N;++j){
iterator it;
ia>>it;
BOOST_CHECK(*it==j*SHUFFLE);
}
iterator it;
ia>>it;
BOOST_CHECK(it==hs2.end());
for(std::size_t buc=0;buc<hs2.bucket_count();++buc){
for(std::size_t k=0;k<hs2.bucket_size(buc);++k){
int n;
local_iterator it;
ia>>n;
ia>>it;
BOOST_CHECK(*it==n);
}
local_iterator it2;
ia>>it2;
BOOST_CHECK(it2==hs2.end(buc));
}
}
void test_serialization2()
{
{
@@ -113,7 +34,8 @@ void test_serialization2()
>,
random_access<>,
sequenced<>
>
>,
non_std_allocator<pair_of_ints>
> multi_index_t;
multi_index_t m;
@@ -156,5 +78,4 @@ void test_serialization2()
m.insert(pair_of_ints(3,2));
test_serialization(m);
}
test_hashed_index_serialization();
}
+99
View File
@@ -0,0 +1,99 @@
/* Boost.MultiIndex test for serialization, part 3.
*
* Copyright 2003-2007 Joaquín M López Muñoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/multi_index for library home page.
*/
#include "test_serialization3.hpp"
#include "test_serialization_template.hpp"
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/multi_index/key_extractors.hpp>
#include "non_std_allocator.hpp"
using namespace boost::multi_index;
void test_serialization3()
{
const int N=100;
const int SHUFFLE=10232;
typedef multi_index_container<
int,
indexed_by<
hashed_unique<identity<int> >,
sequenced<>
>,
non_std_allocator<int>
> hashed_set;
typedef hashed_set::iterator iterator;
typedef hashed_set::local_iterator local_iterator;
hashed_set hs;
for(int i=0;i<N;++i){
hs.insert(i*SHUFFLE);
}
std::ostringstream oss;
{
boost::archive::text_oarchive oa(oss);
oa<<const_cast<const hashed_set&>(hs);
std::vector<iterator> its(N);
for(int i=0;i<N;++i){
iterator it=hs.find(i*SHUFFLE);
its.push_back(it);
oa<<const_cast<const iterator&>(its.back());
}
iterator it=hs.end();
oa<<const_cast<const iterator&>(it);
std::vector<local_iterator> lits(2*N);
for(std::size_t buc=0;buc<hs.bucket_count();++buc){
for(local_iterator lit=hs.begin(buc),lit_end=hs.end(buc);
lit!=lit_end;++lit){
oa<<*lit;
lits.push_back(lit);
oa<<const_cast<const local_iterator&>(lits.back());
}
local_iterator lit2=hs.end(buc);
lits.push_back(lit2);
oa<<const_cast<const local_iterator&>(lits.back());
}
}
hashed_set hs2;
std::istringstream iss(oss.str());
boost::archive::text_iarchive ia(iss);
ia>>hs2;
BOOST_CHECK(boost::multi_index::get<1>(hs)==boost::multi_index::get<1>(hs2));
for(int j=0;j<N;++j){
iterator it;
ia>>it;
BOOST_CHECK(*it==j*SHUFFLE);
}
iterator it;
ia>>it;
BOOST_CHECK(it==hs2.end());
for(std::size_t buc=0;buc<hs2.bucket_count();++buc){
for(std::size_t k=0;k<hs2.bucket_size(buc);++k){
int n;
local_iterator it;
ia>>n;
ia>>it;
BOOST_CHECK(*it==n);
}
local_iterator it2;
ia>>it2;
BOOST_CHECK(it2==hs2.end(buc));
}
}
+11
View File
@@ -0,0 +1,11 @@
/* Boost.MultiIndex test for serialization, part 3.
*
* Copyright 2003-2007 Joaquín M López Muñoz.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* See http://www.boost.org/libs/multi_index for library home page.
*/
void test_serialization3();
+4 -8
View File
@@ -1,6 +1,6 @@
/* Boost.MultiIndex serialization tests template.
*
* Copyright 2003-2006 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)
@@ -26,9 +26,7 @@ struct all_indices_equal_helper
static bool compare(
const MultiIndexContainer& m1,const MultiIndexContainer& m2)
{
using namespace boost::multi_index;
if(!(get<N>(m1)==get<N>(m2))){
if(!(boost::multi_index::get<N>(m1)==boost::multi_index::get<N>(m2))){
return false;
}
return all_indices_equal_helper<N-1>::compare(m1,m2);
@@ -60,8 +58,6 @@ bool all_indices_equal(
template<class MultiIndexContainer>
void test_serialization(const MultiIndexContainer& m)
{
using namespace boost::multi_index;
typedef typename MultiIndexContainer::iterator iterator;
typedef typename MultiIndexContainer::const_iterator const_iterator;
@@ -100,10 +96,10 @@ void test_serialization(const MultiIndexContainer& m)
iterator it4;
it4=--it2;
BOOST_CHECK(it==it4);
BOOST_CHECK(it==project<0>(m2,it4));
BOOST_CHECK(it==boost::multi_index::project<0>(m2,it4));
}
iterator it2;
ia>>it2;
BOOST_CHECK(it_end==it2);
BOOST_CHECK(it_end==project<0>(m2,it2));
BOOST_CHECK(it_end==boost::multi_index::project<0>(m2,it2));
}
+39 -18
View File
@@ -1,6 +1,6 @@
/* Boost.MultiIndex test for replace(), modify() and modify_key().
*
* Copyright 2003-2006 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)
@@ -15,6 +15,7 @@
#include "pre_multi_index.hpp"
#include "employee.hpp"
#include "pair_of_ints.hpp"
#include <boost/next_prior.hpp>
#include <boost/test/test_tools.hpp>
using namespace boost::multi_index;
@@ -64,34 +65,44 @@ void test_update()
BOOST_CHECK(!ii2.replace(ii2.begin(),pair_of_ints(0,5)));
BOOST_CHECK(!ii1.replace(project<1>(iis,iis.begin()),pair_of_ints(5,11)));
BOOST_CHECK(!iis.replace(iis.begin(),pair_of_ints(11,5)));
BOOST_CHECK(!iis.replace(++iis.begin(),pair_of_ints(10,5)));
BOOST_CHECK(!iis.replace(boost::next(iis.begin()),pair_of_ints(10,5)));
BOOST_CHECK(!ii1.replace(
project<1>(iis,++iis.begin()),pair_of_ints(5,10)));
BOOST_CHECK(!iis.replace(--iis.end(),pair_of_ints(5,10)));
BOOST_CHECK(!ii2.replace(--ii2.end(),pair_of_ints(10,5)));
project<1>(iis,boost::next(iis.begin())),pair_of_ints(5,10)));
BOOST_CHECK(!iis.replace(boost::prior(iis.end()),pair_of_ints(5,10)));
BOOST_CHECK(!ii2.replace(boost::prior(ii2.end()),pair_of_ints(10,5)));
BOOST_CHECK(iis.modify(iis.begin(),increment_first));
BOOST_CHECK(ii2.modify(ii2.begin(),increment_first));
BOOST_CHECK(ii1.modify(project<1>(iis,iis.begin()),increment_first));
BOOST_CHECK(ii2.modify(ii2.begin(),increment_first));
BOOST_CHECK(ii2.modify(ii2.begin(),increment_first,decrement_first));
BOOST_CHECK(!iis.modify(iis.begin(),increment_first,decrement_first));
BOOST_CHECK(iis.size()==3);
BOOST_CHECK(!iis.modify(iis.begin(),increment_first));
BOOST_CHECK(iis.size()==2);
iis.insert(pair_of_ints(0,0));
BOOST_CHECK(ii2.modify(--ii2.end(),increment_second));
BOOST_CHECK(iis.modify(iis.begin(),increment_second));
BOOST_CHECK(ii2.modify(--ii2.end(),increment_second));
BOOST_CHECK(ii2.modify(boost::prior(ii2.end()),increment_second));
BOOST_CHECK(iis.modify(iis.begin(),increment_second));
BOOST_CHECK(ii2.modify(boost::prior(ii2.end()),increment_second));
BOOST_CHECK(iis.modify(iis.begin(),increment_second,decrement_second));
BOOST_CHECK(!ii2.modify(--ii2.end(),increment_second));
BOOST_CHECK(!ii2.modify(
boost::prior(ii2.end()),increment_second,decrement_second));
BOOST_CHECK(ii2.size()==3);
BOOST_CHECK(!ii2.modify(boost::prior(ii2.end()),increment_second));
BOOST_CHECK(ii2.size()==2);
iis.insert(pair_of_ints(0,0));
BOOST_CHECK(iis.modify_key(iis.begin(),increment_int));
BOOST_CHECK(iis.modify_key(iis.begin(),increment_int,decrement_int));
BOOST_CHECK(iis.modify_key(iis.begin(),increment_int));
BOOST_CHECK(iis.modify_key(iis.begin(),increment_int));
BOOST_CHECK(iis.modify_key(iis.begin(),increment_int));
BOOST_CHECK(!iis.modify_key(iis.begin(),increment_int,decrement_int));
BOOST_CHECK(iis.size()==3);
BOOST_CHECK(!iis.modify_key(iis.begin(),increment_int));
BOOST_CHECK(iis.size()==2);
@@ -99,8 +110,11 @@ void test_update()
nth_index_iterator<int_int_set,1>::type it=ii1.find(5);
BOOST_CHECK(ii1.modify_key(it,increment_int));
BOOST_CHECK(ii1.modify_key(it,increment_int));
BOOST_CHECK(ii1.modify_key(it,increment_int,decrement_int));
BOOST_CHECK(ii1.modify_key(it,increment_int));
BOOST_CHECK(ii1.modify_key(it,increment_int));
BOOST_CHECK(!ii1.modify_key(it,increment_int,decrement_int));
BOOST_CHECK(ii1.size()==2);
BOOST_CHECK(!ii1.modify_key(it,increment_int));
BOOST_CHECK(ii1.size()==1);
@@ -127,23 +141,30 @@ void test_update()
BOOST_CHECK(!iis.replace(p2,pair_of_ints(10,5)));
BOOST_CHECK(!iis.replace(p2,pair_of_ints(5,10)));
BOOST_CHECK(!iis.replace(p3,pair_of_ints(5,10)));
BOOST_CHECK(!ii1.replace(--ii1.end(),pair_of_ints(10,5)));
BOOST_CHECK(!ii1.replace(boost::prior(ii1.end()),pair_of_ints(10,5)));
BOOST_CHECK(iis.modify(p1,increment_first));
BOOST_CHECK(ii1.modify(ii1.begin(),increment_first));
BOOST_CHECK(iis.modify(p1,increment_first));
BOOST_CHECK(ii1.modify(ii1.begin(),increment_first));
BOOST_CHECK(ii1.modify(ii1.begin(),increment_first,decrement_first));
BOOST_CHECK(!iis.modify(p1,increment_first,decrement_first));
BOOST_CHECK(iis.size()==3);
BOOST_CHECK(!iis.modify(p1,increment_first));
BOOST_CHECK(iis.size()==2);
p1=iis.insert(pair_of_ints(0,0)).first;
BOOST_CHECK(ii1.modify(--ii1.end(),increment_second));
BOOST_CHECK(iis.modify(p1,increment_second));
BOOST_CHECK(ii1.modify(--ii1.end(),increment_second));
BOOST_CHECK(ii1.modify(boost::prior(ii1.end()),increment_second));
BOOST_CHECK(iis.modify(p1,increment_second,decrement_second));
BOOST_CHECK(ii1.modify(boost::prior(ii1.end()),increment_second));
BOOST_CHECK(iis.modify(p1,increment_second));
BOOST_CHECK(!ii1.modify(--ii1.end(),increment_second));
BOOST_CHECK(!ii1.modify(
boost::prior(ii1.end()),increment_second,decrement_second));
BOOST_CHECK(ii1.size()==3);
BOOST_CHECK(!ii1.modify(boost::prior(ii1.end()),increment_second));
BOOST_CHECK(ii1.size()==2);
}
}