mirror of
https://github.com/boostorg/container.git
synced 2025-08-02 14:04:26 +02:00
* Add missing extract() and insert(node_type) funtion to associative containers.
* Simplify select1st
This commit is contained in:
@@ -36,6 +36,8 @@ doxygen autodoc
|
||||
\"BOOST_RV_REF(T)=T&&\" \\
|
||||
\"BOOST_RV_REF_BEG=\" \\
|
||||
\"BOOST_RV_REF_END=&&\" \\
|
||||
\"BOOST_RV_REF_BEG_IF_CXX11=\" \\
|
||||
\"BOOST_RV_REF_END_IF_CXX11=&&\" \\
|
||||
\"BOOST_COPY_ASSIGN_REF(T)=const T &\" \\
|
||||
\"BOOST_FWD_REF(a)=a &&\" \\
|
||||
\"BOOST_INTRUSIVE_OPTION_CONSTANT(OPTION_NAME, TYPE, VALUE, CONSTANT_NAME) = template<TYPE VALUE> struct OPTION_NAME{};\" \\
|
||||
|
@@ -1231,7 +1231,9 @@ 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"]].
|
||||
|
||||
* Revised noexcept expressions of default and move constructors in all containers.
|
||||
* Implemented C++17 `insert_or_assign` and `try_emplace`for [classref boost::container::map map] and [classref boost::container::flat_map flat_map].
|
||||
* 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 `extract`/`insert(node)` for [classref boost::container::map map], [classref boost::container::multimap multimap],
|
||||
[classref boost::container::set set], [classref boost::container::multiset multiset].
|
||||
|
||||
[endsect]
|
||||
|
||||
|
@@ -62,19 +62,18 @@ using boost::move_detail::disable_if_and;
|
||||
using boost::move_detail::enable_if_or;
|
||||
using boost::move_detail::disable_if_or;
|
||||
|
||||
|
||||
template <class Pair>
|
||||
template <class FirstType>
|
||||
struct select1st
|
||||
{
|
||||
typedef Pair argument_type;
|
||||
typedef typename Pair::first_type result_type;
|
||||
typedef FirstType type;
|
||||
|
||||
template<class OtherPair>
|
||||
const typename Pair::first_type& operator()(const OtherPair& x) const
|
||||
template<class T>
|
||||
const type& operator()(const T& x) const
|
||||
{ return x.first; }
|
||||
|
||||
const typename Pair::first_type& operator()(const typename Pair::first_type& x) const
|
||||
{ return x; }
|
||||
template<class T>
|
||||
type& operator()(T& x)
|
||||
{ return const_cast<type&>(x.first); }
|
||||
};
|
||||
|
||||
} //namespace container_detail {
|
||||
|
@@ -201,7 +201,7 @@ struct pair
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
template< class KeyType, class ...Args>
|
||||
pair(const try_emplace_t &, BOOST_FWD_REF(KeyType) k, Args && ...args)
|
||||
pair(try_emplace_t, BOOST_FWD_REF(KeyType) k, Args && ...args)
|
||||
: first(boost::forward<KeyType>(k)), second(::boost::forward<Args>(args)...)\
|
||||
{}
|
||||
#else
|
||||
|
@@ -25,6 +25,7 @@
|
||||
#include <boost/container/allocator_traits.hpp>
|
||||
#include <boost/container/container_fwd.hpp>
|
||||
#include <boost/container/options.hpp>
|
||||
#include <boost/container/node_handle.hpp>
|
||||
|
||||
// container/detail
|
||||
#include <boost/container/detail/algorithm.hpp> //algo_equal(), algo_lexicographical_compare
|
||||
@@ -135,7 +136,7 @@ struct tree_node
|
||||
typedef typename tree_internal_data_type<T>::type internal_type;
|
||||
|
||||
typedef tree_node< T, VoidPointer
|
||||
, tree_type_value, OptimizeSize> node_type;
|
||||
, tree_type_value, OptimizeSize> node_t;
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE T &get_data()
|
||||
{
|
||||
@@ -294,18 +295,18 @@ 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_type;
|
||||
, tree_type_value, OptimizeSize> node_t;
|
||||
typedef value_to_node_compare
|
||||
<node_type, ValueCompare> node_compare_type;
|
||||
//Deducing the hook type from node_type (e.g. node_type::hook_type) would
|
||||
//provoke an early instantiation of node_type that could ruin recursive
|
||||
<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.
|
||||
typedef typename intrusive_tree_hook
|
||||
<void_pointer, tree_type_value
|
||||
, OptimizeSize>::type hook_type;
|
||||
public:
|
||||
typedef typename intrusive_tree_dispatch
|
||||
< node_type, node_compare_type
|
||||
< node_t, node_compare_type
|
||||
, size_type, hook_type
|
||||
, tree_type_value>::type type;
|
||||
};
|
||||
@@ -351,7 +352,7 @@ template<class AllocHolder, bool DoMove>
|
||||
class RecyclingCloner
|
||||
{
|
||||
typedef typename AllocHolder::intrusive_container intrusive_container;
|
||||
typedef typename AllocHolder::Node node_type;
|
||||
typedef typename AllocHolder::Node node_t;
|
||||
typedef typename AllocHolder::NodePtr node_ptr_type;
|
||||
|
||||
public:
|
||||
@@ -359,13 +360,13 @@ class RecyclingCloner
|
||||
: m_holder(holder), m_icont(itree)
|
||||
{}
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE static void do_assign(node_ptr_type &p, const node_type &other, bool_<true>)
|
||||
{ p->do_move_assign(const_cast<node_type &>(other).m_data); }
|
||||
BOOST_CONTAINER_FORCEINLINE static void do_assign(node_ptr_type &p, const node_t &other, bool_<true>)
|
||||
{ p->do_move_assign(const_cast<node_t &>(other).m_data); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE static void do_assign(node_ptr_type &p, const node_type &other, bool_<false>)
|
||||
BOOST_CONTAINER_FORCEINLINE static void do_assign(node_ptr_type &p, const node_t &other, bool_<false>)
|
||||
{ p->do_assign(other.m_data); }
|
||||
|
||||
node_ptr_type operator()(const node_type &other) const
|
||||
node_ptr_type operator()(const node_t &other) const
|
||||
{
|
||||
if(node_ptr_type p = m_icont.unlink_leftmost_without_rebalance()){
|
||||
//First recycle a node (this can't throw)
|
||||
@@ -479,11 +480,19 @@ class tree
|
||||
allocator_traits<Allocator>::size_type size_type;
|
||||
typedef typename boost::container::
|
||||
allocator_traits<Allocator>::difference_type difference_type;
|
||||
typedef difference_type tree_difference_type;
|
||||
typedef pointer tree_pointer;
|
||||
typedef const_pointer tree_const_pointer;
|
||||
typedef reference tree_reference;
|
||||
typedef const_reference tree_const_reference;
|
||||
typedef container_detail::iterator_from_iiterator
|
||||
<iiterator, false> iterator;
|
||||
typedef container_detail::iterator_from_iiterator
|
||||
<iiterator, true > const_iterator;
|
||||
typedef boost::container::reverse_iterator
|
||||
<iterator> reverse_iterator;
|
||||
typedef boost::container::reverse_iterator
|
||||
<const_iterator> const_reverse_iterator;
|
||||
typedef node_handle
|
||||
< Node, value_type, allocator_type, void> node_type;
|
||||
typedef insert_return_type_base
|
||||
<iterator, node_type> insert_return_type;
|
||||
|
||||
typedef NodeAlloc stored_allocator_type;
|
||||
|
||||
private:
|
||||
@@ -491,10 +500,6 @@ class tree
|
||||
typedef key_node_compare<value_compare, Node> KeyNodeCompare;
|
||||
|
||||
public:
|
||||
typedef container_detail::iterator_from_iiterator<iiterator, false> iterator;
|
||||
typedef container_detail::iterator_from_iiterator<iiterator, true > const_iterator;
|
||||
typedef boost::container::reverse_iterator<iterator> reverse_iterator;
|
||||
typedef boost::container::reverse_iterator<const_iterator> const_reverse_iterator;
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE tree()
|
||||
: AllocHolder()
|
||||
@@ -823,15 +828,6 @@ class tree
|
||||
return std::pair<iterator, bool>(iterator(ret.first), ret.second);
|
||||
}
|
||||
|
||||
iterator insert_unique_commit(const value_type& v, insert_commit_data &data)
|
||||
{
|
||||
NodePtr tmp = AllocHolder::create_node(v);
|
||||
scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());
|
||||
iterator ret(this->icont().insert_unique_commit(*tmp, data));
|
||||
destroy_deallocator.release();
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<class MovableConvertible>
|
||||
iterator insert_unique_commit
|
||||
(BOOST_FWD_REF(MovableConvertible) v, insert_commit_data &data)
|
||||
@@ -843,17 +839,6 @@ class tree
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::pair<iterator,bool> insert_unique(const value_type& v)
|
||||
{
|
||||
insert_commit_data data;
|
||||
std::pair<iterator,bool> ret =
|
||||
this->insert_unique_check(KeyOfValue()(v), data);
|
||||
if(ret.second){
|
||||
ret.first = this->insert_unique_commit(v, data);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<class MovableConvertible>
|
||||
std::pair<iterator,bool> insert_unique(BOOST_FWD_REF(MovableConvertible) v)
|
||||
{
|
||||
@@ -868,17 +853,6 @@ class tree
|
||||
|
||||
private:
|
||||
|
||||
template<class KeyConvertible>
|
||||
iterator priv_insert_unique_key_commit
|
||||
(BOOST_FWD_REF(KeyConvertible) key, insert_commit_data &data)
|
||||
{
|
||||
NodePtr tmp = AllocHolder::create_node_from_key(boost::forward<KeyConvertible>(key));
|
||||
scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());
|
||||
iterator ret(this->icont().insert_unique_commit(*tmp, data));
|
||||
destroy_deallocator.release();
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<class KeyConvertible, class M>
|
||||
iiterator priv_insert_or_assign_commit
|
||||
(BOOST_FWD_REF(KeyConvertible) key, BOOST_FWD_REF(M) obj, insert_commit_data &data)
|
||||
@@ -1100,18 +1074,6 @@ class tree
|
||||
this->insert_equal(*first);
|
||||
}
|
||||
|
||||
template<class KeyConvertible>
|
||||
iterator insert_from_key(BOOST_FWD_REF(KeyConvertible) key)
|
||||
{
|
||||
insert_commit_data data;
|
||||
const key_type & k = key; //Support emulated rvalue references
|
||||
std::pair<iiterator, bool> ret =
|
||||
this->icont().insert_unique_check(k, KeyNodeCompare(value_comp()), data);
|
||||
return ret.second
|
||||
? this->priv_insert_unique_key_commit(boost::forward<KeyConvertible>(key), data)
|
||||
: iterator(ret.first);
|
||||
}
|
||||
|
||||
template<class KeyType, class M>
|
||||
std::pair<iterator, bool> insert_or_assign(const_iterator hint, BOOST_FWD_REF(KeyType) key, BOOST_FWD_REF(M) obj)
|
||||
{
|
||||
@@ -1145,6 +1107,73 @@ class tree
|
||||
return iterator(AllocHolder::erase_range(first.get(), last.get(), alloc_version()));
|
||||
}
|
||||
|
||||
node_type extract(const key_type& k)
|
||||
{
|
||||
iterator const it = this->find(k);
|
||||
if(this->end() != it){
|
||||
return this->extract(it);
|
||||
}
|
||||
return node_type();
|
||||
}
|
||||
|
||||
node_type extract(const_iterator position)
|
||||
{
|
||||
BOOST_ASSERT(position != this->cend() && (priv_is_linked)(position));
|
||||
iiterator const iit(position.get());
|
||||
this->icont().erase(iit);
|
||||
return node_type(iit.operator->(), this->node_alloc());
|
||||
}
|
||||
|
||||
insert_return_type insert_unique_node(BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)
|
||||
{
|
||||
return this->insert_unique_node(this->end(), boost::move(nh));
|
||||
}
|
||||
|
||||
insert_return_type insert_unique_node(const_iterator hint, BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)
|
||||
{
|
||||
insert_return_type irt; //inserted == false, node.empty()
|
||||
if(!nh.empty()){
|
||||
insert_commit_data data;
|
||||
std::pair<iterator,bool> ret =
|
||||
this->insert_unique_check(hint, KeyOfValue()(nh.value()), data);
|
||||
if(ret.second){
|
||||
irt.inserted = true;
|
||||
irt.position = iterator(this->icont().insert_unique_commit(*nh.get_node_pointer(), data));
|
||||
nh.release();
|
||||
}
|
||||
else{
|
||||
irt.position = ret.first;
|
||||
irt.node = boost::move(nh);
|
||||
}
|
||||
}
|
||||
else{
|
||||
irt.position = this->end();
|
||||
}
|
||||
return BOOST_MOVE_RET(insert_return_type, irt);
|
||||
}
|
||||
|
||||
iterator insert_equal_node(BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)
|
||||
{
|
||||
if(nh.empty()){
|
||||
return this->end();
|
||||
}
|
||||
else{
|
||||
NodePtr const p(nh.release());
|
||||
return iterator(this->icont().insert_equal(*p));
|
||||
}
|
||||
}
|
||||
|
||||
iterator insert_equal_node(const_iterator hint, BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)
|
||||
{
|
||||
if(nh.empty()){
|
||||
return this->end();
|
||||
}
|
||||
else{
|
||||
NodePtr const p(nh.release());
|
||||
return iterator(this->icont().insert_equal(hint.get(), *p));
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE void clear()
|
||||
{ AllocHolder::clear(alloc_version()); }
|
||||
|
||||
|
@@ -112,14 +112,14 @@ class flat_map
|
||||
//This is the tree that we should store if pair was movable
|
||||
typedef container_detail::flat_tree<Key,
|
||||
std::pair<Key, T>,
|
||||
container_detail::select1st< 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,
|
||||
container_detail::pair<Key, T>,
|
||||
container_detail::select1st<container_detail::pair<Key, T> >,
|
||||
container_detail::select1st<Key>,
|
||||
Compare,
|
||||
typename allocator_traits<Allocator>::template portable_rebind_alloc
|
||||
<container_detail::pair<Key, T> >::type> impl_tree_t;
|
||||
@@ -131,7 +131,7 @@ class flat_map
|
||||
typedef typename impl_tree_t::allocator_type impl_allocator_type;
|
||||
typedef container_detail::flat_tree_value_compare
|
||||
< Compare
|
||||
, container_detail::select1st< std::pair<Key, T> >
|
||||
, container_detail::select1st<Key>
|
||||
, std::pair<Key, T> > value_compare_impl;
|
||||
typedef typename container_detail::get_flat_tree_iterators
|
||||
<typename allocator_traits<Allocator>::pointer>::iterator iterator_impl;
|
||||
@@ -782,17 +782,17 @@ class flat_map
|
||||
, boost::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
//! <b>Requires<b>: value_type shall be EmplaceConstructible into map from piecewise_construct,
|
||||
//! <b>Requires</b>: value_type shall be EmplaceConstructible into map from piecewise_construct,
|
||||
//! forward_as_tuple(k), forward_as_tuple(forward<Args>(args)...).
|
||||
//!
|
||||
//! <b>Effects<b>: If the map already contains an element whose key is equivalent to k, there is no effect. Otherwise
|
||||
//! <b>Effects</b>: If the map already contains an element whose key is equivalent to k, there is no effect. Otherwise
|
||||
//! inserts an object of type value_type constructed with piecewise_construct, forward_as_tuple(k),
|
||||
//! forward_as_tuple(forward<Args>(args)...).
|
||||
//!
|
||||
//! <b>Returns<b>: The bool component of the returned pair is true if and only if the
|
||||
//! <b>Returns</b>: The bool component of the returned pair is true if and only if the
|
||||
//! insertion took place. The returned iterator points to the map element whose key is equivalent to k.
|
||||
//!
|
||||
//! <b>Complexity:<b> Logarithmic.
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
template <class... Args>
|
||||
BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> try_emplace(const key_type& k, BOOST_FWD_REF(Args)... args)
|
||||
{
|
||||
@@ -800,14 +800,14 @@ class flat_map
|
||||
m_flat_tree.try_emplace(impl_const_iterator(), k, boost::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
//! <b>Requires<b>: value_type shall be EmplaceConstructible into map from piecewise_construct,
|
||||
//! <b>Requires</b>: value_type shall be EmplaceConstructible into map from piecewise_construct,
|
||||
//! forward_as_tuple(k), forward_as_tuple(forward<Args>(args)...).
|
||||
//!
|
||||
//! <b>Effects<b>: If the map already contains an element whose key is equivalent to k, there is no effect. Otherwise
|
||||
//! <b>Effects</b>: If the map already contains an element whose key is equivalent to k, there is no effect. Otherwise
|
||||
//! inserts an object of type value_type constructed with piecewise_construct, forward_as_tuple(k),
|
||||
//! forward_as_tuple(forward<Args>(args)...).
|
||||
//!
|
||||
//! <b>Returns<b>: The returned iterator points to the map element whose key is equivalent to k.
|
||||
//! <b>Returns</b>: The returned iterator points to the map element whose key is equivalent to k.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if value
|
||||
//! is inserted right before p.
|
||||
@@ -818,17 +818,17 @@ class flat_map
|
||||
(container_detail::force_copy<impl_const_iterator>(hint), k, boost::forward<Args>(args)...).first);
|
||||
}
|
||||
|
||||
//! <b>Requires<b>: value_type shall be EmplaceConstructible into map from piecewise_construct,
|
||||
//! <b>Requires</b>: value_type shall be EmplaceConstructible into map from piecewise_construct,
|
||||
//! forward_as_tuple(move(k)), forward_as_tuple(forward<Args>(args)...).
|
||||
//!
|
||||
//! <b>Effects<b>: If the map already contains an element whose key is equivalent to k, there is no effect. Otherwise
|
||||
//! <b>Effects</b>: If the map already contains an element whose key is equivalent to k, there is no effect. Otherwise
|
||||
//! inserts an object of type value_type constructed with piecewise_construct, forward_as_tuple(move(k)),
|
||||
//! forward_as_tuple(forward<Args>(args)...).
|
||||
//!
|
||||
//! <b>Returns<b>: The bool component of the returned pair is true if and only if the
|
||||
//! <b>Returns</b>: The bool component of the returned pair is true if and only if the
|
||||
//! insertion took place. The returned iterator points to the map element whose key is equivalent to k.
|
||||
//!
|
||||
//! <b>Complexity:<b> Logarithmic.
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
template <class... Args>
|
||||
BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> try_emplace(BOOST_RV_REF(key_type) k, BOOST_FWD_REF(Args)... args)
|
||||
{
|
||||
@@ -836,14 +836,14 @@ class flat_map
|
||||
(m_flat_tree.try_emplace(impl_const_iterator(), boost::move(k), boost::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
//! <b>Requires<b>: value_type shall be EmplaceConstructible into map from piecewise_construct,
|
||||
//! <b>Requires</b>: value_type shall be EmplaceConstructible into map from piecewise_construct,
|
||||
//! forward_as_tuple(move(k)), forward_as_tuple(forward<Args>(args)...).
|
||||
//!
|
||||
//! <b>Effects<b>: If the map already contains an element whose key is equivalent to k, there is no effect. Otherwise
|
||||
//! <b>Effects</b>: If the map already contains an element whose key is equivalent to k, there is no effect. Otherwise
|
||||
//! inserts an object of type value_type constructed with piecewise_construct, forward_as_tuple(move(k)),
|
||||
//! forward_as_tuple(forward<Args>(args)...).
|
||||
//!
|
||||
//! <b>Returns<b>: The returned iterator points to the map element whose key is equivalent to k.
|
||||
//! <b>Returns</b>: The returned iterator points to the map element whose key is equivalent to k.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if value
|
||||
//! is inserted right before p.
|
||||
@@ -1328,13 +1328,13 @@ class flat_multimap
|
||||
BOOST_COPYABLE_AND_MOVABLE(flat_multimap)
|
||||
typedef container_detail::flat_tree<Key,
|
||||
std::pair<Key, T>,
|
||||
container_detail::select1st< 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,
|
||||
container_detail::pair<Key, T>,
|
||||
container_detail::select1st<container_detail::pair<Key, T> >,
|
||||
container_detail::select1st<Key>,
|
||||
Compare,
|
||||
typename allocator_traits<Allocator>::template portable_rebind_alloc
|
||||
<container_detail::pair<Key, T> >::type> impl_tree_t;
|
||||
@@ -1346,7 +1346,7 @@ class flat_multimap
|
||||
typedef typename impl_tree_t::allocator_type impl_allocator_type;
|
||||
typedef container_detail::flat_tree_value_compare
|
||||
< Compare
|
||||
, container_detail::select1st< std::pair<Key, T> >
|
||||
, container_detail::select1st<Key>
|
||||
, std::pair<Key, T> > value_compare_impl;
|
||||
typedef typename container_detail::get_flat_tree_iterators
|
||||
<typename allocator_traits<Allocator>::pointer>::iterator iterator_impl;
|
||||
|
@@ -53,6 +53,34 @@
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
///@cond
|
||||
|
||||
template<class Key, class Mapped>
|
||||
struct pair_key_mapped_of_value
|
||||
{
|
||||
typedef Key key_type;
|
||||
typedef Mapped mapped_type;
|
||||
|
||||
template<class Pair>
|
||||
const key_type & key_of_value(const Pair &p) const
|
||||
{ return p.first; }
|
||||
|
||||
template<class Pair>
|
||||
const mapped_type & mapped_of_value(const Pair &p) const
|
||||
{ return p.second; }
|
||||
|
||||
template<class Pair>
|
||||
key_type & key_of_value(Pair &p) const
|
||||
{ return const_cast<key_type&>(p.first); }
|
||||
|
||||
template<class Pair>
|
||||
mapped_type & mapped_of_value(Pair &p) const
|
||||
{ return p.second; }
|
||||
|
||||
};
|
||||
|
||||
///@endcond
|
||||
|
||||
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
//! A map is a kind of associative container that supports unique keys (contains at
|
||||
@@ -78,7 +106,7 @@ class map
|
||||
///@cond
|
||||
: public container_detail::tree
|
||||
< Key, std::pair<const Key, T>
|
||||
, container_detail::select1st< std::pair<const Key, T> >
|
||||
, container_detail::select1st<Key>
|
||||
, Compare, Allocator, MapOptions>
|
||||
///@endcond
|
||||
{
|
||||
@@ -86,13 +114,13 @@ class map
|
||||
private:
|
||||
BOOST_COPYABLE_AND_MOVABLE(map)
|
||||
|
||||
typedef std::pair<const Key, T> value_type_impl;
|
||||
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, container_detail::select1st<value_type_impl>, Compare, Allocator, MapOptions> base_t;
|
||||
typedef container_detail::pair <Key, T> movable_value_type_impl;
|
||||
<Key, value_type_impl, select_1st_t, Compare, Allocator, MapOptions> base_t;
|
||||
typedef container_detail::pair <Key, T> movable_value_type_impl;
|
||||
typedef container_detail::tree_value_compare
|
||||
< Key, value_type_impl, Compare, container_detail::select1st<value_type_impl>
|
||||
> value_compare_impl;
|
||||
< Key, value_type_impl, Compare, select_1st_t> value_compare_impl;
|
||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
public:
|
||||
@@ -102,10 +130,10 @@ class map
|
||||
//
|
||||
//////////////////////////////////////////////
|
||||
|
||||
typedef Key key_type;
|
||||
typedef ::boost::container::allocator_traits<Allocator> allocator_traits_type;
|
||||
typedef T mapped_type;
|
||||
typedef std::pair<const Key, T> value_type;
|
||||
typedef Key key_type;
|
||||
typedef ::boost::container::allocator_traits<Allocator> allocator_traits_type;
|
||||
typedef T mapped_type;
|
||||
typedef std::pair<const Key, T> value_type;
|
||||
typedef typename boost::container::allocator_traits<Allocator>::pointer pointer;
|
||||
typedef typename boost::container::allocator_traits<Allocator>::const_pointer const_pointer;
|
||||
typedef typename boost::container::allocator_traits<Allocator>::reference reference;
|
||||
@@ -122,6 +150,14 @@ class map
|
||||
typedef typename BOOST_CONTAINER_IMPDEF(base_t::const_reverse_iterator) const_reverse_iterator;
|
||||
typedef std::pair<key_type, mapped_type> nonconst_value_type;
|
||||
typedef BOOST_CONTAINER_IMPDEF(movable_value_type_impl) movable_value_type;
|
||||
typedef BOOST_CONTAINER_IMPDEF(node_handle<
|
||||
typename base_t::node_type::container_node_type
|
||||
BOOST_MOVE_I value_type
|
||||
BOOST_MOVE_I allocator_type
|
||||
BOOST_MOVE_I pair_key_mapped_of_value
|
||||
<key_type BOOST_MOVE_I mapped_type> >) node_type;
|
||||
typedef BOOST_CONTAINER_IMPDEF
|
||||
(insert_return_type_base<iterator BOOST_MOVE_I node_type>) insert_return_type;
|
||||
|
||||
//////////////////////////////////////////////
|
||||
//
|
||||
@@ -484,20 +520,20 @@ class map
|
||||
#endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
//! <b>Effects<b>: If there is no key equivalent to x in the map, inserts
|
||||
//! <b>Effects</b>: If there is no key equivalent to x in the map, inserts
|
||||
//! value_type(x, T()) into the map.
|
||||
//!
|
||||
//! <b>Returns<b>: A reference to the mapped_type corresponding to x in *this.
|
||||
//! <b>Returns</b>: A reference to the mapped_type corresponding to x in *this.
|
||||
//!
|
||||
//! <b>Complexity<b>: Logarithmic.
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
mapped_type& operator[](const key_type &k);
|
||||
|
||||
//! <b>Effects<b>: If there is no key equivalent to x in the map, inserts
|
||||
//! <b>Effects</b>: If there is no key equivalent to x in the map, inserts
|
||||
//! value_type(boost::move(x), T()) into the map (the key is move-constructed)
|
||||
//!
|
||||
//! <b>Returns<b>: A reference to the mapped_type corresponding to x in *this.
|
||||
//! <b>Returns</b>: A reference to the mapped_type corresponding to x in *this.
|
||||
//!
|
||||
//! <b>Complexity<b>: Logarithmic.
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
mapped_type& operator[](key_type &&k);
|
||||
#elif defined(BOOST_MOVE_HELPERS_RETURN_SFINAE_BROKEN)
|
||||
//in compilers like GCC 3.4, we can't catch temporaries
|
||||
@@ -507,7 +543,7 @@ class map
|
||||
BOOST_MOVE_CONVERSION_AWARE_CATCH( operator[] , key_type, mapped_type&, this->priv_subscript)
|
||||
#endif
|
||||
|
||||
//! <b>Effects<b>: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
|
||||
//! <b>Effects</b>: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
|
||||
//! to the mapped_type corresponding to the key k. If the key does not exist, inserts the new value
|
||||
//! as if by insert, constructing it from value_type(k, forward<M>(obj)).
|
||||
//!
|
||||
@@ -515,15 +551,15 @@ class map
|
||||
//! to the element obtained while it is held in the node handle are invalidated, and pointers and
|
||||
//! references obtained to that element before it was extracted become valid.
|
||||
//!
|
||||
//! <b>Returns<b>: The bool component is true if the insertion took place and false if the assignment
|
||||
//! <b>Returns</b>: The bool component is true if the insertion took place and false if the assignment
|
||||
//! took place. The iterator component is pointing at the element that was inserted or updated.
|
||||
//!
|
||||
//! <b>Complexity<b>: Logarithmic in the size of the container.
|
||||
//! <b>Complexity</b>: Logarithmic in the size of the container.
|
||||
template <class M>
|
||||
BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> insert_or_assign(const key_type& k, BOOST_FWD_REF(M) obj)
|
||||
{ return this->base_t::insert_or_assign(const_iterator(), k, ::boost::forward<M>(obj)); }
|
||||
|
||||
//! <b>Effects<b>: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
|
||||
//! <b>Effects</b>: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
|
||||
//! to the mapped_type corresponding to the key k. If the key does not exist, inserts the new value
|
||||
//! as if by insert, constructing it from value_type(k, move(obj)).
|
||||
//!
|
||||
@@ -531,15 +567,15 @@ class map
|
||||
//! to the element obtained while it is held in the node handle are invalidated, and pointers and
|
||||
//! references obtained to that element before it was extracted become valid.
|
||||
//!
|
||||
//! <b>Returns<b>: The bool component is true if the insertion took place and false if the assignment
|
||||
//! <b>Returns</b>: The bool component is true if the insertion took place and false if the assignment
|
||||
//! took place. The iterator component is pointing at the element that was inserted or updated.
|
||||
//!
|
||||
//! <b>Complexity<b>: Logarithmic in the size of the container.
|
||||
//! <b>Complexity</b>: Logarithmic in the size of the container.
|
||||
template <class M>
|
||||
BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> insert_or_assign(BOOST_RV_REF(key_type) k, BOOST_FWD_REF(M) obj)
|
||||
{ return this->base_t::insert_or_assign(const_iterator(), ::boost::move(k), ::boost::forward<M>(obj)); }
|
||||
|
||||
//! <b>Effects<b>: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
|
||||
//! <b>Effects</b>: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
|
||||
//! to the mapped_type corresponding to the key k. If the key does not exist, inserts the new value
|
||||
//! as if by insert, constructing it from value_type(k, forward<M>(obj)) and the new element
|
||||
//! to the container as close as possible to the position just before hint.
|
||||
@@ -548,16 +584,16 @@ class map
|
||||
//! to the element obtained while it is held in the node handle are invalidated, and pointers and
|
||||
//! references obtained to that element before it was extracted become valid.
|
||||
//!
|
||||
//! <b>Returns<b>: The bool component is true if the insertion took place and false if the assignment
|
||||
//! <b>Returns</b>: The bool component is true if the insertion took place and false if the assignment
|
||||
//! took place. The iterator component is pointing at the element that was inserted or updated.
|
||||
//!
|
||||
//! <b>Complexity<b>: Logarithmic in the size of the container in general, but amortized constant if
|
||||
//! <b>Complexity</b>: Logarithmic in the size of the container in general, but amortized constant if
|
||||
//! the new element is inserted just before hint.
|
||||
template <class M>
|
||||
BOOST_CONTAINER_FORCEINLINE iterator insert_or_assign(const_iterator hint, const key_type& k, BOOST_FWD_REF(M) obj)
|
||||
{ return this->base_t::insert_or_assign(hint, k, ::boost::forward<M>(obj)); }
|
||||
|
||||
//! <b>Effects<b>: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
|
||||
//! <b>Effects</b>: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
|
||||
//! to the mapped_type corresponding to the key k. If the key does not exist, inserts the new value
|
||||
//! as if by insert, constructing it from value_type(k, move(obj)) and the new element
|
||||
//! to the container as close as possible to the position just before hint.
|
||||
@@ -566,18 +602,18 @@ class map
|
||||
//! to the element obtained while it is held in the node handle are invalidated, and pointers and
|
||||
//! references obtained to that element before it was extracted become valid.
|
||||
//!
|
||||
//! <b>Returns<b>: The bool component is true if the insertion took place and false if the assignment
|
||||
//! <b>Returns</b>: The bool component is true if the insertion took place and false if the assignment
|
||||
//! took place. The iterator component is pointing at the element that was inserted or updated.
|
||||
//!
|
||||
//! <b>Complexity<b>: Logarithmic in the size of the container in general, but amortized constant if
|
||||
//! <b>Complexity</b>: Logarithmic in the size of the container in general, but amortized constant if
|
||||
//! the new element is inserted just before hint.
|
||||
template <class M>
|
||||
BOOST_CONTAINER_FORCEINLINE iterator insert_or_assign(const_iterator hint, BOOST_RV_REF(key_type) k, BOOST_FWD_REF(M) obj)
|
||||
{ return this->base_t::insert_or_assign(hint, ::boost::move(k), ::boost::forward<M>(obj)); }
|
||||
|
||||
//! <b>Returns<b>: A reference to the element whose key is equivalent to x.
|
||||
//! <b>Returns</b>: A reference to the element whose key is equivalent to x.
|
||||
//! Throws: An exception object of type out_of_range if no such element is present.
|
||||
//! <b>Complexity<b>: logarithmic.
|
||||
//! <b>Complexity</b>: logarithmic.
|
||||
T& at(const key_type& k)
|
||||
{
|
||||
iterator i = this->find(k);
|
||||
@@ -587,9 +623,9 @@ class map
|
||||
return i->second;
|
||||
}
|
||||
|
||||
//! <b>Returns<b>: A reference to the element whose key is equivalent to x.
|
||||
//! <b>Returns</b>: A reference to the element whose key is equivalent to x.
|
||||
//! Throws: An exception object of type out_of_range if no such element is present.
|
||||
//! <b>Complexity<b>: logarithmic.
|
||||
//! <b>Complexity</b>: logarithmic.
|
||||
const T& at(const key_type& k) const
|
||||
{
|
||||
const_iterator i = this->find(k);
|
||||
@@ -625,7 +661,7 @@ class map
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> insert(const nonconst_value_type& x)
|
||||
{ return this->base_t::insert_unique(x); }
|
||||
{ return this->try_emplace(x.first, x.second); }
|
||||
|
||||
//! <b>Effects</b>: Inserts a new value_type move constructed from the pair if and
|
||||
//! only if there is no element in the container with key equivalent to the key of x.
|
||||
@@ -636,7 +672,7 @@ class map
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> insert(BOOST_RV_REF(nonconst_value_type) x)
|
||||
{ return this->base_t::insert_unique(boost::move(x)); }
|
||||
{ return this->try_emplace(boost::move(x.first), boost::move(x.second)); }
|
||||
|
||||
//! <b>Effects</b>: Inserts a new value_type move constructed from the pair if and
|
||||
//! only if there is no element in the container with key equivalent to the key of x.
|
||||
@@ -647,7 +683,7 @@ class map
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> insert(BOOST_RV_REF(movable_value_type) x)
|
||||
{ return this->base_t::insert_unique(boost::move(x)); }
|
||||
{ return this->try_emplace(boost::move(x.first), boost::move(x.second)); }
|
||||
|
||||
//! <b>Effects</b>: Move constructs a new value from x if and only if there is
|
||||
//! no element in the container with key equivalent to the key of x.
|
||||
@@ -682,7 +718,7 @@ class map
|
||||
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
|
||||
//! is inserted right before p.
|
||||
iterator insert(const_iterator p, BOOST_RV_REF(nonconst_value_type) x)
|
||||
{ return this->base_t::insert_unique_convertible(p, boost::move(x)); }
|
||||
{ return this->try_emplace(p, boost::move(x.first), boost::move(x.second)); }
|
||||
|
||||
//! <b>Effects</b>: Move constructs a new value from x if and only if there is
|
||||
//! no element in the container with key equivalent to the key of x.
|
||||
@@ -694,7 +730,7 @@ class map
|
||||
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
|
||||
//! is inserted right before p.
|
||||
iterator insert(const_iterator p, BOOST_RV_REF(movable_value_type) x)
|
||||
{ return this->base_t::insert_unique_convertible(p, boost::move(x)); }
|
||||
{ return this->try_emplace(p, boost::move(x.first), boost::move(x.second)); }
|
||||
|
||||
//! <b>Effects</b>: Inserts a copy of x in the container.
|
||||
//! p is a hint pointing to where the insert should start to search.
|
||||
@@ -703,7 +739,7 @@ class map
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
iterator insert(const_iterator p, const nonconst_value_type& x)
|
||||
{ return this->base_t::insert_unique_convertible(p, x); }
|
||||
{ return this->try_emplace(p, x.first, x.second); }
|
||||
|
||||
//! <b>Effects</b>: Inserts an element move constructed from x in the container.
|
||||
//! p is a hint pointing to where the insert should start to search.
|
||||
@@ -733,6 +769,38 @@ class map
|
||||
{ this->base_t::insert_unique(il.begin(), il.end()); }
|
||||
#endif
|
||||
|
||||
//! <b>Requires</b>: nh is empty or this->get_allocator() == nh.get_allocator().
|
||||
//!
|
||||
//! <b>Effects</b>: If nh is empty, has no effect. Otherwise, inserts the element owned
|
||||
//! by nh if and only if there is no element in the container with a key equivalent to nh.key().
|
||||
//!
|
||||
//! <b>Returns</b>: If nh is empty, insert_return_type.inserted is false, insert_return_type.position
|
||||
//! is end(), and insert_return_type.node is empty. Otherwise if the insertion took place,
|
||||
//! insert_return_type.inserted is true, insert_return_type.position points to the inserted element,
|
||||
//! and insert_return_type.node is empty; if the insertion failed, insert_return_type.inserted is
|
||||
//! false, insert_return_type.node has the previous value of nh, and insert_return_type.position
|
||||
//! points to an element with a key equivalent to nh.key().
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
insert_return_type insert(BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)
|
||||
{
|
||||
typename base_t::node_type n(boost::move(nh));
|
||||
typename base_t::insert_return_type base_ret(this->base_t::insert_unique_node(boost::move(n)));
|
||||
return insert_return_type (base_ret.inserted, base_ret.position, boost::move(base_ret.node));
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Same as `insert(node_type && nh)` but the element is inserted as close as possible
|
||||
//! to the position just prior to "hint".
|
||||
//!
|
||||
//! <b>Complexity</b>: logarithmic in general, but amortized constant if the element is inserted
|
||||
//! right before "hint".
|
||||
insert_return_type insert(const_iterator hint, BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)
|
||||
{
|
||||
typename base_t::node_type n(boost::move(nh));
|
||||
typename base_t::insert_return_type base_ret(this->base_t::insert_unique_node(hint, boost::move(n)));
|
||||
return insert_return_type (base_ret.inserted, base_ret.position, boost::move(base_ret.node));
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
//! <b>Effects</b>: Inserts an object x of type T constructed with
|
||||
@@ -764,29 +832,29 @@ class map
|
||||
BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator p, BOOST_FWD_REF(Args)... args)
|
||||
{ return this->base_t::emplace_hint_unique(p, boost::forward<Args>(args)...); }
|
||||
|
||||
//! <b>Requires<b>: value_type shall be EmplaceConstructible into map from piecewise_construct,
|
||||
//! <b>Requires</b>: value_type shall be EmplaceConstructible into map from piecewise_construct,
|
||||
//! forward_as_tuple(k), forward_as_tuple(forward<Args>(args)...).
|
||||
//!
|
||||
//! <b>Effects<b>: If the map already contains an element whose key is equivalent to k, there is no effect. Otherwise
|
||||
//! <b>Effects</b>: If the map already contains an element whose key is equivalent to k, there is no effect. Otherwise
|
||||
//! inserts an object of type value_type constructed with piecewise_construct, forward_as_tuple(k),
|
||||
//! forward_as_tuple(forward<Args>(args)...).
|
||||
//!
|
||||
//! <b>Returns<b>: The bool component of the returned pair is true if and only if the
|
||||
//! <b>Returns</b>: The bool component of the returned pair is true if and only if the
|
||||
//! insertion took place. The returned iterator points to the map element whose key is equivalent to k.
|
||||
//!
|
||||
//! <b>Complexity:<b> Logarithmic.
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
template <class... Args>
|
||||
BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> try_emplace(const key_type& k, BOOST_FWD_REF(Args)... args)
|
||||
{ return this->base_t::try_emplace(const_iterator(), k, boost::forward<Args>(args)...); }
|
||||
|
||||
//! <b>Requires<b>: value_type shall be EmplaceConstructible into map from piecewise_construct,
|
||||
//! <b>Requires</b>: value_type shall be EmplaceConstructible into map from piecewise_construct,
|
||||
//! forward_as_tuple(k), forward_as_tuple(forward<Args>(args)...).
|
||||
//!
|
||||
//! <b>Effects<b>: If the map already contains an element whose key is equivalent to k, there is no effect. Otherwise
|
||||
//! <b>Effects</b>: If the map already contains an element whose key is equivalent to k, there is no effect. Otherwise
|
||||
//! inserts an object of type value_type constructed with piecewise_construct, forward_as_tuple(k),
|
||||
//! forward_as_tuple(forward<Args>(args)...).
|
||||
//!
|
||||
//! <b>Returns<b>: The returned iterator points to the map element whose key is equivalent to k.
|
||||
//! <b>Returns</b>: The returned iterator points to the map element whose key is equivalent to k.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if value
|
||||
//! is inserted right before p.
|
||||
@@ -794,29 +862,29 @@ class map
|
||||
BOOST_CONTAINER_FORCEINLINE iterator try_emplace(const_iterator hint, const key_type &k, BOOST_FWD_REF(Args)... args)
|
||||
{ return this->base_t::try_emplace(hint, k, boost::forward<Args>(args)...).first; }
|
||||
|
||||
//! <b>Requires<b>: value_type shall be EmplaceConstructible into map from piecewise_construct,
|
||||
//! <b>Requires</b>: value_type shall be EmplaceConstructible into map from piecewise_construct,
|
||||
//! forward_as_tuple(move(k)), forward_as_tuple(forward<Args>(args)...).
|
||||
//!
|
||||
//! <b>Effects<b>: If the map already contains an element whose key is equivalent to k, there is no effect. Otherwise
|
||||
//! <b>Effects</b>: If the map already contains an element whose key is equivalent to k, there is no effect. Otherwise
|
||||
//! inserts an object of type value_type constructed with piecewise_construct, forward_as_tuple(move(k)),
|
||||
//! forward_as_tuple(forward<Args>(args)...).
|
||||
//!
|
||||
//! <b>Returns<b>: The bool component of the returned pair is true if and only if the
|
||||
//! <b>Returns</b>: The bool component of the returned pair is true if and only if the
|
||||
//! insertion took place. The returned iterator points to the map element whose key is equivalent to k.
|
||||
//!
|
||||
//! <b>Complexity:<b> Logarithmic.
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
template <class... Args>
|
||||
BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> try_emplace(BOOST_RV_REF(key_type) k, BOOST_FWD_REF(Args)... args)
|
||||
{ return this->base_t::try_emplace(const_iterator(), boost::move(k), boost::forward<Args>(args)...); }
|
||||
|
||||
//! <b>Requires<b>: value_type shall be EmplaceConstructible into map from piecewise_construct,
|
||||
//! <b>Requires</b>: value_type shall be EmplaceConstructible into map from piecewise_construct,
|
||||
//! forward_as_tuple(move(k)), forward_as_tuple(forward<Args>(args)...).
|
||||
//!
|
||||
//! <b>Effects<b>: If the map already contains an element whose key is equivalent to k, there is no effect. Otherwise
|
||||
//! <b>Effects</b>: If the map already contains an element whose key is equivalent to k, there is no effect. Otherwise
|
||||
//! inserts an object of type value_type constructed with piecewise_construct, forward_as_tuple(move(k)),
|
||||
//! forward_as_tuple(forward<Args>(args)...).
|
||||
//!
|
||||
//! <b>Returns<b>: The returned iterator points to the map element whose key is equivalent to k.
|
||||
//! <b>Returns</b>: The returned iterator points to the map element whose key is equivalent to k.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if value
|
||||
//! is inserted right before p.
|
||||
@@ -881,6 +949,33 @@ class map
|
||||
//! <b>Complexity</b>: log(size())+N where N is the distance from first to last.
|
||||
iterator erase(const_iterator first, const_iterator last) BOOST_NOEXCEPT_OR_NOTHROW;
|
||||
|
||||
#endif
|
||||
|
||||
//! <b>Effects</b>: Removes the first element in the container with key equivalent to k.
|
||||
//!
|
||||
//! <b>Returns</b>: A node_type owning the element if found, otherwise an empty node_type.
|
||||
//!
|
||||
//! <b>Complexity</b>: log(a.size()).
|
||||
node_type extract(const key_type& k)
|
||||
{
|
||||
typename base_t::node_type base_nh(this->base_t::extract(k));
|
||||
node_type nh(boost::move(base_nh));
|
||||
return BOOST_MOVE_RET(node_type, nh);
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Removes the element pointed to by "position".
|
||||
//!
|
||||
//! <b>Returns</b>: A node_type owning the element, otherwise an empty node_type.
|
||||
//!
|
||||
//! <b>Complexity</b>: Amortized constant.
|
||||
node_type extract(const_iterator position)
|
||||
{
|
||||
typename base_t::node_type base_nh(this->base_t::extract(position));
|
||||
node_type nh(boost::move(base_nh));
|
||||
return BOOST_MOVE_RET(node_type, nh);
|
||||
}
|
||||
|
||||
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
//! <b>Effects</b>: Swaps the contents of *this and x.
|
||||
//!
|
||||
//! <b>Throws</b>: Nothing.
|
||||
@@ -1012,7 +1107,7 @@ class map
|
||||
template<class KeyConvertible>
|
||||
BOOST_CONTAINER_FORCEINLINE mapped_type& priv_subscript(BOOST_FWD_REF(KeyConvertible) k)
|
||||
{
|
||||
return this->insert_from_key(boost::forward<KeyConvertible>(k))->second;
|
||||
return this->try_emplace(boost::forward<KeyConvertible>(k)).first->second;
|
||||
}
|
||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
};
|
||||
@@ -1063,7 +1158,7 @@ class multimap
|
||||
///@cond
|
||||
: public container_detail::tree
|
||||
< Key, std::pair<const Key, T>
|
||||
, container_detail::select1st< std::pair<const Key, T> >
|
||||
, container_detail::select1st<Key>
|
||||
, Compare, Allocator, MultiMapOptions>
|
||||
///@endcond
|
||||
{
|
||||
@@ -1071,16 +1166,16 @@ class multimap
|
||||
private:
|
||||
BOOST_COPYABLE_AND_MOVABLE(multimap)
|
||||
|
||||
typedef std::pair<const Key, T> value_type_impl;
|
||||
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, container_detail::select1st<value_type_impl>, Compare, Allocator, MultiMapOptions> base_t;
|
||||
typedef container_detail::pair <Key, T> movable_value_type_impl;
|
||||
<Key, value_type_impl, select_1st_t, Compare, Allocator, MultiMapOptions> base_t;
|
||||
typedef container_detail::pair <Key, T> movable_value_type_impl;
|
||||
typedef container_detail::tree_value_compare
|
||||
< Key, value_type_impl, Compare, container_detail::select1st<value_type_impl>
|
||||
> value_compare_impl;
|
||||
<Key, value_type_impl, Compare, select_1st_t> value_compare_impl;
|
||||
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
|
||||
|
||||
typedef ::boost::container::allocator_traits<Allocator> allocator_traits_type;
|
||||
typedef ::boost::container::allocator_traits<Allocator> allocator_traits_type;
|
||||
|
||||
public:
|
||||
//////////////////////////////////////////////
|
||||
@@ -1108,6 +1203,12 @@ class multimap
|
||||
typedef typename BOOST_CONTAINER_IMPDEF(base_t::const_reverse_iterator) const_reverse_iterator;
|
||||
typedef std::pair<key_type, mapped_type> nonconst_value_type;
|
||||
typedef BOOST_CONTAINER_IMPDEF(movable_value_type_impl) movable_value_type;
|
||||
typedef BOOST_CONTAINER_IMPDEF(node_handle<
|
||||
typename base_t::node_type::container_node_type
|
||||
BOOST_MOVE_I value_type
|
||||
BOOST_MOVE_I allocator_type
|
||||
BOOST_MOVE_I pair_key_mapped_of_value
|
||||
<key_type BOOST_MOVE_I mapped_type> >) node_type;
|
||||
|
||||
//////////////////////////////////////////////
|
||||
//
|
||||
@@ -1426,21 +1527,21 @@ class multimap
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
BOOST_CONTAINER_FORCEINLINE iterator insert(const nonconst_value_type& x)
|
||||
{ return this->base_t::insert_equal(x); }
|
||||
{ return this->base_t::emplace_equal(x); }
|
||||
|
||||
//! <b>Effects</b>: Inserts a new value move-constructed from x and returns
|
||||
//! the iterator pointing to the newly inserted element.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
BOOST_CONTAINER_FORCEINLINE iterator insert(BOOST_RV_REF(nonconst_value_type) x)
|
||||
{ return this->base_t::insert_equal(boost::move(x)); }
|
||||
{ return this->base_t::emplace_equal(boost::move(x)); }
|
||||
|
||||
//! <b>Effects</b>: Inserts a new value move-constructed from x and returns
|
||||
//! the iterator pointing to the newly inserted element.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic.
|
||||
iterator insert(BOOST_RV_REF(movable_value_type) x)
|
||||
{ return this->base_t::insert_equal(boost::move(x)); }
|
||||
{ return this->base_t::emplace_equal(boost::move(x)); }
|
||||
|
||||
//! <b>Effects</b>: Inserts a copy of x in the container.
|
||||
//! p is a hint pointing to where the insert should start to search.
|
||||
@@ -1462,7 +1563,7 @@ class multimap
|
||||
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
|
||||
//! is inserted right before p.
|
||||
BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, const nonconst_value_type& x)
|
||||
{ return this->base_t::insert_equal_convertible(p, x); }
|
||||
{ return this->base_t::emplace_hint_equal(p, x); }
|
||||
|
||||
//! <b>Effects</b>: Inserts a new value move constructed from x in the container.
|
||||
//! p is a hint pointing to where the insert should start to search.
|
||||
@@ -1473,7 +1574,7 @@ class multimap
|
||||
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
|
||||
//! is inserted right before p.
|
||||
BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(nonconst_value_type) x)
|
||||
{ return this->base_t::insert_equal_convertible(p, boost::move(x)); }
|
||||
{ return this->base_t::emplace_hint_equal(p, boost::move(x)); }
|
||||
|
||||
//! <b>Effects</b>: Inserts a new value move constructed from x in the container.
|
||||
//! p is a hint pointing to where the insert should start to search.
|
||||
@@ -1484,7 +1585,7 @@ class multimap
|
||||
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
|
||||
//! is inserted right before p.
|
||||
BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(movable_value_type) x)
|
||||
{ return this->base_t::insert_equal_convertible(p, boost::move(x)); }
|
||||
{ return this->base_t::emplace_hint_equal(p, boost::move(x)); }
|
||||
|
||||
//! <b>Requires</b>: first, last are not iterators into *this.
|
||||
//!
|
||||
@@ -1503,6 +1604,31 @@ class multimap
|
||||
{ this->base_t::insert_equal(il.begin(), il.end()); }
|
||||
#endif
|
||||
|
||||
//! <b>Requires</b>: nh is empty or this->get_allocator() == nh.get_allocator().
|
||||
//!
|
||||
//! <b>Effects/Returns</b>: If nh is empty, has no effect and returns end(). Otherwise, inserts
|
||||
//! the element owned by nh and returns an iterator pointing to the newly inserted element.
|
||||
//! If a range containing elements with keys equivalent to nh.key() exists,
|
||||
//! the element is inserted at the end of that range. nh is always emptied.
|
||||
//!
|
||||
//! <b>Complexity</b>: Logarithmic
|
||||
iterator insert(BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)
|
||||
{
|
||||
typename base_t::node_type n(boost::move(nh));
|
||||
return this->base_t::insert_equal_node(boost::move(n));
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Same as `insert(node_type && nh)` but the element is inserted as close as possible
|
||||
//! to the position just prior to "hint".
|
||||
//!
|
||||
//! <b>Complexity</b>: logarithmic in general, but amortized constant if the element is inserted
|
||||
//! right before "hint".
|
||||
iterator insert(const_iterator hint, BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)
|
||||
{
|
||||
typename base_t::node_type n(boost::move(nh));
|
||||
return this->base_t::insert_equal_node(hint, boost::move(n));
|
||||
}
|
||||
|
||||
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
//! @copydoc ::boost::container::set::erase(const_iterator)
|
||||
@@ -1513,7 +1639,23 @@ class multimap
|
||||
|
||||
//! @copydoc ::boost::container::set::erase(const_iterator,const_iterator)
|
||||
iterator erase(const_iterator first, const_iterator last);
|
||||
#endif
|
||||
|
||||
//! @copydoc ::boost::container::map::extract(const key_type&)
|
||||
node_type extract(const key_type& k)
|
||||
{
|
||||
typename base_t::node_type base_nh(this->base_t::extract(k));
|
||||
return node_type(boost::move(base_nh));
|
||||
}
|
||||
|
||||
//! @copydoc ::boost::container::map::extract(const_iterator)
|
||||
node_type extract(const_iterator position)
|
||||
{
|
||||
typename base_t::node_type base_nh(this->base_t::extract(position));
|
||||
return node_type (boost::move(base_nh));
|
||||
}
|
||||
|
||||
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
//! @copydoc ::boost::container::set::swap
|
||||
void swap(multiset& x)
|
||||
BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value
|
||||
|
@@ -100,6 +100,8 @@ class set
|
||||
typedef typename BOOST_CONTAINER_IMPDEF(base_t::const_iterator) const_iterator;
|
||||
typedef typename BOOST_CONTAINER_IMPDEF(base_t::reverse_iterator) reverse_iterator;
|
||||
typedef typename BOOST_CONTAINER_IMPDEF(base_t::const_reverse_iterator) const_reverse_iterator;
|
||||
typedef typename BOOST_CONTAINER_IMPDEF(base_t::node_type) node_type;
|
||||
typedef typename BOOST_CONTAINER_IMPDEF(base_t::insert_return_type) insert_return_type;
|
||||
|
||||
//////////////////////////////////////////////
|
||||
//
|
||||
@@ -523,6 +525,14 @@ class set
|
||||
{ this->base_t::insert_unique(il.begin(), il.end()); }
|
||||
#endif
|
||||
|
||||
//! @copydoc ::boost::container::map::insert(node_type&&)
|
||||
insert_return_type insert(BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)
|
||||
{ return this->base_t::insert_unique_node(boost::move(nh)); }
|
||||
|
||||
//! @copydoc ::boost::container::map::insert(const_iterator, node_type&&)
|
||||
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)); }
|
||||
|
||||
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
//! <b>Effects</b>: Erases the element pointed to by p.
|
||||
@@ -782,6 +792,7 @@ class multiset
|
||||
typedef typename BOOST_CONTAINER_IMPDEF(base_t::const_iterator) const_iterator;
|
||||
typedef typename BOOST_CONTAINER_IMPDEF(base_t::reverse_iterator) reverse_iterator;
|
||||
typedef typename BOOST_CONTAINER_IMPDEF(base_t::const_reverse_iterator) const_reverse_iterator;
|
||||
typedef typename BOOST_CONTAINER_IMPDEF(base_t::node_type) node_type;
|
||||
|
||||
//////////////////////////////////////////////
|
||||
//
|
||||
@@ -1049,6 +1060,14 @@ class multiset
|
||||
{ this->base_t::insert_equal(il.begin(), il.end()); }
|
||||
#endif
|
||||
|
||||
//! @copydoc ::boost::container::multimap::insert(node_type&&)
|
||||
iterator insert(BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)
|
||||
{ return this->base_t::insert_equal_node(boost::move(nh)); }
|
||||
|
||||
//! @copydoc ::boost::container::multimap::insert(const_iterator, node_type&&)
|
||||
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)); }
|
||||
|
||||
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
//! @copydoc ::boost::container::set::erase(const_iterator)
|
||||
|
@@ -108,9 +108,6 @@
|
||||
<File
|
||||
RelativePath="..\..\src\global_resource.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\build\Jamfile.v2">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\monotonic_buffer_resource.cpp">
|
||||
</File>
|
||||
|
@@ -303,6 +303,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pmr_string_test", "pmr_stri
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "node_handle_test", "node_handle_test.vcproj", "{5A17C6C5-6C29-A74F-48FE-A7FA7A063106}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfiguration) = preSolution
|
||||
Debug = Debug
|
||||
@@ -613,6 +617,10 @@ Global
|
||||
{85EADC21-42FA-F8A3-306C-A2029D5E7233}.Debug.Build.0 = Debug|Win32
|
||||
{85EADC21-42FA-F8A3-306C-A2029D5E7233}.Release.ActiveCfg = Release|Win32
|
||||
{85EADC21-42FA-F8A3-306C-A2029D5E7233}.Release.Build.0 = Release|Win32
|
||||
{5A17C6C5-6C29-A74F-48FE-A7FA7A063106}.Debug.ActiveCfg = Debug|Win32
|
||||
{5A17C6C5-6C29-A74F-48FE-A7FA7A063106}.Debug.Build.0 = Debug|Win32
|
||||
{5A17C6C5-6C29-A74F-48FE-A7FA7A063106}.Release.ActiveCfg = Release|Win32
|
||||
{5A17C6C5-6C29-A74F-48FE-A7FA7A063106}.Release.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
EndGlobalSection
|
||||
|
@@ -131,6 +131,9 @@
|
||||
<File
|
||||
RelativePath="..\..\..\..\boost\container\node_allocator.hpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\..\boost\container\node_handle.hpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\..\boost\container\options.hpp">
|
||||
</File>
|
||||
@@ -523,9 +526,6 @@
|
||||
<File
|
||||
RelativePath="..\..\test\static_vector_test.hpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\test\util.hpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\test\vector_test.hpp">
|
||||
</File>
|
||||
|
@@ -110,6 +110,118 @@ void test_move()
|
||||
move_assign.swap(original);
|
||||
}
|
||||
|
||||
bool node_type_test()
|
||||
{
|
||||
using namespace boost::container;
|
||||
{
|
||||
typedef map<test::movable_int, test::movable_int> map_type;
|
||||
map_type src;
|
||||
{
|
||||
test::movable_int mv_1(1), mv_2(2), mv_3(3), mv_11(11), mv_12(12), mv_13(13);
|
||||
src.try_emplace(boost::move(mv_1), boost::move(mv_11));
|
||||
src.try_emplace(boost::move(mv_2), boost::move(mv_12));
|
||||
src.try_emplace(boost::move(mv_3), boost::move(mv_13));
|
||||
}
|
||||
if(src.size() != 3)
|
||||
return false;
|
||||
|
||||
map_type dst;
|
||||
{
|
||||
test::movable_int mv_3(3), mv_33(33);
|
||||
dst.try_emplace(boost::move(mv_3), boost::move(mv_33));
|
||||
}
|
||||
|
||||
if(dst.size() != 1)
|
||||
return false;
|
||||
|
||||
const test::movable_int mv_1(1);
|
||||
const test::movable_int mv_2(2);
|
||||
const test::movable_int mv_3(3);
|
||||
const test::movable_int mv_33(33);
|
||||
const test::movable_int mv_13(13);
|
||||
map_type::insert_return_type r;
|
||||
|
||||
r = dst.insert(src.extract(mv_33)); // Key version, try to insert empty node
|
||||
if(! (r.position == dst.end() && r.inserted == false && r.node.empty()) )
|
||||
return false;
|
||||
r = dst.insert(src.extract(src.find(mv_1))); // Iterator version, successful
|
||||
if(! (r.position == dst.find(mv_1) && r.inserted == true && r.node.empty()) )
|
||||
return false;
|
||||
r = dst.insert(dst.begin(), src.extract(mv_2)); // Key type version, successful
|
||||
if(! (r.position == dst.find(mv_2) && r.inserted == true && r.node.empty()) )
|
||||
return false;
|
||||
r = dst.insert(src.extract(mv_3)); // Key type version, unsuccessful
|
||||
|
||||
if(!src.empty())
|
||||
return false;
|
||||
if(dst.size() != 3)
|
||||
return false;
|
||||
if(! (r.position == dst.find(mv_3) && r.inserted == false && r.node.key() == mv_3 && r.node.mapped() == mv_13) )
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
typedef multimap<test::movable_int, test::movable_int> multimap_type;
|
||||
multimap_type src;
|
||||
{
|
||||
test::movable_int mv_1(1), mv_2(2), mv_3(3), mv_3bis(3), mv_11(11), mv_12(12), mv_13(13), mv_23(23);
|
||||
src.emplace(boost::move(mv_1), boost::move(mv_11));
|
||||
src.emplace(boost::move(mv_2), boost::move(mv_12));
|
||||
src.emplace(boost::move(mv_3), boost::move(mv_13));
|
||||
src.emplace_hint(src.begin(), boost::move(mv_3bis), boost::move(mv_23));
|
||||
}
|
||||
if(src.size() != 4)
|
||||
return false;
|
||||
|
||||
multimap_type dst;
|
||||
{
|
||||
test::movable_int mv_3(3), mv_33(33);
|
||||
dst.emplace(boost::move(mv_3), boost::move(mv_33));
|
||||
}
|
||||
|
||||
if(dst.size() != 1)
|
||||
return false;
|
||||
|
||||
const test::movable_int mv_1(1);
|
||||
const test::movable_int mv_2(2);
|
||||
const test::movable_int mv_3(3);
|
||||
const test::movable_int mv_4(4);
|
||||
const test::movable_int mv_33(33);
|
||||
const test::movable_int mv_13(13);
|
||||
const test::movable_int mv_23(23);
|
||||
multimap_type::iterator r;
|
||||
|
||||
multimap_type::node_type nt(src.extract(mv_3));
|
||||
r = dst.insert(dst.begin(), boost::move(nt));
|
||||
if(! (r->first == mv_3 && r->second == mv_23 && dst.find(mv_3) == r && nt.empty()) )
|
||||
return false;
|
||||
|
||||
nt = src.extract(src.find(mv_1));
|
||||
r = dst.insert(boost::move(nt)); // Iterator version, successful
|
||||
if(! (r->first == mv_1 && nt.empty()) )
|
||||
return false;
|
||||
|
||||
nt = src.extract(mv_2);
|
||||
r = dst.insert(boost::move(nt)); // Key type version, successful
|
||||
if(! (r->first == mv_2 && nt.empty()) )
|
||||
return false;
|
||||
|
||||
r = dst.insert(src.extract(mv_3)); // Key type version, successful
|
||||
if(! (r->first == mv_3 && r->second == mv_13 && r == --multimap_type::iterator(dst.upper_bound(mv_3)) && nt.empty()) )
|
||||
return false;
|
||||
|
||||
r = dst.insert(src.extract(mv_4)); // Key type version, unsuccessful
|
||||
if(! (r == dst.end()) )
|
||||
return false;
|
||||
|
||||
if(!src.empty())
|
||||
return false;
|
||||
if(dst.size() != 5)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class VoidAllocator, boost::container::tree_type_enum tree_type_value>
|
||||
struct GetAllocatorMap
|
||||
{
|
||||
@@ -329,6 +441,12 @@ int main ()
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////
|
||||
// Node extraction/insertion testing functions
|
||||
////////////////////////////////////
|
||||
if(!node_type_test())
|
||||
return 1;
|
||||
|
||||
////////////////////////////////////
|
||||
// Test optimize_size option
|
||||
////////////////////////////////////
|
||||
|
@@ -136,6 +136,114 @@ void test_move()
|
||||
move_assign.swap(original);
|
||||
}
|
||||
|
||||
bool node_type_test()
|
||||
{
|
||||
using namespace boost::container;
|
||||
{
|
||||
typedef set<test::movable_int> set_type;
|
||||
set_type src;
|
||||
{
|
||||
test::movable_int mv_1(1), mv_2(2), mv_3(3);
|
||||
src.emplace(boost::move(mv_1));
|
||||
src.emplace(boost::move(mv_2));
|
||||
src.emplace(boost::move(mv_3));
|
||||
}
|
||||
if(src.size() != 3)
|
||||
return false;
|
||||
|
||||
set_type dst;
|
||||
{
|
||||
test::movable_int mv_3(3);
|
||||
dst.emplace(boost::move(mv_3));
|
||||
}
|
||||
|
||||
if(dst.size() != 1)
|
||||
return false;
|
||||
|
||||
const test::movable_int mv_1(1);
|
||||
const test::movable_int mv_2(2);
|
||||
const test::movable_int mv_3(3);
|
||||
const test::movable_int mv_33(33);
|
||||
set_type::insert_return_type r;
|
||||
|
||||
r = dst.insert(src.extract(mv_33)); // Key version, try to insert empty node
|
||||
if(! (r.position == dst.end() && r.inserted == false && r.node.empty()) )
|
||||
return false;
|
||||
r = dst.insert(src.extract(src.find(mv_1))); // Iterator version, successful
|
||||
if(! (r.position == dst.find(mv_1) && r.inserted == true && r.node.empty()) )
|
||||
return false;
|
||||
r = dst.insert(dst.begin(), src.extract(mv_2)); // Key type version, successful
|
||||
if(! (r.position == dst.find(mv_2) && r.inserted == true && r.node.empty()) )
|
||||
return false;
|
||||
r = dst.insert(src.extract(mv_3)); // Key type version, unsuccessful
|
||||
|
||||
if(!src.empty())
|
||||
return false;
|
||||
if(dst.size() != 3)
|
||||
return false;
|
||||
if(! (r.position == dst.find(mv_3) && r.inserted == false && r.node.value() == mv_3) )
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
typedef multiset<test::movable_int> multiset_type;
|
||||
multiset_type src;
|
||||
{
|
||||
test::movable_int mv_1(1), mv_2(2), mv_3(3), mv_3bis(3);
|
||||
src.emplace(boost::move(mv_1));
|
||||
src.emplace(boost::move(mv_2));
|
||||
src.emplace(boost::move(mv_3));
|
||||
src.emplace_hint(src.begin(), boost::move(mv_3bis));
|
||||
}
|
||||
if(src.size() != 4)
|
||||
return false;
|
||||
|
||||
multiset_type dst;
|
||||
{
|
||||
test::movable_int mv_3(3);
|
||||
dst.emplace(boost::move(mv_3));
|
||||
}
|
||||
|
||||
if(dst.size() != 1)
|
||||
return false;
|
||||
|
||||
const test::movable_int mv_1(1);
|
||||
const test::movable_int mv_2(2);
|
||||
const test::movable_int mv_3(3);
|
||||
const test::movable_int mv_4(4);
|
||||
multiset_type::iterator r;
|
||||
|
||||
multiset_type::node_type nt(src.extract(mv_3));
|
||||
r = dst.insert(dst.begin(), boost::move(nt));
|
||||
if(! (*r == mv_3 && dst.find(mv_3) == r && nt.empty()) )
|
||||
return false;
|
||||
|
||||
nt = src.extract(src.find(mv_1));
|
||||
r = dst.insert(boost::move(nt)); // Iterator version, successful
|
||||
if(! (*r == mv_1 && nt.empty()) )
|
||||
return false;
|
||||
|
||||
nt = src.extract(mv_2);
|
||||
r = dst.insert(boost::move(nt)); // Key type version, successful
|
||||
if(! (*r == mv_2 && nt.empty()) )
|
||||
return false;
|
||||
|
||||
r = dst.insert(src.extract(mv_3)); // Key type version, successful
|
||||
if(! (*r == mv_3 && r == --multiset_type::iterator(dst.upper_bound(mv_3)) && nt.empty()) )
|
||||
return false;
|
||||
|
||||
r = dst.insert(src.extract(mv_4)); // Key type version, unsuccessful
|
||||
if(! (r == dst.end()) )
|
||||
return false;
|
||||
|
||||
if(!src.empty())
|
||||
return false;
|
||||
if(dst.size() != 5)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
struct boost_container_set;
|
||||
struct boost_container_multiset;
|
||||
|
||||
@@ -271,7 +379,6 @@ int main ()
|
||||
std::pair<int,int> p(0, 0);
|
||||
s.insert(p);
|
||||
s.emplace(p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////
|
||||
@@ -382,6 +489,13 @@ int main ()
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////
|
||||
// Node extraction/insertion testing functions
|
||||
////////////////////////////////////
|
||||
if(!node_type_test())
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user