mirror of
https://github.com/boostorg/container.git
synced 2025-08-02 14:04:26 +02:00
Implemented missing try_emplace member for maps.
This commit is contained in:
@@ -1231,7 +1231,7 @@ 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 `insert_or_assign` for [classref boost::container::map map] and [classref boost::container::flat_map flat_map].
|
||||
* Implemented C++17 `insert_or_assign` and `try_emplace`for [classref boost::container::map map] and [classref boost::container::flat_map flat_map].
|
||||
|
||||
[endsect]
|
||||
|
||||
|
@@ -589,6 +589,29 @@ class flat_tree
|
||||
return this->insert_equal(hint, ::boost::move(val));
|
||||
}
|
||||
|
||||
template <class KeyType, class... Args>
|
||||
BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> try_emplace
|
||||
(const_iterator hint, BOOST_FWD_REF(KeyType) key, BOOST_FWD_REF(Args)... args)
|
||||
{
|
||||
std::pair<iterator,bool> ret;
|
||||
insert_commit_data data;
|
||||
const key_type & k = key;
|
||||
ret.second = hint == const_iterator()
|
||||
? this->priv_insert_unique_prepare(k, data)
|
||||
: this->priv_insert_unique_prepare(hint, k, data);
|
||||
|
||||
if(!ret.second){
|
||||
ret.first = this->nth(data.position - this->cbegin());
|
||||
}
|
||||
else{
|
||||
typedef typename emplace_functor_type<try_emplace_t, KeyType, Args...>::type func_t;
|
||||
typedef emplace_iterator<value_type, func_t, difference_type> it_t;
|
||||
func_t func(try_emplace_t(), ::boost::forward<KeyType>(key), ::boost::forward<Args>(args)...);
|
||||
ret.first = this->m_data.m_vect.insert(data.position, it_t(func), it_t());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
#define BOOST_CONTAINER_FLAT_TREE_EMPLACE_CODE(N) \
|
||||
@@ -635,8 +658,30 @@ class flat_tree
|
||||
value_destructor<stored_allocator_type> d(a, val);\
|
||||
return this->insert_equal(hint, ::boost::move(val));\
|
||||
}\
|
||||
template <class KeyType BOOST_MOVE_I##N BOOST_MOVE_CLASS##N>\
|
||||
BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool>\
|
||||
try_emplace(const_iterator hint, BOOST_FWD_REF(KeyType) key BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
|
||||
{\
|
||||
std::pair<iterator,bool> ret;\
|
||||
insert_commit_data data;\
|
||||
const key_type & k = key;\
|
||||
ret.second = hint == const_iterator()\
|
||||
? this->priv_insert_unique_prepare(k, data)\
|
||||
: this->priv_insert_unique_prepare(hint, k, data);\
|
||||
\
|
||||
if(!ret.second){\
|
||||
ret.first = this->nth(data.position - this->cbegin());\
|
||||
}\
|
||||
else{\
|
||||
typedef typename emplace_functor_type<try_emplace_t, KeyType BOOST_MOVE_I##N BOOST_MOVE_TARG##N>::type func_t;\
|
||||
typedef emplace_iterator<value_type, func_t, difference_type> it_t;\
|
||||
func_t func(try_emplace_t(), ::boost::forward<KeyType>(key) BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
|
||||
ret.first = this->m_data.m_vect.insert(data.position, it_t(func), it_t());\
|
||||
}\
|
||||
return ret;\
|
||||
}\
|
||||
//
|
||||
BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_FLAT_TREE_EMPLACE_CODE)
|
||||
BOOST_MOVE_ITERATE_0TO7(BOOST_CONTAINER_FLAT_TREE_EMPLACE_CODE)
|
||||
#undef BOOST_CONTAINER_FLAT_TREE_EMPLACE_CODE
|
||||
|
||||
#endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
@@ -70,6 +70,8 @@ namespace container {
|
||||
|
||||
typedef const std::piecewise_construct_t & piecewise_construct_t;
|
||||
|
||||
struct try_emplace_t{};
|
||||
|
||||
#else
|
||||
|
||||
//! The piecewise_construct_t struct is an empty structure type used as a unique type to
|
||||
@@ -197,6 +199,25 @@ struct pair
|
||||
: first(::boost::move(p.first)), second(::boost::move(p.second))
|
||||
{}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
template< class KeyType, class ...Args>
|
||||
pair(const try_emplace_t &, BOOST_FWD_REF(KeyType) k, Args && ...args)
|
||||
: first(boost::forward<KeyType>(k)), second(::boost::forward<Args>(args)...)\
|
||||
{}
|
||||
#else
|
||||
|
||||
//piecewise construction from boost::tuple
|
||||
#define BOOST_PAIR_TRY_EMPLACE_CONSTRUCT_CODE(N)\
|
||||
template< class KeyType BOOST_MOVE_I##N BOOST_MOVE_CLASS##N > \
|
||||
pair( try_emplace_t, BOOST_FWD_REF(KeyType) k BOOST_MOVE_I##N BOOST_MOVE_UREF##N )\
|
||||
: first(boost::forward<KeyType>(k)), second(BOOST_MOVE_FWD##N)\
|
||||
{}\
|
||||
//
|
||||
BOOST_MOVE_ITERATE_0TO9(BOOST_PAIR_TRY_EMPLACE_CONSTRUCT_CODE)
|
||||
#undef BOOST_PAIR_TRY_EMPLACE_CONSTRUCT_CODE
|
||||
|
||||
#endif //BOOST_NO_CXX11_VARIADIC_TEMPLATES
|
||||
|
||||
//piecewise construction from boost::tuple
|
||||
#define BOOST_PAIR_PIECEWISE_CONSTRUCT_BOOST_TUPLE_CODE(N,M)\
|
||||
template< template<class, class, class, class, class, class, class, class, class, class> class BoostTuple \
|
||||
|
@@ -920,7 +920,7 @@ class tree
|
||||
//No throw insertion part, release rollback
|
||||
destroy_deallocator.release();
|
||||
return std::pair<iterator,bool>
|
||||
( iterator(iiterator(this->icont().insert_unique_commit(*p, data)))
|
||||
( iterator(this->icont().insert_unique_commit(*p, data))
|
||||
, true );
|
||||
}
|
||||
|
||||
@@ -935,7 +935,7 @@ class tree
|
||||
Destroyer(this->node_alloc())(p);
|
||||
return ret.first;
|
||||
}
|
||||
return iterator(iiterator(this->icont().insert_unique_commit(*p, data)));
|
||||
return iterator(this->icont().insert_unique_commit(*p, data));
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -971,6 +971,22 @@ class tree
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <class KeyType, class... Args>
|
||||
BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> try_emplace
|
||||
(const_iterator hint, BOOST_FWD_REF(KeyType) key, BOOST_FWD_REF(Args)... args)
|
||||
{
|
||||
insert_commit_data data;
|
||||
const key_type & k = key; //Support emulated rvalue references
|
||||
std::pair<iiterator, bool> ret =
|
||||
hint == const_iterator() ? this->icont().insert_unique_check( k, KeyNodeCompare(value_comp()), data)
|
||||
: this->icont().insert_unique_check(hint.get(), k, KeyNodeCompare(value_comp()), data);
|
||||
if(ret.second){
|
||||
ret.first = this->icont().insert_unique_commit
|
||||
(*AllocHolder::create_node(try_emplace_t(), boost::forward<KeyType>(key), boost::forward<Args>(args)...), data);
|
||||
}
|
||||
return std::pair<iterator, bool>(iterator(ret.first), ret.second);
|
||||
}
|
||||
|
||||
#else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
#define BOOST_CONTAINER_TREE_EMPLACE_CODE(N) \
|
||||
@@ -1002,6 +1018,22 @@ class tree
|
||||
destroy_deallocator.release();\
|
||||
return ret;\
|
||||
}\
|
||||
\
|
||||
template <class KeyType BOOST_MOVE_I##N BOOST_MOVE_CLASS##N>\
|
||||
BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool>\
|
||||
try_emplace(const_iterator hint, BOOST_FWD_REF(KeyType) key BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
|
||||
{\
|
||||
insert_commit_data data;\
|
||||
const key_type & k = key;\
|
||||
std::pair<iiterator, bool> ret =\
|
||||
hint == const_iterator() ? this->icont().insert_unique_check( k, KeyNodeCompare(value_comp()), data)\
|
||||
: this->icont().insert_unique_check(hint.get(), k, KeyNodeCompare(value_comp()), data);\
|
||||
if(ret.second){\
|
||||
ret.first = this->icont().insert_unique_commit\
|
||||
(*AllocHolder::create_node(try_emplace_t(), boost::forward<KeyType>(key) BOOST_MOVE_I##N BOOST_MOVE_FWD##N), data);\
|
||||
}\
|
||||
return std::pair<iterator, bool>(iterator(ret.first), ret.second);\
|
||||
}\
|
||||
//
|
||||
BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_TREE_EMPLACE_CODE)
|
||||
#undef BOOST_CONTAINER_TREE_EMPLACE_CODE
|
||||
|
@@ -621,8 +621,7 @@ class flat_map
|
||||
{
|
||||
return container_detail::force_copy< std::pair<iterator, bool> >
|
||||
(this->m_flat_tree.insert_or_assign
|
||||
( container_detail::force_copy<impl_const_iterator>(const_iterator())
|
||||
, k, ::boost::forward<M>(obj))
|
||||
( impl_const_iterator(), k, ::boost::forward<M>(obj))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -643,8 +642,7 @@ class flat_map
|
||||
{
|
||||
return container_detail::force_copy< std::pair<iterator, bool> >
|
||||
(this->m_flat_tree.insert_or_assign
|
||||
( container_detail::force_copy<impl_const_iterator>(const_iterator())
|
||||
, ::boost::move(k), ::boost::forward<M>(obj))
|
||||
( impl_const_iterator(), ::boost::move(k), ::boost::forward<M>(obj))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -784,6 +782,79 @@ class flat_map
|
||||
, boost::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
//! <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
|
||||
//! 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
|
||||
//! insertion took place. The returned iterator points to the map element whose key is equivalent to k.
|
||||
//!
|
||||
//! <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 container_detail::force_copy< std::pair<iterator, bool> >(
|
||||
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,
|
||||
//! 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
|
||||
//! 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>Complexity</b>: Logarithmic in general, but amortized constant if value
|
||||
//! is inserted right before p.
|
||||
template <class... Args>
|
||||
BOOST_CONTAINER_FORCEINLINE iterator try_emplace(const_iterator hint, const key_type &k, BOOST_FWD_REF(Args)... args)
|
||||
{
|
||||
return container_detail::force_copy<iterator>(m_flat_tree.try_emplace
|
||||
(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,
|
||||
//! 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
|
||||
//! 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
|
||||
//! insertion took place. The returned iterator points to the map element whose key is equivalent to k.
|
||||
//!
|
||||
//! <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 container_detail::force_copy< std::pair<iterator, bool> >
|
||||
(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,
|
||||
//! 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
|
||||
//! 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>Complexity</b>: Logarithmic in general, but amortized constant if value
|
||||
//! is inserted right before p.
|
||||
template <class... Args>
|
||||
BOOST_CONTAINER_FORCEINLINE iterator try_emplace(const_iterator hint, BOOST_RV_REF(key_type) k, BOOST_FWD_REF(Args)... args)
|
||||
{
|
||||
return container_detail::force_copy<iterator>
|
||||
(m_flat_tree.try_emplace(container_detail::force_copy
|
||||
<impl_const_iterator>(hint), boost::move(k), boost::forward<Args>(args)...).first);
|
||||
}
|
||||
|
||||
#else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
#define BOOST_CONTAINER_FLAT_MAP_EMPLACE_CODE(N) \
|
||||
@@ -800,6 +871,29 @@ class flat_map
|
||||
return container_detail::force_copy<iterator>(m_flat_tree.emplace_hint_unique\
|
||||
(container_detail::force_copy<impl_const_iterator>(hint) BOOST_MOVE_I##N BOOST_MOVE_FWD##N));\
|
||||
}\
|
||||
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
|
||||
BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> try_emplace(const key_type& k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
|
||||
{\
|
||||
return container_detail::force_copy< std::pair<iterator, bool> >\
|
||||
(m_flat_tree.try_emplace(impl_const_iterator(), k BOOST_MOVE_I##N BOOST_MOVE_FWD##N));\
|
||||
}\
|
||||
\
|
||||
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
|
||||
BOOST_CONTAINER_FORCEINLINE iterator try_emplace(const_iterator hint, const key_type &k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
|
||||
{ return container_detail::force_copy<iterator>(m_flat_tree.try_emplace\
|
||||
(container_detail::force_copy<impl_const_iterator>(hint), k BOOST_MOVE_I##N BOOST_MOVE_FWD##N).first); }\
|
||||
\
|
||||
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
|
||||
BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> try_emplace(BOOST_RV_REF(key_type) k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
|
||||
{\
|
||||
return container_detail::force_copy< std::pair<iterator, bool> >\
|
||||
(m_flat_tree.try_emplace(impl_const_iterator(), boost::move(k) BOOST_MOVE_I##N BOOST_MOVE_FWD##N));\
|
||||
}\
|
||||
\
|
||||
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
|
||||
BOOST_CONTAINER_FORCEINLINE iterator try_emplace(const_iterator hint, BOOST_RV_REF(key_type) k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
|
||||
{ return container_detail::force_copy<iterator>(m_flat_tree.try_emplace\
|
||||
(container_detail::force_copy<impl_const_iterator>(hint), boost::move(k) BOOST_MOVE_I##N BOOST_MOVE_FWD##N).first); }\
|
||||
//
|
||||
BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_FLAT_MAP_EMPLACE_CODE)
|
||||
#undef BOOST_CONTAINER_FLAT_MAP_EMPLACE_CODE
|
||||
|
@@ -484,20 +484,20 @@ class map
|
||||
#endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
|
||||
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
|
||||
//! Effects: 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.
|
||||
//!
|
||||
//! Returns: 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.
|
||||
//!
|
||||
//! Complexity: Logarithmic.
|
||||
//! <b>Complexity<b>: Logarithmic.
|
||||
mapped_type& operator[](const key_type &k);
|
||||
|
||||
//! Effects: 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)
|
||||
//!
|
||||
//! Returns: 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.
|
||||
//!
|
||||
//! Complexity: 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 +507,7 @@ class map
|
||||
BOOST_MOVE_CONVERSION_AWARE_CATCH( operator[] , key_type, mapped_type&, this->priv_subscript)
|
||||
#endif
|
||||
|
||||
//! Effects: 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 +515,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.
|
||||
//!
|
||||
//! Returns: 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.
|
||||
//!
|
||||
//! Complexity: 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)); }
|
||||
|
||||
//! Effects: 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 +531,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.
|
||||
//!
|
||||
//! Returns: 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.
|
||||
//!
|
||||
//! Complexity: 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)); }
|
||||
|
||||
//! Effects: 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 +548,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.
|
||||
//!
|
||||
//! Returns: 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.
|
||||
//!
|
||||
//! Complexity: 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)); }
|
||||
|
||||
//! Effects: 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 +566,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.
|
||||
//!
|
||||
//! Returns: 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.
|
||||
//!
|
||||
//! Complexity: 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)); }
|
||||
|
||||
//! Returns: 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.
|
||||
//! Complexity: logarithmic.
|
||||
//! <b>Complexity<b>: logarithmic.
|
||||
T& at(const key_type& k)
|
||||
{
|
||||
iterator i = this->find(k);
|
||||
@@ -587,9 +587,9 @@ class map
|
||||
return i->second;
|
||||
}
|
||||
|
||||
//! Returns: 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.
|
||||
//! Complexity: logarithmic.
|
||||
//! <b>Complexity<b>: logarithmic.
|
||||
const T& at(const key_type& k) const
|
||||
{
|
||||
const_iterator i = this->find(k);
|
||||
@@ -764,6 +764,66 @@ 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,
|
||||
//! 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
|
||||
//! 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
|
||||
//! insertion took place. The returned iterator points to the map element whose key is equivalent to k.
|
||||
//!
|
||||
//! <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,
|
||||
//! 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
|
||||
//! 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>Complexity</b>: Logarithmic in general, but amortized constant if value
|
||||
//! is inserted right before p.
|
||||
template <class... Args>
|
||||
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,
|
||||
//! 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
|
||||
//! 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
|
||||
//! insertion took place. The returned iterator points to the map element whose key is equivalent to k.
|
||||
//!
|
||||
//! <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,
|
||||
//! 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
|
||||
//! 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>Complexity</b>: Logarithmic in general, but amortized constant if value
|
||||
//! is inserted right before p.
|
||||
template <class... Args>
|
||||
BOOST_CONTAINER_FORCEINLINE iterator try_emplace(const_iterator hint, BOOST_RV_REF(key_type) k, BOOST_FWD_REF(Args)... args)
|
||||
{ return this->base_t::try_emplace(hint, boost::move(k), boost::forward<Args>(args)...).first; }
|
||||
|
||||
#else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
|
||||
#define BOOST_CONTAINER_MAP_EMPLACE_CODE(N) \
|
||||
@@ -774,6 +834,22 @@ class map
|
||||
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
|
||||
BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
|
||||
{ return this->base_t::emplace_hint_unique(hint BOOST_MOVE_I##N BOOST_MOVE_FWD##N); }\
|
||||
\
|
||||
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
|
||||
BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> try_emplace(const key_type& k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
|
||||
{ return this->base_t::try_emplace(const_iterator(), k BOOST_MOVE_I##N BOOST_MOVE_FWD##N); }\
|
||||
\
|
||||
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
|
||||
BOOST_CONTAINER_FORCEINLINE iterator try_emplace(const_iterator hint, const key_type &k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
|
||||
{ return this->base_t::try_emplace(hint, k BOOST_MOVE_I##N BOOST_MOVE_FWD##N).first; }\
|
||||
\
|
||||
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
|
||||
BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> try_emplace(BOOST_RV_REF(key_type) k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
|
||||
{ return this->base_t::try_emplace(const_iterator(), boost::move(k) BOOST_MOVE_I##N BOOST_MOVE_FWD##N); }\
|
||||
\
|
||||
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
|
||||
BOOST_CONTAINER_FORCEINLINE iterator try_emplace(const_iterator hint, BOOST_RV_REF(key_type) k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
|
||||
{ return this->base_t::try_emplace(hint, boost::move(k) BOOST_MOVE_I##N BOOST_MOVE_FWD##N).first; }\
|
||||
//
|
||||
BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_MAP_EMPLACE_CODE)
|
||||
#undef BOOST_CONTAINER_MAP_EMPLACE_CODE
|
||||
|
@@ -726,6 +726,75 @@ int map_test()
|
||||
if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
|
||||
}
|
||||
|
||||
{ //try_emplace
|
||||
boostmap.clear();
|
||||
boostmultimap.clear();
|
||||
stdmap.clear();
|
||||
stdmultimap.clear();
|
||||
|
||||
IntPairType aux_vect[max];
|
||||
for(int i = 0; i < max; ++i){
|
||||
IntType i1(i);
|
||||
IntType i2(i);
|
||||
new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
|
||||
}
|
||||
|
||||
IntPairType aux_vect2[max];
|
||||
for(int i = 0; i < max; ++i){
|
||||
IntType i1(i);
|
||||
IntType i2(max-i);
|
||||
new(&aux_vect2[i])IntPairType(boost::move(i1), boost::move(i2));
|
||||
}
|
||||
|
||||
typedef typename MyBoostMap::iterator iterator;
|
||||
for(int i = 0; i < max; ++i){
|
||||
iterator it;
|
||||
if(i&1){
|
||||
std::pair<typename MyBoostMap::iterator, bool> ret =
|
||||
boostmap.try_emplace(boost::move(aux_vect[i].first), boost::move(aux_vect[i].second));
|
||||
if(!ret.second)
|
||||
return 1;
|
||||
it = ret.first;
|
||||
}
|
||||
else{
|
||||
it = boostmap.try_emplace
|
||||
(boostmap.upper_bound(aux_vect[i].first), boost::move(aux_vect[i].first), boost::move(aux_vect[i].second));
|
||||
}
|
||||
if(boostmap.end() == it || it->first != aux_vect2[i].first || it->second != aux_vect2[i].first){
|
||||
return 1;
|
||||
}
|
||||
stdmap[i] = i;
|
||||
}
|
||||
|
||||
if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
|
||||
if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
|
||||
|
||||
for(int i = 0; i < max; ++i){
|
||||
iterator it;
|
||||
iterator itex = boostmap.find(aux_vect2[i].first);
|
||||
if(itex == boostmap.end())
|
||||
return 1;
|
||||
if(i&1){
|
||||
std::pair<typename MyBoostMap::iterator, bool> ret =
|
||||
boostmap.try_emplace(boost::move(aux_vect2[i].first), boost::move(aux_vect2[i].second));
|
||||
if(ret.second)
|
||||
return 1;
|
||||
it = ret.first;
|
||||
}
|
||||
else{
|
||||
it = boostmap.try_emplace
|
||||
(boostmap.upper_bound(aux_vect2[i].first), boost::move(aux_vect2[i].first), boost::move(aux_vect2[i].second));
|
||||
}
|
||||
const IntType test_int(i);
|
||||
if(boostmap.end() == it || it != itex || it->second != test_int){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
|
||||
if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
|
||||
}
|
||||
|
||||
if(map_test_copyable<MyBoostMap, MyStdMap, MyBoostMultiMap, MyStdMultiMap>
|
||||
(container_detail::bool_<boost::container::test::is_copyable<IntType>::value>())){
|
||||
return 1;
|
||||
@@ -740,33 +809,33 @@ bool test_map_support_for_initialization_list_for()
|
||||
const std::initializer_list<std::pair<typename MapType::value_type::first_type, typename MapType::mapped_type>> il
|
||||
= { std::make_pair(1, 2), std::make_pair(3, 4) };
|
||||
|
||||
const MapType expected(il.begin(), il.end());
|
||||
const MapType expected_map(il.begin(), il.end());
|
||||
{
|
||||
const MapType sil = il;
|
||||
if (sil != expected)
|
||||
if (sil != expected_map)
|
||||
return false;
|
||||
|
||||
MapType sila(il, typename MapType::allocator_type());
|
||||
if (sila != expected)
|
||||
if (sila != expected_map)
|
||||
return false;
|
||||
|
||||
MapType silca(il, typename MapType::key_compare(), typename MapType::allocator_type());
|
||||
if (silca != expected)
|
||||
if (silca != expected_map)
|
||||
return false;
|
||||
|
||||
const MapType sil_ordered(ordered_unique_range, il);
|
||||
if (sil_ordered != expected)
|
||||
if (sil_ordered != expected_map)
|
||||
return false;
|
||||
|
||||
MapType sil_assign = { std::make_pair(99, 100) };
|
||||
sil_assign = il;
|
||||
if (sil_assign != expected)
|
||||
if (sil_assign != expected_map)
|
||||
return false;
|
||||
}
|
||||
{
|
||||
MapType sil;
|
||||
sil.insert(il);
|
||||
if (sil != expected)
|
||||
if (sil != expected_map)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
Reference in New Issue
Block a user