* Implemented merge operations for associative containers.

* Update tree-based containers to changes done in Intrusive internal utilities in order to fix Trac 12432.
This commit is contained in:
Ion Gaztañaga
2016-09-03 00:03:42 +02:00
parent 0617d0e538
commit f540b83ccd
13 changed files with 722 additions and 172 deletions

View File

@@ -1231,10 +1231,11 @@ use [*Boost.Container]? There are several reasons for that:
* [@https://svn.boost.org/trac/boost/ticket/12319 Trac #12319: ['"flat_set` should be nothrow move constructible"]]. * [@https://svn.boost.org/trac/boost/ticket/12319 Trac #12319: ['"flat_set` should be nothrow move constructible"]].
* Revised noexcept expressions of default and move constructors in all containers. * Revised noexcept expressions of default and move constructors in all containers.
* Implemented C++17 `insert_or_assign`/`try_emplace` for [classref boost::container::map map] and [classref boost::container::flat_map flat_map]. * Implemented C++17's `insert_or_assign`/`try_emplace` for [classref boost::container::map map] and [classref boost::container::flat_map flat_map].
* Implemented C++17 `extract`/`insert(node)` for [classref boost::container::map map], [classref boost::container::multimap multimap], * Implemented C++17's [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0083r3.pdf ['Splicing Maps and Sets (Revision 5)]]
Splicing Maps and Sets (Revision 5) for [classref boost::container::map map], [classref boost::container::multimap multimap],
[classref boost::container::set set], [classref boost::container::multiset multiset]. [classref boost::container::set set], [classref boost::container::multiset multiset].
* Implemented C++17's [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0084r2.pdf P0084R2 Emplace Return Type] * Implemented C++17's [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0084r2.pdf ['P0084R2 Emplace Return Type]]
in `deque`, `vector`, `stable_vector`, `small_vector`, `static_vector`, `list` and `slist`. in `deque`, `vector`, `stable_vector`, `small_vector`, `static_vector`, `list` and `slist`.
[endsect] [endsect]

View File

@@ -46,6 +46,7 @@
#endif #endif
#include <boost/intrusive/detail/minimal_pair_header.hpp> //pair #include <boost/intrusive/detail/minimal_pair_header.hpp> //pair
#include <boost/move/iterator.hpp>
namespace boost { namespace boost {
namespace container { namespace container {
@@ -100,7 +101,7 @@ struct get_flat_tree_iterators
typedef boost::container::reverse_iterator<const_iterator> const_reverse_iterator; typedef boost::container::reverse_iterator<const_iterator> const_reverse_iterator;
}; };
template <class Key, class Value, class KeyOfValue, template <class Value, class KeyOfValue,
class Compare, class Allocator> class Compare, class Allocator>
class flat_tree class flat_tree
{ {
@@ -185,7 +186,7 @@ class flat_tree
typedef typename vector_t::const_pointer const_pointer; typedef typename vector_t::const_pointer const_pointer;
typedef typename vector_t::reference reference; typedef typename vector_t::reference reference;
typedef typename vector_t::const_reference const_reference; typedef typename vector_t::const_reference const_reference;
typedef Key key_type; typedef typename KeyOfValue::type key_type;
typedef Compare key_compare; typedef Compare key_compare;
typedef typename vector_t::allocator_type allocator_type; typedef typename vector_t::allocator_type allocator_type;
typedef typename vector_t::size_type size_type; typedef typename vector_t::size_type size_type;
@@ -778,6 +779,36 @@ class flat_tree
return n; return n;
} }
template<class C2>
void merge_unique(flat_tree<Value, KeyOfValue, C2, Allocator>& source)
{
this->insert( boost::make_move_iterator(source.begin())
, boost::make_move_iterator(source.end()));
}
template<class C2>
void merge_equal(flat_tree<Value, KeyOfValue, C2, Allocator>& source)
{
this->insert( boost::make_move_iterator(source.begin())
, boost::make_move_iterator(source.end()));
}
void merge_unique(flat_tree& source)
{
this->m_data.m_vect.merge_unique
( boost::make_move_iterator(source.begin())
, boost::make_move_iterator(source.end())
, static_cast<const value_compare &>(this->m_data));
}
void merge_equal(flat_tree& source)
{
this->m_data.m_vect.merge
( boost::make_move_iterator(source.begin())
, boost::make_move_iterator(source.end())
, static_cast<const value_compare &>(this->m_data));
}
BOOST_CONTAINER_FORCEINLINE iterator lower_bound(const key_type& k) BOOST_CONTAINER_FORCEINLINE iterator lower_bound(const key_type& k)
{ return this->priv_lower_bound(this->begin(), this->end(), k); } { return this->priv_lower_bound(this->begin(), this->end(), k); }
@@ -1062,9 +1093,9 @@ class flat_tree
//!has_trivial_destructor_after_move<> == true_type //!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations //!specialization for optimizations
template <class Key, class T, class KeyOfValue, template <class T, class KeyOfValue,
class Compare, class Allocator> class Compare, class Allocator>
struct has_trivial_destructor_after_move<boost::container::container_detail::flat_tree<Key, T, KeyOfValue, Compare, Allocator> > struct has_trivial_destructor_after_move<boost::container::container_detail::flat_tree<T, KeyOfValue, Compare, Allocator> >
{ {
typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer; typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer;
static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value && static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value &&

View File

@@ -394,12 +394,6 @@ struct node_alloc_holder
ICont &non_const_icont() const ICont &non_const_icont() const
{ return const_cast<ICont&>(this->members_.m_icont); } { return const_cast<ICont&>(this->members_.m_icont); }
ICont &icont()
{ return this->members_.m_icont; }
const ICont &icont() const
{ return this->members_.m_icont; }
NodeAlloc &node_alloc() NodeAlloc &node_alloc()
{ return static_cast<NodeAlloc &>(this->members_); } { return static_cast<NodeAlloc &>(this->members_); }
@@ -407,6 +401,13 @@ struct node_alloc_holder
{ return static_cast<const NodeAlloc &>(this->members_); } { return static_cast<const NodeAlloc &>(this->members_); }
members_holder members_; members_holder members_;
public:
ICont &icont()
{ return this->members_.m_icont; }
const ICont &icont() const
{ return this->members_.m_icont; }
}; };
} //namespace container_detail { } //namespace container_detail {

View File

@@ -295,9 +295,9 @@ struct intrusive_tree_type
allocator_traits<Allocator>::size_type size_type; allocator_traits<Allocator>::size_type size_type;
typedef typename container_detail::tree_node typedef typename container_detail::tree_node
< value_type, void_pointer < value_type, void_pointer
, tree_type_value, OptimizeSize> node_t; , tree_type_value, OptimizeSize> node_t;
typedef value_to_node_compare typedef value_to_node_compare
<node_t, ValueCompare> node_compare_type; <node_t, ValueCompare> node_compare_type;
//Deducing the hook type from node_t (e.g. node_t::hook_type) would //Deducing the hook type from node_t (e.g. node_t::hook_type) would
//provoke an early instantiation of node_t that could ruin recursive //provoke an early instantiation of node_t that could ruin recursive
//tree definitions, so retype the complete type to avoid any problem. //tree definitions, so retype the complete type to avoid any problem.
@@ -429,26 +429,28 @@ struct key_node_compare
{ return this->key_comp()(key_of_value()(nonkey1.get_data()), key_of_value()(nonkey2.get_data())); } { return this->key_comp()(key_of_value()(nonkey1.get_data()), key_of_value()(nonkey2.get_data())); }
}; };
template <class Key, class T, class KeyOfValue, template <class T, class KeyOfValue,
class Compare, class Allocator, class Compare, class Allocator,
class Options = tree_assoc_defaults> class Options = tree_assoc_defaults>
class tree class tree
: protected container_detail::node_alloc_holder : public container_detail::node_alloc_holder
< Allocator < Allocator
, typename container_detail::intrusive_tree_type , typename container_detail::intrusive_tree_type
< Allocator, tree_value_compare<Compare, KeyOfValue> //ValComp < Allocator, tree_value_compare
<typename allocator_traits<Allocator>::pointer, Compare, KeyOfValue>
, Options::tree_type, Options::optimize_size>::type , Options::tree_type, Options::optimize_size>::type
> >
{ {
typedef tree_value_compare typedef tree_value_compare
<Compare, KeyOfValue> ValComp; < typename allocator_traits<Allocator>::pointer
, Compare, KeyOfValue> ValComp;
typedef typename container_detail::intrusive_tree_type typedef typename container_detail::intrusive_tree_type
< Allocator, ValComp, Options::tree_type < Allocator, ValComp, Options::tree_type
, Options::optimize_size>::type Icont; , Options::optimize_size>::type Icont;
typedef container_detail::node_alloc_holder typedef container_detail::node_alloc_holder
<Allocator, Icont> AllocHolder; <Allocator, Icont> AllocHolder;
typedef typename AllocHolder::NodePtr NodePtr; typedef typename AllocHolder::NodePtr NodePtr;
typedef tree < Key, T, KeyOfValue typedef tree < T, KeyOfValue
, Compare, Allocator, Options> ThisType; , Compare, Allocator, Options> ThisType;
typedef typename AllocHolder::NodeAlloc NodeAlloc; typedef typename AllocHolder::NodeAlloc NodeAlloc;
typedef boost::container:: typedef boost::container::
@@ -465,7 +467,7 @@ class tree
public: public:
typedef Key key_type; typedef typename KeyOfValue::type key_type;
typedef T value_type; typedef T value_type;
typedef Allocator allocator_type; typedef Allocator allocator_type;
typedef Compare key_compare; typedef Compare key_compare;
@@ -1176,6 +1178,13 @@ class tree
} }
} }
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge_unique(tree<T, KeyOfValue, C2, Allocator, Options>& source)
{ return this->icont().merge_unique(source.icont()); }
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge_equal(tree<T, KeyOfValue, C2, Allocator, Options>& source)
{ return this->icont().merge_equal(source.icont()); }
BOOST_CONTAINER_FORCEINLINE void clear() BOOST_CONTAINER_FORCEINLINE void clear()
{ AllocHolder::clear(alloc_version()); } { AllocHolder::clear(alloc_version()); }
@@ -1265,11 +1274,11 @@ struct has_trivial_destructor_after_move;
//!has_trivial_destructor_after_move<> == true_type //!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations //!specialization for optimizations
template <class Key, class T, class KeyOfValue, class Compare, class Allocator, class Options> template <class T, class KeyOfValue, class Compare, class Allocator, class Options>
struct has_trivial_destructor_after_move struct has_trivial_destructor_after_move
< <
::boost::container::container_detail::tree ::boost::container::container_detail::tree
<Key, T, KeyOfValue, Compare, Allocator, Options> <T, KeyOfValue, Compare, Allocator, Options>
> >
{ {
typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer; typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer;

View File

@@ -53,6 +53,9 @@ namespace container {
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
template <class Key, class T, class Compare, class Allocator>
class flat_multimap;
namespace container_detail{ namespace container_detail{
template<class D, class S> template<class D, class S>
@@ -110,14 +113,14 @@ class flat_map
private: private:
BOOST_COPYABLE_AND_MOVABLE(flat_map) BOOST_COPYABLE_AND_MOVABLE(flat_map)
//This is the tree that we should store if pair was movable //This is the tree that we should store if pair was movable
typedef container_detail::flat_tree<Key, typedef container_detail::flat_tree<
std::pair<Key, T>, std::pair<Key, T>,
container_detail::select1st<Key>, container_detail::select1st<Key>,
Compare, Compare,
Allocator> tree_t; Allocator> tree_t;
//This is the real tree stored here. It's based on a movable pair //This is the real tree stored here. It's based on a movable pair
typedef container_detail::flat_tree<Key, typedef container_detail::flat_tree<
container_detail::pair<Key, T>, container_detail::pair<Key, T>,
container_detail::select1st<Key>, container_detail::select1st<Key>,
Compare, Compare,
@@ -143,6 +146,13 @@ class flat_map
<typename allocator_traits<Allocator>::pointer>::const_reverse_iterator const_reverse_iterator_impl; <typename allocator_traits<Allocator>::pointer>::const_reverse_iterator const_reverse_iterator_impl;
public: public:
typedef typename impl_tree_t::stored_allocator_type impl_stored_allocator_type; typedef typename impl_tree_t::stored_allocator_type impl_stored_allocator_type;
impl_tree_t &tree()
{ return m_flat_tree; }
const impl_tree_t &tree() const
{ return m_flat_tree; }
private: private:
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
@@ -1056,6 +1066,39 @@ class flat_map
{ m_flat_tree.insert_unique(ordered_unique_range, il.begin(), il.end()); } { m_flat_tree.insert_unique(ordered_unique_range, il.begin(), il.end()); }
#endif #endif
//! <b>Requires</b>: this->get_allocator() == source.get_allocator().
//!
//! <b>Effects</b>: Attempts to extract each element in source and insert it into a using
//! the comparison object of *this. If there is an element in a with key equivalent to the
//! key of an element from source, then that element is not extracted from source.
//!
//! <b>Postcondition</b>: Pointers and references to the transferred elements of source refer
//! to those same elements but as members of *this. Iterators referring to the transferred
//! elements will continue to refer to their elements, but they now behave as iterators into *this,
//! not into source.
//!
//! <b>Throws</b>: Nothing unless the comparison object throws.
//!
//! <b>Complexity</b>: N log(a.size() + N) (N has the value source.size())
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(flat_map<Key, T, C2, Allocator>& source)
{ m_flat_tree.merge_unique(source.tree()); }
//! @copydoc ::boost::container::flat_map::merge(flat_map<Key, T, C2, Allocator>&)
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_map<Key, T, C2, Allocator> BOOST_RV_REF_END source)
{ return this->merge(static_cast<flat_map<Key, T, C2, Allocator>&>(source)); }
//! @copydoc ::boost::container::flat_map::merge(flat_map<Key, T, C2, Allocator>&)
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(flat_multimap<Key, T, C2, Allocator>& source)
{ m_flat_tree.merge_unique(source.tree()); }
//! @copydoc ::boost::container::flat_map::merge(flat_map<Key, T, C2, Allocator>&)
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_multimap<Key, T, C2, Allocator> BOOST_RV_REF_END source)
{ return this->merge(static_cast<flat_multimap<Key, T, C2, Allocator>&>(source)); }
//! <b>Effects</b>: Erases the element pointed to by p. //! <b>Effects</b>: Erases the element pointed to by p.
//! //!
//! <b>Returns</b>: Returns an iterator pointing to the element immediately //! <b>Returns</b>: Returns an iterator pointing to the element immediately
@@ -1326,13 +1369,13 @@ class flat_multimap
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private: private:
BOOST_COPYABLE_AND_MOVABLE(flat_multimap) BOOST_COPYABLE_AND_MOVABLE(flat_multimap)
typedef container_detail::flat_tree<Key, typedef container_detail::flat_tree<
std::pair<Key, T>, std::pair<Key, T>,
container_detail::select1st<Key>, container_detail::select1st<Key>,
Compare, Compare,
Allocator> tree_t; Allocator> tree_t;
//This is the real tree stored here. It's based on a movable pair //This is the real tree stored here. It's based on a movable pair
typedef container_detail::flat_tree<Key, typedef container_detail::flat_tree<
container_detail::pair<Key, T>, container_detail::pair<Key, T>,
container_detail::select1st<Key>, container_detail::select1st<Key>,
Compare, Compare,
@@ -1358,6 +1401,13 @@ class flat_multimap
<typename allocator_traits<Allocator>::pointer>::const_reverse_iterator const_reverse_iterator_impl; <typename allocator_traits<Allocator>::pointer>::const_reverse_iterator const_reverse_iterator_impl;
public: public:
typedef typename impl_tree_t::stored_allocator_type impl_stored_allocator_type; typedef typename impl_tree_t::stored_allocator_type impl_stored_allocator_type;
impl_tree_t &tree()
{ return m_flat_tree; }
const impl_tree_t &tree() const
{ return m_flat_tree; }
private: private:
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
@@ -1993,6 +2043,38 @@ class flat_multimap
{ m_flat_tree.insert_equal(ordered_range, il.begin(), il.end()); } { m_flat_tree.insert_equal(ordered_range, il.begin(), il.end()); }
#endif #endif
//! <b>Requires</b>: this->get_allocator() == source.get_allocator().
//!
//! <b>Effects</b>: Extracts each element in source and insert it into a using
//! the comparison object of *this.
//!
//! <b>Postcondition</b>: Pointers and references to the transferred elements of source refer
//! to those same elements but as members of *this. Iterators referring to the transferred
//! elements will continue to refer to their elements, but they now behave as iterators into *this,
//! not into source.
//!
//! <b>Throws</b>: Nothing unless the comparison object throws.
//!
//! <b>Complexity</b>: N log(a.size() + N) (N has the value source.size())
template<class C2>
void merge(flat_multimap<Key, T, C2, Allocator>& source)
{ m_flat_tree.merge_equal(source.tree()); }
//! @copydoc ::boost::container::flat_multimap::merge(flat_multimap<Key, T, C2, Allocator>&)
template<class C2>
void merge(BOOST_RV_REF_BEG flat_multimap<Key, T, C2, Allocator> BOOST_RV_REF_END source)
{ return this->merge(static_cast<flat_multimap<Key, T, C2, Allocator>&>(source)); }
//! @copydoc ::boost::container::flat_multimap::merge(flat_multimap<Key, T, C2, Allocator>&)
template<class C2>
void merge(flat_map<Key, T, C2, Allocator>& source)
{ m_flat_tree.merge_equal(source.tree()); }
//! @copydoc ::boost::container::flat_multimap::merge(flat_multimap<Key, T, C2, Allocator>&)
template<class C2>
void merge(BOOST_RV_REF_BEG flat_map<Key, T, C2, Allocator> BOOST_RV_REF_END source)
{ return this->merge(static_cast<flat_map<Key, T, C2, Allocator>&>(source)); }
//! <b>Effects</b>: Erases the element pointed to by p. //! <b>Effects</b>: Erases the element pointed to by p.
//! //!
//! <b>Returns</b>: Returns an iterator pointing to the element immediately //! <b>Returns</b>: Returns an iterator pointing to the element immediately

View File

@@ -47,6 +47,11 @@
namespace boost { namespace boost {
namespace container { namespace container {
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
template <class Key, class T, class Compare, class Allocator>
class flat_multimap;
#endif
//! flat_set is a Sorted Associative Container that stores objects of type Key. //! flat_set is a Sorted Associative Container that stores objects of type Key.
//! It is also a Unique Associative Container, meaning that no two elements are the same. //! It is also a Unique Associative Container, meaning that no two elements are the same.
//! //!
@@ -69,13 +74,21 @@ template <class Key, class Compare, class Allocator>
#endif #endif
class flat_set class flat_set
///@cond ///@cond
: public container_detail::flat_tree<Key, Key, container_detail::identity<Key>, Compare, Allocator> : public container_detail::flat_tree<Key, container_detail::identity<Key>, Compare, Allocator>
///@endcond ///@endcond
{ {
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private: private:
BOOST_COPYABLE_AND_MOVABLE(flat_set) BOOST_COPYABLE_AND_MOVABLE(flat_set)
typedef container_detail::flat_tree<Key, Key, container_detail::identity<Key>, Compare, Allocator> base_t; typedef container_detail::flat_tree<Key, container_detail::identity<Key>, Compare, Allocator> base_t;
public:
base_t &tree()
{ return *this; }
const base_t &tree() const
{ return *this; }
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public: public:
@@ -605,6 +618,26 @@ class flat_set
{ this->base_t::insert_unique(ordered_unique_range, il.begin(), il.end()); } { this->base_t::insert_unique(ordered_unique_range, il.begin(), il.end()); }
#endif #endif
//! @copydoc ::boost::container::flat_map::merge(flat_map<Key, T, C2, Allocator>&)
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(flat_set<Key, C2, Allocator>& source)
{ this->base_t::merge_unique(source.tree()); }
//! @copydoc ::boost::container::flat_map::merge(flat_set<Key, C2, Allocator>&)
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_set<Key, C2, Allocator> BOOST_RV_REF_END source)
{ return this->merge(static_cast<flat_set<Key, C2, Allocator>&>(source)); }
//! @copydoc ::boost::container::flat_map::merge(flat_multimap<Key, T, C2, Allocator>&)
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(flat_multiset<Key, C2, Allocator>& source)
{ this->base_t::merge_unique(source.tree()); }
//! @copydoc ::boost::container::flat_map::merge(flat_multiset<Key, C2, Allocator>&)
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_multiset<Key, C2, Allocator> BOOST_RV_REF_END source)
{ return this->merge(static_cast<flat_multiset<Key, C2, Allocator>&>(source)); }
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! <b>Effects</b>: Erases the element pointed to by p. //! <b>Effects</b>: Erases the element pointed to by p.
@@ -867,13 +900,20 @@ template <class Key, class Compare, class Allocator>
#endif #endif
class flat_multiset class flat_multiset
///@cond ///@cond
: public container_detail::flat_tree<Key, Key, container_detail::identity<Key>, Compare, Allocator> : public container_detail::flat_tree<Key, container_detail::identity<Key>, Compare, Allocator>
///@endcond ///@endcond
{ {
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private: private:
BOOST_COPYABLE_AND_MOVABLE(flat_multiset) BOOST_COPYABLE_AND_MOVABLE(flat_multiset)
typedef container_detail::flat_tree<Key, Key, container_detail::identity<Key>, Compare, Allocator> base_t; typedef container_detail::flat_tree<Key, container_detail::identity<Key>, Compare, Allocator> base_t;
public:
base_t &tree()
{ return *this; }
const base_t &tree() const
{ return *this; }
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public: public:
@@ -1233,6 +1273,26 @@ class flat_multiset
{ this->base_t::insert_equal(ordered_range, il.begin(), il.end()); } { this->base_t::insert_equal(ordered_range, il.begin(), il.end()); }
#endif #endif
//! @copydoc ::boost::container::flat_multimap::merge(flat_multimap<Key, T, C2, Allocator>&)
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(flat_multiset<Key, C2, Allocator>& source)
{ this->base_t::merge_equal(source.tree()); }
//! @copydoc ::boost::container::flat_multiset::merge(flat_multiset<Key, C2, Allocator>&)
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_multiset<Key, C2, Allocator> BOOST_RV_REF_END source)
{ return this->merge(static_cast<flat_multiset<Key, C2, Allocator>&>(source)); }
//! @copydoc ::boost::container::flat_multimap::merge(flat_map<Key, T, C2, Allocator>&)
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(flat_set<Key, C2, Allocator>& source)
{ this->base_t::merge_equal(source.tree()); }
//! @copydoc ::boost::container::flat_multiset::merge(flat_set<Key, C2, Allocator>&)
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_set<Key, C2, Allocator> BOOST_RV_REF_END source)
{ return this->merge(static_cast<flat_set<Key, C2, Allocator>&>(source)); }
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! @copydoc ::boost::container::flat_set::erase(const_iterator) //! @copydoc ::boost::container::flat_set::erase(const_iterator)

View File

@@ -96,18 +96,18 @@ struct pair_key_mapped_of_value
//! \tparam Compare is the ordering function for Keys (e.g. <i>std::less<Key></i>). //! \tparam Compare is the ordering function for Keys (e.g. <i>std::less<Key></i>).
//! \tparam Allocator is the allocator to allocate the <code>value_type</code>s //! \tparam Allocator is the allocator to allocate the <code>value_type</code>s
//! (e.g. <i>allocator< std::pair<const Key, T> > </i>). //! (e.g. <i>allocator< std::pair<const Key, T> > </i>).
//! \tparam MapOptions is an packed option type generated using using boost::container::tree_assoc_options. //! \tparam Options is an packed option type generated using using boost::container::tree_assoc_options.
template < class Key, class T, class Compare = std::less<Key> template < class Key, class T, class Compare = std::less<Key>
, class Allocator = new_allocator< std::pair< const Key, T> >, class MapOptions = tree_assoc_defaults > , class Allocator = new_allocator< std::pair< const Key, T> >, class Options = tree_assoc_defaults >
#else #else
template <class Key, class T, class Compare, class Allocator, class MapOptions> template <class Key, class T, class Compare, class Allocator, class Options>
#endif #endif
class map class map
///@cond ///@cond
: public container_detail::tree : public container_detail::tree
< Key, std::pair<const Key, T> < std::pair<const Key, T>
, container_detail::select1st<Key> , container_detail::select1st<Key>
, Compare, Allocator, MapOptions> , Compare, Allocator, Options>
///@endcond ///@endcond
{ {
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
@@ -117,10 +117,9 @@ class map
typedef container_detail::select1st<Key> select_1st_t; typedef container_detail::select1st<Key> select_1st_t;
typedef std::pair<const Key, T> value_type_impl; typedef std::pair<const Key, T> value_type_impl;
typedef container_detail::tree typedef container_detail::tree
<Key, value_type_impl, select_1st_t, Compare, Allocator, MapOptions> base_t; <value_type_impl, select_1st_t, Compare, Allocator, Options> base_t;
typedef container_detail::pair <Key, T> movable_value_type_impl; typedef container_detail::pair <Key, T> movable_value_type_impl;
typedef container_detail::tree_value_compare typedef typename base_t::value_compare value_compare_impl;
<Compare, select_1st_t> value_compare_impl;
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public: public:
@@ -975,6 +974,47 @@ class map
return BOOST_MOVE_RET(node_type, nh); return BOOST_MOVE_RET(node_type, nh);
} }
//! <b>Requires</b>: this->get_allocator() == source.get_allocator().
//!
//! <b>Effects</b>: Attempts to extract each element in source and insert it into a using
//! the comparison object of *this. If there is an element in a with key equivalent to the
//! key of an element from source, then that element is not extracted from source.
//!
//! <b>Postcondition</b>: Pointers and references to the transferred elements of source refer
//! to those same elements but as members of *this. Iterators referring to the transferred
//! elements will continue to refer to their elements, but they now behave as iterators into *this,
//! not into source.
//!
//! <b>Throws</b>: Nothing unless the comparison object throws.
//!
//! <b>Complexity</b>: N log(a.size() + N) (N has the value source.size())
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(map<Key, T, C2, Allocator, Options>& source)
{
typedef container_detail::tree
<value_type_impl, select_1st_t, C2, Allocator, Options> base2_t;
this->merge_unique(static_cast<base2_t&>(source));
}
//! @copydoc ::boost::container::map::merge(map<Key, T, C2, Allocator, Options>&)
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG map<Key, T, C2, Allocator, Options> BOOST_RV_REF_END source)
{ return this->merge(static_cast<map<Key, T, C2, Allocator, Options>&>(source)); }
//! @copydoc ::boost::container::map::merge(map<Key, T, C2, Allocator, Options>&)
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(multimap<Key, T, C2, Allocator, Options>& source)
{
typedef container_detail::tree
<value_type_impl, select_1st_t, C2, Allocator, Options> base2_t;
this->base_t::merge_unique(static_cast<base2_t&>(source));
}
//! @copydoc ::boost::container::map::merge(map<Key, T, C2, Allocator, Options>&)
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG multimap<Key, T, C2, Allocator, Options> BOOST_RV_REF_END source)
{ return this->merge(static_cast<multimap<Key, T, C2, Allocator, Options>&>(source)); }
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! <b>Effects</b>: Swaps the contents of *this and x. //! <b>Effects</b>: Swaps the contents of *this and x.
//! //!
@@ -1148,18 +1188,18 @@ namespace container {
//! \tparam Compare is the ordering function for Keys (e.g. <i>std::less<Key></i>). //! \tparam Compare is the ordering function for Keys (e.g. <i>std::less<Key></i>).
//! \tparam Allocator is the allocator to allocate the <code>value_type</code>s //! \tparam Allocator is the allocator to allocate the <code>value_type</code>s
//! (e.g. <i>allocator< std::pair<const Key, T> > </i>). //! (e.g. <i>allocator< std::pair<const Key, T> > </i>).
//! \tparam MultiMapOptions is an packed option type generated using using boost::container::tree_assoc_options. //! \tparam Options is an packed option type generated using using boost::container::tree_assoc_options.
template < class Key, class T, class Compare = std::less<Key> template < class Key, class T, class Compare = std::less<Key>
, class Allocator = new_allocator< std::pair< const Key, T> >, class MultiMapOptions = tree_assoc_defaults> , class Allocator = new_allocator< std::pair< const Key, T> >, class Options = tree_assoc_defaults>
#else #else
template <class Key, class T, class Compare, class Allocator, class MultiMapOptions> template <class Key, class T, class Compare, class Allocator, class Options>
#endif #endif
class multimap class multimap
///@cond ///@cond
: public container_detail::tree : public container_detail::tree
< Key, std::pair<const Key, T> < std::pair<const Key, T>
, container_detail::select1st<Key> , container_detail::select1st<Key>
, Compare, Allocator, MultiMapOptions> , Compare, Allocator, Options>
///@endcond ///@endcond
{ {
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
@@ -1169,10 +1209,9 @@ class multimap
typedef container_detail::select1st<Key> select_1st_t; typedef container_detail::select1st<Key> select_1st_t;
typedef std::pair<const Key, T> value_type_impl; typedef std::pair<const Key, T> value_type_impl;
typedef container_detail::tree typedef container_detail::tree
<Key, value_type_impl, select_1st_t, Compare, Allocator, MultiMapOptions> base_t; <value_type_impl, select_1st_t, Compare, Allocator, Options> base_t;
typedef container_detail::pair <Key, T> movable_value_type_impl; typedef container_detail::pair <Key, T> movable_value_type_impl;
typedef container_detail::tree_value_compare typedef typename base_t::value_compare value_compare_impl;
<Compare, select_1st_t> value_compare_impl;
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
typedef ::boost::container::allocator_traits<Allocator> allocator_traits_type; typedef ::boost::container::allocator_traits<Allocator> allocator_traits_type;
@@ -1655,6 +1694,46 @@ class multimap
return node_type (boost::move(base_nh)); return node_type (boost::move(base_nh));
} }
//! <b>Requires</b>: this->get_allocator() == source.get_allocator().
//!
//! <b>Effects</b>: Extracts each element in source and insert it into a using
//! the comparison object of *this.
//!
//! <b>Postcondition</b>: Pointers and references to the transferred elements of source refer
//! to those same elements but as members of *this. Iterators referring to the transferred
//! elements will continue to refer to their elements, but they now behave as iterators into *this,
//! not into source.
//!
//! <b>Throws</b>: Nothing unless the comparison object throws.
//!
//! <b>Complexity</b>: N log(a.size() + N) (N has the value source.size())
template<class C2>
void merge(multimap<Key, T, C2, Allocator, Options>& source)
{
typedef container_detail::tree
<value_type_impl, select_1st_t, C2, Allocator, Options> base2_t;
this->base_t::merge_equal(static_cast<base2_t&>(source));
}
//! @copydoc ::boost::container::multimap::merge(multimap<Key, T, C2, Allocator, Options>&)
template<class C2>
void merge(BOOST_RV_REF_BEG multimap<Key, T, C2, Allocator, Options> BOOST_RV_REF_END source)
{ return this->merge(static_cast<multimap<Key, T, C2, Allocator, Options>&>(source)); }
//! @copydoc ::boost::container::multimap::merge(multimap<Key, T, C2, Allocator, Options>&)
template<class C2>
void merge(map<Key, T, C2, Allocator, Options>& source)
{
typedef container_detail::tree
<value_type_impl, select_1st_t, C2, Allocator, Options> base2_t;
this->base_t::merge_equal(static_cast<base2_t&>(source));
}
//! @copydoc ::boost::container::multimap::merge(multimap<Key, T, C2, Allocator, Options>&)
template<class C2>
void merge(BOOST_RV_REF_BEG map<Key, T, C2, Allocator, Options> BOOST_RV_REF_END source)
{ return this->merge(static_cast<map<Key, T, C2, Allocator, Options>&>(source)); }
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! @copydoc ::boost::container::set::swap //! @copydoc ::boost::container::set::swap
void swap(multiset& x) void swap(multiset& x)

View File

@@ -59,22 +59,22 @@ namespace container {
//! \tparam Key is the type to be inserted in the set, which is also the key_type //! \tparam Key is the type to be inserted in the set, which is also the key_type
//! \tparam Compare is the comparison functor used to order keys //! \tparam Compare is the comparison functor used to order keys
//! \tparam Allocator is the allocator to be used to allocate memory for this container //! \tparam Allocator is the allocator to be used to allocate memory for this container
//! \tparam SetOptions is an packed option type generated using using boost::container::tree_assoc_options. //! \tparam Options is an packed option type generated using using boost::container::tree_assoc_options.
template <class Key, class Compare = std::less<Key>, class Allocator = new_allocator<Key>, class SetOptions = tree_assoc_defaults > template <class Key, class Compare = std::less<Key>, class Allocator = new_allocator<Key>, class Options = tree_assoc_defaults >
#else #else
template <class Key, class Compare, class Allocator, class SetOptions> template <class Key, class Compare, class Allocator, class Options>
#endif #endif
class set class set
///@cond ///@cond
: public container_detail::tree : public container_detail::tree
< Key, Key, container_detail::identity<Key>, Compare, Allocator, SetOptions> < Key, container_detail::identity<Key>, Compare, Allocator, Options>
///@endcond ///@endcond
{ {
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private: private:
BOOST_COPYABLE_AND_MOVABLE(set) BOOST_COPYABLE_AND_MOVABLE(set)
typedef container_detail::tree typedef container_detail::tree
< Key, Key, container_detail::identity<Key>, Compare, Allocator, SetOptions> base_t; < Key, container_detail::identity<Key>, Compare, Allocator, Options> base_t;
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public: public:
@@ -533,6 +533,34 @@ class set
insert_return_type insert(const_iterator hint, BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh) insert_return_type insert(const_iterator hint, BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)
{ return this->base_t::insert_unique_node(hint, boost::move(nh)); } { return this->base_t::insert_unique_node(hint, boost::move(nh)); }
//! @copydoc ::boost::container::map::merge(map<Key, T, C2, Allocator, Options>&)
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(set<Key, C2, Allocator, Options>& source)
{
typedef container_detail::tree
<Key, container_detail::identity<Key>, C2, Allocator, Options> base2_t;
this->base_t::merge_unique(static_cast<base2_t&>(source));
}
//! @copydoc ::boost::container::set::merge(set<Key, C2, Allocator, Options>&)
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG set<Key, C2, Allocator, Options> BOOST_RV_REF_END source)
{ return this->merge(static_cast<set<Key, C2, Allocator, Options>&>(source)); }
//! @copydoc ::boost::container::map::merge(multimap<Key, T, C2, Allocator, Options>&)
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(multiset<Key, C2, Allocator, Options>& source)
{
typedef container_detail::tree
<Key, container_detail::identity<Key>, C2, Allocator, Options> base2_t;
this->base_t::merge_unique(static_cast<base2_t&>(source));
}
//! @copydoc ::boost::container::set::merge(multiset<Key, C2, Allocator, Options>&)
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG multiset<Key, C2, Allocator, Options> BOOST_RV_REF_END source)
{ return this->merge(static_cast<multiset<Key, C2, Allocator, Options>&>(source)); }
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! <b>Effects</b>: Erases the element pointed to by p. //! <b>Effects</b>: Erases the element pointed to by p.
@@ -724,8 +752,8 @@ class set
//!has_trivial_destructor_after_move<> == true_type //!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations //!specialization for optimizations
template <class Key, class Compare, class SetOptions, class Allocator> template <class Key, class Compare, class Options, class Allocator>
struct has_trivial_destructor_after_move<boost::container::set<Key, Compare, Allocator, SetOptions> > struct has_trivial_destructor_after_move<boost::container::set<Key, Compare, Allocator, Options> >
{ {
typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer; typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer;
static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value && static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value &&
@@ -750,22 +778,22 @@ namespace container {
//! \tparam Key is the type to be inserted in the set, which is also the key_type //! \tparam Key is the type to be inserted in the set, which is also the key_type
//! \tparam Compare is the comparison functor used to order keys //! \tparam Compare is the comparison functor used to order keys
//! \tparam Allocator is the allocator to be used to allocate memory for this container //! \tparam Allocator is the allocator to be used to allocate memory for this container
//! \tparam MultiSetOptions is an packed option type generated using using boost::container::tree_assoc_options. //! \tparam Options is an packed option type generated using using boost::container::tree_assoc_options.
template <class Key, class Compare = std::less<Key>, class Allocator = new_allocator<Key>, class MultiSetOptions = tree_assoc_defaults > template <class Key, class Compare = std::less<Key>, class Allocator = new_allocator<Key>, class Options = tree_assoc_defaults >
#else #else
template <class Key, class Compare, class Allocator, class MultiSetOptions> template <class Key, class Compare, class Allocator, class Options>
#endif #endif
class multiset class multiset
/// @cond /// @cond
: public container_detail::tree : public container_detail::tree
<Key, Key,container_detail::identity<Key>, Compare, Allocator, MultiSetOptions> <Key,container_detail::identity<Key>, Compare, Allocator, Options>
/// @endcond /// @endcond
{ {
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private: private:
BOOST_COPYABLE_AND_MOVABLE(multiset) BOOST_COPYABLE_AND_MOVABLE(multiset)
typedef container_detail::tree typedef container_detail::tree
<Key, Key,container_detail::identity<Key>, Compare, Allocator, MultiSetOptions> base_t; <Key,container_detail::identity<Key>, Compare, Allocator, Options> base_t;
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public: public:
@@ -1068,6 +1096,34 @@ class multiset
iterator insert(const_iterator hint, BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh) iterator insert(const_iterator hint, BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)
{ return this->base_t::insert_equal_node(hint, boost::move(nh)); } { return this->base_t::insert_equal_node(hint, boost::move(nh)); }
//! @copydoc ::boost::container::multimap::merge(multimap<Key, T, C2, Allocator, Options>&)
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(multiset<Key, C2, Allocator, Options>& source)
{
typedef container_detail::tree
<Key, container_detail::identity<Key>, C2, Allocator, Options> base2_t;
this->base_t::merge_equal(static_cast<base2_t&>(source));
}
//! @copydoc ::boost::container::multiset::merge(multiset<Key, C2, Allocator, Options>&)
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG multiset<Key, C2, Allocator, Options> BOOST_RV_REF_END source)
{ return this->merge(static_cast<multiset<Key, C2, Allocator, Options>&>(source)); }
//! @copydoc ::boost::container::multimap::merge(map<Key, T, C2, Allocator, Options>&)
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(set<Key, C2, Allocator, Options>& source)
{
typedef container_detail::tree
<Key, container_detail::identity<Key>, C2, Allocator, Options> base2_t;
this->base_t::merge_equal(static_cast<base2_t&>(source));
}
//! @copydoc ::boost::container::multiset::merge(set<Key, C2, Allocator, Options>&)
template<class C2>
BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG set<Key, C2, Allocator, Options> BOOST_RV_REF_END source)
{ return this->merge(static_cast<set<Key, C2, Allocator, Options>&>(source)); }
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! @copydoc ::boost::container::set::erase(const_iterator) //! @copydoc ::boost::container::set::erase(const_iterator)
@@ -1179,8 +1235,8 @@ class multiset
//!has_trivial_destructor_after_move<> == true_type //!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations //!specialization for optimizations
template <class Key, class Compare, class Allocator, class MultiSetOptions> template <class Key, class Compare, class Allocator, class Options>
struct has_trivial_destructor_after_move<boost::container::multiset<Key, Compare, Allocator, MultiSetOptions> > struct has_trivial_destructor_after_move<boost::container::multiset<Key, Compare, Allocator, Options> >
{ {
typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer; typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer;
static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value && static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value &&

View File

@@ -62,7 +62,6 @@ namespace container_detail {
//Instantiate base class as previous instantiations don't instantiate inherited members //Instantiate base class as previous instantiations don't instantiate inherited members
template class flat_tree template class flat_tree
< test::movable_and_copyable_int < test::movable_and_copyable_int
, test::movable_and_copyable_int
, identity<test::movable_and_copyable_int> , identity<test::movable_and_copyable_int>
, std::less<test::movable_and_copyable_int> , std::less<test::movable_and_copyable_int>
, test::simple_allocator<test::movable_and_copyable_int> , test::simple_allocator<test::movable_and_copyable_int>
@@ -70,7 +69,6 @@ template class flat_tree
template class flat_tree template class flat_tree
< test::movable_and_copyable_int < test::movable_and_copyable_int
, test::movable_and_copyable_int
, identity<test::movable_and_copyable_int> , identity<test::movable_and_copyable_int>
, std::less<test::movable_and_copyable_int> , std::less<test::movable_and_copyable_int>
, allocator<test::movable_and_copyable_int> , allocator<test::movable_and_copyable_int>

View File

@@ -23,6 +23,8 @@
using namespace boost::container; using namespace boost::container;
typedef std::pair<const test::movable_and_copyable_int, test::movable_and_copyable_int> pair_t;
namespace boost { namespace boost {
namespace container { namespace container {
@@ -33,34 +35,59 @@ template class map
< test::movable_and_copyable_int < test::movable_and_copyable_int
, test::movable_and_copyable_int , test::movable_and_copyable_int
, std::less<test::movable_and_copyable_int> , std::less<test::movable_and_copyable_int>
, test::simple_allocator , test::simple_allocator< pair_t >
< std::pair<const test::movable_and_copyable_int, test::movable_and_copyable_int> >
>; >;
template class map template class map
< test::movable_and_copyable_int < test::movable_and_copyable_int
, test::movable_and_copyable_int , test::movable_and_copyable_int
, std::less<test::movable_and_copyable_int> , std::less<test::movable_and_copyable_int>
, std::allocator , std::allocator< pair_t >
< std::pair<const test::movable_and_copyable_int, test::movable_and_copyable_int> >
>; >;
template class map template class map
< test::movable_and_copyable_int < test::movable_and_copyable_int
, test::movable_and_copyable_int , test::movable_and_copyable_int
, std::less<test::movable_and_copyable_int> , std::less<test::movable_and_copyable_int>
, adaptive_pool , adaptive_pool< pair_t >
< std::pair<const test::movable_and_copyable_int, test::movable_and_copyable_int> >
>; >;
template class multimap template class multimap
< test::movable_and_copyable_int < test::movable_and_copyable_int
, test::movable_and_copyable_int , test::movable_and_copyable_int
, std::less<test::movable_and_copyable_int> , std::less<test::movable_and_copyable_int>
, std::allocator , std::allocator< pair_t >
< std::pair<const test::movable_and_copyable_int, test::movable_and_copyable_int> >
>; >;
namespace container_detail {
//Instantiate base class as previous instantiations don't instantiate inherited members
template class tree
< pair_t
, select1st<test::movable_and_copyable_int>
, std::less<test::movable_and_copyable_int>
, test::simple_allocator<pair_t>
, tree_assoc_defaults
>;
template class tree
< pair_t
, select1st<test::movable_and_copyable_int>
, std::less<test::movable_and_copyable_int>
, std::allocator<pair_t>
, tree_assoc_defaults
>;
template class tree
< pair_t
, select1st<test::movable_and_copyable_int>
, std::less<test::movable_and_copyable_int>
, adaptive_pool<pair_t>
, tree_assoc_defaults
>;
} //container_detail {
}} //boost::container }} //boost::container
class recursive_map class recursive_map
@@ -334,6 +361,13 @@ struct alloc_propagate_base<boost_container_multimap>
}; };
}; };
void test_merge_from_different_comparison()
{
map<int, int> map1;
map<int, int, std::greater<int> > map2;
map1.merge(map2);
}
}}} //namespace boost::container::test }}} //namespace boost::container::test
int main () int main ()
@@ -357,7 +391,6 @@ int main ()
//Test std::pair value type as tree has workarounds to make old std::pair //Test std::pair value type as tree has workarounds to make old std::pair
//implementations movable that can break things //implementations movable that can break things
{ {
typedef std::pair<int,int> pair_t;
boost::container::map<pair_t, pair_t> s; boost::container::map<pair_t, pair_t> s;
std::pair<const pair_t,pair_t> p; std::pair<const pair_t,pair_t> p;
s.insert(p); s.insert(p);
@@ -447,6 +480,8 @@ int main ()
if(!node_type_test()) if(!node_type_test())
return 1; return 1;
test::test_merge_from_different_comparison();
//////////////////////////////////// ////////////////////////////////////
// Test optimize_size option // Test optimize_size option
//////////////////////////////////// ////////////////////////////////////

View File

@@ -68,7 +68,7 @@ int map_test_copyable(boost::container::container_detail::true_type)
typedef container_detail::pair<IntType, IntType> IntPairType; typedef container_detail::pair<IntType, IntType> IntPairType;
typedef typename MyStdMap::value_type StdPairType; typedef typename MyStdMap::value_type StdPairType;
const int max = 50; const int MaxElem = 50;
::boost::movelib::unique_ptr<MyBoostMap> const pboostmap = ::boost::movelib::make_unique<MyBoostMap>(); ::boost::movelib::unique_ptr<MyBoostMap> const pboostmap = ::boost::movelib::make_unique<MyBoostMap>();
::boost::movelib::unique_ptr<MyStdMap> const pstdmap = ::boost::movelib::make_unique<MyStdMap>(); ::boost::movelib::unique_ptr<MyStdMap> const pstdmap = ::boost::movelib::make_unique<MyStdMap>();
@@ -86,7 +86,7 @@ int map_test_copyable(boost::container::container_detail::true_type)
boostmultimap.insert(boostmultimap.begin(), boostmultimap.end()); boostmultimap.insert(boostmultimap.begin(), boostmultimap.end());
int i; int i;
for(i = 0; i < max; ++i){ for(i = 0; i < MaxElem; ++i){
{ {
IntType i1(i), i2(i); IntType i1(i), i2(i);
IntPairType intpair1(boost::move(i1), boost::move(i2)); IntPairType intpair1(boost::move(i1), boost::move(i2));
@@ -138,7 +138,7 @@ int map_test()
typedef typename MyBoostMap::key_type IntType; typedef typename MyBoostMap::key_type IntType;
typedef container_detail::pair<IntType, IntType> IntPairType; typedef container_detail::pair<IntType, IntType> IntPairType;
typedef typename MyStdMap::value_type StdPairType; typedef typename MyStdMap::value_type StdPairType;
const int max = 50; const int MaxElem = 50;
typedef typename MyStdMap::value_type StdValueType; typedef typename MyStdMap::value_type StdValueType;
typedef typename MyStdMap::key_type StdKeyType; typedef typename MyStdMap::key_type StdKeyType;
typedef typename MyStdMap::mapped_type StdMappedType; typedef typename MyStdMap::mapped_type StdMappedType;
@@ -146,20 +146,20 @@ int map_test()
//Test construction from a range //Test construction from a range
{ {
IntPairType aux_vect[50]; IntPairType aux_vect[MaxElem];
for(int i = 0; i < 50; ++i){ for(int i = 0; i < MaxElem; ++i){
IntType i1(i/2); IntType i1(i/2);
IntType i2(i/2); IntType i2(i/2);
new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2)); new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
} }
StdValueType aux_vect2[50]; StdValueType aux_vect2[MaxElem];
for(int i = 0; i < 50; ++i){ for(int i = 0; i < MaxElem; ++i){
new(&aux_vect2[i])StdValueType(StdKeyType(i/2), StdMappedType(i/2)); new(&aux_vect2[i])StdValueType(StdKeyType(i/2), StdMappedType(i/2));
} }
IntPairType aux_vect3[50]; IntPairType aux_vect3[MaxElem];
for(int i = 0; i < 50; ++i){ for(int i = 0; i < MaxElem; ++i){
IntType i1(i/2); IntType i1(i/2);
IntType i2(i/2); IntType i2(i/2);
new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2)); new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2));
@@ -167,33 +167,33 @@ int map_test()
::boost::movelib::unique_ptr<MyBoostMap> const pboostmap = ::boost::movelib::make_unique<MyBoostMap> ::boost::movelib::unique_ptr<MyBoostMap> const pboostmap = ::boost::movelib::make_unique<MyBoostMap>
( boost::make_move_iterator(&aux_vect[0]) ( boost::make_move_iterator(&aux_vect[0])
, boost::make_move_iterator(&aux_vect[0] + 50), typename MyBoostMap::key_compare()); , boost::make_move_iterator(&aux_vect[0] + MaxElem), typename MyBoostMap::key_compare());
::boost::movelib::unique_ptr<MyStdMap> const pstdmap = ::boost::movelib::make_unique<MyStdMap> ::boost::movelib::unique_ptr<MyStdMap> const pstdmap = ::boost::movelib::make_unique<MyStdMap>
(&aux_vect2[0], &aux_vect2[0] + 50, typename MyStdMap::key_compare()); (&aux_vect2[0], &aux_vect2[0] + MaxElem, typename MyStdMap::key_compare());
if(!CheckEqualContainers(*pboostmap, *pstdmap)) return 1; if(!CheckEqualContainers(*pboostmap, *pstdmap)) return 1;
::boost::movelib::unique_ptr<MyBoostMultiMap> const pboostmultimap = ::boost::movelib::make_unique<MyBoostMultiMap> ::boost::movelib::unique_ptr<MyBoostMultiMap> const pboostmultimap = ::boost::movelib::make_unique<MyBoostMultiMap>
( boost::make_move_iterator(&aux_vect3[0]) ( boost::make_move_iterator(&aux_vect3[0])
, boost::make_move_iterator(&aux_vect3[0] + 50), typename MyBoostMap::key_compare()); , boost::make_move_iterator(&aux_vect3[0] + MaxElem), typename MyBoostMap::key_compare());
::boost::movelib::unique_ptr<MyStdMultiMap> const pstdmultimap = ::boost::movelib::make_unique<MyStdMultiMap> ::boost::movelib::unique_ptr<MyStdMultiMap> const pstdmultimap = ::boost::movelib::make_unique<MyStdMultiMap>
(&aux_vect2[0], &aux_vect2[0] + 50, typename MyStdMap::key_compare()); (&aux_vect2[0], &aux_vect2[0] + MaxElem, typename MyStdMap::key_compare());
if(!CheckEqualContainers(*pboostmultimap, *pstdmultimap)) return 1; if(!CheckEqualContainers(*pboostmultimap, *pstdmultimap)) return 1;
} }
{ {
IntPairType aux_vect[50]; IntPairType aux_vect[MaxElem];
for(int i = 0; i < 50; ++i){ for(int i = 0; i < MaxElem; ++i){
IntType i1(i/2); IntType i1(i/2);
IntType i2(i/2); IntType i2(i/2);
new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2)); new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
} }
StdValueType aux_vect2[50]; StdValueType aux_vect2[MaxElem];
for(int i = 0; i < 50; ++i){ for(int i = 0; i < MaxElem; ++i){
new(&aux_vect2[i])StdValueType(StdKeyType(i/2), StdMappedType(i/2)); new(&aux_vect2[i])StdValueType(StdKeyType(i/2), StdMappedType(i/2));
} }
IntPairType aux_vect3[50]; IntPairType aux_vect3[MaxElem];
for(int i = 0; i < 50; ++i){ for(int i = 0; i < MaxElem; ++i){
IntType i1(i/2); IntType i1(i/2);
IntType i2(i/2); IntType i2(i/2);
new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2)); new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2));
@@ -201,16 +201,16 @@ int map_test()
::boost::movelib::unique_ptr<MyBoostMap> const pboostmap = ::boost::movelib::make_unique<MyBoostMap> ::boost::movelib::unique_ptr<MyBoostMap> const pboostmap = ::boost::movelib::make_unique<MyBoostMap>
( boost::make_move_iterator(&aux_vect[0]) ( boost::make_move_iterator(&aux_vect[0])
, boost::make_move_iterator(&aux_vect[0] + 50), typename MyBoostMap::allocator_type()); , boost::make_move_iterator(&aux_vect[0] + MaxElem), typename MyBoostMap::allocator_type());
::boost::movelib::unique_ptr<MyStdMap> const pstdmap = ::boost::movelib::make_unique<MyStdMap> ::boost::movelib::unique_ptr<MyStdMap> const pstdmap = ::boost::movelib::make_unique<MyStdMap>
(&aux_vect2[0], &aux_vect2[0] + 50, typename MyStdMap::key_compare()); (&aux_vect2[0], &aux_vect2[0] + MaxElem, typename MyStdMap::key_compare());
if(!CheckEqualContainers(*pboostmap, *pstdmap)) return 1; if(!CheckEqualContainers(*pboostmap, *pstdmap)) return 1;
::boost::movelib::unique_ptr<MyBoostMultiMap> const pboostmultimap = ::boost::movelib::make_unique<MyBoostMultiMap> ::boost::movelib::unique_ptr<MyBoostMultiMap> const pboostmultimap = ::boost::movelib::make_unique<MyBoostMultiMap>
( boost::make_move_iterator(&aux_vect3[0]) ( boost::make_move_iterator(&aux_vect3[0])
, boost::make_move_iterator(&aux_vect3[0] + 50), typename MyBoostMap::allocator_type()); , boost::make_move_iterator(&aux_vect3[0] + MaxElem), typename MyBoostMap::allocator_type());
::boost::movelib::unique_ptr<MyStdMultiMap> const pstdmultimap = ::boost::movelib::make_unique<MyStdMultiMap> ::boost::movelib::unique_ptr<MyStdMultiMap> const pstdmultimap = ::boost::movelib::make_unique<MyStdMultiMap>
(&aux_vect2[0], &aux_vect2[0] + 50, typename MyStdMap::key_compare()); (&aux_vect2[0], &aux_vect2[0] + MaxElem, typename MyStdMap::key_compare());
if(!CheckEqualContainers(*pboostmultimap, *pstdmultimap)) return 1; if(!CheckEqualContainers(*pboostmultimap, *pstdmultimap)) return 1;
} }
@@ -225,8 +225,8 @@ int map_test()
{ {
//This is really nasty, but we have no other simple choice //This is really nasty, but we have no other simple choice
IntPairType aux_vect[50]; IntPairType aux_vect[MaxElem];
for(int i = 0; i < 50; ++i){ for(int i = 0; i < MaxElem; ++i){
IntType i1(i/2); IntType i1(i/2);
IntType i2(i/2); IntType i2(i/2);
new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2)); new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
@@ -235,13 +235,13 @@ int map_test()
typedef typename MyStdMap::value_type StdValueType; typedef typename MyStdMap::value_type StdValueType;
typedef typename MyStdMap::key_type StdKeyType; typedef typename MyStdMap::key_type StdKeyType;
typedef typename MyStdMap::mapped_type StdMappedType; typedef typename MyStdMap::mapped_type StdMappedType;
StdValueType aux_vect2[50]; StdValueType aux_vect2[MaxElem];
for(int i = 0; i < 50; ++i){ for(int i = 0; i < MaxElem; ++i){
new(&aux_vect2[i])StdValueType(StdKeyType(i/2), StdMappedType(i/2)); new(&aux_vect2[i])StdValueType(StdKeyType(i/2), StdMappedType(i/2));
} }
IntPairType aux_vect3[50]; IntPairType aux_vect3[MaxElem];
for(int i = 0; i < 50; ++i){ for(int i = 0; i < MaxElem; ++i){
IntType i1(i/2); IntType i1(i/2);
IntType i2(i/2); IntType i2(i/2);
new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2)); new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2));
@@ -249,14 +249,14 @@ int map_test()
::boost::movelib::unique_ptr<MyBoostMap> const pboostmap2 = ::boost::movelib::make_unique<MyBoostMap> ::boost::movelib::unique_ptr<MyBoostMap> const pboostmap2 = ::boost::movelib::make_unique<MyBoostMap>
( boost::make_move_iterator(&aux_vect[0]) ( boost::make_move_iterator(&aux_vect[0])
, boost::make_move_iterator(&aux_vect[0] + 50)); , boost::make_move_iterator(&aux_vect[0] + MaxElem));
::boost::movelib::unique_ptr<MyStdMap> const pstdmap2 = ::boost::movelib::make_unique<MyStdMap> ::boost::movelib::unique_ptr<MyStdMap> const pstdmap2 = ::boost::movelib::make_unique<MyStdMap>
(&aux_vect2[0], &aux_vect2[0] + 50); (&aux_vect2[0], &aux_vect2[0] + MaxElem);
::boost::movelib::unique_ptr<MyBoostMultiMap> const pboostmultimap2 = ::boost::movelib::make_unique<MyBoostMultiMap> ::boost::movelib::unique_ptr<MyBoostMultiMap> const pboostmultimap2 = ::boost::movelib::make_unique<MyBoostMultiMap>
( boost::make_move_iterator(&aux_vect3[0]) ( boost::make_move_iterator(&aux_vect3[0])
, boost::make_move_iterator(&aux_vect3[0] + 50)); , boost::make_move_iterator(&aux_vect3[0] + MaxElem));
::boost::movelib::unique_ptr<MyStdMultiMap> const pstdmultimap2 = ::boost::movelib::make_unique<MyStdMultiMap> ::boost::movelib::unique_ptr<MyStdMultiMap> const pstdmultimap2 = ::boost::movelib::make_unique<MyStdMultiMap>
(&aux_vect2[0], &aux_vect2[0] + 50); (&aux_vect2[0], &aux_vect2[0] + MaxElem);
MyBoostMap &boostmap2 = *pboostmap2; MyBoostMap &boostmap2 = *pboostmap2;
MyStdMap &stdmap2 = *pstdmap2; MyStdMap &stdmap2 = *pstdmap2;
MyBoostMultiMap &boostmultimap2 = *pboostmultimap2; MyBoostMultiMap &boostmultimap2 = *pboostmultimap2;
@@ -267,17 +267,17 @@ int map_test()
//ordered range insertion //ordered range insertion
//This is really nasty, but we have no other simple choice //This is really nasty, but we have no other simple choice
for(int i = 0; i < 50; ++i){ for(int i = 0; i < MaxElem; ++i){
IntType i1(i); IntType i1(i);
IntType i2(i); IntType i2(i);
new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2)); new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
} }
for(int i = 0; i < 50; ++i){ for(int i = 0; i < MaxElem; ++i){
new(&aux_vect2[i])StdValueType(StdKeyType(i), StdMappedType(i)); new(&aux_vect2[i])StdValueType(StdKeyType(i), StdMappedType(i));
} }
for(int i = 0; i < 50; ++i){ for(int i = 0; i < MaxElem; ++i){
IntType i1(i); IntType i1(i);
IntType i2(i); IntType i2(i);
new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2)); new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2));
@@ -301,14 +301,14 @@ int map_test()
::boost::movelib::unique_ptr<MyBoostMap> const pboostmap3 = ::boost::movelib::make_unique<MyBoostMap> ::boost::movelib::unique_ptr<MyBoostMap> const pboostmap3 = ::boost::movelib::make_unique<MyBoostMap>
( boost::make_move_iterator(&aux_vect[0]) ( boost::make_move_iterator(&aux_vect[0])
, boost::make_move_iterator(&aux_vect[0] + 50)); , boost::make_move_iterator(&aux_vect[0] + MaxElem));
::boost::movelib::unique_ptr<MyStdMap> const pstdmap3 = ::boost::movelib::make_unique<MyStdMap> ::boost::movelib::unique_ptr<MyStdMap> const pstdmap3 = ::boost::movelib::make_unique<MyStdMap>
(&aux_vect2[0], &aux_vect2[0] + 50); (&aux_vect2[0], &aux_vect2[0] + MaxElem);
::boost::movelib::unique_ptr<MyBoostMultiMap> const pboostmultimap3 = ::boost::movelib::make_unique<MyBoostMultiMap> ::boost::movelib::unique_ptr<MyBoostMultiMap> const pboostmultimap3 = ::boost::movelib::make_unique<MyBoostMultiMap>
( boost::make_move_iterator(&aux_vect3[0]) ( boost::make_move_iterator(&aux_vect3[0])
, boost::make_move_iterator(&aux_vect3[0] + 50)); , boost::make_move_iterator(&aux_vect3[0] + MaxElem));
::boost::movelib::unique_ptr<MyStdMultiMap> const pstdmultimap3 = ::boost::movelib::make_unique<MyStdMultiMap> ::boost::movelib::unique_ptr<MyStdMultiMap> const pstdmultimap3 = ::boost::movelib::make_unique<MyStdMultiMap>
(&aux_vect2[0], &aux_vect2[0] + 50); (&aux_vect2[0], &aux_vect2[0] + MaxElem);
MyBoostMap &boostmap3 = *pboostmap3; MyBoostMap &boostmap3 = *pboostmap3;
MyStdMap &stdmap3 = *pstdmap3; MyStdMap &stdmap3 = *pstdmap3;
MyBoostMultiMap &boostmultimap3 = *pboostmultimap3; MyBoostMultiMap &boostmultimap3 = *pboostmultimap3;
@@ -344,20 +344,20 @@ int map_test()
} }
{ {
//This is really nasty, but we have no other simple choice //This is really nasty, but we have no other simple choice
IntPairType aux_vect[max]; IntPairType aux_vect[MaxElem];
for(int i = 0; i < max; ++i){ for(int i = 0; i < MaxElem; ++i){
IntType i1(i); IntType i1(i);
IntType i2(i); IntType i2(i);
new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2)); new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
} }
IntPairType aux_vect3[max]; IntPairType aux_vect3[MaxElem];
for(int i = 0; i < max; ++i){ for(int i = 0; i < MaxElem; ++i){
IntType i1(i); IntType i1(i);
IntType i2(i); IntType i2(i);
new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2)); new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2));
} }
for(int i = 0; i < max; ++i){ for(int i = 0; i < MaxElem; ++i){
boostmap.insert(boost::move(aux_vect[i])); boostmap.insert(boost::move(aux_vect[i]));
stdmap.insert(StdPairType(i, i)); stdmap.insert(StdPairType(i, i));
boostmultimap.insert(boost::move(aux_vect3[i])); boostmultimap.insert(boost::move(aux_vect3[i]));
@@ -405,22 +405,22 @@ int map_test()
//Initialize values //Initialize values
{ {
//This is really nasty, but we have no other simple choice //This is really nasty, but we have no other simple choice
IntPairType aux_vect[50]; IntPairType aux_vect[MaxElem];
for(int i = 0; i < 50; ++i){ for(int i = 0; i < MaxElem; ++i){
IntType i1(-1); IntType i1(-1);
IntType i2(-1); IntType i2(-1);
new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2)); new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
} }
IntPairType aux_vect3[50]; IntPairType aux_vect3[MaxElem];
for(int i = 0; i < 50; ++i){ for(int i = 0; i < MaxElem; ++i){
IntType i1(-1); IntType i1(-1);
IntType i2(-1); IntType i2(-1);
new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2)); new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2));
} }
boostmap.insert(boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(&aux_vect[0] + 50)); boostmap.insert(boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(&aux_vect[0] + MaxElem));
boostmultimap.insert(boost::make_move_iterator(&aux_vect3[0]), boost::make_move_iterator(&aux_vect3[0] + 50)); boostmultimap.insert(boost::make_move_iterator(&aux_vect3[0]), boost::make_move_iterator(&aux_vect3[0] + MaxElem));
for(std::size_t i = 0; i != 50; ++i){ for(int i = 0; i != MaxElem; ++i){
StdPairType stdpairtype(-1, -1); StdPairType stdpairtype(-1, -1);
stdmap.insert(stdpairtype); stdmap.insert(stdpairtype);
stdmultimap.insert(stdpairtype); stdmultimap.insert(stdpairtype);
@@ -439,40 +439,40 @@ int map_test()
if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1; if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
} }
{ {
IntPairType aux_vect[50]; IntPairType aux_vect[MaxElem];
for(int i = 0; i < 50; ++i){ for(int i = 0; i < MaxElem; ++i){
IntType i1(-1); IntType i1(-1);
IntType i2(-1); IntType i2(-1);
new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2)); new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
} }
IntPairType aux_vect3[50]; IntPairType aux_vect3[MaxElem];
for(int i = 0; i < 50; ++i){ for(int i = 0; i < MaxElem; ++i){
IntType i1(-1); IntType i1(-1);
IntType i2(-1); IntType i2(-1);
new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2)); new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2));
} }
IntPairType aux_vect4[50]; IntPairType aux_vect4[MaxElem];
for(int i = 0; i < 50; ++i){ for(int i = 0; i < MaxElem; ++i){
IntType i1(-1); IntType i1(-1);
IntType i2(-1); IntType i2(-1);
new(&aux_vect4[i])IntPairType(boost::move(i1), boost::move(i2)); new(&aux_vect4[i])IntPairType(boost::move(i1), boost::move(i2));
} }
IntPairType aux_vect5[50]; IntPairType aux_vect5[MaxElem];
for(int i = 0; i < 50; ++i){ for(int i = 0; i < MaxElem; ++i){
IntType i1(-1); IntType i1(-1);
IntType i2(-1); IntType i2(-1);
new(&aux_vect5[i])IntPairType(boost::move(i1), boost::move(i2)); new(&aux_vect5[i])IntPairType(boost::move(i1), boost::move(i2));
} }
boostmap.insert(boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(&aux_vect[0] + 50)); boostmap.insert(boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(&aux_vect[0] + MaxElem));
boostmap.insert(boost::make_move_iterator(&aux_vect3[0]), boost::make_move_iterator(&aux_vect3[0] + 50)); boostmap.insert(boost::make_move_iterator(&aux_vect3[0]), boost::make_move_iterator(&aux_vect3[0] + MaxElem));
boostmultimap.insert(boost::make_move_iterator(&aux_vect4[0]), boost::make_move_iterator(aux_vect4 + 50)); boostmultimap.insert(boost::make_move_iterator(&aux_vect4[0]), boost::make_move_iterator(aux_vect4 + MaxElem));
boostmultimap.insert(boost::make_move_iterator(&aux_vect5[0]), boost::make_move_iterator(aux_vect5 + 50)); boostmultimap.insert(boost::make_move_iterator(&aux_vect5[0]), boost::make_move_iterator(aux_vect5 + MaxElem));
for(std::size_t i = 0; i != 50; ++i){ for(int i = 0; i != MaxElem; ++i){
StdPairType stdpairtype(-1, -1); StdPairType stdpairtype(-1, -1);
stdmap.insert(stdpairtype); stdmap.insert(stdpairtype);
stdmultimap.insert(stdpairtype); stdmultimap.insert(stdpairtype);
@@ -492,20 +492,20 @@ int map_test()
{ {
//This is really nasty, but we have no other simple choice //This is really nasty, but we have no other simple choice
IntPairType aux_vect[max]; IntPairType aux_vect[MaxElem];
for(int i = 0; i < max; ++i){ for(int i = 0; i < MaxElem; ++i){
IntType i1(i); IntType i1(i);
IntType i2(i); IntType i2(i);
new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2)); new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
} }
IntPairType aux_vect3[max]; IntPairType aux_vect3[MaxElem];
for(int i = 0; i < max; ++i){ for(int i = 0; i < MaxElem; ++i){
IntType i1(i); IntType i1(i);
IntType i2(i); IntType i2(i);
new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2)); new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2));
} }
for(int i = 0; i < max; ++i){ for(int i = 0; i < MaxElem; ++i){
boostmap.insert(boost::move(aux_vect[i])); boostmap.insert(boost::move(aux_vect[i]));
stdmap.insert(StdPairType(i, i)); stdmap.insert(StdPairType(i, i));
boostmultimap.insert(boost::move(aux_vect3[i])); boostmultimap.insert(boost::move(aux_vect3[i]));
@@ -515,7 +515,7 @@ int map_test()
if(!CheckEqualPairContainers(boostmap, stdmap)) return 1; if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1; if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
for(int i = 0; i < max; ++i){ for(int i = 0; i < MaxElem; ++i){
IntPairType intpair; IntPairType intpair;
{ {
IntType i1(i); IntType i1(i);
@@ -629,7 +629,7 @@ int map_test()
} }
//Compare count with std containers //Compare count with std containers
for(int i = 0; i < max; ++i){ for(int i = 0; i < MaxElem; ++i){
IntType k(i); IntType k(i);
if(boostmap.count(k) != stdmap.count(i)){ if(boostmap.count(k) != stdmap.count(i)){
return -1; return -1;
@@ -673,14 +673,14 @@ int map_test()
stdmap.clear(); stdmap.clear();
stdmultimap.clear(); stdmultimap.clear();
IntPairType aux_vect[max]; IntPairType aux_vect[MaxElem];
for(int i = 0; i < max; ++i){ for(int i = 0; i < MaxElem; ++i){
IntType i1(i); IntType i1(i);
IntType i2(i); IntType i2(i);
new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2)); new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
} }
for(int i = 0; i < max; ++i){ for(int i = 0; i < MaxElem; ++i){
boostmap[boost::move(aux_vect[i].first)] = boost::move(aux_vect[i].second); boostmap[boost::move(aux_vect[i].first)] = boost::move(aux_vect[i].second);
stdmap[i] = i; stdmap[i] = i;
} }
@@ -695,21 +695,21 @@ int map_test()
stdmap.clear(); stdmap.clear();
stdmultimap.clear(); stdmultimap.clear();
IntPairType aux_vect[max]; IntPairType aux_vect[MaxElem];
for(int i = 0; i < max; ++i){ for(int i = 0; i < MaxElem; ++i){
IntType i1(i); IntType i1(i);
IntType i2(i); IntType i2(i);
new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2)); new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
} }
IntPairType aux_vect2[max]; IntPairType aux_vect2[MaxElem];
for(int i = 0; i < max; ++i){ for(int i = 0; i < MaxElem; ++i){
IntType i1(i); IntType i1(i);
IntType i2(max-i); IntType i2(MaxElem-i);
new(&aux_vect2[i])IntPairType(boost::move(i1), boost::move(i2)); new(&aux_vect2[i])IntPairType(boost::move(i1), boost::move(i2));
} }
for(int i = 0; i < max; ++i){ for(int i = 0; i < MaxElem; ++i){
boostmap.insert_or_assign(boost::move(aux_vect[i].first), boost::move(aux_vect[i].second)); boostmap.insert_or_assign(boost::move(aux_vect[i].first), boost::move(aux_vect[i].second));
stdmap[i] = i; stdmap[i] = i;
} }
@@ -717,9 +717,9 @@ int map_test()
if(!CheckEqualPairContainers(boostmap, stdmap)) return 1; if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1; if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
for(int i = 0; i < max; ++i){ for(int i = 0; i < MaxElem; ++i){
boostmap.insert_or_assign(boost::move(aux_vect2[i].first), boost::move(aux_vect2[i].second)); boostmap.insert_or_assign(boost::move(aux_vect2[i].first), boost::move(aux_vect2[i].second));
stdmap[i] = max-i; stdmap[i] = MaxElem-i;
} }
if(!CheckEqualPairContainers(boostmap, stdmap)) return 1; if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
@@ -732,22 +732,22 @@ int map_test()
stdmap.clear(); stdmap.clear();
stdmultimap.clear(); stdmultimap.clear();
IntPairType aux_vect[max]; IntPairType aux_vect[MaxElem];
for(int i = 0; i < max; ++i){ for(int i = 0; i < MaxElem; ++i){
IntType i1(i); IntType i1(i);
IntType i2(i); IntType i2(i);
new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2)); new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
} }
IntPairType aux_vect2[max]; IntPairType aux_vect2[MaxElem];
for(int i = 0; i < max; ++i){ for(int i = 0; i < MaxElem; ++i){
IntType i1(i); IntType i1(i);
IntType i2(max-i); IntType i2(MaxElem-i);
new(&aux_vect2[i])IntPairType(boost::move(i1), boost::move(i2)); new(&aux_vect2[i])IntPairType(boost::move(i1), boost::move(i2));
} }
typedef typename MyBoostMap::iterator iterator; typedef typename MyBoostMap::iterator iterator;
for(int i = 0; i < max; ++i){ for(int i = 0; i < MaxElem; ++i){
iterator it; iterator it;
if(i&1){ if(i&1){
std::pair<typename MyBoostMap::iterator, bool> ret = std::pair<typename MyBoostMap::iterator, bool> ret =
@@ -769,7 +769,7 @@ int map_test()
if(!CheckEqualPairContainers(boostmap, stdmap)) return 1; if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1; if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
for(int i = 0; i < max; ++i){ for(int i = 0; i < MaxElem; ++i){
iterator it; iterator it;
iterator itex = boostmap.find(aux_vect2[i].first); iterator itex = boostmap.find(aux_vect2[i].first);
if(itex == boostmap.end()) if(itex == boostmap.end())
@@ -795,6 +795,108 @@ int map_test()
if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1; if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
} }
{ //merge
::boost::movelib::unique_ptr<MyBoostMap> const pboostmap2 = ::boost::movelib::make_unique<MyBoostMap>();
::boost::movelib::unique_ptr<MyBoostMultiMap> const pboostmultimap2 = ::boost::movelib::make_unique<MyBoostMultiMap>();
MyBoostMap &boostmap2 = *pboostmap2;
MyBoostMultiMap &boostmultimap2 = *pboostmultimap2;
boostmap.clear();
boostmap2.clear();
boostmultimap.clear();
boostmultimap2.clear();
stdmap.clear();
stdmultimap.clear();
{
IntPairType aux_vect[MaxElem];
for(int i = 0; i < MaxElem; ++i){
IntType i1(i);
IntType i2(i);
new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
}
IntPairType aux_vect2[MaxElem];
for(int i = 0; i < MaxElem; ++i){
IntType i1(MaxElem/2+i);
IntType i2(MaxElem-i);
new(&aux_vect2[i])IntPairType(boost::move(i1), boost::move(i2));
}
IntPairType aux_vect3[MaxElem];
for(int i = 0; i < MaxElem; ++i){
IntType i1(MaxElem*2/2+i);
IntType i2(MaxElem*2+i);
new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2));
}
boostmap.insert(boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(&aux_vect[0] + MaxElem));
boostmap2.insert(boost::make_move_iterator(&aux_vect2[0]), boost::make_move_iterator(&aux_vect2[0] + MaxElem));
boostmultimap2.insert(boost::make_move_iterator(&aux_vect3[0]), boost::make_move_iterator(&aux_vect3[0] + MaxElem));
}
for(int i = 0; i < MaxElem; ++i){
stdmap.insert(StdPairType(i, i));
}
for(int i = 0; i < MaxElem; ++i){
stdmap.insert(StdPairType(MaxElem/2+i, MaxElem-i));
}
boostmap.merge(boost::move(boostmap2));
if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
for(int i = 0; i < MaxElem; ++i){
stdmap.insert(StdPairType(MaxElem*2/2+i, MaxElem*2+i));
}
boostmap.merge(boost::move(boostmultimap2));
if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
boostmap.clear();
boostmap2.clear();
boostmultimap.clear();
boostmultimap2.clear();
stdmap.clear();
stdmultimap.clear();
{
IntPairType aux_vect[MaxElem];
for(int i = 0; i < MaxElem; ++i){
IntType i1(i);
IntType i2(i);
new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
}
IntPairType aux_vect2[MaxElem];
for(int i = 0; i < MaxElem; ++i){
IntType i1(MaxElem/2+i);
IntType i2(MaxElem-i);
new(&aux_vect2[i])IntPairType(boost::move(i1), boost::move(i2));
}
IntPairType aux_vect3[MaxElem];
for(int i = 0; i < MaxElem; ++i){
IntType i1(MaxElem*2/2+i);
IntType i2(MaxElem*2+i);
new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2));
}
boostmultimap.insert(boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(&aux_vect[0] + MaxElem));
boostmultimap2.insert(boost::make_move_iterator(&aux_vect2[0]), boost::make_move_iterator(&aux_vect2[0] + MaxElem));
boostmap2.insert(boost::make_move_iterator(&aux_vect3[0]), boost::make_move_iterator(&aux_vect3[0] + MaxElem));
}
for(int i = 0; i < MaxElem; ++i){
stdmultimap.insert(StdPairType(i, i));
}
for(int i = 0; i < MaxElem; ++i){
stdmultimap.insert(StdPairType(MaxElem/2+i, MaxElem-i));
}
boostmultimap.merge(boost::move(boostmultimap2));
if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
for(int i = 0; i < MaxElem; ++i){
stdmultimap.insert(StdPairType(MaxElem*2/2+i, MaxElem*2+i));
}
boostmultimap.merge(boost::move(boostmap2));
if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
}
if(map_test_copyable<MyBoostMap, MyStdMap, MyBoostMultiMap, MyStdMultiMap> if(map_test_copyable<MyBoostMap, MyStdMap, MyBoostMultiMap, MyStdMultiMap>
(container_detail::bool_<boost::container::test::is_copyable<IntType>::value>())){ (container_detail::bool_<boost::container::test::is_copyable<IntType>::value>())){
return 1; return 1;

View File

@@ -58,7 +58,6 @@ namespace container_detail {
//Instantiate base class as previous instantiations don't instantiate inherited members //Instantiate base class as previous instantiations don't instantiate inherited members
template class tree template class tree
< test::movable_and_copyable_int < test::movable_and_copyable_int
, test::movable_and_copyable_int
, identity<test::movable_and_copyable_int> , identity<test::movable_and_copyable_int>
, std::less<test::movable_and_copyable_int> , std::less<test::movable_and_copyable_int>
, test::simple_allocator<test::movable_and_copyable_int> , test::simple_allocator<test::movable_and_copyable_int>
@@ -67,7 +66,6 @@ template class tree
template class tree template class tree
< test::movable_and_copyable_int < test::movable_and_copyable_int
, test::movable_and_copyable_int
, identity<test::movable_and_copyable_int> , identity<test::movable_and_copyable_int>
, std::less<test::movable_and_copyable_int> , std::less<test::movable_and_copyable_int>
, std::allocator<test::movable_and_copyable_int> , std::allocator<test::movable_and_copyable_int>
@@ -76,7 +74,6 @@ template class tree
template class tree template class tree
< test::movable_and_copyable_int < test::movable_and_copyable_int
, test::movable_and_copyable_int
, identity<test::movable_and_copyable_int> , identity<test::movable_and_copyable_int>
, std::less<test::movable_and_copyable_int> , std::less<test::movable_and_copyable_int>
, adaptive_pool<test::movable_and_copyable_int> , adaptive_pool<test::movable_and_copyable_int>
@@ -354,6 +351,13 @@ int test_set_variants()
return 0; return 0;
} }
void test_merge_from_different_comparison()
{
set<int> set1;
set<int, std::greater<int> > set2;
set1.merge(set2);
}
int main () int main ()
{ {
@@ -381,6 +385,8 @@ int main ()
s.emplace(p); s.emplace(p);
} }
test_merge_from_different_comparison();
//////////////////////////////////// ////////////////////////////////////
// Testing allocator implementations // Testing allocator implementations
//////////////////////////////////// ////////////////////////////////////

View File

@@ -46,6 +46,8 @@ template<class MyBoostSet
int set_test_copyable(boost::container::container_detail::false_type) int set_test_copyable(boost::container::container_detail::false_type)
{ return 0; } { return 0; }
const int MaxElem = 50;
template<class MyBoostSet template<class MyBoostSet
,class MyStdSet ,class MyStdSet
,class MyBoostMultiSet ,class MyBoostMultiSet
@@ -53,7 +55,6 @@ template<class MyBoostSet
int set_test_copyable(boost::container::container_detail::true_type) int set_test_copyable(boost::container::container_detail::true_type)
{ {
typedef typename MyBoostSet::value_type IntType; typedef typename MyBoostSet::value_type IntType;
const int max = 50;
::boost::movelib::unique_ptr<MyBoostSet> const pboostset = ::boost::movelib::make_unique<MyBoostSet>(); ::boost::movelib::unique_ptr<MyBoostSet> const pboostset = ::boost::movelib::make_unique<MyBoostSet>();
::boost::movelib::unique_ptr<MyStdSet> const pstdset = ::boost::movelib::make_unique<MyStdSet>(); ::boost::movelib::unique_ptr<MyStdSet> const pstdset = ::boost::movelib::make_unique<MyStdSet>();
@@ -71,7 +72,7 @@ int set_test_copyable(boost::container::container_detail::true_type)
boostset.insert(boostset.begin(), boostset.end()); boostset.insert(boostset.begin(), boostset.end());
boostmultiset.insert(boostmultiset.begin(), boostmultiset.end()); boostmultiset.insert(boostmultiset.begin(), boostmultiset.end());
for(int i = 0; i < max; ++i){ for(int i = 0; i < MaxElem; ++i){
IntType move_me(i); IntType move_me(i);
boostset.insert(boost::move(move_me)); boostset.insert(boost::move(move_me));
stdset.insert(i); stdset.insert(i);
@@ -134,7 +135,6 @@ template<class MyBoostSet
int set_test () int set_test ()
{ {
typedef typename MyBoostSet::value_type IntType; typedef typename MyBoostSet::value_type IntType;
const int max = 50;
::boost::movelib::unique_ptr<MyBoostSet> const pboostset = ::boost::movelib::make_unique<MyBoostSet>(); ::boost::movelib::unique_ptr<MyBoostSet> const pboostset = ::boost::movelib::make_unique<MyBoostSet>();
::boost::movelib::unique_ptr<MyStdSet> const pstdset = ::boost::movelib::make_unique<MyStdSet>(); ::boost::movelib::unique_ptr<MyStdSet> const pstdset = ::boost::movelib::make_unique<MyStdSet>();
@@ -293,7 +293,7 @@ int set_test ()
} }
} }
for(int i = 0; i < max; ++i){ for(int i = 0; i < MaxElem; ++i){
IntType move_me(i); IntType move_me(i);
boostset.insert(boost::move(move_me)); boostset.insert(boost::move(move_me));
stdset.insert(i); stdset.insert(i);
@@ -474,7 +474,7 @@ int set_test ()
} }
} }
for(int i = 0; i < max; ++i){ for(int i = 0; i < MaxElem; ++i){
IntType move_me(i); IntType move_me(i);
boostset.insert(boost::move(move_me)); boostset.insert(boost::move(move_me));
stdset.insert(i); stdset.insert(i);
@@ -492,7 +492,7 @@ int set_test ()
return 1; return 1;
} }
for(int i = 0; i < max; ++i){ for(int i = 0; i < MaxElem; ++i){
{ {
IntType move_me(i); IntType move_me(i);
boostset.insert(boostset.begin(), boost::move(move_me)); boostset.insert(boostset.begin(), boost::move(move_me));
@@ -579,7 +579,7 @@ int set_test ()
} }
//Compare count with std containers //Compare count with std containers
for(int i = 0; i < max; ++i){ for(int i = 0; i < MaxElem; ++i){
IntType count_me(i); IntType count_me(i);
if(boostset.count(count_me) != stdset.count(i)){ if(boostset.count(count_me) != stdset.count(i)){
return -1; return -1;
@@ -703,6 +703,96 @@ int set_test ()
} }
} }
{ //merge
::boost::movelib::unique_ptr<MyBoostSet> const pboostset2 = ::boost::movelib::make_unique<MyBoostSet>();
::boost::movelib::unique_ptr<MyBoostMultiSet> const pboostmultiset2 = ::boost::movelib::make_unique<MyBoostMultiSet>();
MyBoostSet &boostset2 = *pboostset2;
MyBoostMultiSet &boostmultiset2 = *pboostmultiset2;
boostset.clear();
boostset2.clear();
boostmultiset.clear();
boostmultiset2.clear();
stdset.clear();
stdmultiset.clear();
{
IntType aux_vect[MaxElem];
for(int i = 0; i < MaxElem; ++i){
aux_vect[i] = i;
}
IntType aux_vect2[MaxElem];
for(int i = 0; i < MaxElem; ++i){
aux_vect2[i] = MaxElem/2+i;
}
IntType aux_vect3[MaxElem];
for(int i = 0; i < MaxElem; ++i){
aux_vect3[i] = MaxElem*2/2+i;
}
boostset.insert(boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(&aux_vect[0] + MaxElem));
boostset2.insert(boost::make_move_iterator(&aux_vect2[0]), boost::make_move_iterator(&aux_vect2[0] + MaxElem));
boostmultiset2.insert(boost::make_move_iterator(&aux_vect3[0]), boost::make_move_iterator(&aux_vect3[0] + MaxElem));
}
for(int i = 0; i < MaxElem; ++i){
stdset.insert(i);
}
for(int i = 0; i < MaxElem; ++i){
stdset.insert(MaxElem/2+i);
}
boostset.merge(boost::move(boostset2));
if(!CheckEqualContainers(boostset, stdset)) return 1;
for(int i = 0; i < MaxElem; ++i){
stdset.insert(MaxElem*2/2+i);
}
boostset.merge(boost::move(boostmultiset2));
if(!CheckEqualContainers(boostset, stdset)) return 1;
boostset.clear();
boostset2.clear();
boostmultiset.clear();
boostmultiset2.clear();
stdset.clear();
stdmultiset.clear();
{
IntType aux_vect[MaxElem];
for(int i = 0; i < MaxElem; ++i){
aux_vect[i] = i;
}
IntType aux_vect2[MaxElem];
for(int i = 0; i < MaxElem; ++i){
aux_vect2[i] = MaxElem/2+i;
}
IntType aux_vect3[MaxElem];
for(int i = 0; i < MaxElem; ++i){
aux_vect3[i] = MaxElem*2/2+i;
}
boostmultiset.insert(boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(&aux_vect[0] + MaxElem));
boostmultiset2.insert(boost::make_move_iterator(&aux_vect2[0]), boost::make_move_iterator(&aux_vect2[0] + MaxElem));
boostset2.insert(boost::make_move_iterator(&aux_vect3[0]), boost::make_move_iterator(&aux_vect3[0] + MaxElem));
}
for(int i = 0; i < MaxElem; ++i){
stdmultiset.insert(i);
}
for(int i = 0; i < MaxElem; ++i){
stdmultiset.insert(MaxElem/2+i);
}
boostmultiset.merge(boost::move(boostmultiset2));
if(!CheckEqualContainers(boostmultiset, stdmultiset)) return 1;
for(int i = 0; i < MaxElem; ++i){
stdmultiset.insert(MaxElem*2/2+i);
}
boostmultiset.merge(boost::move(boostset2));
if(!CheckEqualContainers(boostmultiset, stdmultiset)) return 1;
}
if(set_test_copyable<MyBoostSet, MyStdSet, MyBoostMultiSet, MyStdMultiSet> if(set_test_copyable<MyBoostSet, MyStdSet, MyBoostMultiSet, MyStdMultiSet>
(container_detail::bool_<boost::container::test::is_copyable<IntType>::value>())){ (container_detail::bool_<boost::container::test::is_copyable<IntType>::value>())){
return 1; return 1;