Add experimental (macro protected) support for lighter iterators

This commit is contained in:
Ion Gaztañaga
2024-04-16 11:36:04 +02:00
parent 03abe8c02c
commit 429024ca4e

View File

@@ -106,6 +106,10 @@ namespace dtl {
// [map, map + map_size).
// A pointer in the range [map, map + map_size) points to an allocated node
// if and only if the pointer is in the range [start.node, finish.node].
#define BOOST_CONTAINER_DEQUE_LIGHTER_ITERATOR_LEVEL 0
#if BOOST_CONTAINER_DEQUE_LIGHTER_ITERATOR_LEVEL == 0
template<class Pointer, bool IsConst>
class deque_iterator
{
@@ -241,15 +245,15 @@ class deque_iterator
if (!n)
return *this;
BOOST_ASSERT(!!m_cur);
difference_type offset = n + (this->m_cur - this->m_first);
const difference_type offset = n + (this->m_cur - this->m_first);
const difference_type block_size = m_last - m_first;
BOOST_ASSERT(block_size);
if (offset >= 0 && offset < block_size)
this->m_cur += difference_type(n);
else {
difference_type node_offset =
offset > 0 ? (offset / block_size)
: (-difference_type((-offset - 1) / block_size) - 1);
const difference_type node_offset =
offset > 0 ? (offset / block_size)
: (-difference_type((-offset - 1) / block_size) - 1);
this->priv_set_node(this->m_node + node_offset, size_type(block_size));
this->m_cur = this->m_first +
(offset - node_offset * block_size);
@@ -313,6 +317,447 @@ class deque_iterator
}
};
#elif BOOST_CONTAINER_DEQUE_LIGHTER_ITERATOR_LEVEL == 1
template<class Pointer, bool IsConst, unsigned BlockBytes, unsigned BlockSize>
class deque_iterator
{
public:
typedef std::random_access_iterator_tag iterator_category;
typedef typename boost::intrusive::pointer_traits<Pointer>::element_type value_type;
typedef typename boost::intrusive::pointer_traits<Pointer>::difference_type difference_type;
typedef typename boost::intrusive::pointer_traits<Pointer>::size_type size_type;
typedef typename if_c
< IsConst
, typename boost::intrusive::pointer_traits<Pointer>::template
rebind_pointer<const value_type>::type
, Pointer
>::type pointer;
typedef typename if_c
< IsConst
, const value_type&
, value_type&
>::type reference;
BOOST_CONSTEXPR inline static size_type get_block_size() BOOST_NOEXCEPT_OR_NOTHROW
{ return deque_block_size<value_type, BlockBytes, BlockSize>::value; }
BOOST_CONSTEXPR inline static difference_type get_block_ssize() BOOST_NOEXCEPT_OR_NOTHROW
{ return difference_type((get_block_size())); }
class nat;
typedef typename dtl::if_c< IsConst
, deque_iterator<Pointer, false, BlockBytes, BlockSize>
, nat>::type nonconst_iterator;
typedef Pointer val_alloc_ptr;
typedef typename boost::intrusive::pointer_traits<Pointer>::
template rebind_pointer<Pointer>::type index_pointer;
Pointer m_cur;
Pointer m_first;
index_pointer m_node;
public:
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline Pointer get_cur() const { return m_cur; }
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline Pointer get_first() const { return m_first; }
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline Pointer get_last() const { return m_first + get_block_ssize(); }
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline index_pointer get_node() const { return m_node; }
inline deque_iterator(val_alloc_ptr x, index_pointer y, difference_type ) BOOST_NOEXCEPT_OR_NOTHROW
: m_cur(x), m_first(*y), m_node(y)
{}
inline deque_iterator(val_alloc_ptr x, index_pointer y, size_type ) BOOST_NOEXCEPT_OR_NOTHROW
: m_cur(x), m_first(*y), m_node(y)
{}
inline deque_iterator() BOOST_NOEXCEPT_OR_NOTHROW
: m_cur(), m_first(), m_node() //Value initialization to achieve "null iterators" (N3644)
{}
inline deque_iterator(const deque_iterator& x) BOOST_NOEXCEPT_OR_NOTHROW
: m_cur(x.get_cur()), m_first(x.get_first()), m_node(x.get_node())
{}
inline deque_iterator(const nonconst_iterator& x) BOOST_NOEXCEPT_OR_NOTHROW
: m_cur(x.get_cur()), m_first(x.get_first()), m_node(x.get_node())
{}
inline deque_iterator(Pointer cur, Pointer first, index_pointer node) BOOST_NOEXCEPT_OR_NOTHROW
: m_cur(cur), m_first(first), m_node(node)
{}
inline deque_iterator& operator=(const deque_iterator& x) BOOST_NOEXCEPT_OR_NOTHROW
{ m_cur = x.get_cur(); m_first = x.get_first(); m_node = x.get_node(); return *this; }
inline nonconst_iterator unconst() const BOOST_NOEXCEPT_OR_NOTHROW
{
return nonconst_iterator(this->get_cur(), this->get_first(), this->get_node());
}
inline reference operator*() const BOOST_NOEXCEPT_OR_NOTHROW
{ return *this->m_cur; }
inline pointer operator->() const BOOST_NOEXCEPT_OR_NOTHROW
{ return this->m_cur; }
BOOST_CONTAINER_ATTRIBUTE_NODISCARD difference_type operator-(const deque_iterator& x) const BOOST_NOEXCEPT_OR_NOTHROW
{
if(!this->m_cur && !x.m_cur){
return 0;
}
const difference_type block_size = get_block_ssize();
BOOST_ASSERT(block_size);
return block_size * (this->m_node - x.m_node - 1) +
(this->m_cur - this->m_first) + ((x.m_first+block_size) - x.m_cur);
}
deque_iterator& operator++() BOOST_NOEXCEPT_OR_NOTHROW
{
BOOST_ASSERT(!!m_cur);
++this->m_cur;
const difference_type block_size = get_block_ssize();
if (this->m_cur == (this->m_first+block_size)) {
BOOST_ASSERT(block_size);
++this->m_node;
this->m_first = *this->m_node;
this->m_cur = this->m_first;
}
return *this;
}
inline deque_iterator operator++(int) BOOST_NOEXCEPT_OR_NOTHROW
{
deque_iterator tmp(*this);
++*this;
return tmp;
}
deque_iterator& operator--() BOOST_NOEXCEPT_OR_NOTHROW
{
BOOST_ASSERT(!!m_cur);
if (this->m_cur == this->m_first) {
--this->m_node;
this->m_first = *this->m_node;
this->m_cur = this->m_first + get_block_ssize();
}
--this->m_cur;
return *this;
}
inline deque_iterator operator--(int) BOOST_NOEXCEPT_OR_NOTHROW
{
deque_iterator tmp(*this);
--*this;
return tmp;
}
deque_iterator& operator+=(difference_type n) BOOST_NOEXCEPT_OR_NOTHROW
{
if (!n)
return *this;
BOOST_ASSERT(!!m_cur);
const difference_type offset = n + (this->m_cur - this->m_first);
const difference_type block_size = get_block_ssize();
BOOST_ASSERT(block_size);
if (offset >= 0 && offset < block_size)
this->m_cur += difference_type(n);
else {
const difference_type node_offset =
offset > 0 ? (offset / block_size)
: (-difference_type((-offset - 1) / block_size) - 1);
this->m_node += node_offset;
this->m_first = *this->m_node;
this->m_cur = this->m_first + (offset - node_offset * block_size);
}
return *this;
}
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
deque_iterator operator+(difference_type n) const BOOST_NOEXCEPT_OR_NOTHROW
{ deque_iterator tmp(*this); return tmp += n; }
inline
deque_iterator& operator-=(difference_type n) BOOST_NOEXCEPT_OR_NOTHROW
{ return *this += -n; }
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
deque_iterator operator-(difference_type n) const BOOST_NOEXCEPT_OR_NOTHROW
{ deque_iterator tmp(*this); return tmp -= n; }
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
reference operator[](difference_type n) const BOOST_NOEXCEPT_OR_NOTHROW
{ return *(*this + n); }
//Comparisons
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
friend bool operator==(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
{ return l.m_cur == r.m_cur; }
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
friend bool operator!=(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
{ return l.m_cur != r.m_cur; }
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
friend bool operator<(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
{ return (l.m_node == r.m_node) ? (l.m_cur < r.m_cur) : (l.m_node < r.m_node); }
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
friend bool operator>(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
{ return r < l; }
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
friend bool operator<=(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
{ return !(r < l); }
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
friend bool operator>=(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
{ return !(l < r); }
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
friend deque_iterator operator+(difference_type n, deque_iterator x) BOOST_NOEXCEPT_OR_NOTHROW
{ return x += n; }
inline void priv_set_node(index_pointer new_node, size_type ) BOOST_NOEXCEPT_OR_NOTHROW
{ return this->priv_set_node(new_node, difference_type()); }
inline void priv_set_node(index_pointer new_node, difference_type) BOOST_NOEXCEPT_OR_NOTHROW
{
this->m_node = new_node;
this->m_first = *new_node;
}
};
#elif BOOST_CONTAINER_DEQUE_LIGHTER_ITERATOR_LEVEL == 2
template<class Pointer, bool IsConst, unsigned BlockBytes, unsigned BlockSize>
class deque_iterator
{
public:
typedef std::random_access_iterator_tag iterator_category;
typedef typename boost::intrusive::pointer_traits<Pointer>::element_type value_type;
typedef typename boost::intrusive::pointer_traits<Pointer>::difference_type difference_type;
typedef typename boost::intrusive::pointer_traits<Pointer>::size_type size_type;
typedef typename if_c
< IsConst
, typename boost::intrusive::pointer_traits<Pointer>::template
rebind_pointer<const value_type>::type
, Pointer
>::type pointer;
typedef typename if_c
< IsConst
, const value_type&
, value_type&
>::type reference;
BOOST_CONSTEXPR inline static size_type get_block_size() BOOST_NOEXCEPT_OR_NOTHROW
{
BOOST_CONTAINER_STATIC_ASSERT((deque_block_size<value_type, BlockBytes, BlockSize>::value));
return deque_block_size<value_type, BlockBytes, BlockSize>::value;
}
BOOST_CONSTEXPR inline static difference_type get_block_ssize() BOOST_NOEXCEPT_OR_NOTHROW
{ return difference_type((get_block_size())); }
class nat;
typedef typename dtl::if_c< IsConst
, deque_iterator<Pointer, false, BlockBytes, BlockSize>
, nat>::type nonconst_iterator;
typedef Pointer val_alloc_ptr;
typedef typename boost::intrusive::pointer_traits<Pointer>::
template rebind_pointer<Pointer>::type index_pointer;
Pointer m_cur;
index_pointer m_node;
public:
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline Pointer get_cur() const { return m_cur; }
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline Pointer get_first() const { return *m_node; }
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline Pointer get_last() const { return *m_node + get_block_ssize(); }
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline index_pointer get_node() const { return m_node; }
inline deque_iterator(val_alloc_ptr x, index_pointer y, difference_type ) BOOST_NOEXCEPT_OR_NOTHROW
: m_cur(x), m_node(y)
{}
inline deque_iterator(val_alloc_ptr x, index_pointer y, size_type ) BOOST_NOEXCEPT_OR_NOTHROW
: m_cur(x), m_node(y)
{}
inline deque_iterator() BOOST_NOEXCEPT_OR_NOTHROW
: m_cur(), m_node() //Value initialization to achieve "null iterators" (N3644)
{}
inline deque_iterator(const deque_iterator& x) BOOST_NOEXCEPT_OR_NOTHROW
: m_cur(x.get_cur()), m_node(x.get_node())
{}
inline deque_iterator(const nonconst_iterator& x) BOOST_NOEXCEPT_OR_NOTHROW
: m_cur(x.get_cur()), m_node(x.get_node())
{}
inline deque_iterator(Pointer cur, index_pointer node) BOOST_NOEXCEPT_OR_NOTHROW
: m_cur(cur), m_node(node)
{}
inline deque_iterator& operator=(const deque_iterator& x) BOOST_NOEXCEPT_OR_NOTHROW
{ m_cur = x.get_cur(); m_node = x.get_node(); return *this; }
inline nonconst_iterator unconst() const BOOST_NOEXCEPT_OR_NOTHROW
{
return nonconst_iterator(this->get_cur(), this->get_node());
}
inline reference operator*() const BOOST_NOEXCEPT_OR_NOTHROW
{ return *this->m_cur; }
inline pointer operator->() const BOOST_NOEXCEPT_OR_NOTHROW
{ return this->m_cur; }
BOOST_CONTAINER_ATTRIBUTE_NODISCARD difference_type operator-(const deque_iterator& x) const BOOST_NOEXCEPT_OR_NOTHROW
{
if(!this->m_cur && !x.m_cur){
return 0;
}
const difference_type block_size = get_block_ssize();
BOOST_ASSERT(block_size);
return block_size * (this->m_node - x.m_node - 1) +
(this->m_cur - this->get_first()) + (x.get_last() - x.m_cur);
}
deque_iterator& operator++() BOOST_NOEXCEPT_OR_NOTHROW
{
BOOST_ASSERT(!!m_cur);
++this->m_cur;
if (this->m_cur == (this->get_last())) {
++this->m_node;
this->m_cur = *this->m_node;
}
return *this;
}
inline deque_iterator operator++(int) BOOST_NOEXCEPT_OR_NOTHROW
{
deque_iterator tmp(*this);
++*this;
return tmp;
}
deque_iterator& operator--() BOOST_NOEXCEPT_OR_NOTHROW
{
BOOST_ASSERT(!!m_cur);
if (this->m_cur == this->get_first()) {
--this->m_node;
this->m_cur = this->get_last();
}
--this->m_cur;
return *this;
}
inline deque_iterator operator--(int) BOOST_NOEXCEPT_OR_NOTHROW
{
deque_iterator tmp(*this);
--*this;
return tmp;
}
deque_iterator& operator+=(difference_type n) BOOST_NOEXCEPT_OR_NOTHROW
{
if (!n)
return *this;
BOOST_ASSERT(!!m_cur);
const difference_type offset = n + (this->m_cur - this->get_first());
const difference_type block_size = get_block_ssize();
BOOST_ASSERT(block_size);
if (offset >= 0 && offset < block_size)
this->m_cur += difference_type(n);
else {
const difference_type node_offset =
offset > 0 ? (offset / block_size)
: (-difference_type((-offset - 1) / block_size) - 1);
this->m_node += node_offset;
this->m_cur = this->get_first() + (offset - node_offset * block_size);
}
return *this;
}
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
deque_iterator operator+(difference_type n) const BOOST_NOEXCEPT_OR_NOTHROW
{ deque_iterator tmp(*this); return tmp += n; }
inline
deque_iterator& operator-=(difference_type n) BOOST_NOEXCEPT_OR_NOTHROW
{ return *this += -n; }
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
deque_iterator operator-(difference_type n) const BOOST_NOEXCEPT_OR_NOTHROW
{ deque_iterator tmp(*this); return tmp -= n; }
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
reference operator[](difference_type n) const BOOST_NOEXCEPT_OR_NOTHROW
{
BOOST_ASSERT(!!m_cur);
const difference_type offset = n + (this->m_cur - this->get_first());
const difference_type block_size = get_block_ssize();
if (offset >= 0 && offset < block_size)
return this->m_cur[difference_type(n)];
else {
const difference_type node_offset = offset > 0
? (offset / block_size)
: (-difference_type((-offset - 1) / block_size) - 1);
return (this->m_node[node_offset]) [offset - node_offset * block_size];
}
}
//Comparisons
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
friend bool operator==(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
{ return l.m_cur == r.m_cur; }
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
friend bool operator!=(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
{ return l.m_cur != r.m_cur; }
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
friend bool operator<(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
{ return (l.m_node == r.m_node) ? (l.m_cur < r.m_cur) : (l.m_node < r.m_node); }
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
friend bool operator>(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
{ return r < l; }
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
friend bool operator<=(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
{ return !(r < l); }
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
friend bool operator>=(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
{ return !(l < r); }
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
friend deque_iterator operator+(difference_type n, deque_iterator x) BOOST_NOEXCEPT_OR_NOTHROW
{ return x += n; }
inline void priv_set_node(index_pointer new_node, size_type ) BOOST_NOEXCEPT_OR_NOTHROW
{ return this->priv_set_node(new_node, difference_type()); }
inline void priv_set_node(index_pointer new_node, difference_type) BOOST_NOEXCEPT_OR_NOTHROW
{
this->m_node = new_node;
}
};
#else
#error "Invalid BOOST_CONTAINER_DEQUE_LIGHTER_ITERATOR_LEVEL"
#endif
} //namespace dtl {
template<class Options>
@@ -360,15 +805,20 @@ class deque_base
typedef typename get_deque_opt<Options>::type options_type;
protected:
#if BOOST_CONTAINER_DEQUE_LIGHTER_ITERATOR_LEVEL == 0
typedef dtl::deque_iterator<val_alloc_ptr, false> iterator;
typedef dtl::deque_iterator<val_alloc_ptr, true > const_iterator;
typedef dtl::deque_iterator<val_alloc_ptr, true> const_iterator;
#else
typedef dtl::deque_iterator<val_alloc_ptr, false, options_type::block_bytes, options_type::block_size> iterator;
typedef dtl::deque_iterator<val_alloc_ptr, true, options_type::block_bytes, options_type::block_size> const_iterator;
#endif
BOOST_CONSTEXPR inline static val_alloc_diff get_block_ssize() BOOST_NOEXCEPT_OR_NOTHROW
{ return val_alloc_diff((get_block_size())); }
BOOST_CONSTEXPR inline static size_type get_block_size() BOOST_NOEXCEPT_OR_NOTHROW
{ return deque_block_size<val_alloc_val, options_type::block_bytes, options_type::block_size>::value; }
BOOST_CONSTEXPR inline static val_alloc_diff get_block_ssize() BOOST_NOEXCEPT_OR_NOTHROW
{ return val_alloc_diff((get_block_size)()); }
typedef deque_value_traits<val_alloc_val> traits_t;
typedef ptr_alloc_t map_allocator_type;
@@ -446,8 +896,8 @@ class deque_base
this->members_.m_start.priv_set_node(nstart, get_block_size());
this->members_.m_finish.priv_set_node(nfinish - 1, get_block_size());
this->members_.m_start.m_cur = this->members_.m_start.m_first;
this->members_.m_finish.m_cur = this->members_.m_finish.m_first + difference_type(num_elements % get_block_size());
this->members_.m_start.m_cur = this->members_.m_start.get_first();
this->members_.m_finish.m_cur = this->members_.m_finish.get_first() + difference_type(num_elements % get_block_size());
// }
}
@@ -1741,7 +2191,7 @@ class deque : protected deque_base<typename real_allocator<T, Allocator>::type,
void pop_front() BOOST_NOEXCEPT_OR_NOTHROW
{
BOOST_ASSERT(!this->empty());
if (this->members_.m_start.m_cur != this->members_.m_start.m_last - 1) {
if (this->members_.m_start.m_cur != this->members_.m_start.get_last() - 1) {
allocator_traits_type::destroy
( this->alloc()
, boost::movelib::to_raw_pointer(this->members_.m_start.m_cur)
@@ -1760,7 +2210,7 @@ class deque : protected deque_base<typename real_allocator<T, Allocator>::type,
void pop_back() BOOST_NOEXCEPT_OR_NOTHROW
{
BOOST_ASSERT(!this->empty());
if (this->members_.m_finish.m_cur != this->members_.m_finish.m_first) {
if (this->members_.m_finish.m_cur != this->members_.m_finish.get_first()) {
--this->members_.m_finish.m_cur;
allocator_traits_type::destroy
( this->alloc()
@@ -1865,9 +2315,9 @@ class deque : protected deque_base<typename real_allocator<T, Allocator>::type,
}
if (this->members_.m_start.m_node != this->members_.m_finish.m_node) {
this->priv_destroy_range(this->members_.m_start.m_cur, this->members_.m_start.m_last);
this->priv_destroy_range(this->members_.m_finish.m_first, this->members_.m_finish.m_cur);
this->priv_deallocate_node(this->members_.m_finish.m_first);
this->priv_destroy_range(this->members_.m_start.m_cur, this->members_.m_start.get_last());
this->priv_destroy_range(this->members_.m_finish.get_first(), this->members_.m_finish.m_cur);
this->priv_deallocate_node(this->members_.m_finish.get_first());
}
else
this->priv_destroy_range(this->members_.m_start.m_cur, this->members_.m_finish.m_cur);
@@ -2016,7 +2466,7 @@ class deque : protected deque_base<typename real_allocator<T, Allocator>::type,
inline bool priv_push_back_simple_available() const
{
return this->members_.m_map &&
(this->members_.m_finish.m_cur != (this->members_.m_finish.m_last - 1));
(this->members_.m_finish.m_cur != (this->members_.m_finish.get_last() - 1));
}
inline T *priv_push_back_simple_pos() const
@@ -2032,7 +2482,7 @@ class deque : protected deque_base<typename real_allocator<T, Allocator>::type,
inline bool priv_push_front_simple_available() const
{
return this->members_.m_map &&
(this->members_.m_start.m_cur != this->members_.m_start.m_first);
(this->members_.m_start.m_cur != this->members_.m_start.get_first());
}
inline T *priv_push_front_simple_pos() const
@@ -2060,84 +2510,117 @@ class deque : protected deque_base<typename real_allocator<T, Allocator>::type,
}
template<class InsertProxy>
iterator priv_insert_aux_impl(const_iterator p, size_type n, InsertProxy proxy)
iterator priv_insert_middle_aux_impl(const_iterator p, const size_type elemsbefore, const size_type length, const size_type n, InsertProxy proxy)
{
iterator pos(p.unconst());
const size_type pos_n = size_type(p - this->cbegin());
if(!this->members_.m_map){
if (!this->members_.m_map) {
this->priv_initialize_map(0);
pos = this->begin();
p = this->cbegin();
}
const size_type elemsbefore = static_cast<size_type>(pos - this->members_.m_start);
const size_type length = this->size();
iterator pos(p.unconst());
const size_type pos_n = size_type(p - this->cbegin());
if (elemsbefore < length / 2) {
const iterator new_start = this->priv_reserve_elements_at_front(n);
const iterator old_start = this->members_.m_start;
if(!elemsbefore){
proxy.uninitialized_copy_n_and_update(this->alloc(), new_start, n);
this->members_.m_start = new_start;
}
else{
pos = this->members_.m_start + difference_type(elemsbefore);
if (elemsbefore >= n) {
const iterator start_n = this->members_.m_start + difference_type(n);
pos = this->members_.m_start + difference_type(elemsbefore);
if (elemsbefore >= n) {
const iterator start_n = this->members_.m_start + difference_type(n);
BOOST_CONTAINER_TRY {
::boost::container::uninitialized_move_alloc
(this->alloc(), this->members_.m_start, start_n, new_start);
this->members_.m_start = new_start;
boost::container::move(start_n, pos, old_start);
proxy.copy_n_and_update(this->alloc(), pos - difference_type(n), n);
}
else {
const size_type mid_count = n - elemsbefore;
const iterator mid_start = old_start - difference_type(mid_count);
BOOST_CONTAINER_CATCH(...) {
this->priv_destroy_nodes(new_start.m_node, this->members_.m_start.m_node);
BOOST_CONTAINER_RETHROW
}
BOOST_CONTAINER_CATCH_END
this->members_.m_start = new_start;
boost::container::move(start_n, pos, old_start);
proxy.copy_n_and_update(this->alloc(), pos - difference_type(n), n);
}
else {
const size_type mid_count = n - elemsbefore;
const iterator mid_start = old_start - difference_type(mid_count);
BOOST_CONTAINER_TRY {
proxy.uninitialized_copy_n_and_update(this->alloc(), mid_start, mid_count);
this->members_.m_start = mid_start;
::boost::container::uninitialized_move_alloc
(this->alloc(), old_start, pos, new_start);
this->members_.m_start = new_start;
proxy.copy_n_and_update(this->alloc(), old_start, elemsbefore);
::boost::container::uninitialized_move_alloc(this->alloc(), old_start, pos, new_start);
}
BOOST_CONTAINER_CATCH(...) {
this->priv_destroy_nodes(new_start.m_node, this->members_.m_start.m_node);
BOOST_CONTAINER_RETHROW
}
BOOST_CONTAINER_CATCH_END
this->members_.m_start = new_start;
proxy.copy_n_and_update(this->alloc(), old_start, elemsbefore);
}
}
else {
const iterator new_finish = this->priv_reserve_elements_at_back(n);
const iterator old_finish = this->members_.m_finish;
const size_type elemsafter = length - elemsbefore;
if(!elemsafter){
proxy.uninitialized_copy_n_and_update(this->alloc(), old_finish, n);
this->members_.m_finish = new_finish;
}
else{
pos = old_finish - difference_type(elemsafter);
if (elemsafter >= n) {
iterator finish_n = old_finish - difference_type(n);
::boost::container::uninitialized_move_alloc
(this->alloc(), finish_n, old_finish, old_finish);
this->members_.m_finish = new_finish;
boost::container::move_backward(pos, finish_n, old_finish);
proxy.copy_n_and_update(this->alloc(), pos, n);
pos = old_finish - difference_type(elemsafter);
if (elemsafter >= n) {
iterator finish_n = old_finish - difference_type(n);
BOOST_CONTAINER_TRY {
::boost::container::uninitialized_move_alloc(this->alloc(), finish_n, old_finish, old_finish);
}
else {
const size_type raw_gap = n - elemsafter;
BOOST_CONTAINER_CATCH(...) {
this->priv_destroy_nodes(this->members_.m_finish.m_node + 1, new_finish.m_node + 1);
BOOST_CONTAINER_RETHROW
}
BOOST_CONTAINER_CATCH_END
this->members_.m_finish = new_finish;
boost::container::move_backward(pos, finish_n, old_finish);
proxy.copy_n_and_update(this->alloc(), pos, n);
}
else {
const size_type raw_gap = n - elemsafter;
BOOST_CONTAINER_TRY{
::boost::container::uninitialized_move_alloc
(this->alloc(), pos, old_finish, old_finish + difference_type(raw_gap));
BOOST_CONTAINER_TRY{
proxy.copy_n_and_update(this->alloc(), pos, elemsafter);
proxy.uninitialized_copy_n_and_update(this->alloc(), old_finish, raw_gap);
}
BOOST_CONTAINER_CATCH(...){
BOOST_CONTAINER_CATCH(...) {
this->priv_destroy_range(old_finish, old_finish + difference_type(elemsafter));
BOOST_CONTAINER_RETHROW
}
BOOST_CONTAINER_CATCH_END
this->members_.m_finish = new_finish;
}
BOOST_CONTAINER_CATCH(...) {
this->priv_destroy_nodes(this->members_.m_finish.m_node + 1, new_finish.m_node + 1);
BOOST_CONTAINER_RETHROW
}
BOOST_CONTAINER_CATCH_END
this->members_.m_finish = new_finish;
}
}
return this->begin() + difference_type(pos_n);
}
template<class InsertProxy>
iterator priv_insert_aux_impl(const_iterator p, size_type n, InsertProxy proxy)
{
iterator pos(p.unconst());
const size_type elemsbefore = static_cast<size_type>(pos - this->members_.m_start);
const size_type length = this->size();
if (!elemsbefore) {
return this->priv_insert_front_aux_impl(n, proxy);
}
else if (elemsbefore == length) {
return this->priv_insert_back_aux_impl(n, proxy);
}
else {
return this->priv_insert_middle_aux_impl(p, elemsbefore, length, n, proxy);
}
}
template <class InsertProxy>
iterator priv_insert_back_aux_impl(size_type n, InsertProxy proxy)
{
@@ -2146,8 +2629,14 @@ class deque : protected deque_base<typename real_allocator<T, Allocator>::type,
}
iterator new_finish = this->priv_reserve_elements_at_back(n);
iterator old_finish = this->members_.m_finish;
proxy.uninitialized_copy_n_and_update(this->alloc(), old_finish, n);
BOOST_CONTAINER_TRY{
proxy.uninitialized_copy_n_and_update(this->alloc(), this->members_.m_finish, n);
}
BOOST_CONTAINER_CATCH(...) {
this->priv_destroy_nodes(this->members_.m_finish.m_node + 1, new_finish.m_node + 1);
BOOST_CONTAINER_RETHROW
}
BOOST_CONTAINER_CATCH_END
this->members_.m_finish = new_finish;
return iterator(this->members_.m_finish - difference_type(n));
}
@@ -2160,7 +2649,15 @@ class deque : protected deque_base<typename real_allocator<T, Allocator>::type,
}
iterator new_start = this->priv_reserve_elements_at_front(n);
proxy.uninitialized_copy_n_and_update(this->alloc(), new_start, n);
BOOST_CONTAINER_TRY{
proxy.uninitialized_copy_n_and_update(this->alloc(), new_start, n);
}
BOOST_CONTAINER_CATCH(...) {
this->priv_destroy_nodes(new_start.m_node, this->members_.m_start.m_node);
BOOST_CONTAINER_RETHROW
}
BOOST_CONTAINER_CATCH_END
this->members_.m_start = new_start;
return new_start;
}
@@ -2181,7 +2678,7 @@ class deque : protected deque_base<typename real_allocator<T, Allocator>::type,
(this->alloc(), *cur, *cur + get_block_ssize(), value);
}
boost::container::uninitialized_fill_alloc
(this->alloc(), this->members_.m_finish.m_first, this->members_.m_finish.m_cur, value);
(this->alloc(), this->members_.m_finish.get_first(), this->members_.m_finish.m_cur, value);
}
BOOST_CONTAINER_CATCH(...){
this->priv_destroy_range(this->members_.m_start, iterator(*cur, cur, get_block_size()));
@@ -2220,7 +2717,7 @@ class deque : protected deque_base<typename real_allocator<T, Allocator>::type,
::boost::container::uninitialized_copy_alloc(this->alloc(), first, mid, *cur_node);
first = mid;
}
::boost::container::uninitialized_copy_alloc(this->alloc(), first, last, this->members_.m_finish.m_first);
::boost::container::uninitialized_copy_alloc(this->alloc(), first, last, this->members_.m_finish.get_first());
}
BOOST_CONTAINER_CATCH(...){
this->priv_destroy_range(this->members_.m_start, iterator(*cur_node, cur_node, get_block_size()));
@@ -2229,21 +2726,21 @@ class deque : protected deque_base<typename real_allocator<T, Allocator>::type,
BOOST_CONTAINER_CATCH_END
}
// Called only if this->members_.m_finish.m_cur == this->members_.m_finish.m_first.
// Called only if this->members_.m_finish.m_cur == this->members_.m_finish.get_first().
void priv_pop_back_aux() BOOST_NOEXCEPT_OR_NOTHROW
{
this->priv_deallocate_node(this->members_.m_finish.m_first);
this->priv_deallocate_node(this->members_.m_finish.get_first());
this->members_.m_finish.priv_set_node(this->members_.m_finish.m_node - 1, get_block_size());
this->members_.m_finish.m_cur = this->members_.m_finish.m_last - 1;
this->members_.m_finish.m_cur = this->members_.m_finish.get_last() - 1;
allocator_traits_type::destroy
( this->alloc()
, boost::movelib::to_raw_pointer(this->members_.m_finish.m_cur)
);
}
// Called only if this->members_.m_start.m_cur == this->members_.m_start.m_last - 1. Note that
// Called only if this->members_.m_start.m_cur == this->members_.m_start.get_last() - 1. Note that
// if the deque has at least one element (a precondition for this member
// function), and if this->members_.m_start.m_cur == this->members_.m_start.m_last, then the deque
// function), and if this->members_.m_start.m_cur == this->members_.m_start.get_last(), then the deque
// must have at least two nodes.
void priv_pop_front_aux() BOOST_NOEXCEPT_OR_NOTHROW
{
@@ -2251,14 +2748,14 @@ class deque : protected deque_base<typename real_allocator<T, Allocator>::type,
( this->alloc()
, boost::movelib::to_raw_pointer(this->members_.m_start.m_cur)
);
this->priv_deallocate_node(this->members_.m_start.m_first);
this->priv_deallocate_node(this->members_.m_start.get_first());
this->members_.m_start.priv_set_node(this->members_.m_start.m_node + 1, get_block_size());
this->members_.m_start.m_cur = this->members_.m_start.m_first;
this->members_.m_start.m_cur = this->members_.m_start.get_first();
}
iterator priv_reserve_elements_at_front(size_type n)
{
size_type vacancies = size_type(this->members_.m_start.m_cur - this->members_.m_start.m_first);
size_type vacancies = size_type(this->members_.m_start.m_cur - this->members_.m_start.get_first());
if (n > vacancies){
size_type new_elems = n-vacancies;
size_type new_nodes = (new_elems + get_block_size() - 1u) / get_block_size();
@@ -2283,7 +2780,7 @@ class deque : protected deque_base<typename real_allocator<T, Allocator>::type,
iterator priv_reserve_elements_at_back(size_type n)
{
size_type vacancies = size_type(this->members_.m_finish.m_last - this->members_.m_finish.m_cur - 1);
size_type vacancies = size_type(this->members_.m_finish.get_last() - this->members_.m_finish.m_cur - 1);
if (n > vacancies){
size_type new_elems = size_type(n - vacancies);
size_type new_nodes = size_type(new_elems + get_block_size() - 1u)/get_block_size();
@@ -2348,7 +2845,8 @@ template <typename InputIterator, typename Allocator>
deque(InputIterator, InputIterator, Allocator const&) -> deque<typename iterator_traits<InputIterator>::value_type, Allocator>;
#endif
}}
} //namespace container
} //namespace boost
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED