* Add missing extract() and insert(node_type) funtion to associative containers.

* Simplify select1st
This commit is contained in:
Ion Gaztañaga
2016-08-29 00:06:57 +02:00
parent 6ccf9dacae
commit 4298d1984b
13 changed files with 596 additions and 166 deletions

View File

@@ -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{};\" \\

View File

@@ -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]

View File

@@ -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 {

View File

@@ -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

View File

@@ -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()); }

View File

@@ -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;

View File

@@ -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

View File

@@ -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)

View File

@@ -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>

View 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

View File

@@ -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>

View 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
////////////////////////////////////

View File

@@ -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;
}