mirror of
https://github.com/boostorg/multi_index.git
synced 2025-05-09 23:14:04 +00:00
made multi_index_container AllocatorAware (#30)
This commit is contained in:
parent
89b4ff7bbf
commit
a8d34a56f7
@ -37,6 +37,7 @@ We list some of the possible limitations along with suitable workarounds when av
|
||||
|
||||
<ul>
|
||||
<li><a href="#move">Move semantics</a></li>
|
||||
<li><a href="#allocator_awareness">Allocator awareness</a></li>
|
||||
<li><a href="#emplace">Emplace functions</a></li>
|
||||
<li><a href="#initializer_list">Initializer lists</a></li>
|
||||
<li><a href="#tuple">Tuples</a></li>
|
||||
@ -59,6 +60,17 @@ increased efficiency in insertion and handling of moveable-only elements will
|
||||
require that <code>Value</code> be suitably instrumented.
|
||||
</p>
|
||||
|
||||
<h2><a name="allocator_awareness">Allocator awareness</a></h2>
|
||||
|
||||
<p>
|
||||
In pre-C++11 compilers or defective environments without proper
|
||||
<a href="https://en.cppreference.com/w/cpp/named_req/AllocatorAwareContainer">allocator
|
||||
awareness</a> machinery (basically, <code>std::allocator_traits</code>),
|
||||
Boost.MultiIndex behaves as if
|
||||
<code>std::allocator_traits<allocator_type>::propagate_on_container_*::value</code>
|
||||
were <code>false</code> for all allocators.
|
||||
</p>
|
||||
|
||||
<h2><a name="emplace">Emplace functions</a></h2>
|
||||
|
||||
<p>
|
||||
@ -377,9 +389,9 @@ Performance
|
||||
|
||||
<br>
|
||||
|
||||
<p>Revised August 20th 2014</p>
|
||||
<p>Revised January 25th 2020</p>
|
||||
|
||||
<p>© Copyright 2003-2014 Joaquín M López Muñoz.
|
||||
<p>© Copyright 2003-2020 Joaquín M López Muñoz.
|
||||
Distributed under the Boost Software
|
||||
License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">
|
||||
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
|
||||
|
@ -305,6 +305,12 @@ operators and functions associated with the index (vg. comparison and
|
||||
<span class=keyword>const</span> <span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>&</span> <span class=identifier>x</span><span class=special>);</span>
|
||||
<span class=identifier>multi_index_container</span><span class=special>(</span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>&&</span> <span class=identifier>x</span><span class=special>);</span>
|
||||
<span class=identifier>multi_index_container</span><span class=special>(</span>
|
||||
<span class=keyword>const</span> <span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>&</span> <span class=identifier>x</span><span class=special>,</span>
|
||||
<span class=keyword>const</span> <span class=identifier>allocator_type</span><span class=special>&</span> <span class=identifier>al</span><span class=special>);</span>
|
||||
<span class=identifier>multi_index_container</span><span class=special>(</span>
|
||||
<span class=identifier>multi_index_container</span><span class=special><</span><span class=identifier>Value</span><span class=special>,</span><span class=identifier>IndexSpecifierList</span><span class=special>,</span><span class=identifier>Allocator</span><span class=special>>&&</span> <span class=identifier>x</span><span class=special>,</span>
|
||||
<span class=keyword>const</span> <span class=identifier>allocator_type</span><span class=special>&</span> <span class=identifier>al</span><span class=special>);</span>
|
||||
|
||||
<span class=special>~</span><span class=identifier>multi_index_container</span><span class=special>();</span>
|
||||
|
||||
@ -747,7 +753,7 @@ of the <code>multi_index_container</code> is preserved as well.<br>
|
||||
multi_index_container<Value,IndexSpecifierList,Allocator>&& x);</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Effects:</b> Constructs a <code>multi_index_container</code> by moving the
|
||||
<b>Effects:</b> Constructs a <code>multi_index_container</code> by transferring the
|
||||
elements of <code>x</code> and copying its internal objects (those specified
|
||||
in <code>ctor_args_list</code> and the allocator.)<br>
|
||||
<b>Postconditions:</b> If <code>x==y</code> just
|
||||
@ -756,7 +762,43 @@ of the <code>multi_index_container</code> is preserved as well.<br>
|
||||
<b>Complexity:</b> Constant.
|
||||
</blockquote>
|
||||
|
||||
<code>multi_index_container(<br>
|
||||
const multi_index_container<Value,IndexSpecifierList,Allocator>& x,<br>
|
||||
const allocator_type& al);</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>Value</code> is <code>CopyInsertable</code> into
|
||||
<code>multi_index_container</code>.<br>
|
||||
<b>Effects:</b> Constructs a copy of <code>x</code>, copying its
|
||||
elements and its internal objects (those specified
|
||||
in <code>ctor_args_list</code>) and using a copy of the allocator
|
||||
<code>al</code> provided.<br>
|
||||
<b>Postconditions:</b> <code>*this==x</code>. The order on every index
|
||||
of the <code>multi_index_container</code> is preserved as well.<br>
|
||||
<b>Complexity:</b> <code>O(x.size()*log(x.size()) + C(x.size()))</code>.
|
||||
</blockquote>
|
||||
|
||||
<code>multi_index_container(<br>
|
||||
multi_index_container<Value,IndexSpecifierList,Allocator>&& x,<br>
|
||||
const allocator_type& al);</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>Value</code> is <code>MoveInsertable</code> into
|
||||
<code>multi_index_container</code>.<br>
|
||||
<b>Effects:</b> Constructs a <code>multi_index_container</code> by transferring/moving
|
||||
the elements of <code>x</code>, copying its internal objects (those specified
|
||||
in <code>ctor_args_list</code>) and using a copy of the allocator
|
||||
<code>al</code> provided. If <code>x.get_allocator()==al</code>, elements are transferred
|
||||
(no constructions involved), otherwise they are move constructed from <code>x</code>.<br>
|
||||
<b>Postconditions:</b> If <code>x==y</code> just
|
||||
before the movement, <code>*this==y</code>. The order on every index
|
||||
of the <code>multi_index_container</code> is preserved as well.<br>
|
||||
<b>Complexity:</b> Constant if <code>x.get_allocator()==al</code>, otherwise
|
||||
<code>O(x.size()*log(x.size()) + C(x.size()))</code>.
|
||||
</blockquote>
|
||||
|
||||
<code>~multi_index_container()</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Effects:</b> Destroys the <code>multi_index_container</code> and all the elements
|
||||
contained. The order in which the elements are destroyed is not specified.<br>
|
||||
@ -769,8 +811,12 @@ contained. The order in which the elements are destroyed is not specified.<br>
|
||||
<blockquote>
|
||||
<b>Requires:</b> <code>Value</code> is <code>CopyInsertable</code> into
|
||||
<code>multi_index_container</code>.<br>
|
||||
<b>Effects:</b> Replaces the elements and internal objects of the <code>multi_index_container</code>
|
||||
with copies from <code>x</code>.<br>
|
||||
<b>Effects:</b> Replaces the elements and internal objects (those specified
|
||||
in <code>ctor_args_list</code>) of the <code>multi_index_container</code>
|
||||
with copies from <code>x</code>. The internal allocator is replaced with a
|
||||
copy of <code>x.get_allocator()</code> if and only if
|
||||
<code>std::allocator_traits<allocator_type>::propagate_on_container_copy_assignment::value</code>
|
||||
is <code>true</code>.<br>
|
||||
<b>Postconditions:</b> <code>*this==x</code>. The order on every index
|
||||
of the <code>multi_index_container</code> is preserved as well.<br>
|
||||
<b>Returns:</b> <code>*this</code>.<br>
|
||||
@ -784,14 +830,27 @@ of the types of <code>ctor_args_list</code> do not throw.
|
||||
multi_index_container<Value,IndexSpecifierList,Allocator>&& x);</code>
|
||||
|
||||
<blockquote>
|
||||
<b>Requires:</b> If <code>std::allocator_traits<allocator_type>::propagate_on_container_move_assignment::value</code>
|
||||
is <code>true</code>, <code>Value</code> is <code>MoveInsertable</code> into
|
||||
<code>multi_index_container</code>.<br>
|
||||
<b>Effects:</b> Replaces the elements of <code>multi_index_container</code>
|
||||
with those of <code>x</code> and its internal objects with copies from the
|
||||
corresponding objects in <code>x</code>.<br>
|
||||
with those of <code>x</code> or with copies move-constructed from those of <code>x</code>.
|
||||
Replaces the internal objects (those specified
|
||||
in <code>ctor_args_list</code>) with copies from the
|
||||
corresponding objects in <code>x</code>. Replaces the internal allocator with a
|
||||
copy of <code>x.get_allocator()</code> if and only if
|
||||
<code>std::allocator_traits<allocator_type>::propagate_on_container_move_assignment::value</code>
|
||||
is <code>true</code>.
|
||||
Elements of <code>x</code> are transferred (no constructions involved) if and only if
|
||||
<code>x.get_allocator()</code> is copied or is equal to the previous value of the internal
|
||||
allocator.
|
||||
<br>
|
||||
<b>Postconditions:</b> If <code>x==y</code> just
|
||||
before the movement, <code>*this==y</code>. The order on every index
|
||||
of the <code>multi_index_container</code> is preserved as well.<br>
|
||||
<b>Returns:</b> <code>*this</code>.<br>
|
||||
<b>Complexity:</b> <code>O(n)</code>.<br>
|
||||
<b>Complexity:</b> <code>O(n)</code> if elements of <code>x</code> are transferred,
|
||||
otherwise <code>O(n + x.size()*log(x.size()) + C(x.size()))</code>.<br>
|
||||
<b>Exception safety:</b> Strong, provided the copy and assignment operations
|
||||
of the types of <code>ctor_args_list</code> do not throw.
|
||||
</blockquote>
|
||||
@ -1001,9 +1060,9 @@ Index reference
|
||||
|
||||
<br>
|
||||
|
||||
<p>Revised April 13th 2018</p>
|
||||
<p>Revised January 25th 2020</p>
|
||||
|
||||
<p>© Copyright 2003-2018 Joaquín M López Muñoz.
|
||||
<p>© Copyright 2003-2020 Joaquín M López Muñoz.
|
||||
Distributed under the Boost Software
|
||||
License, Version 1.0. (See accompanying file <a href="../../../../LICENSE_1_0.txt">
|
||||
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
|
||||
|
@ -66,6 +66,9 @@ Acknowledgements
|
||||
|
||||
<p>
|
||||
<ul>
|
||||
<li><code>multi_index_container</code> is now
|
||||
<a href="https://en.cppreference.com/w/cpp/named_req/AllocatorAwareContainer"><code>AllocatorAware</code></a>.
|
||||
</li>
|
||||
<li>Swapping of internal <code>KeyFromValue</code>, <code>Compare</code>, <code>Hash</code>
|
||||
and <code>Pred</code> objects now selects the appropriate <code>swap</code>
|
||||
function between <code>std::swap</code> and ADL candidates,
|
||||
@ -654,7 +657,7 @@ Acknowledgements
|
||||
|
||||
<br>
|
||||
|
||||
<p>Revised January 21st 2020</p>
|
||||
<p>Revised January 25th 2020</p>
|
||||
|
||||
<p>© Copyright 2003-2020 Joaquín M López Muñoz.
|
||||
Distributed under the Boost Software
|
||||
|
@ -43,100 +43,105 @@ with some of the least common features offered by Boost.MultiIndex.
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="../test/test_alloc_awareness.cpp"><code>test_alloc_awareness.cpp</code></a></td>
|
||||
<td>Checks <a href="https://en.cppreference.com/w/cpp/named_req/AllocatorAwareContainer">allocator
|
||||
awareness</a>.</td>
|
||||
</tr>
|
||||
<tr class="odd_tr">
|
||||
<td><a href="../test/test_basic.cpp"><code>test_basic.cpp</code></a></td>
|
||||
<td>Simple program along the lines of the employees example studied in the
|
||||
tutorial.</td>
|
||||
</tr>
|
||||
<tr class="odd_tr">
|
||||
<tr>
|
||||
<td><a href="../test/test_capacity.cpp"><code>test_capacity.cpp</code></a></td>
|
||||
<td><code>empty</code>, <code>size</code>, <code>resize</code>
|
||||
(non key-based indices) and <code>reserve</code>/<code>capacity</code>
|
||||
(random access indices only).</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr class="odd_tr">
|
||||
<td><a href="../test/test_comparison.cpp"><code>test_comparison.cpp</code></a></td>
|
||||
<td>Comparison between indices.</td>
|
||||
</tr>
|
||||
<tr class="odd_tr">
|
||||
<tr>
|
||||
<td><a href="../test/test_composite_key.cpp"><code>test_composite_key.cpp</code></a></td>
|
||||
<td><code>composite_key</code> and <code>composite_key_compare</code>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr class="odd_tr">
|
||||
<td><a href="../test/test_conv_iterators.cpp"><code>test_conv_iterators.cpp</code></a></td>
|
||||
<td>Checks convertibility of non-constant to constant iterators.</td>
|
||||
</tr>
|
||||
<tr class="odd_tr">
|
||||
<tr>
|
||||
<td><a href="../test/test_copy_assignment.cpp"><code>test_copy_assignment.cpp</code></a></td>
|
||||
<td>Various forms of assignment: copy, <code>operator =</code>, insertion,
|
||||
(non key-based indices only) <code>assign</code> .
|
||||
</tr>
|
||||
<tr>
|
||||
<tr class="odd_tr">
|
||||
<td><a href="../test/test_hash_ops.cpp"><code>test_hash_ops.cpp</code></a></td>
|
||||
<td>Hashing operations.</td>
|
||||
</tr>
|
||||
<tr class="odd_tr">
|
||||
<tr>
|
||||
<td><a href="../test/test_iterators.cpp"><code>test_iterators.cpp</code></a></td>
|
||||
<td>Constant and non-constant iterators and their reverse variants.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr class="odd_tr">
|
||||
<td><a href="../test/test_key.cpp"><code>test_key.cpp</code></a></td>
|
||||
<td>Terse key specification syntax.</td>
|
||||
</tr>
|
||||
<tr class="odd_tr">
|
||||
<tr>
|
||||
<td><a href="../test/test_key_extractors.cpp"><code>test_key_extractors.cpp</code></a></td>
|
||||
<td>Covers all use cases of key extractors shipped with the library.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr class="odd_tr">
|
||||
<td><a href="../test/test_list_ops.cpp"><code>test_list_ops.cpp</code></a></td>
|
||||
<td>List-like operations particular to sequenced and random access indices.</td>
|
||||
</tr>
|
||||
<tr class="odd_tr">
|
||||
<tr>
|
||||
<td><a href="../test/test_modifiers.cpp"><code>test_modifiers.cpp</code></a></td>
|
||||
<td>Checks the family of insertion and erasing operations.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr class="odd_tr">
|
||||
<td><a href="../test/test_mpl_ops.cpp"><code>test_mpl_ops.cpp</code></a></td>
|
||||
<td>Metaprogramming manipulations of <code>multi_index_container</code> types.</td>
|
||||
</tr>
|
||||
<tr class="odd_tr">
|
||||
<tr>
|
||||
<td><a href="../test/test_observers.cpp"><code>test_observers.cpp</code></a></td>
|
||||
<td>Checks observer member functions of ordered and hashed indices.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr class="odd_tr">
|
||||
<td><a href="../test/test_projection.cpp"><code>test_projection.cpp</code></a></td>
|
||||
<td>Projection of iterators among indices.</td>
|
||||
</tr>
|
||||
<tr class="odd_tr">
|
||||
<tr>
|
||||
<td><a href="../test/test_range.cpp"><code>test_range.cpp</code></a></td>
|
||||
<td>Exercises the <code>range</code> facility (ordered indices only).</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr class="odd_tr">
|
||||
<td><a href="../test/test_rank_ops.cpp"><code>test_rank_ops.cpp</code></a></td>
|
||||
<td>Specific operations of ranked indices.</td>
|
||||
</tr>
|
||||
<tr class="odd_tr">
|
||||
<tr>
|
||||
<td><a href="../test/test_rearrange.cpp"><code>test_rearrange.cpp</code></a></td>
|
||||
<td>Rearrange functions of sequenced and random access indices.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr class="odd_tr">
|
||||
<td><a href="../test/test_safe_mode.cpp"><code>test_safe_mode.cpp</code></a></td>
|
||||
<td>Comprehensive coverage of all conditions checked in safe mode.</td>
|
||||
</tr>
|
||||
<tr class="odd_tr">
|
||||
<tr>
|
||||
<td><a href="../test/test_serialization1.cpp"><code>test_serialization1.cpp</code></a><br>
|
||||
<a href="../test/test_serialization2.cpp"><code>test_serialization2.cpp</code></a><br>
|
||||
<a href="../test/test_serialization3.cpp"><code>test_serialization3.cpp</code></a></td>
|
||||
<td>Serialization support.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr class="odd_tr">
|
||||
<td><a href="../test/test_set_ops.cpp"><code>test_set_ops.cpp</code></a></td>
|
||||
<td>Set-like operations particular to ordered indices.</td>
|
||||
</tr>
|
||||
<tr class="odd_tr">
|
||||
<tr>
|
||||
<td><a href="../test/test_special_set_ops.cpp"><code>test_special_set_ops.cpp</code></a></td>
|
||||
<td>Checks special lookup operations using compatible sorting criteria.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr class="odd_tr">
|
||||
<td><a href="../test/test_update.cpp"><code>test_update.cpp</code></a></td>
|
||||
<td><code>replace</code>, <code>modify</code> and <code>modify_key</code>.</td>
|
||||
</tr>
|
||||
@ -157,9 +162,9 @@ Future work
|
||||
|
||||
<br>
|
||||
|
||||
<p>Revised August 17th 2018</p>
|
||||
<p>Revised January 25th 2020</p>
|
||||
|
||||
<p>© Copyright 2003-2018 Joaquín M López Muñoz.
|
||||
<p>© Copyright 2003-2020 Joaquín M López Muñoz.
|
||||
Distributed under the Boost Software
|
||||
License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">
|
||||
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2018 Joaquin M Lopez Munoz.
|
||||
/* Copyright 2003-2020 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@ -22,6 +22,7 @@
|
||||
#include <boost/move/core.hpp>
|
||||
#include <boost/move/utility_core.hpp>
|
||||
#include <boost/multi_index/detail/vartempl_support.hpp>
|
||||
#include <boost/type_traits/integral_constant.hpp>
|
||||
#include <new>
|
||||
#endif
|
||||
|
||||
@ -75,6 +76,10 @@ struct allocator_traits
|
||||
typedef typename Allocator::difference_type difference_type;
|
||||
typedef typename Allocator::size_type size_type;
|
||||
|
||||
typedef boost::false_type propagate_on_container_copy_assignment;
|
||||
typedef boost::false_type propagate_on_container_move_assignment;
|
||||
typedef boost::false_type propagate_on_container_swap;
|
||||
|
||||
template<typename T>
|
||||
struct rebind_alloc
|
||||
{
|
||||
@ -123,6 +128,11 @@ struct allocator_traits
|
||||
#endif
|
||||
|
||||
static size_type max_size(Allocator& a)BOOST_NOEXCEPT{return a.max_size();}
|
||||
|
||||
static Allocator select_on_container_copy_construction(const Allocator& a)
|
||||
{
|
||||
return a;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2018 Joaquin M Lopez Munoz.
|
||||
/* Copyright 2003-2020 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@ -18,6 +18,7 @@
|
||||
#include <boost/multi_index/detail/adl_swap.hpp>
|
||||
#include <boost/multi_index/detail/allocator_traits.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/type_traits/integral_constant.hpp>
|
||||
#include <memory>
|
||||
|
||||
namespace boost{
|
||||
@ -64,11 +65,25 @@ struct auto_space:private noncopyable
|
||||
|
||||
void swap(auto_space& x)
|
||||
{
|
||||
if(al_!=x.al_)adl_swap(al_,x.al_);
|
||||
swap(
|
||||
x,
|
||||
boost::integral_constant<
|
||||
bool,alloc_traits::propagate_on_container_swap::value>());
|
||||
}
|
||||
|
||||
void swap(auto_space& x,boost::true_type /* swap_allocators */)
|
||||
{
|
||||
adl_swap(al_,x.al_);
|
||||
std::swap(n_,x.n_);
|
||||
std::swap(data_,x.data_);
|
||||
}
|
||||
|
||||
void swap(auto_space& x,boost::false_type /* swap_allocators */)
|
||||
{
|
||||
std::swap(n_,x.n_);
|
||||
std::swap(data_,x.data_);
|
||||
}
|
||||
|
||||
private:
|
||||
allocator al_;
|
||||
size_type n_;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2018 Joaquin M Lopez Munoz.
|
||||
/* Copyright 2003-2020 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@ -173,6 +173,13 @@ public:
|
||||
spc.swap(x.spc);
|
||||
}
|
||||
|
||||
template<typename BoolConstant>
|
||||
void swap(bucket_array& x,BoolConstant swap_allocators)
|
||||
{
|
||||
std::swap(size_index_,x.size_index_);
|
||||
spc.swap(x.spc,swap_allocators);
|
||||
}
|
||||
|
||||
private:
|
||||
typedef auto_space<base_node_impl_type,Allocator> auto_space_type;
|
||||
typedef typename auto_space_type::size_type auto_space_size_type;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2018 Joaquin M Lopez Munoz.
|
||||
/* Copyright 2003-2020 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@ -17,6 +17,7 @@
|
||||
#include <algorithm>
|
||||
#include <boost/core/addressof.hpp>
|
||||
#include <boost/detail/no_exceptions_support.hpp>
|
||||
#include <boost/move/core.hpp>
|
||||
#include <boost/multi_index/detail/allocator_traits.hpp>
|
||||
#include <boost/multi_index/detail/auto_space.hpp>
|
||||
#include <boost/multi_index/detail/raw_ptr.hpp>
|
||||
@ -55,6 +56,18 @@ struct copy_map_entry
|
||||
}
|
||||
};
|
||||
|
||||
struct copy_map_value_copier
|
||||
{
|
||||
template<typename Value>
|
||||
const Value& operator()(Value& x)const{return x;}
|
||||
};
|
||||
|
||||
struct copy_map_value_mover
|
||||
{
|
||||
template<typename Value>
|
||||
BOOST_RV_REF(Value) operator()(Value& x)const{return boost::move(x);}
|
||||
};
|
||||
|
||||
template <typename Node,typename Allocator>
|
||||
class copy_map:private noncopyable
|
||||
{
|
||||
@ -88,27 +101,8 @@ public:
|
||||
const_iterator begin()const{return raw_ptr<const_iterator>(spc.data());}
|
||||
const_iterator end()const{return raw_ptr<const_iterator>(spc.data()+n);}
|
||||
|
||||
void clone(Node* node)
|
||||
{
|
||||
(spc.data()+n)->first=node;
|
||||
(spc.data()+n)->second=raw_ptr<Node*>(allocate());
|
||||
BOOST_TRY{
|
||||
alloc_traits::construct(
|
||||
al_,boost::addressof((spc.data()+n)->second->value()),node->value());
|
||||
}
|
||||
BOOST_CATCH(...){
|
||||
deallocate((spc.data()+n)->second);
|
||||
BOOST_RETHROW;
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
++n;
|
||||
|
||||
if(n==size_){
|
||||
std::sort(
|
||||
raw_ptr<copy_map_entry<Node>*>(spc.data()),
|
||||
raw_ptr<copy_map_entry<Node>*>(spc.data())+size_);
|
||||
}
|
||||
}
|
||||
void copy_clone(Node* node){clone(node,copy_map_value_copier());}
|
||||
void move_clone(Node* node){clone(node,copy_map_value_mover());}
|
||||
|
||||
Node* find(Node* node)const
|
||||
{
|
||||
@ -140,6 +134,30 @@ private:
|
||||
{
|
||||
alloc_traits::deallocate(al_,static_cast<pointer>(node),1);
|
||||
}
|
||||
|
||||
template<typename ValueAccess>
|
||||
void clone(Node* node,ValueAccess access)
|
||||
{
|
||||
(spc.data()+n)->first=node;
|
||||
(spc.data()+n)->second=raw_ptr<Node*>(allocate());
|
||||
BOOST_TRY{
|
||||
alloc_traits::construct(
|
||||
al_,boost::addressof((spc.data()+n)->second->value()),
|
||||
access(node->value()));
|
||||
}
|
||||
BOOST_CATCH(...){
|
||||
deallocate((spc.data()+n)->second);
|
||||
BOOST_RETHROW;
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
++n;
|
||||
|
||||
if(n==size_){
|
||||
std::sort(
|
||||
raw_ptr<copy_map_entry<Node>*>(spc.data()),
|
||||
raw_ptr<copy_map_entry<Node>*>(spc.data())+size_);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace multi_index::detail */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2018 Joaquin M Lopez Munoz.
|
||||
/* Copyright 2003-2020 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@ -162,7 +162,11 @@ protected:
|
||||
|
||||
void clear_(){}
|
||||
|
||||
void swap_(index_base<Value,IndexSpecifierList,Allocator>&){}
|
||||
template<typename BoolConstant>
|
||||
void swap_(
|
||||
index_base<Value,IndexSpecifierList,Allocator>&,
|
||||
BoolConstant /* swap_allocators */)
|
||||
{}
|
||||
|
||||
void swap_elements_(index_base<Value,IndexSpecifierList,Allocator>&){}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2019 Joaquin M Lopez Munoz.
|
||||
/* Copyright 2003-2020 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@ -771,9 +771,11 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename BoolConstant>
|
||||
void swap_(
|
||||
ordered_index_impl<
|
||||
KeyFromValue,Compare,SuperMeta,TagList,Category,AugmentPolicy>& x)
|
||||
KeyFromValue,Compare,SuperMeta,TagList,Category,AugmentPolicy>& x,
|
||||
BoolConstant swap_allocators)
|
||||
{
|
||||
adl_swap(key,x.key);
|
||||
adl_swap(comp_,x.comp_);
|
||||
@ -782,7 +784,7 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
|
||||
safe_super::swap(x);
|
||||
#endif
|
||||
|
||||
super::swap_(x);
|
||||
super::swap_(x,swap_allocators);
|
||||
}
|
||||
|
||||
void swap_elements_(
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2018 Joaquin M Lopez Munoz.
|
||||
/* Copyright 2003-2020 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@ -110,6 +110,14 @@ public:
|
||||
spc.swap(x.spc);
|
||||
}
|
||||
|
||||
template<typename BoolConstant>
|
||||
void swap(random_access_index_ptr_array& x,BoolConstant swap_allocators)
|
||||
{
|
||||
std::swap(size_,x.size_);
|
||||
std::swap(capacity_,x.capacity_);
|
||||
spc.swap(x.spc,swap_allocators);
|
||||
}
|
||||
|
||||
private:
|
||||
size_type size_;
|
||||
size_type capacity_;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2019 Joaquin M Lopez Munoz.
|
||||
/* Copyright 2003-2020 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@ -876,13 +876,15 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename BoolConstant>
|
||||
void swap_(
|
||||
hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x)
|
||||
hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,
|
||||
BoolConstant swap_allocators)
|
||||
{
|
||||
adl_swap(key,x.key);
|
||||
adl_swap(hash_,x.hash_);
|
||||
adl_swap(eq_,x.eq_);
|
||||
buckets.swap(x.buckets);
|
||||
buckets.swap(x.buckets,swap_allocators);
|
||||
std::swap(mlf,x.mlf);
|
||||
std::swap(max_load,x.max_load);
|
||||
|
||||
@ -890,7 +892,7 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
|
||||
safe_super::swap(x);
|
||||
#endif
|
||||
|
||||
super::swap_(x);
|
||||
super::swap_(x,swap_allocators);
|
||||
}
|
||||
|
||||
void swap_elements_(
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2018 Joaquin M Lopez Munoz.
|
||||
/* Copyright 2003-2020 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@ -823,15 +823,17 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
|
||||
#endif
|
||||
}
|
||||
|
||||
void swap_(random_access_index<SuperMeta,TagList>& x)
|
||||
template<typename BoolConstant>
|
||||
void swap_(
|
||||
random_access_index<SuperMeta,TagList>& x,BoolConstant swap_allocators)
|
||||
{
|
||||
ptrs.swap(x.ptrs);
|
||||
ptrs.swap(x.ptrs,swap_allocators);
|
||||
|
||||
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
|
||||
safe_super::swap(x);
|
||||
#endif
|
||||
|
||||
super::swap_(x);
|
||||
super::swap_(x,swap_allocators);
|
||||
}
|
||||
|
||||
void swap_elements_(random_access_index<SuperMeta,TagList>& x)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright 2003-2019 Joaquin M Lopez Munoz.
|
||||
/* Copyright 2003-2020 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@ -720,13 +720,15 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
|
||||
#endif
|
||||
}
|
||||
|
||||
void swap_(sequenced_index<SuperMeta,TagList>& x)
|
||||
template<typename BoolConstant>
|
||||
void swap_(
|
||||
sequenced_index<SuperMeta,TagList>& x,BoolConstant swap_allocators)
|
||||
{
|
||||
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
|
||||
safe_super::swap(x);
|
||||
#endif
|
||||
|
||||
super::swap_(x);
|
||||
super::swap_(x,swap_allocators);
|
||||
}
|
||||
|
||||
void swap_elements_(sequenced_index<SuperMeta,TagList>& x)
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* Multiply indexed container.
|
||||
*
|
||||
* Copyright 2003-2018 Joaquin M Lopez Munoz.
|
||||
* Copyright 2003-2020 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@ -43,6 +43,7 @@
|
||||
#include <boost/multi_index/detail/scope_guard.hpp>
|
||||
#include <boost/multi_index/detail/vartempl_support.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/type_traits/integral_constant.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/utility/base_from_member.hpp>
|
||||
|
||||
@ -77,6 +78,12 @@ namespace boost{
|
||||
|
||||
namespace multi_index{
|
||||
|
||||
namespace detail{
|
||||
|
||||
struct unequal_alloc_move_ctor_tag{};
|
||||
|
||||
} /* namespace multi_index::detail */
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1500))
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4522) /* spurious warning on multiple operator=()'s */
|
||||
@ -123,7 +130,7 @@ private:
|
||||
#endif
|
||||
|
||||
typedef typename detail::multi_index_base_type<
|
||||
Value,IndexSpecifierList,Allocator>::type super;
|
||||
Value,IndexSpecifierList,Allocator>::type super;
|
||||
typedef typename detail::rebind_alloc_for<
|
||||
Allocator,
|
||||
typename super::node_type
|
||||
@ -271,28 +278,18 @@ public:
|
||||
|
||||
multi_index_container(
|
||||
const multi_index_container<Value,IndexSpecifierList,Allocator>& x):
|
||||
bfm_allocator(x.bfm_allocator::member),
|
||||
bfm_allocator(
|
||||
node_alloc_traits::select_on_container_copy_construction(
|
||||
x.bfm_allocator::member)),
|
||||
bfm_header(),
|
||||
super(x),
|
||||
node_count(0)
|
||||
{
|
||||
copy_map_type map(bfm_allocator::member,x.size(),x.header(),header());
|
||||
for(const_iterator it=x.begin(),it_end=x.end();it!=it_end;++it){
|
||||
map.clone(it.get_node());
|
||||
}
|
||||
super::copy_(x,map);
|
||||
map.release();
|
||||
node_count=x.size();
|
||||
|
||||
/* Not until this point are the indices required to be consistent,
|
||||
* hence the position of the invariant checker.
|
||||
*/
|
||||
|
||||
BOOST_MULTI_INDEX_CHECK_INVARIANT;
|
||||
copy_construct_from(x);
|
||||
}
|
||||
|
||||
multi_index_container(BOOST_RV_REF(multi_index_container) x):
|
||||
bfm_allocator(x.bfm_allocator::member),
|
||||
bfm_allocator(boost::move(x.bfm_allocator::member)),
|
||||
bfm_header(),
|
||||
super(x,detail::do_not_copy_elements_tag()),
|
||||
node_count(0)
|
||||
@ -302,6 +299,36 @@ public:
|
||||
swap_elements_(x);
|
||||
}
|
||||
|
||||
multi_index_container(
|
||||
const multi_index_container<Value,IndexSpecifierList,Allocator>& x,
|
||||
const allocator_type& al):
|
||||
bfm_allocator(al),
|
||||
bfm_header(),
|
||||
super(x),
|
||||
node_count(0)
|
||||
{
|
||||
copy_construct_from(x);
|
||||
}
|
||||
|
||||
multi_index_container(
|
||||
BOOST_RV_REF(multi_index_container) x,const allocator_type& al):
|
||||
bfm_allocator(al),
|
||||
bfm_header(),
|
||||
super(x,detail::do_not_copy_elements_tag()),
|
||||
node_count(0)
|
||||
{
|
||||
BOOST_MULTI_INDEX_CHECK_INVARIANT;
|
||||
BOOST_MULTI_INDEX_CHECK_INVARIANT_OF(x);
|
||||
|
||||
if(al==x.get_allocator()){
|
||||
swap_elements_(x);
|
||||
}
|
||||
else{
|
||||
multi_index_container y(x,al,detail::unequal_alloc_move_ctor_tag());
|
||||
swap_elements_(y);
|
||||
}
|
||||
}
|
||||
|
||||
~multi_index_container()
|
||||
{
|
||||
delete_all_nodes_();
|
||||
@ -315,8 +342,11 @@ public:
|
||||
multi_index_container<Value,IndexSpecifierList,Allocator>& operator=(
|
||||
const multi_index_container<Value,IndexSpecifierList,Allocator>& x)
|
||||
{
|
||||
multi_index_container y(x);
|
||||
this->swap(y);
|
||||
multi_index_container y(
|
||||
x,
|
||||
node_alloc_traits::propagate_on_container_copy_assignment::value?
|
||||
x.get_allocator():this->get_allocator());
|
||||
swap_(y,boost::true_type() /* swap_allocators */);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
@ -324,16 +354,44 @@ public:
|
||||
multi_index_container<Value,IndexSpecifierList,Allocator>& operator=(
|
||||
BOOST_COPY_ASSIGN_REF(multi_index_container) x)
|
||||
{
|
||||
multi_index_container y(x);
|
||||
this->swap(y);
|
||||
multi_index_container y(
|
||||
x,
|
||||
node_alloc_traits::propagate_on_container_copy_assignment::value?
|
||||
x.get_allocator():this->get_allocator());
|
||||
swap_(y,boost::true_type() /* swap_allocators */);
|
||||
return *this;
|
||||
}
|
||||
|
||||
multi_index_container<Value,IndexSpecifierList,Allocator>& operator=(
|
||||
BOOST_RV_REF(multi_index_container) x)
|
||||
{
|
||||
this->swap(x);
|
||||
#if !defined(BOOST_NO_CXX17_IF_CONSTEXPR)
|
||||
#define BOOST_MULTI_INDEX_IF_CONSTEXPR if constexpr
|
||||
#else
|
||||
#define BOOST_MULTI_INDEX_IF_CONSTEXPR if
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4127) /* conditional expression is constant */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
BOOST_MULTI_INDEX_IF_CONSTEXPR(
|
||||
node_alloc_traits::propagate_on_container_move_assignment::value){
|
||||
swap_(x,boost::true_type() /* swap_allocators */);
|
||||
}
|
||||
else if(this->get_allocator()==x.get_allocator()){
|
||||
swap_(x,boost::false_type() /* swap_allocators */);
|
||||
}
|
||||
else{
|
||||
multi_index_container y(boost::move(x),this->get_allocator());
|
||||
swap_(y,boost::true_type() /* swap_allocators */);
|
||||
}
|
||||
return *this;
|
||||
|
||||
#undef BOOST_MULTI_INDEX_IF_CONSTEXPR
|
||||
#if defined(BOOST_NO_CXX17_IF_CONSTEXPR)&&defined(BOOST_MSVC)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
||||
@ -518,6 +576,39 @@ public:
|
||||
BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
|
||||
typedef typename super::copy_map_type copy_map_type;
|
||||
|
||||
multi_index_container(
|
||||
multi_index_container<Value,IndexSpecifierList,Allocator>& x,
|
||||
const allocator_type& al,
|
||||
detail::unequal_alloc_move_ctor_tag):
|
||||
bfm_allocator(al),
|
||||
bfm_header(),
|
||||
super(x),
|
||||
node_count(0)
|
||||
{
|
||||
BOOST_MULTI_INDEX_CHECK_INVARIANT_OF(x);
|
||||
BOOST_TRY{
|
||||
copy_map_type map(bfm_allocator::member,x.size(),x.header(),header());
|
||||
for(const_iterator it=x.begin(),it_end=x.end();it!=it_end;++it){
|
||||
map.move_clone(it.get_node());
|
||||
}
|
||||
super::copy_(x,map);
|
||||
map.release();
|
||||
node_count=x.size();
|
||||
x.clear();
|
||||
}
|
||||
BOOST_CATCH(...){
|
||||
x.clear();
|
||||
BOOST_RETHROW;
|
||||
}
|
||||
BOOST_CATCH_END
|
||||
|
||||
/* Not until this point are the indices required to be consistent,
|
||||
* hence the position of the invariant checker.
|
||||
*/
|
||||
|
||||
BOOST_MULTI_INDEX_CHECK_INVARIANT;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
||||
multi_index_container(
|
||||
const multi_index_container<Value,IndexSpecifierList,Allocator>& x,
|
||||
@ -531,6 +622,24 @@ BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
|
||||
}
|
||||
#endif
|
||||
|
||||
void copy_construct_from(
|
||||
const multi_index_container<Value,IndexSpecifierList,Allocator>& x)
|
||||
{
|
||||
copy_map_type map(bfm_allocator::member,x.size(),x.header(),header());
|
||||
for(const_iterator it=x.begin(),it_end=x.end();it!=it_end;++it){
|
||||
map.copy_clone(it.get_node());
|
||||
}
|
||||
super::copy_(x,map);
|
||||
map.release();
|
||||
node_count=x.size();
|
||||
|
||||
/* Not until this point are the indices required to be consistent,
|
||||
* hence the position of the invariant checker.
|
||||
*/
|
||||
|
||||
BOOST_MULTI_INDEX_CHECK_INVARIANT;
|
||||
}
|
||||
|
||||
node_type* header()const
|
||||
{
|
||||
return &*bfm_header::member;
|
||||
@ -811,11 +920,28 @@ 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){
|
||||
detail::adl_swap(bfm_allocator::member,x.bfm_allocator::member);
|
||||
}
|
||||
swap_(
|
||||
x,
|
||||
boost::integral_constant<
|
||||
bool,node_alloc_traits::propagate_on_container_swap::value>());
|
||||
}
|
||||
|
||||
void swap_(
|
||||
multi_index_container<Value,IndexSpecifierList,Allocator>& x,
|
||||
boost::true_type swap_allocators)
|
||||
{
|
||||
detail::adl_swap(bfm_allocator::member,x.bfm_allocator::member);
|
||||
std::swap(bfm_header::member,x.bfm_header::member);
|
||||
super::swap_(x);
|
||||
super::swap_(x,swap_allocators);
|
||||
std::swap(node_count,x.node_count);
|
||||
}
|
||||
|
||||
void swap_(
|
||||
multi_index_container<Value,IndexSpecifierList,Allocator>& x,
|
||||
boost::false_type swap_allocators)
|
||||
{
|
||||
std::swap(bfm_header::member,x.bfm_header::member);
|
||||
super::swap_(x,swap_allocators);
|
||||
std::swap(node_count,x.node_count);
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Boost.MultiIndex tests Jamfile
|
||||
#
|
||||
# Copyright 2003-2018 Joaqu匤 M L<>ez Mu<4D>z.
|
||||
# Copyright 2003-2020 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)
|
||||
@ -38,6 +38,7 @@ obj boost_multi_index_key_supported : check_bmi_key_supported.cpp ;
|
||||
explicit boost_multi_index_key_supported ;
|
||||
|
||||
test-suite "multi_index" :
|
||||
[ run test_alloc_awareness.cpp test_alloc_awareness_main.cpp ]
|
||||
[ run test_basic.cpp test_basic_main.cpp ]
|
||||
[ run test_capacity.cpp test_capacity_main.cpp ]
|
||||
[ run test_comparison.cpp test_comparison_main.cpp ]
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* Boost.MultiIndex test suite.
|
||||
*
|
||||
* Copyright 2003-2018 Joaquin M Lopez Munoz.
|
||||
* Copyright 2003-2020 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
@ -9,6 +9,7 @@
|
||||
*/
|
||||
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include "test_alloc_awareness.hpp"
|
||||
#include "test_basic.hpp"
|
||||
#include "test_capacity.hpp"
|
||||
#include "test_comparison.hpp"
|
||||
@ -35,6 +36,7 @@
|
||||
|
||||
int main()
|
||||
{
|
||||
test_allocator_awareness();
|
||||
test_basic();
|
||||
test_capacity();
|
||||
test_comparison();
|
||||
|
192
test/test_alloc_awareness.cpp
Normal file
192
test/test_alloc_awareness.cpp
Normal file
@ -0,0 +1,192 @@
|
||||
/* Boost.MultiIndex test for allocator awareness.
|
||||
*
|
||||
* Copyright 2003-2020 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* See http://www.boost.org/libs/multi_index for library home page.
|
||||
*/
|
||||
|
||||
#include "test_alloc_awareness.hpp"
|
||||
|
||||
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <boost/move/core.hpp>
|
||||
#include "pre_multi_index.hpp"
|
||||
#include <boost/multi_index_container.hpp>
|
||||
#include <boost/multi_index/hashed_index.hpp>
|
||||
#include <boost/multi_index/member.hpp>
|
||||
#include <boost/multi_index/ordered_index.hpp>
|
||||
#include <boost/multi_index/random_access_index.hpp>
|
||||
#include <boost/multi_index/ranked_index.hpp>
|
||||
#include <boost/multi_index/sequenced_index.hpp>
|
||||
#include <boost/type_traits/integral_constant.hpp>
|
||||
#include <memory>
|
||||
|
||||
struct move_tracker
|
||||
{
|
||||
move_tracker(int n):n(n),move_cted(false){}
|
||||
move_tracker(const move_tracker& x):n(x.n),move_cted(false){}
|
||||
move_tracker(BOOST_RV_REF(move_tracker) x):n(x.n),move_cted(true){}
|
||||
|
||||
int n;
|
||||
bool move_cted;
|
||||
};
|
||||
|
||||
inline bool operator==(const move_tracker& x,const move_tracker& y)
|
||||
{
|
||||
return x.n==y.n;
|
||||
}
|
||||
|
||||
inline bool operator<(const move_tracker& x,const move_tracker& y)
|
||||
{
|
||||
return x.n<y.n;
|
||||
}
|
||||
|
||||
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
|
||||
namespace boost{
|
||||
#endif
|
||||
|
||||
inline std::size_t hash_value(const move_tracker& x)
|
||||
{
|
||||
boost::hash<int> h;
|
||||
return h(x.n);
|
||||
}
|
||||
|
||||
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
|
||||
} /* namespace boost */
|
||||
#endif
|
||||
|
||||
template<
|
||||
typename T,
|
||||
typename Propagate=boost::true_type,typename AlwaysEqual=boost::true_type
|
||||
>
|
||||
struct rooted_allocator:std::allocator<T>
|
||||
{
|
||||
typedef Propagate propagate_on_container_copy_assignment;
|
||||
typedef Propagate propagate_on_container_move_assignment;
|
||||
typedef Propagate propagate_on_container_swap;
|
||||
typedef AlwaysEqual is_always_equal;
|
||||
template<typename U>
|
||||
struct rebind{typedef rooted_allocator<U,Propagate,AlwaysEqual> other;};
|
||||
|
||||
rooted_allocator():root(0){}
|
||||
explicit rooted_allocator(int):root(this){}
|
||||
template<typename U>
|
||||
rooted_allocator(const rooted_allocator<U,Propagate,AlwaysEqual>& x):
|
||||
root(x.root){}
|
||||
|
||||
template<typename U>
|
||||
bool operator==(const rooted_allocator<U,Propagate,AlwaysEqual>& x)const
|
||||
{return AlwaysEqual::value?true:root==x.root;}
|
||||
template<typename U>
|
||||
bool operator!=(const rooted_allocator<U,Propagate,AlwaysEqual>& x)const
|
||||
{return !(*this==x);}
|
||||
|
||||
template<typename U>
|
||||
bool comes_from(const rooted_allocator<U,Propagate,AlwaysEqual>& x)const
|
||||
{return root==&x;}
|
||||
|
||||
private:
|
||||
template<typename,typename,typename> friend struct rooted_allocator;
|
||||
|
||||
const void* root;
|
||||
};
|
||||
|
||||
#if defined(BOOST_NO_CXX17_IF_CONSTEXPR)&&defined(BOOST_MSVC)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4127) /* conditional expression is constant */
|
||||
#endif
|
||||
|
||||
template<bool Propagate,bool AlwaysEqual>
|
||||
void test_allocator_awareness_for()
|
||||
{
|
||||
using namespace boost::multi_index;
|
||||
|
||||
typedef rooted_allocator<
|
||||
move_tracker,
|
||||
boost::integral_constant<bool, Propagate>,
|
||||
boost::integral_constant<bool, AlwaysEqual>
|
||||
> allocator;
|
||||
typedef multi_index_container<
|
||||
move_tracker,
|
||||
indexed_by<
|
||||
hashed_unique<identity<move_tracker> >,
|
||||
ordered_unique<identity<move_tracker> >,
|
||||
random_access<>,
|
||||
ranked_unique<identity<move_tracker> >,
|
||||
sequenced<>
|
||||
>,
|
||||
allocator
|
||||
> container;
|
||||
|
||||
allocator root1(0),root2(0);
|
||||
container c(root1);
|
||||
for(int i=0;i<10;++i)c.emplace(i);
|
||||
|
||||
BOOST_TEST(c.get_allocator().comes_from(root1));
|
||||
|
||||
{
|
||||
container c2(c,root2);
|
||||
BOOST_TEST(c2.get_allocator().comes_from(root2));
|
||||
BOOST_TEST(c2==c);
|
||||
}
|
||||
{
|
||||
container c2(c);
|
||||
const move_tracker* pfirst=&*c2.begin();
|
||||
container c3(boost::move(c2),root2);
|
||||
BOOST_TEST(c3.get_allocator().comes_from(root2));
|
||||
BOOST_TEST(c3==c);
|
||||
BOOST_TEST(c2.empty());
|
||||
BOOST_TEST(AlwaysEqual==(&*c3.begin()==pfirst));
|
||||
BOOST_TEST(!AlwaysEqual==(c3.begin()->move_cted));
|
||||
}
|
||||
{
|
||||
container c2(root2);
|
||||
c2=c;
|
||||
BOOST_TEST(c2.get_allocator().comes_from(Propagate?root1:root2));
|
||||
BOOST_TEST(c2==c);
|
||||
}
|
||||
{
|
||||
container c2(c);
|
||||
const move_tracker* pfirst=&*c2.begin();
|
||||
container c3(root2);
|
||||
c3=boost::move(c2);
|
||||
BOOST_TEST(c3.get_allocator().comes_from(Propagate?root1:root2));
|
||||
BOOST_TEST(c3==c);
|
||||
BOOST_TEST(c2.empty());
|
||||
BOOST_TEST(AlwaysEqual==(&*c3.begin()==pfirst));
|
||||
BOOST_TEST(!AlwaysEqual==(c3.begin()->move_cted));
|
||||
}
|
||||
if(Propagate||AlwaysEqual){
|
||||
container c2(c);
|
||||
const move_tracker* pfirst=&*c2.begin();
|
||||
container c3(root2);
|
||||
c3.swap(c2);
|
||||
BOOST_TEST(c2.get_allocator().comes_from(Propagate?root2:root1));
|
||||
BOOST_TEST(c3.get_allocator().comes_from(Propagate?root1:root2));
|
||||
BOOST_TEST(c3==c);
|
||||
BOOST_TEST(c2.empty());
|
||||
BOOST_TEST(&*c3.begin()==pfirst);
|
||||
BOOST_TEST(!c3.begin()->move_cted);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(BOOST_NO_CXX17_IF_CONSTEXPR)&&defined(BOOST_MSVC)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
void test_allocator_awareness()
|
||||
{
|
||||
test_allocator_awareness_for<false,false>();
|
||||
test_allocator_awareness_for<false,true>();
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
|
||||
/* only in C+11 onwards are allocators potentially expected to propagate */
|
||||
|
||||
test_allocator_awareness_for<true,false>();
|
||||
test_allocator_awareness_for<true,true>();
|
||||
|
||||
#endif
|
||||
}
|
11
test/test_alloc_awareness.hpp
Normal file
11
test/test_alloc_awareness.hpp
Normal file
@ -0,0 +1,11 @@
|
||||
/* Boost.MultiIndex test for allocator awareness.
|
||||
*
|
||||
* Copyright 2003-2020 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* See http://www.boost.org/libs/multi_index for library home page.
|
||||
*/
|
||||
|
||||
void test_allocator_awareness();
|
18
test/test_alloc_awareness_main.cpp
Normal file
18
test/test_alloc_awareness_main.cpp
Normal file
@ -0,0 +1,18 @@
|
||||
/* Boost.MultiIndex test for allocator awareness.
|
||||
*
|
||||
* Copyright 2003-2020 Joaquin M Lopez Munoz.
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE_1_0.txt or copy at
|
||||
* http://www.boost.org/LICENSE_1_0.txt)
|
||||
*
|
||||
* See http://www.boost.org/libs/multi_index for library home page.
|
||||
*/
|
||||
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include "test_alloc_awareness.hpp"
|
||||
|
||||
int main()
|
||||
{
|
||||
test_allocator_awareness();
|
||||
return boost::report_errors();
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user