mirror of
https://github.com/boostorg/container.git
synced 2025-08-02 14:04:26 +02:00
Implemented P0084R2 (Emplace Return Type)
This commit is contained in:
@@ -1234,6 +1234,8 @@ use [*Boost.Container]? There are several reasons for that:
|
||||
* Implemented C++17 `insert_or_assign`/`try_emplace` for [classref boost::container::map map] and [classref boost::container::flat_map flat_map].
|
||||
* Implemented C++17 `extract`/`insert(node)` for [classref boost::container::map map], [classref boost::container::multimap multimap],
|
||||
[classref boost::container::set set], [classref boost::container::multiset multiset].
|
||||
* Implemented C++17's [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0084r2.pdf P0084R2 Emplace Return Type]
|
||||
in `deque`, `vector`, `stable_vector`, `small_vector`, `static_vector`, `list` and `slist`.
|
||||
|
||||
[endsect]
|
||||
|
||||
|
@@ -1348,44 +1348,52 @@ class deque : protected deque_base<Allocator>
|
||||
//! <b>Effects</b>: Inserts an object of type T constructed with
|
||||
//! std::forward<Args>(args)... in the beginning of the deque.
|
||||
//!
|
||||
//! <b>Returns</b>: A reference to the created object.
|
||||
//!
|
||||
//! <b>Throws</b>: If memory allocation throws or the in-place constructor throws.
|
||||
//!
|
||||
//! <b>Complexity</b>: Amortized constant time
|
||||
template <class... Args>
|
||||
void emplace_front(BOOST_FWD_REF(Args)... args)
|
||||
reference emplace_front(BOOST_FWD_REF(Args)... args)
|
||||
{
|
||||
if(this->priv_push_front_simple_available()){
|
||||
reference r = *this->priv_push_front_simple_pos();
|
||||
allocator_traits_type::construct
|
||||
( this->alloc()
|
||||
, this->priv_push_front_simple_pos()
|
||||
, boost::forward<Args>(args)...);
|
||||
this->priv_push_front_simple_commit();
|
||||
return r;
|
||||
}
|
||||
else{
|
||||
typedef container_detail::insert_nonmovable_emplace_proxy<Allocator, iterator, Args...> type;
|
||||
this->priv_insert_front_aux_impl(1, type(boost::forward<Args>(args)...));
|
||||
return *this->priv_insert_front_aux_impl(1, type(boost::forward<Args>(args)...));
|
||||
}
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Inserts an object of type T constructed with
|
||||
//! std::forward<Args>(args)... in the end of the deque.
|
||||
//!
|
||||
//! <b>Returns</b>: A reference to the created object.
|
||||
//!
|
||||
//! <b>Throws</b>: If memory allocation throws or the in-place constructor throws.
|
||||
//!
|
||||
//! <b>Complexity</b>: Amortized constant time
|
||||
template <class... Args>
|
||||
void emplace_back(BOOST_FWD_REF(Args)... args)
|
||||
reference emplace_back(BOOST_FWD_REF(Args)... args)
|
||||
{
|
||||
if(this->priv_push_back_simple_available()){
|
||||
reference r = *this->priv_push_back_simple_pos();
|
||||
allocator_traits_type::construct
|
||||
( this->alloc()
|
||||
, this->priv_push_back_simple_pos()
|
||||
, boost::forward<Args>(args)...);
|
||||
this->priv_push_back_simple_commit();
|
||||
return r;
|
||||
}
|
||||
else{
|
||||
typedef container_detail::insert_nonmovable_emplace_proxy<Allocator, iterator, Args...> type;
|
||||
this->priv_insert_back_aux_impl(1, type(boost::forward<Args>(args)...));
|
||||
return *this->priv_insert_back_aux_impl(1, type(boost::forward<Args>(args)...));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1420,32 +1428,36 @@ class deque : protected deque_base<Allocator>
|
||||
|
||||
#define BOOST_CONTAINER_DEQUE_EMPLACE_CODE(N) \
|
||||
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N\
|
||||
void emplace_front(BOOST_MOVE_UREF##N)\
|
||||
reference emplace_front(BOOST_MOVE_UREF##N)\
|
||||
{\
|
||||
if(priv_push_front_simple_available()){\
|
||||
reference r = *this->priv_push_front_simple_pos();\
|
||||
allocator_traits_type::construct\
|
||||
( this->alloc(), this->priv_push_front_simple_pos() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
|
||||
priv_push_front_simple_commit();\
|
||||
return r;\
|
||||
}\
|
||||
else{\
|
||||
typedef container_detail::insert_nonmovable_emplace_proxy##N\
|
||||
<Allocator, iterator BOOST_MOVE_I##N BOOST_MOVE_TARG##N> type;\
|
||||
priv_insert_front_aux_impl(1, type(BOOST_MOVE_FWD##N));\
|
||||
return *priv_insert_front_aux_impl(1, type(BOOST_MOVE_FWD##N));\
|
||||
}\
|
||||
}\
|
||||
\
|
||||
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N\
|
||||
void emplace_back(BOOST_MOVE_UREF##N)\
|
||||
reference emplace_back(BOOST_MOVE_UREF##N)\
|
||||
{\
|
||||
if(priv_push_back_simple_available()){\
|
||||
reference r = *this->priv_push_back_simple_pos();\
|
||||
allocator_traits_type::construct\
|
||||
( this->alloc(), this->priv_push_back_simple_pos() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
|
||||
priv_push_back_simple_commit();\
|
||||
return r;\
|
||||
}\
|
||||
else{\
|
||||
typedef container_detail::insert_nonmovable_emplace_proxy##N\
|
||||
<Allocator, iterator BOOST_MOVE_I##N BOOST_MOVE_TARG##N> type;\
|
||||
priv_insert_back_aux_impl(1, type(BOOST_MOVE_FWD##N));\
|
||||
return *priv_insert_back_aux_impl(1, type(BOOST_MOVE_FWD##N));\
|
||||
}\
|
||||
}\
|
||||
\
|
||||
|
@@ -709,24 +709,28 @@ class list
|
||||
//! <b>Effects</b>: Inserts an object of type T constructed with
|
||||
//! std::forward<Args>(args)... in the end of the list.
|
||||
//!
|
||||
//! <b>Returns</b>: A reference to the created object.
|
||||
//!
|
||||
//! <b>Throws</b>: If memory allocation throws or
|
||||
//! T's in-place constructor throws.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
template <class... Args>
|
||||
void emplace_back(BOOST_FWD_REF(Args)... args)
|
||||
{ this->emplace(this->cend(), boost::forward<Args>(args)...); }
|
||||
reference emplace_back(BOOST_FWD_REF(Args)... args)
|
||||
{ return *this->emplace(this->cend(), boost::forward<Args>(args)...); }
|
||||
|
||||
//! <b>Effects</b>: Inserts an object of type T constructed with
|
||||
//! std::forward<Args>(args)... in the beginning of the list.
|
||||
//!
|
||||
//! <b>Returns</b>: A reference to the created object.
|
||||
//!
|
||||
//! <b>Throws</b>: If memory allocation throws or
|
||||
//! T's in-place constructor throws.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant
|
||||
template <class... Args>
|
||||
void emplace_front(BOOST_FWD_REF(Args)... args)
|
||||
{ this->emplace(this->cbegin(), boost::forward<Args>(args)...); }
|
||||
reference emplace_front(BOOST_FWD_REF(Args)... args)
|
||||
{ return *this->emplace(this->cbegin(), boost::forward<Args>(args)...); }
|
||||
|
||||
//! <b>Effects</b>: Inserts an object of type T constructed with
|
||||
//! std::forward<Args>(args)... before p.
|
||||
@@ -747,12 +751,12 @@ class list
|
||||
|
||||
#define BOOST_CONTAINER_LIST_EMPLACE_CODE(N) \
|
||||
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
|
||||
void emplace_back(BOOST_MOVE_UREF##N)\
|
||||
{ this->emplace(this->cend() BOOST_MOVE_I##N BOOST_MOVE_FWD##N); }\
|
||||
reference emplace_back(BOOST_MOVE_UREF##N)\
|
||||
{ return *this->emplace(this->cend() BOOST_MOVE_I##N BOOST_MOVE_FWD##N); }\
|
||||
\
|
||||
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
|
||||
void emplace_front(BOOST_MOVE_UREF##N)\
|
||||
{ this->emplace(this->cbegin() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);}\
|
||||
reference emplace_front(BOOST_MOVE_UREF##N)\
|
||||
{ return *this->emplace(this->cbegin() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);}\
|
||||
\
|
||||
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
|
||||
iterator emplace(const_iterator position BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
|
||||
|
@@ -714,13 +714,15 @@ class slist
|
||||
//! <b>Effects</b>: Inserts an object of type T constructed with
|
||||
//! std::forward<Args>(args)... in the front of the list
|
||||
//!
|
||||
//! <b>Returns</b>: A reference to the created object.
|
||||
//!
|
||||
//! <b>Throws</b>: If memory allocation throws or
|
||||
//! T's copy constructor throws.
|
||||
//!
|
||||
//! <b>Complexity</b>: Amortized constant time.
|
||||
template <class... Args>
|
||||
void emplace_front(BOOST_FWD_REF(Args)... args)
|
||||
{ this->emplace_after(this->cbefore_begin(), boost::forward<Args>(args)...); }
|
||||
reference emplace_front(BOOST_FWD_REF(Args)... args)
|
||||
{ return *this->emplace_after(this->cbefore_begin(), boost::forward<Args>(args)...); }
|
||||
|
||||
//! <b>Effects</b>: Inserts an object of type T constructed with
|
||||
//! std::forward<Args>(args)... after prev
|
||||
@@ -740,8 +742,8 @@ class slist
|
||||
|
||||
#define BOOST_CONTAINER_SLIST_EMPLACE_CODE(N) \
|
||||
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
|
||||
void emplace_front(BOOST_MOVE_UREF##N)\
|
||||
{ this->emplace_after(this->cbefore_begin() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);}\
|
||||
reference emplace_front(BOOST_MOVE_UREF##N)\
|
||||
{ return *this->emplace_after(this->cbefore_begin() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);}\
|
||||
\
|
||||
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
|
||||
iterator emplace_after(const_iterator p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
|
||||
|
@@ -1374,16 +1374,18 @@ class stable_vector
|
||||
//! <b>Effects</b>: Inserts an object of type T constructed with
|
||||
//! std::forward<Args>(args)... in the end of the stable_vector.
|
||||
//!
|
||||
//! <b>Returns</b>: A reference to the created object.
|
||||
//!
|
||||
//! <b>Throws</b>: If memory allocation throws or the in-place constructor throws.
|
||||
//!
|
||||
//! <b>Complexity</b>: Amortized constant time.
|
||||
template<class ...Args>
|
||||
void emplace_back(Args &&...args)
|
||||
reference emplace_back(Args &&...args)
|
||||
{
|
||||
typedef emplace_functor<Args...> EmplaceFunctor;
|
||||
typedef emplace_iterator<value_type, EmplaceFunctor, difference_type> EmplaceIterator;
|
||||
EmplaceFunctor &&ef = EmplaceFunctor(boost::forward<Args>(args)...);
|
||||
this->insert(this->cend(), EmplaceIterator(ef), EmplaceIterator());
|
||||
return *this->insert(this->cend(), EmplaceIterator(ef), EmplaceIterator());
|
||||
}
|
||||
|
||||
//! <b>Requires</b>: p must be a valid iterator of *this.
|
||||
@@ -1411,13 +1413,13 @@ class stable_vector
|
||||
|
||||
#define BOOST_CONTAINER_STABLE_VECTOR_EMPLACE_CODE(N) \
|
||||
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
|
||||
void emplace_back(BOOST_MOVE_UREF##N)\
|
||||
reference emplace_back(BOOST_MOVE_UREF##N)\
|
||||
{\
|
||||
typedef emplace_functor##N\
|
||||
BOOST_MOVE_LT##N BOOST_MOVE_TARG##N BOOST_MOVE_GT##N EmplaceFunctor;\
|
||||
typedef emplace_iterator<value_type, EmplaceFunctor, difference_type> EmplaceIterator;\
|
||||
EmplaceFunctor ef BOOST_MOVE_LP##N BOOST_MOVE_FWD##N BOOST_MOVE_RP##N;\
|
||||
this->insert(this->cend() , EmplaceIterator(ef), EmplaceIterator());\
|
||||
return *this->insert(this->cend() , EmplaceIterator(ef), EmplaceIterator());\
|
||||
}\
|
||||
\
|
||||
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
|
||||
|
@@ -677,6 +677,8 @@ public:
|
||||
//! @brief Inserts a Value constructed with
|
||||
//! \c std::forward<Args>(args)... in the end of the container.
|
||||
//!
|
||||
//! @return A reference to the created object.
|
||||
//!
|
||||
//! @param args The arguments of the constructor of the new element which will be created at the end of the container.
|
||||
//!
|
||||
//! @par Throws
|
||||
@@ -685,7 +687,7 @@ public:
|
||||
//! @par Complexity
|
||||
//! Constant O(1).
|
||||
template<class ...Args>
|
||||
void emplace_back(Args &&...args);
|
||||
reference emplace_back(Args &&...args);
|
||||
|
||||
//! @pre
|
||||
//! @li \c p must be a valid iterator of \c *this in range <tt>[begin(), end()]</tt>
|
||||
|
@@ -1724,21 +1724,24 @@ class vector
|
||||
//! <b>Effects</b>: Inserts an object of type T constructed with
|
||||
//! std::forward<Args>(args)... in the end of the vector.
|
||||
//!
|
||||
//! <b>Returns</b>: A reference to the created object.
|
||||
//!
|
||||
//! <b>Throws</b>: If memory allocation throws or the in-place constructor throws or
|
||||
//! T's copy/move constructor throws.
|
||||
//!
|
||||
//! <b>Complexity</b>: Amortized constant time.
|
||||
template<class ...Args>
|
||||
BOOST_CONTAINER_FORCEINLINE void emplace_back(BOOST_FWD_REF(Args)...args)
|
||||
BOOST_CONTAINER_FORCEINLINE reference emplace_back(BOOST_FWD_REF(Args)...args)
|
||||
{
|
||||
if (BOOST_LIKELY(this->room_enough())){
|
||||
//There is more memory, just construct a new object at the end
|
||||
allocator_traits_type::construct(this->m_holder.alloc(), this->priv_raw_end(), ::boost::forward<Args>(args)...);
|
||||
++this->m_holder.m_size;
|
||||
return *this->priv_raw_end();
|
||||
}
|
||||
else{
|
||||
typedef container_detail::insert_emplace_proxy<Allocator, T*, Args...> type;
|
||||
this->priv_forward_range_insert_no_capacity
|
||||
return *this->priv_forward_range_insert_no_capacity
|
||||
(this->back_ptr(), 1, type(::boost::forward<Args>(args)...), alloc_version());
|
||||
}
|
||||
}
|
||||
@@ -1787,16 +1790,17 @@ class vector
|
||||
|
||||
#define BOOST_CONTAINER_VECTOR_EMPLACE_CODE(N) \
|
||||
BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
|
||||
BOOST_CONTAINER_FORCEINLINE void emplace_back(BOOST_MOVE_UREF##N)\
|
||||
BOOST_CONTAINER_FORCEINLINE reference emplace_back(BOOST_MOVE_UREF##N)\
|
||||
{\
|
||||
if (BOOST_LIKELY(this->room_enough())){\
|
||||
allocator_traits_type::construct (this->m_holder.alloc()\
|
||||
, this->priv_raw_end() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
|
||||
++this->m_holder.m_size;\
|
||||
return *this->priv_raw_end();\
|
||||
}\
|
||||
else{\
|
||||
typedef container_detail::insert_emplace_proxy_arg##N<Allocator, T* BOOST_MOVE_I##N BOOST_MOVE_TARG##N> type;\
|
||||
this->priv_forward_range_insert_no_capacity\
|
||||
return *this->priv_forward_range_insert_no_capacity\
|
||||
( this->back_ptr(), 1, type(BOOST_MOVE_FWD##N), alloc_version());\
|
||||
}\
|
||||
}\
|
||||
|
@@ -175,14 +175,19 @@ bool test_emplace_back(container_detail::true_)
|
||||
new(&expected [4]) EmplaceInt(1, 2, 3, 4);
|
||||
new(&expected [5]) EmplaceInt(1, 2, 3, 4, 5);
|
||||
Container c;
|
||||
c.emplace_back();
|
||||
if(!test_expected_container(c, &expected[0], 1)){
|
||||
typedef typename Container::reference reference;
|
||||
{
|
||||
reference r = c.emplace_back();
|
||||
if(&r != &c.back() && !test_expected_container(c, &expected[0], 1)){
|
||||
return false;
|
||||
}
|
||||
c.emplace_back(1);
|
||||
if(!test_expected_container(c, &expected[0], 2)){
|
||||
}
|
||||
{
|
||||
reference r = c.emplace_back(1);
|
||||
if(&r != &c.back() && !test_expected_container(c, &expected[0], 2)){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
c.emplace_back(1, 2);
|
||||
if(!test_expected_container(c, &expected[0], 3)){
|
||||
return false;
|
||||
@@ -222,14 +227,19 @@ bool test_emplace_front(container_detail::true_)
|
||||
new(&expected [4]) EmplaceInt(1);
|
||||
new(&expected [5]) EmplaceInt();
|
||||
Container c;
|
||||
c.emplace_front();
|
||||
if(!test_expected_container(c, &expected[0] + 5, 1)){
|
||||
typedef typename Container::reference reference;
|
||||
{
|
||||
reference r = c.emplace_front();
|
||||
if(&r != &c.front() && !test_expected_container(c, &expected[0] + 5, 1)){
|
||||
return false;
|
||||
}
|
||||
c.emplace_front(1);
|
||||
if(!test_expected_container(c, &expected[0] + 4, 2)){
|
||||
}
|
||||
{
|
||||
reference r = c.emplace_front(1);
|
||||
if(&r != &c.front() && !test_expected_container(c, &expected[0] + 4, 2)){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
c.emplace_front(1, 2);
|
||||
if(!test_expected_container(c, &expected[0] + 3, 3)){
|
||||
return false;
|
||||
|
Reference in New Issue
Block a user