Implemented missing try_emplace member for maps.

This commit is contained in:
Ion Gaztañaga
2016-08-26 01:47:32 +02:00
parent 6d2321a950
commit 1467c51a4e
7 changed files with 374 additions and 37 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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