Rewrite [flat_]map/set insert overloads to be more standard compliant. Fixes #102 ("flat_map::insert ambiguous with initializer list & pairs that need to convert").

This commit is contained in:
Ion Gaztañaga
2021-01-01 23:50:50 +01:00
parent 621cd3a0ab
commit d7e99e56c6
7 changed files with 182 additions and 234 deletions

View File

@@ -1347,6 +1347,7 @@ use [*Boost.Container]? There are several reasons for that:
standard exception classes, you can define `BOOST_CONTAINER_USE_STD_EXCEPTIONS` before using any Boost.Container class.
* Fixed bugs/issues:
* [@https://github.com/boostorg/container/issues/102 GitHub #102: ['"flat_map::insert ambiguous with initializer list & pairs that need to convert"]].
* [@https://github.com/boostorg/container/issues/139 GitHub #139: ['"flat_map merge and iterators"]].
* [@https://github.com/boostorg/container/issues/141 GitHub #141: ['"small_vector does not propagate no throw properties of move operation of contained type"]].
* [@https://github.com/boostorg/container/issues/164 GitHub #164: ['"Compile error when using `pmr::map` with a `std::pair`; works when using a `std::tuple`"]].

View File

@@ -670,7 +670,7 @@ class tree
if(unique_insertion){
const const_iterator end_it(this->cend());
for ( ; first != last; ++first){
this->insert_unique_convertible(end_it, *first);
this->insert_unique_hint_convertible(end_it, *first);
}
}
else{
@@ -694,7 +694,7 @@ class tree
//for the constructor
const const_iterator end_it(this->cend());
for ( ; first != last; ++first){
this->insert_equal_convertible(end_it, *first);
this->insert_equal_hint_convertible(end_it, *first);
}
}
@@ -1006,7 +1006,7 @@ class tree
}
template<class MovableConvertible>
std::pair<iterator,bool> insert_unique(BOOST_FWD_REF(MovableConvertible) v)
std::pair<iterator,bool> insert_unique_convertible(BOOST_FWD_REF(MovableConvertible) v)
{
insert_commit_data data;
std::pair<iterator,bool> ret =
@@ -1017,6 +1017,19 @@ class tree
return ret;
}
template<class MovableConvertible>
iterator insert_unique_hint_convertible(const_iterator hint, BOOST_FWD_REF(MovableConvertible) v)
{
BOOST_ASSERT((priv_is_linked)(hint));
insert_commit_data data;
std::pair<iterator,bool> ret =
this->insert_unique_check(hint, key_of_value_t()(v), data);
if(!ret.second)
return ret.first;
return this->insert_unique_commit(boost::forward<MovableConvertible>(v), data);
}
private:
template<class KeyConvertible, class M>
@@ -1047,7 +1060,7 @@ class tree
this->icont().push_back(*tmp);
}
std::pair<iterator, bool> emplace_unique_impl(NodePtr p)
std::pair<iterator, bool> emplace_unique_node(NodePtr p)
{
value_type &v = p->get_data();
insert_commit_data data;
@@ -1064,7 +1077,7 @@ class tree
, true );
}
iterator emplace_unique_hint_impl(const_iterator hint, NodePtr p)
iterator emplace_hint_unique_node(const_iterator hint, NodePtr p)
{
BOOST_ASSERT((priv_is_linked)(hint));
value_type &v = p->get_data();
@@ -1072,6 +1085,7 @@ class tree
std::pair<iterator,bool> ret =
this->insert_unique_check(hint, key_of_value_t()(v), data);
if(!ret.second){
//Destroy unneeded node
Destroyer(this->node_alloc())(p);
return ret.first;
}
@@ -1084,11 +1098,11 @@ class tree
template <class... Args>
BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> emplace_unique(BOOST_FWD_REF(Args)... args)
{ return this->emplace_unique_impl(AllocHolder::create_node(boost::forward<Args>(args)...)); }
{ return this->emplace_unique_node(AllocHolder::create_node(boost::forward<Args>(args)...)); }
template <class... Args>
BOOST_CONTAINER_FORCEINLINE iterator emplace_hint_unique(const_iterator hint, BOOST_FWD_REF(Args)... args)
{ return this->emplace_unique_hint_impl(hint, AllocHolder::create_node(boost::forward<Args>(args)...)); }
{ return this->emplace_hint_unique_node(hint, AllocHolder::create_node(boost::forward<Args>(args)...)); }
template <class... Args>
iterator emplace_equal(BOOST_FWD_REF(Args)... args)
@@ -1132,11 +1146,11 @@ class tree
#define BOOST_CONTAINER_TREE_EMPLACE_CODE(N) \
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
std::pair<iterator, bool> emplace_unique(BOOST_MOVE_UREF##N)\
{ return this->emplace_unique_impl(AllocHolder::create_node(BOOST_MOVE_FWD##N)); }\
{ return this->emplace_unique_node(AllocHolder::create_node(BOOST_MOVE_FWD##N)); }\
\
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
iterator emplace_hint_unique(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
{ return this->emplace_unique_hint_impl(hint, AllocHolder::create_node(BOOST_MOVE_FWD##N)); }\
{ return this->emplace_hint_unique_node(hint, AllocHolder::create_node(BOOST_MOVE_FWD##N)); }\
\
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
iterator emplace_equal(BOOST_MOVE_UREF##N)\
@@ -1180,38 +1194,17 @@ class tree
#endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template<class MovableConvertible>
iterator insert_unique_convertible(const_iterator hint, BOOST_FWD_REF(MovableConvertible) v)
{
BOOST_ASSERT((priv_is_linked)(hint));
insert_commit_data data;
std::pair<iterator,bool> ret =
this->insert_unique_check(hint, key_of_value_t()(v), data);
if(!ret.second)
return ret.first;
return this->insert_unique_commit(boost::forward<MovableConvertible>(v), data);
}
BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert_unique, value_type, iterator, this->insert_unique_convertible, const_iterator, const_iterator)
//BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert_unique, value_type, iterator, this->insert_unique_hint_convertible, const_iterator, const_iterator)
template <class InputIterator>
void insert_unique(InputIterator first, InputIterator last)
void insert_unique_range(InputIterator first, InputIterator last)
{
for( ; first != last; ++first)
this->insert_unique(*first);
}
iterator insert_equal(const value_type& v)
{
NodePtr tmp(AllocHolder::create_node(v));
scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());
iterator ret(this->icont().insert_equal(this->icont().end(), *tmp));
destroy_deallocator.release();
return ret;
this->insert_unique_convertible(*first);
}
template<class MovableConvertible>
iterator insert_equal(BOOST_FWD_REF(MovableConvertible) v)
iterator insert_equal_convertible(BOOST_FWD_REF(MovableConvertible) v)
{
NodePtr tmp(AllocHolder::create_node(boost::forward<MovableConvertible>(v)));
scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());
@@ -1221,7 +1214,7 @@ class tree
}
template<class MovableConvertible>
iterator insert_equal_convertible(const_iterator hint, BOOST_FWD_REF(MovableConvertible) v)
iterator insert_equal_hint_convertible(const_iterator hint, BOOST_FWD_REF(MovableConvertible) v)
{
BOOST_ASSERT((priv_is_linked)(hint));
NodePtr tmp(AllocHolder::create_node(boost::forward<MovableConvertible>(v)));
@@ -1231,13 +1224,14 @@ class tree
return ret;
}
BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert_equal, value_type, iterator, this->insert_equal_convertible, const_iterator, const_iterator)
BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG
(insert_equal, value_type, iterator, this->insert_equal_hint_convertible, const_iterator, const_iterator)
template <class InputIterator>
void insert_equal(InputIterator first, InputIterator last)
void insert_equal_range(InputIterator first, InputIterator last)
{
for( ; first != last; ++first)
this->insert_equal(*first);
this->insert_equal_convertible(*first);
}
template<class KeyType, class M>

View File

@@ -65,6 +65,7 @@ using ::boost::move_detail::nat;
using ::boost::move_detail::nat2;
using ::boost::move_detail::nat3;
using ::boost::move_detail::max_align_t;
using ::boost::move_detail::is_convertible;
} //namespace dtl {
} //namespace container {

View File

@@ -1077,10 +1077,12 @@ class flat_map
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> insert(BOOST_RV_REF(value_type) x)
{ return dtl::force_copy<std::pair<iterator,bool> >(
m_flat_tree.insert_unique(boost::move(dtl::force<impl_value_type>(x)))); }
{
return dtl::force_copy<std::pair<iterator,bool> >(
m_flat_tree.insert_unique(boost::move(dtl::force<impl_value_type>(x))));
}
//! <b>Effects</b>: Inserts a new value_type move constructed from the pair if and
//! <b>Effects</b>: Inserts a new value_type constructed from the pair if and
//! only if there is no element in the container with key equivalent to the key of x.
//!
//! <b>Returns</b>: The bool component of the returned pair is true if and only
@@ -1091,10 +1093,15 @@ class flat_map
//! to the elements with bigger keys than x.
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> insert(BOOST_RV_REF(movable_value_type) x)
template <class Pair>
BOOST_CONTAINER_FORCEINLINE BOOST_CONTAINER_DOC1ST
( std::pair<iterator BOOST_MOVE_I bool>
, typename dtl::enable_if_c<dtl::is_convertible<Pair BOOST_MOVE_I impl_value_type>::value
BOOST_MOVE_I std::pair<iterator BOOST_MOVE_I bool> >::type)
insert(BOOST_FWD_REF(Pair) x)
{
return dtl::force_copy<std::pair<iterator,bool> >
(m_flat_tree.insert_unique(boost::move(x)));
(m_flat_tree.emplace_unique(boost::forward<Pair>(x)));
}
//! <b>Effects</b>: Inserts a copy of x in the container if and only if there is
@@ -1131,7 +1138,7 @@ class flat_map
, boost::move(dtl::force<impl_value_type>(x))));
}
//! <b>Effects</b>: Inserts an element move constructed from x in the container.
//! <b>Effects</b>: Inserts an element constructed from x in the container.
//! p is a hint pointing to where the insert should start to search.
//!
//! <b>Returns</b>: An iterator pointing to the element with key equivalent to the key of x.
@@ -1140,10 +1147,15 @@ class flat_map
//! right before p) plus insertion linear to the elements with bigger keys than x.
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(movable_value_type) x)
template <class Pair>
BOOST_CONTAINER_FORCEINLINE BOOST_CONTAINER_DOC1ST
( iterator
, typename dtl::enable_if_c<dtl::is_convertible<Pair BOOST_MOVE_I impl_value_type>::value
BOOST_MOVE_I iterator>::type)
insert(const_iterator p, BOOST_FWD_REF(Pair) x)
{
return dtl::force_copy<iterator>(
m_flat_tree.insert_unique(dtl::force_copy<impl_const_iterator>(p), boost::move(x)));
m_flat_tree.emplace_hint_unique(dtl::force_copy<impl_const_iterator>(p), boost::forward<Pair>(x)));
}
//! <b>Requires</b>: first, last are not iterators into *this.
@@ -1608,22 +1620,24 @@ class flat_map
private:
mapped_type &priv_subscript(const key_type& k)
{
iterator i = lower_bound(k);
iterator i = this->lower_bound(k);
// i->first is greater than or equivalent to k.
if (i == end() || key_comp()(k, (*i).first)){
dtl::value_init<mapped_type> m;
i = insert(i, impl_value_type(k, ::boost::move(m.m_t)));
impl_value_type v(k, ::boost::move(m.m_t));
i = this->insert(i, ::boost::move(v));
}
return (*i).second;
}
mapped_type &priv_subscript(BOOST_RV_REF(key_type) mk)
{
key_type &k = mk;
iterator i = lower_bound(k);
iterator i = this->lower_bound(k);
// i->first is greater than or equivalent to k.
if (i == end() || key_comp()(k, (*i).first)){
dtl::value_init<mapped_type> m;
i = insert(i, impl_value_type(boost::move(k), ::boost::move(m.m_t)));
impl_value_type v(::boost::move(k), ::boost::move(m.m_t));
i = this->insert(i, ::boost::move(v));
}
return (*i).second;
}
@@ -2441,25 +2455,20 @@ class flat_multimap
m_flat_tree.insert_equal(dtl::force<const impl_value_type>(x)));
}
//! <b>Effects</b>: Inserts a new value move-constructed from x and returns
//! <b>Effects</b>: Inserts a new value constructed from x and returns
//! the iterator pointing to the newly inserted element.
//!
//! <b>Complexity</b>: Logarithmic search time plus linear insertion
//! to the elements with bigger keys than x.
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
BOOST_CONTAINER_FORCEINLINE iterator insert(BOOST_RV_REF(value_type) x)
{ return dtl::force_copy<iterator>(m_flat_tree.insert_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 search time plus linear insertion
//! to the elements with bigger keys than x.
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
BOOST_CONTAINER_FORCEINLINE iterator insert(BOOST_RV_REF(impl_value_type) x)
{ return dtl::force_copy<iterator>(m_flat_tree.insert_equal(boost::move(x))); }
template<class Pair>
BOOST_CONTAINER_FORCEINLINE BOOST_CONTAINER_DOC1ST
( iterator
, typename dtl::enable_if_c<dtl::is_convertible<Pair BOOST_MOVE_I impl_value_type>::value
BOOST_MOVE_I iterator >::type)
insert(BOOST_FWD_REF(Pair) x)
{ return dtl::force_copy<iterator>(m_flat_tree.emplace_equal(boost::forward<Pair>(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.
@@ -2479,7 +2488,7 @@ class flat_multimap
, dtl::force<const impl_value_type>(x)));
}
//! <b>Effects</b>: Inserts a value move constructed from x in the container.
//! <b>Effects</b>: Inserts a value constructed from x in the container.
//! p is a hint pointing to where the insert should start to search.
//!
//! <b>Returns</b>: An iterator pointing to the element with key equivalent
@@ -2490,28 +2499,15 @@ class flat_multimap
//! to the elements with bigger keys than x.
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(value_type) x)
{
return dtl::force_copy<iterator>
(m_flat_tree.insert_equal(dtl::force_copy<impl_const_iterator>(p)
, boost::move(x)));
}
//! <b>Effects</b>: Inserts a value move constructed from x in the container.
//! p is a hint pointing to where the insert should start to search.
//!
//! <b>Returns</b>: An iterator pointing to the element with key equivalent
//! to the key of x.
//!
//! <b>Complexity</b>: Logarithmic search time (constant time if the value
//! is to be inserted before p) plus linear insertion
//! to the elements with bigger keys than x.
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(impl_value_type) x)
template<class Pair>
BOOST_CONTAINER_FORCEINLINE BOOST_CONTAINER_DOC1ST
( iterator
, typename dtl::enable_if_c<dtl::is_convertible<Pair BOOST_MOVE_I impl_value_type>::value
BOOST_MOVE_I iterator>::type)
insert(const_iterator p, BOOST_FWD_REF(Pair) x)
{
return dtl::force_copy<iterator>(
m_flat_tree.insert_equal(dtl::force_copy<impl_const_iterator>(p), boost::move(x)));
m_flat_tree.emplace_hint_equal(dtl::force_copy<impl_const_iterator>(p), boost::forward<Pair>(x)));
}
//! <b>Requires</b>: first, last are not iterators into *this.

View File

@@ -667,7 +667,7 @@ class flat_set
private:
typedef std::pair<iterator, bool> insert_return_pair;
public:
BOOST_MOVE_CONVERSION_AWARE_CATCH(insert, value_type, insert_return_pair, this->priv_insert)
BOOST_MOVE_CONVERSION_AWARE_CATCH(insert, value_type, insert_return_pair, this->tree_t::insert_unique)
#endif
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
@@ -695,7 +695,7 @@ class flat_set
//! <b>Note</b>: If an element is inserted it might invalidate elements.
iterator insert(const_iterator p, value_type &&x);
#else
BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, value_type, iterator, this->priv_insert, const_iterator, const_iterator)
BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, value_type, iterator, this->tree_t::insert_unique, const_iterator, const_iterator)
#endif
//! <b>Requires</b>: first, last are not iterators into *this.
@@ -1117,17 +1117,6 @@ class flat_set
//! <b>Throws</b>: If the move assignment throws
BOOST_CONTAINER_FORCEINLINE void adopt_sequence(ordered_unique_range_t, BOOST_RV_REF(sequence_type) seq)
{ this->tree_t::adopt_sequence_unique(ordered_unique_range_t(), boost::move(seq)); }
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
template<class KeyType>
BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> priv_insert(BOOST_FWD_REF(KeyType) x)
{ return this->tree_t::insert_unique(::boost::forward<KeyType>(x)); }
template<class KeyType>
BOOST_CONTAINER_FORCEINLINE iterator priv_insert(const_iterator p, BOOST_FWD_REF(KeyType) x)
{ return this->tree_t::insert_unique(p, ::boost::forward<KeyType>(x)); }
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
};
#ifndef BOOST_CONTAINER_NO_CXX17_CTAD
@@ -1617,7 +1606,7 @@ class flat_multiset
//! <b>Note</b>: If an element is inserted it might invalidate elements.
iterator insert(value_type &&x);
#else
BOOST_MOVE_CONVERSION_AWARE_CATCH(insert, value_type, iterator, this->priv_insert)
BOOST_MOVE_CONVERSION_AWARE_CATCH(insert, value_type, iterator, this->tree_t::insert_equal)
#endif
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
@@ -1645,7 +1634,7 @@ class flat_multiset
//! <b>Note</b>: If an element is inserted it might invalidate elements.
iterator insert(const_iterator p, value_type &&x);
#else
BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, value_type, iterator, this->priv_insert, const_iterator, const_iterator)
BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, value_type, iterator, this->tree_t::insert_equal, const_iterator, const_iterator)
#endif
//! <b>Requires</b>: first, last are not iterators into *this.
@@ -1849,17 +1838,6 @@ class flat_multiset
//! <b>Throws</b>: If the move assignment throws
BOOST_CONTAINER_FORCEINLINE void adopt_sequence(ordered_range_t, BOOST_RV_REF(sequence_type) seq)
{ this->tree_t::adopt_sequence_equal(ordered_range_t(), boost::move(seq)); }
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
template <class KeyType>
BOOST_CONTAINER_FORCEINLINE iterator priv_insert(BOOST_FWD_REF(KeyType) x)
{ return this->tree_t::insert_equal(::boost::forward<KeyType>(x)); }
template <class KeyType>
BOOST_CONTAINER_FORCEINLINE iterator priv_insert(const_iterator p, BOOST_FWD_REF(KeyType) x)
{ return this->tree_t::insert_equal(p, ::boost::forward<KeyType>(x)); }
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
};
#ifndef BOOST_CONTAINER_NO_CXX17_CTAD

View File

@@ -121,7 +121,7 @@ class map
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 std::pair<key_type, mapped_type> nonconst_value_type;
//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::stored_allocator_type
@@ -688,40 +688,7 @@ class map
//!
//! <b>Complexity</b>: Logarithmic.
BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> insert(const value_type& x)
{ return this->base_t::insert_unique(x); }
//! <b>Effects</b>: Inserts a new value_type created from the pair if and only if
//! there is no element in the container with key equivalent to the key of x.
//!
//! <b>Returns</b>: The bool component of the returned pair is true if and only
//! if the insertion takes place, and the iterator component of the pair
//! points to the element with key equivalent to the key of x.
//!
//! <b>Complexity</b>: Logarithmic.
BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> insert(const nonconst_value_type& 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.
//!
//! <b>Returns</b>: The bool component of the returned pair is true if and only
//! if the insertion takes place, and the iterator component of the pair
//! points to the element with key equivalent to the key of x.
//!
//! <b>Complexity</b>: Logarithmic.
BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> insert(BOOST_RV_REF(nonconst_value_type) 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.
//!
//! <b>Returns</b>: The bool component of the returned pair is true if and only
//! if the insertion takes place, and the iterator component of the pair
//! points to the element with key equivalent to the key of x.
//!
//! <b>Complexity</b>: Logarithmic.
BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> insert(BOOST_RV_REF(movable_value_type) x)
{ return this->try_emplace(boost::move(x.first), boost::move(x.second)); }
{ return this->base_t::insert_unique_convertible(x); }
//! <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.
@@ -732,7 +699,28 @@ class map
//!
//! <b>Complexity</b>: Logarithmic.
BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> insert(BOOST_RV_REF(value_type) x)
{ return this->base_t::insert_unique(boost::move(x)); }
{ return this->base_t::insert_unique_convertible(boost::move(x)); }
//! <b>Effects</b>: Inserts a new value_type created from the pair if and only if
//! there is no element in the container with key equivalent to the key of x.
//!
//! <b>Returns</b>: The bool component of the returned pair is true if and only
//! if the insertion takes place, and the iterator component of the pair
//! points to the element with key equivalent to the key of x.
//!
//! <b>Complexity</b>: Logarithmic.
template <class Pair>
BOOST_CONTAINER_FORCEINLINE BOOST_CONTAINER_DOC1ST
( std::pair<iterator BOOST_MOVE_I bool>
, typename dtl::enable_if_c<
dtl::is_convertible<Pair BOOST_MOVE_I value_type>::value ||
dtl::is_convertible<Pair BOOST_MOVE_I movable_value_type>::value
BOOST_MOVE_I std::pair<iterator BOOST_MOVE_I bool> >::type)
insert(BOOST_FWD_REF(Pair) x)
{ return this->base_t::emplace_unique(boost::forward<Pair>(x)); }
BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, const value_type& x)
{ return this->base_t::insert_unique_hint_convertible(p, x); }
//! <b>Effects</b>: Inserts a copy of x in the container if and only if there is
//! no element in the container with key equivalent to the key of x.
@@ -743,9 +731,30 @@ class map
//!
//! <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 value_type& x)
{ return this->base_t::insert_unique(p, x); }
BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(value_type) x)
{ return this->base_t::insert_unique_hint_convertible(p, boost::move(x)); }
//! <b>Effects</b>: Inserts a copy of x in the container if and only if there is
//! no element in the container with key equivalent to the key of x.
//! p is a hint pointing to where the insert should start to search.
//!
//! <b>Returns</b>: An iterator pointing to the element with key equivalent
//! to the key of x.
//!
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
//! is inserted right before p.
template <class Pair>
BOOST_CONTAINER_FORCEINLINE BOOST_CONTAINER_DOC1ST
( iterator
, typename dtl::enable_if_c<
dtl::is_convertible<Pair BOOST_MOVE_I value_type>::value ||
dtl::is_convertible<Pair BOOST_MOVE_I movable_value_type>::value
BOOST_MOVE_I iterator >::type)
insert(const_iterator p, BOOST_FWD_REF(Pair) x)
{ return this->base_t::emplace_hint_unique(p, boost::forward<Pair>(x)); }
/*
//! <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.
//! p is a hint pointing to where the insert should start to search.
@@ -776,18 +785,11 @@ class map
//! <b>Returns</b>: An iterator pointing to the element with key equivalent to the key of x.
//!
//! <b>Complexity</b>: Logarithmic.
iterator insert(const_iterator p, const nonconst_value_type& x)
BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, const nonconst_value_type& 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.
//!
//! <b>Returns</b>: An iterator pointing to the element with key equivalent to the key of x.
//!
//! <b>Complexity</b>: Logarithmic.
BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(value_type) x)
{ return this->base_t::insert_unique(p, boost::move(x)); }
*/
//! <b>Requires</b>: first, last are not iterators into *this.
//!
//! <b>Effects</b>: inserts each element from the range [first,last) if and only
@@ -796,7 +798,7 @@ class map
//! <b>Complexity</b>: At most N log(size()+N) (N is the distance from first to last)
template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE void insert(InputIterator first, InputIterator last)
{ this->base_t::insert_unique(first, last); }
{ this->base_t::insert_unique_range(first, last); }
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
//! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()) if and only
@@ -804,7 +806,7 @@ class map
//!
//! <b>Complexity</b>: At most N log(size()+N) (N is the distance from il.begin() to il.end())
BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il)
{ this->base_t::insert_unique(il.begin(), il.end()); }
{ this->base_t::insert_unique_range(il.begin(), il.end()); }
#endif
//! <b>Requires</b>: nh is empty or this->get_allocator() == nh.get_allocator().
@@ -1446,7 +1448,7 @@ class multimap
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 std::pair<key_type, mapped_type> nonconst_value_type;
//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::stored_allocator_type
@@ -1836,28 +1838,28 @@ class multimap
//!
//! <b>Complexity</b>: Logarithmic.
BOOST_CONTAINER_FORCEINLINE iterator insert(const value_type& x)
{ return this->base_t::insert_equal(x); }
{ return this->base_t::insert_equal_convertible(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(value_type) x)
{ return this->base_t::insert_equal_convertible(boost::move(x)); }
//! <b>Effects</b>: Inserts a new value constructed from x and returns
//! the iterator pointing to the newly inserted element.
//!
//! <b>Complexity</b>: Logarithmic.
BOOST_CONTAINER_FORCEINLINE iterator insert(const nonconst_value_type& 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::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::emplace_equal(boost::move(x)); }
template<class Pair>
BOOST_CONTAINER_FORCEINLINE BOOST_CONTAINER_DOC1ST
( iterator
, typename dtl::enable_if_c<
dtl::is_convertible<Pair BOOST_MOVE_I value_type>::value ||
dtl::is_convertible<Pair BOOST_MOVE_I movable_value_type>::value
BOOST_MOVE_I iterator >::type)
insert(BOOST_FWD_REF(Pair) x)
{ return this->base_t::emplace_equal(boost::forward<Pair>(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.
@@ -1868,29 +1870,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 value_type& x)
{ return this->base_t::insert_equal(p, x); }
//! <b>Effects</b>: Inserts a new value constructed from x in the container.
//! p is a hint pointing to where the insert should start to search.
//!
//! <b>Returns</b>: An iterator pointing to the element with key equivalent
//! to the key of x.
//!
//! <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::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.
//!
//! <b>Returns</b>: An iterator pointing to the element with key equivalent
//! to the key of x.
//!
//! <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::emplace_hint_equal(p, boost::move(x)); }
{ return this->base_t::insert_equal_hint_convertible(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.
@@ -1901,7 +1881,25 @@ 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::emplace_hint_equal(p, boost::move(x)); }
{ return this->base_t::insert_equal_hint_convertible(p, boost::move(x)); }
//! <b>Effects</b>: Inserts a new value constructed from x in the container.
//! p is a hint pointing to where the insert should start to search.
//!
//! <b>Returns</b>: An iterator pointing to the element with key equivalent
//! to the key of x.
//!
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
//! is inserted right before p.
template<class Pair>
BOOST_CONTAINER_FORCEINLINE BOOST_CONTAINER_DOC1ST
( iterator
, typename dtl::enable_if_c<
dtl::is_convertible<Pair BOOST_MOVE_I value_type>::value ||
dtl::is_convertible<Pair BOOST_MOVE_I movable_value_type>::value
BOOST_MOVE_I iterator>::type)
insert(const_iterator p, BOOST_FWD_REF(Pair) x)
{ return this->base_t::emplace_hint_equal(p, boost::forward<Pair>(x)); }
//! <b>Requires</b>: first, last are not iterators into *this.
//!
@@ -1910,14 +1908,14 @@ class multimap
//! <b>Complexity</b>: At most N log(size()+N) (N is the distance from first to last)
template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE void insert(InputIterator first, InputIterator last)
{ this->base_t::insert_equal(first, last); }
{ this->base_t::insert_equal_range(first, last); }
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
//! <b>Effects</b>: inserts each element from the range [il.begin(), il.end().
//!
//! <b>Complexity</b>: At most N log(size()+N) (N is the distance from il.begin() to il.end())
BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il)
{ this->base_t::insert_equal(il.begin(), il.end()); }
{ this->base_t::insert_equal_range(il.begin(), il.end()); }
#endif
//! <b>Requires</b>: nh is empty or this->get_allocator() == nh.get_allocator().

View File

@@ -597,7 +597,8 @@ class set
private:
typedef std::pair<iterator, bool> insert_return_pair;
public:
BOOST_MOVE_CONVERSION_AWARE_CATCH(insert, value_type, insert_return_pair, this->priv_insert)
BOOST_MOVE_CONVERSION_AWARE_CATCH
(insert, value_type, insert_return_pair, this->base_t::insert_unique_convertible)
#endif
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
@@ -620,7 +621,8 @@ class set
//! <b>Complexity</b>: Logarithmic.
iterator insert(const_iterator p, value_type &&x);
#else
BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, value_type, iterator, this->priv_insert, const_iterator, const_iterator)
BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG
(insert, value_type, iterator, this->base_t::insert_unique_hint_convertible, const_iterator, const_iterator)
#endif
//! <b>Requires</b>: first, last are not iterators into *this.
@@ -631,7 +633,7 @@ class set
//! <b>Complexity</b>: At most N log(size()+N) (N is the distance from first to last)
template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE void insert(InputIterator first, InputIterator last)
{ this->base_t::insert_unique(first, last); }
{ this->base_t::insert_unique_range(first, last); }
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
//! <b>Effects</b>: inserts each element from the range [il.begin(),il.end()) if and only
@@ -639,7 +641,7 @@ class set
//!
//! <b>Complexity</b>: At most N log(size()+N) (N is the distance from il.begin() to il.end())
BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il)
{ this->base_t::insert_unique(il.begin(), il.end()); }
{ this->base_t::insert_unique_range(il.begin(), il.end()); }
#endif
//! @copydoc ::boost::container::map::insert(node_type&&)
@@ -948,17 +950,6 @@ class set
friend void swap(set& x, set& y);
#endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
template <class KeyType>
BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> priv_insert(BOOST_FWD_REF(KeyType) x)
{ return this->base_t::insert_unique(::boost::forward<KeyType>(x)); }
template <class KeyType>
BOOST_CONTAINER_FORCEINLINE iterator priv_insert(const_iterator p, BOOST_FWD_REF(KeyType) x)
{ return this->base_t::insert_unique(p, ::boost::forward<KeyType>(x)); }
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
};
#ifndef BOOST_CONTAINER_NO_CXX17_CTAD
@@ -1393,7 +1384,7 @@ class multiset
//! is inserted right before p.
iterator insert(value_type &&x);
#else
BOOST_MOVE_CONVERSION_AWARE_CATCH(insert, value_type, iterator, this->priv_insert)
BOOST_MOVE_CONVERSION_AWARE_CATCH(insert, value_type, iterator, this->base_t::insert_equal_convertible)
#endif
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
@@ -1417,7 +1408,8 @@ class multiset
//! is inserted right before p.
iterator insert(const_iterator p, value_type &&x);
#else
BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, value_type, iterator, this->priv_insert, const_iterator, const_iterator)
BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG
(insert, value_type, iterator, this->base_t::insert_equal_hint_convertible, const_iterator, const_iterator)
#endif
//! <b>Requires</b>: first, last are not iterators into *this.
@@ -1427,12 +1419,12 @@ class multiset
//! <b>Complexity</b>: At most N log(size()+N) (N is the distance from first to last)
template <class InputIterator>
BOOST_CONTAINER_FORCEINLINE void insert(InputIterator first, InputIterator last)
{ this->base_t::insert_equal(first, last); }
{ this->base_t::insert_equal_range(first, last); }
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
//! @copydoc ::boost::container::set::insert(std::initializer_list<value_type>)
BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il)
{ this->base_t::insert_equal(il.begin(), il.end()); }
{ this->base_t::insert_equal_range(il.begin(), il.end()); }
#endif
//! @copydoc ::boost::container::multimap::insert(node_type&&)
@@ -1611,18 +1603,6 @@ class multiset
friend void swap(multiset& x, multiset& y);
#endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
template <class KeyType>
BOOST_CONTAINER_FORCEINLINE iterator priv_insert(BOOST_FWD_REF(KeyType) x)
{ return this->base_t::insert_equal(::boost::forward<KeyType>(x)); }
template <class KeyType>
BOOST_CONTAINER_FORCEINLINE iterator priv_insert(const_iterator p, BOOST_FWD_REF(KeyType) x)
{ return this->base_t::insert_equal(p, ::boost::forward<KeyType>(x)); }
#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
};
#ifndef BOOST_CONTAINER_NO_CXX17_CTAD