* 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
+35 -4
View File
@@ -46,6 +46,7 @@
#endif
#include <boost/intrusive/detail/minimal_pair_header.hpp> //pair
#include <boost/move/iterator.hpp>
namespace boost {
namespace container {
@@ -100,7 +101,7 @@ struct get_flat_tree_iterators
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 flat_tree
{
@@ -185,7 +186,7 @@ class flat_tree
typedef typename vector_t::const_pointer const_pointer;
typedef typename vector_t::reference reference;
typedef typename vector_t::const_reference const_reference;
typedef Key key_type;
typedef typename KeyOfValue::type key_type;
typedef Compare key_compare;
typedef typename vector_t::allocator_type allocator_type;
typedef typename vector_t::size_type size_type;
@@ -778,6 +779,36 @@ class flat_tree
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)
{ return this->priv_lower_bound(this->begin(), this->end(), k); }
@@ -1062,9 +1093,9 @@ class flat_tree
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
template <class Key, class T, class KeyOfValue,
template <class T, class KeyOfValue,
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;
static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value &&
@@ -394,12 +394,6 @@ struct node_alloc_holder
ICont &non_const_icont() const
{ 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()
{ return static_cast<NodeAlloc &>(this->members_); }
@@ -407,6 +401,13 @@ struct node_alloc_holder
{ return static_cast<const NodeAlloc &>(this->members_); }
members_holder members_;
public:
ICont &icont()
{ return this->members_.m_icont; }
const ICont &icont() const
{ return this->members_.m_icont; }
};
} //namespace container_detail {
+19 -10
View File
@@ -295,9 +295,9 @@ struct intrusive_tree_type
allocator_traits<Allocator>::size_type size_type;
typedef typename container_detail::tree_node
< value_type, void_pointer
, tree_type_value, OptimizeSize> node_t;
, tree_type_value, OptimizeSize> node_t;
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
//provoke an early instantiation of node_t that could ruin recursive
//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())); }
};
template <class Key, class T, class KeyOfValue,
template <class T, class KeyOfValue,
class Compare, class Allocator,
class Options = tree_assoc_defaults>
class tree
: protected container_detail::node_alloc_holder
: public container_detail::node_alloc_holder
< Allocator
, 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
>
{
typedef tree_value_compare
<Compare, KeyOfValue> ValComp;
< typename allocator_traits<Allocator>::pointer
, Compare, KeyOfValue> ValComp;
typedef typename container_detail::intrusive_tree_type
< Allocator, ValComp, Options::tree_type
, Options::optimize_size>::type Icont;
typedef container_detail::node_alloc_holder
<Allocator, Icont> AllocHolder;
typedef typename AllocHolder::NodePtr NodePtr;
typedef tree < Key, T, KeyOfValue
typedef tree < T, KeyOfValue
, Compare, Allocator, Options> ThisType;
typedef typename AllocHolder::NodeAlloc NodeAlloc;
typedef boost::container::
@@ -465,7 +467,7 @@ class tree
public:
typedef Key key_type;
typedef typename KeyOfValue::type key_type;
typedef T value_type;
typedef Allocator allocator_type;
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()
{ AllocHolder::clear(alloc_version()); }
@@ -1265,11 +1274,11 @@ struct has_trivial_destructor_after_move;
//!has_trivial_destructor_after_move<> == true_type
//!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
<
::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;
+86 -4
View File
@@ -53,6 +53,9 @@ namespace container {
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
template <class Key, class T, class Compare, class Allocator>
class flat_multimap;
namespace container_detail{
template<class D, class S>
@@ -110,14 +113,14 @@ class flat_map
private:
BOOST_COPYABLE_AND_MOVABLE(flat_map)
//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>,
container_detail::select1st<Key>,
Compare,
Allocator> tree_t;
//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::select1st<Key>,
Compare,
@@ -143,6 +146,13 @@ class flat_map
<typename allocator_traits<Allocator>::pointer>::const_reverse_iterator const_reverse_iterator_impl;
public:
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:
#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()); }
#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>Returns</b>: Returns an iterator pointing to the element immediately
@@ -1326,13 +1369,13 @@ class flat_multimap
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
BOOST_COPYABLE_AND_MOVABLE(flat_multimap)
typedef container_detail::flat_tree<Key,
typedef container_detail::flat_tree<
std::pair<Key, T>,
container_detail::select1st<Key>,
Compare,
Allocator> tree_t;
//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::select1st<Key>,
Compare,
@@ -1358,6 +1401,13 @@ class flat_multimap
<typename allocator_traits<Allocator>::pointer>::const_reverse_iterator const_reverse_iterator_impl;
public:
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:
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
@@ -1993,6 +2043,38 @@ class flat_multimap
{ m_flat_tree.insert_equal(ordered_range, il.begin(), il.end()); }
#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>Returns</b>: Returns an iterator pointing to the element immediately
+64 -4
View File
@@ -47,6 +47,11 @@
namespace boost {
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.
//! 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
class flat_set
///@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
{
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
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
public:
@@ -605,6 +618,26 @@ class flat_set
{ this->base_t::insert_unique(ordered_unique_range, il.begin(), il.end()); }
#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)
//! <b>Effects</b>: Erases the element pointed to by p.
@@ -867,13 +900,20 @@ template <class Key, class Compare, class Allocator>
#endif
class flat_multiset
///@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
{
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
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
public:
@@ -1233,6 +1273,26 @@ class flat_multiset
{ this->base_t::insert_equal(ordered_range, il.begin(), il.end()); }
#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)
//! @copydoc ::boost::container::flat_set::erase(const_iterator)
+95 -16
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 Allocator is the allocator to allocate the <code>value_type</code>s
//! (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>
, 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
template <class Key, class T, class Compare, class Allocator, class MapOptions>
template <class Key, class T, class Compare, class Allocator, class Options>
#endif
class map
///@cond
: public container_detail::tree
< Key, std::pair<const Key, T>
< std::pair<const Key, T>
, container_detail::select1st<Key>
, Compare, Allocator, MapOptions>
, Compare, Allocator, Options>
///@endcond
{
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
@@ -117,10 +117,9 @@ class map
typedef container_detail::select1st<Key> select_1st_t;
typedef std::pair<const Key, T> value_type_impl;
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::tree_value_compare
<Compare, select_1st_t> value_compare_impl;
typedef typename base_t::value_compare value_compare_impl;
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public:
@@ -975,6 +974,47 @@ class map
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)
//! <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 Allocator is the allocator to allocate the <code>value_type</code>s
//! (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>
, 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
template <class Key, class T, class Compare, class Allocator, class MultiMapOptions>
template <class Key, class T, class Compare, class Allocator, class Options>
#endif
class multimap
///@cond
: public container_detail::tree
< Key, std::pair<const Key, T>
< std::pair<const Key, T>
, container_detail::select1st<Key>
, Compare, Allocator, MultiMapOptions>
, Compare, Allocator, Options>
///@endcond
{
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
@@ -1169,10 +1209,9 @@ class multimap
typedef container_detail::select1st<Key> select_1st_t;
typedef std::pair<const Key, T> value_type_impl;
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::tree_value_compare
<Compare, select_1st_t> value_compare_impl;
typedef typename base_t::value_compare value_compare_impl;
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
typedef ::boost::container::allocator_traits<Allocator> allocator_traits_type;
@@ -1655,6 +1694,46 @@ class multimap
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)
//! @copydoc ::boost::container::set::swap
void swap(multiset& x)
+70 -14
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 Compare is the comparison functor used to order keys
//! \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.
template <class Key, class Compare = std::less<Key>, class Allocator = new_allocator<Key>, class SetOptions = tree_assoc_defaults >
//! \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 Options = tree_assoc_defaults >
#else
template <class Key, class Compare, class Allocator, class SetOptions>
template <class Key, class Compare, class Allocator, class Options>
#endif
class set
///@cond
: public container_detail::tree
< Key, Key, container_detail::identity<Key>, Compare, Allocator, SetOptions>
< Key, container_detail::identity<Key>, Compare, Allocator, Options>
///@endcond
{
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
BOOST_COPYABLE_AND_MOVABLE(set)
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
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)
{ 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)
//! <b>Effects</b>: Erases the element pointed to by p.
@@ -724,8 +752,8 @@ class set
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
template <class Key, class Compare, class SetOptions, class Allocator>
struct has_trivial_destructor_after_move<boost::container::set<Key, Compare, Allocator, SetOptions> >
template <class Key, class Compare, class Options, class Allocator>
struct has_trivial_destructor_after_move<boost::container::set<Key, Compare, Allocator, Options> >
{
typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer;
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 Compare is the comparison functor used to order keys
//! \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.
template <class Key, class Compare = std::less<Key>, class Allocator = new_allocator<Key>, class MultiSetOptions = tree_assoc_defaults >
//! \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 Options = tree_assoc_defaults >
#else
template <class Key, class Compare, class Allocator, class MultiSetOptions>
template <class Key, class Compare, class Allocator, class Options>
#endif
class multiset
/// @cond
: public container_detail::tree
<Key, Key,container_detail::identity<Key>, Compare, Allocator, MultiSetOptions>
<Key,container_detail::identity<Key>, Compare, Allocator, Options>
/// @endcond
{
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
BOOST_COPYABLE_AND_MOVABLE(multiset)
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
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)
{ 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)
//! @copydoc ::boost::container::set::erase(const_iterator)
@@ -1179,8 +1235,8 @@ class multiset
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
template <class Key, class Compare, class Allocator, class MultiSetOptions>
struct has_trivial_destructor_after_move<boost::container::multiset<Key, Compare, Allocator, MultiSetOptions> >
template <class Key, class Compare, class Allocator, class Options>
struct has_trivial_destructor_after_move<boost::container::multiset<Key, Compare, Allocator, Options> >
{
typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer;
static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value &&