Implemented LWG Issue #149 (range insertion now returns an iterator) & cleaned up insertion code in most containers

[SVN r80348]
This commit is contained in:
Ion Gaztañaga
2012-09-01 11:01:03 +00:00
parent 011f1fb181
commit 3c256c2282
29 changed files with 1659 additions and 1476 deletions
+124 -156
View File
@@ -943,14 +943,18 @@ class deque : protected deque_base<T, A>
//! throws or T's constructor taking an dereferenced InIt throws.
//!
//! <b>Complexity</b>: Linear to the range [first, last).
template <class InpIt>
deque(InpIt first, InpIt last, const allocator_type& a = allocator_type())
template <class InIt>
deque(InIt first, InIt last, const allocator_type& a = allocator_type()
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, typename container_detail::enable_if_c
< !container_detail::is_convertible<InIt, size_type>::value
>::type * = 0
#endif
)
: Base(a)
{
//Dispatch depending on integer/iterator
const bool aux_boolean = container_detail::is_convertible<InpIt, size_type>::value;
typedef container_detail::bool_<aux_boolean> Result;
this->priv_initialize_dispatch(first, last, Result());
typedef typename std::iterator_traits<InIt>::iterator_category ItCat;
this->priv_range_initialize(first, last, ItCat());
}
//! <b>Effects</b>: Destroys the deque. All stored values are destroyed
@@ -1043,23 +1047,61 @@ class deque : protected deque_base<T, A>
//!
//! <b>Complexity</b>: Linear to n.
void assign(size_type n, const T& val)
{ this->priv_fill_assign(n, val); }
{
typedef constant_iterator<value_type, difference_type> c_it;
this->assign(c_it(val, n), c_it());
}
//! <b>Effects</b>: Assigns the the range [first, last) to *this.
//!
//! <b>Throws</b>: If memory allocation throws or
//! T's constructor from dereferencing InpIt throws.
//! T's constructor from dereferencing InIt throws.
//!
//! <b>Complexity</b>: Linear to n.
template <class InpIt>
void assign(InpIt first, InpIt last)
template <class InIt>
void assign(InIt first, InIt last
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, typename container_detail::enable_if_c
< !container_detail::is_convertible<InIt, size_type>::value
&& container_detail::is_input_iterator<InIt>::value
>::type * = 0
#endif
)
{
//Dispatch depending on integer/iterator
const bool aux_boolean = container_detail::is_convertible<InpIt, size_type>::value;
typedef container_detail::bool_<aux_boolean> Result;
this->priv_assign_dispatch(first, last, Result());
iterator cur = begin();
for ( ; first != last && cur != end(); ++cur, ++first){
*cur = *first;
}
if (first == last){
this->erase(cur, cend());
}
else{
this->insert(cend(), first, last);
}
}
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
template <class FwdIt>
void assign(FwdIt first, FwdIt last
, typename container_detail::enable_if_c
< !container_detail::is_convertible<FwdIt, size_type>::value
&& !container_detail::is_input_iterator<FwdIt>::value
>::type * = 0
)
{
const size_type len = std::distance(first, last);
if (len > size()) {
FwdIt mid = first;
std::advance(mid, size());
boost::copy_or_move(first, mid, begin());
this->insert(cend(), mid, last);
}
else{
this->erase(boost::copy_or_move(first, last, begin()), cend());
}
}
#endif
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! <b>Effects</b>: Inserts a copy of x at the end of the deque.
//!
@@ -1142,6 +1184,8 @@ class deque : protected deque_base<T, A>
//!
//! <b>Effects</b>: Insert a copy of x before position.
//!
//! <b>Returns</b>: an iterator to the inserted element.
//!
//! <b>Throws</b>: If memory allocation throws or x's copy constructor throws.
//!
//! <b>Complexity</b>: If position is end(), amortized constant time
@@ -1152,6 +1196,8 @@ class deque : protected deque_base<T, A>
//!
//! <b>Effects</b>: Insert a new element before position with mx's resources.
//!
//! <b>Returns</b>: an iterator to the inserted element.
//!
//! <b>Throws</b>: If memory allocation throws.
//!
//! <b>Complexity</b>: If position is end(), amortized constant time
@@ -1165,29 +1211,63 @@ class deque : protected deque_base<T, A>
//!
//! <b>Effects</b>: Insert n copies of x before pos.
//!
//! <b>Returns</b>: an iterator to the first inserted element or pos if n is 0.
//!
//! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
//!
//! <b>Complexity</b>: Linear to n.
void insert(const_iterator pos, size_type n, const value_type& x)
{ this->priv_fill_insert(pos, n, x); }
iterator insert(const_iterator pos, size_type n, const value_type& x)
{
typedef constant_iterator<value_type, difference_type> c_it;
return this->insert(pos, c_it(x, n), c_it());
}
//! <b>Requires</b>: pos must be a valid iterator of *this.
//!
//! <b>Effects</b>: Insert a copy of the [first, last) range before pos.
//!
//! <b>Returns</b>: an iterator to the first inserted element or pos if first == last.
//!
//! <b>Throws</b>: If memory allocation throws, T's constructor from a
//! dereferenced InpIt throws or T's copy constructor throws.
//! dereferenced InIt throws or T's copy constructor throws.
//!
//! <b>Complexity</b>: Linear to std::distance [first, last).
template <class InpIt>
void insert(const_iterator pos, InpIt first, InpIt last)
template <class InIt>
iterator insert(const_iterator pos, InIt first, InIt last
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, typename container_detail::enable_if_c
< !container_detail::is_convertible<InIt, size_type>::value
&& container_detail::is_input_iterator<InIt>::value
>::type * = 0
#endif
)
{
//Dispatch depending on integer/iterator
const bool aux_boolean = container_detail::is_convertible<InpIt, size_type>::value;
typedef container_detail::bool_<aux_boolean> Result;
this->priv_insert_dispatch(pos, first, last, Result());
size_type n = 0;
iterator it(pos);
for(;first != last; ++first, ++n){
it = this->emplace(it, *first);
++it;
}
it -= n;
return it;
}
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
template <class FwdIt>
iterator insert(const_iterator p, FwdIt first, FwdIt last
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, typename container_detail::enable_if_c
< !container_detail::is_convertible<FwdIt, size_type>::value
&& !container_detail::is_input_iterator<FwdIt>::value
>::type * = 0
#endif
)
{
container_detail::advanced_insert_aux_proxy<A, FwdIt, iterator> proxy(this->alloc(), first, last);
return priv_insert_aux_impl(p, (size_type)std::distance(first, last), proxy);
}
#endif
#if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! <b>Effects</b>: Inserts an object of type T constructed with
@@ -1257,11 +1337,9 @@ class deque : protected deque_base<T, A>
return (this->end()-1);
}
else{
size_type n = p - this->cbegin();
typedef container_detail::advanced_insert_aux_emplace<A, iterator, Args...> type;
type &&proxy = type(this->alloc(), boost::forward<Args>(args)...);
this->priv_insert_aux_impl(p, 1, proxy);
return iterator(this->begin() + n);
return this->priv_insert_aux_impl(p, 1, proxy);
}
}
@@ -1320,12 +1398,10 @@ class deque : protected deque_base<T, A>
return (this->end()-1); \
} \
else{ \
size_type pos_num = p - this->cbegin(); \
container_detail::BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \
<A, iterator BOOST_PP_ENUM_TRAILING_PARAMS(n, P)> proxy \
(this->alloc() BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
this->priv_insert_aux_impl(p, 1, proxy); \
return iterator(this->begin() + pos_num); \
return this->priv_insert_aux_impl(p, 1, proxy); \
} \
} \
//!
@@ -1361,7 +1437,7 @@ class deque : protected deque_base<T, A>
if (new_size < len)
this->priv_erase_last_n(len - new_size);
else{
size_type n = new_size - this->size();
const size_type n = new_size - this->size();
container_detail::default_construct_aux_proxy<A, iterator> proxy(this->alloc(), n);
priv_insert_back_aux_impl(n, proxy);
}
@@ -1500,9 +1576,7 @@ class deque : protected deque_base<T, A>
return (end()-1);
}
else {
size_type n = position - cbegin();
this->priv_insert_aux(position, size_type(1), x);
return iterator(this->begin() + n);
return this->insert(position, size_type(1), x);
}
}
@@ -1517,10 +1591,7 @@ class deque : protected deque_base<T, A>
return(end()-1);
}
else {
//Just call more general insert(pos, size, value) and return iterator
size_type n = position - begin();
this->priv_insert_aux(position, move_it(r_iterator(mx, 1)), move_it(r_iterator()));
return iterator(this->begin() + n);
return this->insert(position, move_it(r_iterator(mx, 1)), move_it(r_iterator()));
}
}
@@ -1532,7 +1603,7 @@ class deque : protected deque_base<T, A>
this->priv_push_front_simple_commit();
}
else{
this->priv_insert_aux(cbegin(), size_type(1), t);
this->insert(cbegin(), size_type(1), t);
}
}
@@ -1544,7 +1615,7 @@ class deque : protected deque_base<T, A>
this->priv_push_front_simple_commit();
}
else{
this->priv_insert_aux(cbegin(), move_it(r_iterator(t, 1)), move_it(r_iterator()));
this->insert(cbegin(), move_it(r_iterator(t, 1)), move_it(r_iterator()));
}
}
@@ -1556,7 +1627,7 @@ class deque : protected deque_base<T, A>
this->priv_push_back_simple_commit();
}
else{
this->priv_insert_aux(cend(), size_type(1), t);
this->insert(cend(), size_type(1), t);
}
}
@@ -1568,7 +1639,7 @@ class deque : protected deque_base<T, A>
this->priv_push_back_simple_commit();
}
else{
this->priv_insert_aux(cend(), move_it(r_iterator(t, 1)), move_it(r_iterator()));
this->insert(cend(), move_it(r_iterator(t, 1)), move_it(r_iterator()));
}
}
@@ -1600,50 +1671,6 @@ class deque : protected deque_base<T, A>
void priv_push_front_simple_commit()
{ --this->members_.m_start.m_cur; }
template <class InpIt>
void priv_insert_aux(const_iterator pos, InpIt first, InpIt last, std::input_iterator_tag)
{
iterator it(pos);
for(;first != last; ++first){
it = this->emplace(it, *first);
++it;
}
}
template <class FwdIt>
void priv_insert_aux(const_iterator pos, FwdIt first, FwdIt last, std::forward_iterator_tag)
{ this->priv_insert_aux(pos, first, last); }
// assign(), a generalized assignment member function. Two
// versions: one that takes a count, and one that takes a range.
// The range version is a member template, so we dispatch on whether
// or not the type is an integer.
void priv_fill_assign(size_type n, const T& val)
{
if (n > size()) {
std::fill(begin(), end(), val);
this->insert(cend(), n - size(), val);
}
else {
this->erase(cbegin() + n, cend());
std::fill(begin(), end(), val);
}
}
template <class Integer>
void priv_initialize_dispatch(Integer n, Integer x, container_detail::true_)
{
this->priv_initialize_map(n);
this->priv_fill_initialize(x);
}
template <class InpIt>
void priv_initialize_dispatch(InpIt first, InpIt last, container_detail::false_)
{
typedef typename std::iterator_traits<InpIt>::iterator_category ItCat;
this->priv_range_initialize(first, last, ItCat());
}
void priv_destroy_range(iterator p, iterator p2)
{
for(;p != p2; ++p){
@@ -1664,71 +1691,10 @@ class deque : protected deque_base<T, A>
}
}
template <class Integer>
void priv_assign_dispatch(Integer n, Integer val, container_detail::true_)
{ this->priv_fill_assign((size_type) n, (value_type)val); }
template <class InpIt>
void priv_assign_dispatch(InpIt first, InpIt last, container_detail::false_)
{
typedef typename std::iterator_traits<InpIt>::iterator_category ItCat;
this->priv_assign_aux(first, last, ItCat());
}
template <class InpIt>
void priv_assign_aux(InpIt first, InpIt last, std::input_iterator_tag)
{
iterator cur = begin();
for ( ; first != last && cur != end(); ++cur, ++first)
*cur = *first;
if (first == last)
this->erase(cur, cend());
else
this->insert(cend(), first, last);
}
template <class FwdIt>
void priv_assign_aux(FwdIt first, FwdIt last, std::forward_iterator_tag)
{
size_type len = std::distance(first, last);
if (len > size()) {
FwdIt mid = first;
std::advance(mid, size());
boost::copy_or_move(first, mid, begin());
this->insert(cend(), mid, last);
}
else
this->erase(boost::copy_or_move(first, last, begin()), cend());
}
template <class Integer>
void priv_insert_dispatch(const_iterator pos, Integer n, Integer x, container_detail::true_)
{ this->priv_fill_insert(pos, (size_type) n, (value_type)x); }
template <class InpIt>
void priv_insert_dispatch(const_iterator pos,InpIt first, InpIt last, container_detail::false_)
{
typedef typename std::iterator_traits<InpIt>::iterator_category ItCat;
this->priv_insert_aux(pos, first, last, ItCat());
}
void priv_insert_aux(const_iterator pos, size_type n, const value_type& x)
{
typedef constant_iterator<value_type, difference_type> c_it;
this->priv_insert_aux(pos, c_it(x, n), c_it());
}
//Just forward all operations to priv_insert_aux_impl
template <class FwdIt>
void priv_insert_aux(const_iterator p, FwdIt first, FwdIt last)
{
container_detail::advanced_insert_aux_proxy<A, FwdIt, iterator> proxy(this->alloc(), first, last);
priv_insert_aux_impl(p, (size_type)std::distance(first, last), proxy);
}
void priv_insert_aux_impl(const_iterator p, size_type n, advanced_insert_aux_int_t &interf)
iterator priv_insert_aux_impl(const_iterator p, size_type n, advanced_insert_aux_int_t &interf)
{
iterator pos(p);
const size_type pos_n = p - this->cbegin();
if(!this->members_.m_map){
this->priv_initialize_map(0);
pos = this->begin();
@@ -1782,9 +1748,10 @@ class deque : protected deque_base<T, A>
interf.copy_remaining_to(pos);
}
}
return this->begin() + pos_n;
}
void priv_insert_back_aux_impl(size_type n, advanced_insert_aux_int_t &interf)
iterator priv_insert_back_aux_impl(size_type n, advanced_insert_aux_int_t &interf)
{
if(!this->members_.m_map){
this->priv_initialize_map(0);
@@ -1794,9 +1761,10 @@ class deque : protected deque_base<T, A>
iterator old_finish = this->members_.m_finish;
interf.uninitialized_copy_some_and_update(old_finish, n, true);
this->members_.m_finish = new_finish;
return iterator(this->members_.m_finish - n);
}
void priv_insert_front_aux_impl(size_type n, advanced_insert_aux_int_t &interf)
iterator priv_insert_front_aux_impl(size_type n, advanced_insert_aux_int_t &interf)
{
if(!this->members_.m_map){
this->priv_initialize_map(0);
@@ -1805,13 +1773,13 @@ class deque : protected deque_base<T, A>
iterator new_start = this->priv_reserve_elements_at_front(n);
interf.uninitialized_copy_some_and_update(new_start, difference_type(n), true);
this->members_.m_start = new_start;
return new_start;
}
void priv_fill_insert(const_iterator pos, size_type n, const value_type& x)
iterator priv_fill_insert(const_iterator pos, size_type n, const value_type& x)
{
typedef constant_iterator<value_type, difference_type> c_it;
this->insert(pos, c_it(x, n), c_it());
return this->insert(pos, c_it(x, n), c_it());
}
// Precondition: this->members_.m_start and this->members_.m_finish have already been initialized,
@@ -1834,13 +1802,13 @@ class deque : protected deque_base<T, A>
BOOST_CATCH_END
}
template <class InpIt>
void priv_range_initialize(InpIt first, InpIt last, std::input_iterator_tag)
template <class InIt>
void priv_range_initialize(InIt first, InIt last, std::input_iterator_tag)
{
this->priv_initialize_map(0);
BOOST_TRY {
for ( ; first != last; ++first)
this->push_back(*first);
this->emplace_back(*first);
}
BOOST_CATCH(...){
this->clear();