Sync from upstream.

This commit is contained in:
Rene Rivera
2024-04-28 20:30:48 -05:00
5 changed files with 813 additions and 208 deletions

128
.gitignore vendored
View File

@@ -2,121 +2,17 @@
# This .gitignore file was automatically created by Microsoft(R) Visual Studio.
################################################################################
/proj/vs/.vs
/proj/vs/x64
/proj/vs/Win32
/proj/vs/allocator_traits_test.vcxproj.user
/proj/vs/alloc_basic_test.vcxproj.user
/proj/vs/alloc_full_test.vcxproj.user
/proj/vs/alloc_lib.vcxproj.user
/proj/vs/bench_adaptive_node_pool.vcxproj.user
/proj/vs/bench_alloc.vcxproj.user
/proj/vs/bench_alloc_expand_bwd.vcxproj.user
/proj/vs/bench_alloc_expand_fwd.vcxproj.user
/proj/vs/bench_alloc_shrink_to_fit.vcxproj.user
/proj/vs/bench_alloc_stable_vector_burst.vcxproj.user
/proj/vs/bench_flat_multiset.vcxproj.user
/proj/vs/bench_flat_set.vcxproj.user
/proj/vs/bench_hash_map_string_test.vcxproj
/proj/vs/bench_hash_map_string_test.vcxproj.user
/proj/vs/bench_hash_map_test.vcxproj
/proj/vs/bench_hash_map_test.vcxproj.user
/proj/vs/bench_hash_map_uint32_test.vcxproj
/proj/vs/bench_hash_map_uint32_test.vcxproj.user
/proj/vs/bench_hash_map_uint64_test.vcxproj
/proj/vs/bench_hash_map_uint64_test.vcxproj.user
/proj/vs/bench_hash_set_test.vcxproj
/proj/vs/bench_set.vcxproj.user
/proj/vs/bench_set_adaptive_pool.vcxproj.user
/proj/vs/bench_set_alloc_v2.vcxproj.user
/proj/vs/bench_set_avl.vcxproj.user
/proj/vs/bench_set_multi.vcxproj.user
/proj/vs/bench_set_sg.vcxproj.user
/proj/vs/bench_set_sp.vcxproj.user
/proj/vs/bench_static_vector.vcxproj.user
/proj/vs/bench_vectors.vcxproj.user
/proj/vs/boost_iterator_comp_test.vcxproj.user
/proj/vs/common_iterator_test.vcxproj.user
/proj/vs/container.vcxproj
/proj/vs/container.vcxproj.filters
/proj/vs/container.vcxproj.user
/proj/vs/copy_move_algo_test.vcxproj.user
/proj/vs/deque_options_test.vcxproj.user
/proj/vs/deque_test.vcxproj.user
/proj/vs/devector_options_test.vcxproj.user
/proj/vs/devector_test.vcxproj.user
/proj/vs/doc_custom_deque.vcxproj.user
/proj/vs/doc_custom_devector.vcxproj.user
/proj/vs/doc_custom_small_vector.vcxproj.user
/proj/vs/doc_custom_static_vector.vcxproj.user
/proj/vs/doc_custom_tree.vcxproj.user
/proj/vs/doc_custom_vector.vcxproj.user
/proj/vs/doc_emplace.vcxproj.user
/proj/vs/doc_extended_allocators.vcxproj.user
/proj/vs/doc_move_containers.vcxproj.user
/proj/vs/doc_pmr.vcxproj.user
/proj/vs/doc_recursive_containers.vcxproj.user
/proj/vs/doc_type_erasure.vcxproj.user
/proj/vs/explicit_inst_deque_test.vcxproj.user
/proj/vs/explicit_inst_devector_test.vcxproj.user
/proj/vs/explicit_inst_flat_map_test.vcxproj.user
/proj/vs/explicit_inst_flat_set_test.vcxproj.user
/proj/vs/explicit_inst_list_test.vcxproj.user
/proj/vs/explicit_inst_map_test.vcxproj.user
/proj/vs/explicit_inst_set_test.vcxproj.user
/proj/vs/explicit_inst_slist_test.vcxproj.user
/proj/vs/explicit_inst_small_vector_test.vcxproj.user
/proj/vs/explicit_inst_stable_vector_test.vcxproj.user
/proj/vs/explicit_inst_static_vector_test.vcxproj.user
/proj/vs/explicit_inst_string_test.vcxproj.user
/proj/vs/explicit_inst_vector_test.vcxproj.user
/proj/vs/flat_map_adaptor_test.vcxproj.user
/proj/vs/flat_map_test.vcxproj.user
/proj/vs/flat_set_adaptor_test.vcxproj.user
/proj/vs/flat_set_test.vcxproj.user
/proj/vs/flat_tree_test.vcxproj.user
/proj/vs/global_resource.vcxproj.user
/proj/vs/insert_vs_emplace_test.vcxproj.user
/proj/vs/list_test.vcxproj.user
/proj/vs/map_test.vcxproj.user
/proj/vs/memory_resource_test.vcxproj.user
/proj/vs/monotonic_buffer_resource_test.vcxproj.user
/proj/vs/node_handle_test.vcxproj.user
/proj/vs/null_iterators_test.vcxproj.user
/proj/vs/pair_test.vcxproj.user
/proj/vs/pmr_deque_test.vcxproj.user
/proj/vs/pmr_devector_test.vcxproj.user
/proj/vs/pmr_flat_map_test.vcxproj.user
/proj/vs/pmr_flat_set_test.vcxproj.user
/proj/vs/pmr_list_test.vcxproj.user
/proj/vs/pmr_map_test.vcxproj.user
/proj/vs/pmr_set_test.vcxproj.user
/proj/vs/pmr_slist_test.vcxproj.user
/proj/vs/pmr_small_vector_test.vcxproj.user
/proj/vs/pmr_stable_vector_test.vcxproj.user
/proj/vs/pmr_string_test.vcxproj.user
/proj/vs/pmr_vector_test.vcxproj.user
/proj/vs/polymorphic_allocator_test.vcxproj.user
/proj/vs/resource_adaptor.vcxproj.user
/proj/vs/scoped_allocator_adaptor_test.vcxproj.user
/proj/vs/scoped_allocator_usage_test.vcxproj.user
/proj/vs/set_test.vcxproj.user
/proj/vs/slist_test.vcxproj.user
/proj/vs/small_vector_options_test.vcxproj.user
/proj/vs/small_vector_test.vcxproj.user
/proj/vs/stable_vector_test.vcxproj.user
/proj/vs/static_vector_options_test.vcxproj.user
/proj/vs/static_vector_test.vcxproj.user
/proj/vs/string_test.vcxproj.user
/proj/vs/string_view_compat_test.vcxproj.user
/proj/vs/synchronized_pool_resource_test.vcxproj.user
/proj/vs/throw_exception_test.vcxproj.user
/proj/vs/tree_test.vcxproj.user
/proj/vs/unsynchronized_pool_resource_test.vcxproj.user
/proj/vs/uses_allocator_test.vcxproj.user
/proj/vs/vector_options_test.vcxproj.user
/proj/vs/vector_test.vcxproj.user
/proj/
/doc/html
/doc/autodoc.xml
/proj/vs/deque_test.vcxproj
/proj/vs/stable_vector_test.vcxproj
/bench/bench_hash_common.hpp
/bench/bench_hash_map_test.cpp.disabled
/bench/bench_hash_string.cpp.disabled
/bench/bench_hash_uint32.cpp.disabled
/bench/bench_hash_uint64.cpp.disabled
/bench/fca_simple_unordered.hpp
/bench/fca_unordered.hpp
/bench/fxa_common.hpp
/bench/hash_map.hpp
/bench/hash_set.hpp
/bench/detail/hash_table.hpp

View File

@@ -32,6 +32,8 @@
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/type_traits.hpp> //is_empty
#include <boost/container/detail/placement_new.hpp>
#include <boost/container/detail/is_pair.hpp>
#include <boost/container/detail/addressof.hpp>
#ifndef BOOST_CONTAINER_DETAIL_STD_FWD_HPP
#include <boost/container/detail/std_fwd.hpp>
#endif
@@ -81,6 +83,144 @@
namespace boost {
namespace container {
namespace dtl {
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template<class T, class ...Args>
BOOST_CONTAINER_FORCEINLINE void construct_type(T *p, BOOST_FWD_REF(Args) ...args)
{
::new((void*)p, boost_container_new_t()) T(::boost::forward<Args>(args)...);
}
template < class Pair, class KeyType, class ... Args>
typename dtl::enable_if< dtl::is_pair<Pair>, void >::type
construct_type
(Pair* p, try_emplace_t, BOOST_FWD_REF(KeyType) k, BOOST_FWD_REF(Args) ...args)
{
construct_type(dtl::addressof(p->first), ::boost::forward<KeyType>(k));
BOOST_CONTAINER_TRY{
construct_type(dtl::addressof(p->second), ::boost::forward<Args>(args)...);
}
BOOST_CONTAINER_CATCH(...) {
typedef typename Pair::first_type first_type;
dtl::addressof(p->first)->~first_type();
BOOST_CONTAINER_RETHROW
}
BOOST_CONTAINER_CATCH_END
}
#else
#define BOOST_CONTAINER_ALLOCATOR_TRAITS_CONSTRUCT_TYPEJ(N) \
template<class T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N>\
BOOST_CONTAINER_FORCEINLINE \
typename dtl::disable_if_c<dtl::is_pair<T>::value, void >::type \
construct_type(T *p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
{\
::new((void*)p, boost_container_new_t()) T( BOOST_MOVE_FWD##N );\
}\
//
BOOST_MOVE_ITERATE_0TO8(BOOST_CONTAINER_ALLOCATOR_TRAITS_CONSTRUCT_TYPEJ)
#undef BOOST_CONTAINER_ALLOCATOR_TRAITS_CONSTRUCT_TYPEJ
#define BOOST_CONTAINER_ALLOCATOR_TRAITS_CONSTRUCT_TYPE(N) \
template < class Pair, class KeyType BOOST_MOVE_I##N BOOST_MOVE_CLASS##N>\
typename dtl::enable_if< dtl::is_pair<Pair>, void >::type construct_type\
(Pair* p, try_emplace_t, BOOST_FWD_REF(KeyType) k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
{\
construct_type(dtl::addressof(p->first), ::boost::forward<KeyType>(k));\
BOOST_CONTAINER_TRY{\
construct_type(dtl::addressof(p->second) BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
}\
BOOST_CONTAINER_CATCH(...) {\
typedef typename Pair::first_type first_type;\
dtl::addressof(p->first)->~first_type();\
BOOST_CONTAINER_RETHROW\
}\
BOOST_CONTAINER_CATCH_END\
}\
//
BOOST_MOVE_ITERATE_0TO8(BOOST_CONTAINER_ALLOCATOR_TRAITS_CONSTRUCT_TYPE)
#undef BOOST_CONTAINER_ALLOCATOR_TRAITS_CONSTRUCT_TYPE
#endif
template<class T>
inline
typename dtl::enable_if<dtl::is_pair<T>, void >::type
construct_type(T* p)
{
dtl::construct_type(dtl::addressof(p->first));
BOOST_CONTAINER_TRY{
dtl::construct_type(dtl::addressof(p->second));
}
BOOST_CONTAINER_CATCH(...) {
typedef typename T::first_type first_type;
dtl::addressof(p->first)->~first_type();
BOOST_CONTAINER_RETHROW
}
BOOST_CONTAINER_CATCH_END
}
template<class T, class U>
inline
typename dtl::enable_if_c
< dtl::is_pair<T>::value
, void >::type
construct_type(T* p, U &u)
{
dtl::construct_type(dtl::addressof(p->first), u.first);
BOOST_CONTAINER_TRY{
dtl::construct_type(dtl::addressof(p->second), u.second);
}
BOOST_CONTAINER_CATCH(...) {
typedef typename T::first_type first_type;
dtl::addressof(p->first)->~first_type();
BOOST_CONTAINER_RETHROW
}
BOOST_CONTAINER_CATCH_END
}
template<class T, class U>
inline
typename dtl::enable_if_c
< dtl::is_pair<typename dtl::remove_reference<T>::type>::value &&
!boost::move_detail::is_reference<U>::value //This is needed for MSVC10 and ambiguous overloads
, void >::type
construct_type(T* p, BOOST_RV_REF(U) u)
{
dtl::construct_type(dtl::addressof(p->first), ::boost::move(u.first));
BOOST_CONTAINER_TRY{
dtl::construct_type(dtl::addressof(p->second), ::boost::move(u.second));
}
BOOST_CONTAINER_CATCH(...) {
typedef typename T::first_type first_type;
dtl::addressof(p->first)->~first_type();
BOOST_CONTAINER_RETHROW
}
BOOST_CONTAINER_CATCH_END
}
template<class T, class U, class V>
inline
typename dtl::enable_if<dtl::is_pair<T>, void >::type
construct_type(T* p, BOOST_FWD_REF(U) x, BOOST_FWD_REF(V) y)
{
dtl::construct_type(dtl::addressof(p->first), ::boost::forward<U>(x));
BOOST_CONTAINER_TRY{
dtl::construct_type(dtl::addressof(p->second), ::boost::forward<V>(y));
}
BOOST_CONTAINER_CATCH(...) {
typedef typename T::first_type first_type;
dtl::addressof(p->first)->~first_type();
BOOST_CONTAINER_RETHROW
}
BOOST_CONTAINER_CATCH_END
}
} //namespace dtl
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
@@ -419,7 +559,7 @@ struct allocator_traits
template<class T, class ...Args>
inline static void priv_construct(dtl::false_type, Allocator &, T *p, BOOST_FWD_REF(Args) ...args)
{ ::new((void*)p, boost_container_new_t()) T(::boost::forward<Args>(args)...); }
{ dtl::construct_type(p, ::boost::forward<Args>(args)...); }
#else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
public:
@@ -450,7 +590,7 @@ struct allocator_traits
\
template<class T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
inline static void priv_construct(dtl::false_type, Allocator &, T *p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
{ ::new((void*)p, boost_container_new_t()) T(BOOST_MOVE_FWD##N); }\
{ dtl::construct_type(p BOOST_MOVE_I##N BOOST_MOVE_FWD##N); }\
//
BOOST_MOVE_ITERATE_0TO8(BOOST_CONTAINER_ALLOCATOR_TRAITS_PRIV_CONSTRUCT_IMPL)
#undef BOOST_CONTAINER_ALLOCATOR_TRAITS_PRIV_CONSTRUCT_IMPL

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

View File

@@ -24,6 +24,7 @@
#include <boost/container/allocator_traits.hpp>
#include <boost/container/detail/iterators.hpp>
#include <boost/container/detail/value_init.hpp>
#include <boost/container/detail/is_pair.hpp>
namespace boost {
namespace container {
@@ -62,9 +63,42 @@ BOOST_CONTAINER_FORCEINLINE void construct_in_place(Allocator &a, T *dest, empla
//Assignment
template<class T, class U>
BOOST_CONTAINER_FORCEINLINE
typename dtl::disable_if_c
< dtl::is_pair<typename dtl::remove_reference<T>::type>::value
&& dtl::is_pair<typename dtl::remove_reference<U>::type>::value
, void>::type
assign_in_place_ref(T &t, BOOST_FWD_REF(U) u)
{ t = ::boost::forward<U>(u); }
template<class T, class U>
BOOST_CONTAINER_FORCEINLINE
typename dtl::enable_if_c
< dtl::is_pair<typename dtl::remove_reference<T>::type>::value
&& dtl::is_pair<typename dtl::remove_reference<U>::type>::value
, void>::type
assign_in_place_ref(T &t, const U &u)
{
assign_in_place_ref(t.first, u.first);
assign_in_place_ref(t.second, u.second);
}
template<class T, class U>
BOOST_CONTAINER_FORCEINLINE
typename dtl::enable_if_c
< dtl::is_pair<typename dtl::remove_reference<T>::type>::value
&& dtl::is_pair<typename dtl::remove_reference<U>::type>::value
, void>::type
assign_in_place_ref(T &t, BOOST_RV_REF(U) u)
{
assign_in_place_ref(t.first, ::boost::move(u.first));
assign_in_place_ref(t.second, ::boost::move(u.second));
}
template<class DstIt, class InpIt>
BOOST_CONTAINER_FORCEINLINE void assign_in_place(DstIt dest, InpIt source)
{ *dest = *source; }
{ assign_in_place_ref(*dest, *source); }
template<class DstIt, class U>
BOOST_CONTAINER_FORCEINLINE void assign_in_place(DstIt dest, value_init_construct_iterator<U>)

View File

@@ -48,6 +48,11 @@
#include <initializer_list>
#endif
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
#define BOOST_CONTAINER_STD_PAIR_IS_MOVABLE
#endif
namespace boost {
namespace container {
@@ -58,21 +63,37 @@ class flat_multimap;
namespace dtl{
#if defined(BOOST_CONTAINER_STD_PAIR_IS_MOVABLE)
template<class D, class S>
BOOST_CONTAINER_FORCEINLINE static D &force(S &s)
{ return *move_detail::force_ptr<D*>(&s); }
{ return s; }
template<class D, class S>
BOOST_CONTAINER_FORCEINLINE static const D &force(const S &s)
{ return *move_detail::force_ptr<const D*>(&s); }
{ return s; }
template<class D>
BOOST_CONTAINER_FORCEINLINE static D force_copy(D s)
{ return s; }
#else //!BOOST_CONTAINER_DOXYGEN_INVOKED
template<class D, class S>
BOOST_CONTAINER_FORCEINLINE static D &force(S &s)
{ return *move_detail::launder_cast<D*>(&s); }
template<class D, class S>
BOOST_CONTAINER_FORCEINLINE static const D &force(const S &s)
{ return *move_detail::launder_cast<const D*>(&s); }
template<class D, class S>
BOOST_CONTAINER_FORCEINLINE static D force_copy(const S &s)
{
const D *const vp = move_detail::force_ptr<const D *>(&s);
const D *const vp = move_detail::launder_cast<const D *>(&s);
D ret_val(*vp);
return ret_val;
}
#endif //BOOST_CONTAINER_DOXYGEN_INVOKED
} //namespace dtl{
@@ -118,18 +139,27 @@ class flat_map
private:
BOOST_COPYABLE_AND_MOVABLE(flat_map)
//This is the tree that we should store if pair was movable
typedef std::pair<Key, T> std_pair_t;
typedef dtl::flat_tree<
std::pair<Key, T>,
std_pair_t,
dtl::select1st<Key>,
Compare,
AllocatorOrContainer> tree_t;
//This is the real tree stored here. It's based on a movable pair
typedef dtl::pair<Key, T> dtl_pair_t;
#ifdef BOOST_CONTAINER_STD_PAIR_IS_MOVABLE
typedef std_pair_t impl_pair_t;
#else
typedef dtl_pair_t impl_pair_t;
#endif
typedef dtl::flat_tree<
dtl::pair<Key, T>,
impl_pair_t,
dtl::select1st<Key>,
Compare,
typename dtl::container_or_allocator_rebind<AllocatorOrContainer, dtl::pair<Key, T> >::type
typename dtl::container_or_allocator_rebind<AllocatorOrContainer, impl_pair_t >::type
> impl_tree_t;
impl_tree_t m_flat_tree; // flat tree representing flat_map
@@ -851,7 +881,7 @@ class flat_map
//! @copydoc ::boost::container::flat_set::nth(size_type) const
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
{ return dtl::force_copy<iterator>(m_flat_tree.nth(n)); }
{ return dtl::force_copy<const_iterator>(m_flat_tree.nth(n)); }
//! @copydoc ::boost::container::flat_set::index_of(iterator)
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
@@ -1099,7 +1129,7 @@ class flat_map
template <class Pair>
inline BOOST_CONTAINER_DOC1ST
( std::pair<iterator BOOST_MOVE_I bool>
, typename dtl::enable_if_c<dtl::is_convertible<Pair BOOST_MOVE_I impl_value_type>::value
, typename dtl::enable_if_c<dtl::is_convertible<Pair BOOST_MOVE_I dtl_pair_t>::value
BOOST_MOVE_I std::pair<iterator BOOST_MOVE_I bool> >::type)
insert(BOOST_FWD_REF(Pair) x)
{
@@ -1153,7 +1183,7 @@ class flat_map
template <class Pair>
inline BOOST_CONTAINER_DOC1ST
( iterator
, typename dtl::enable_if_c<dtl::is_convertible<Pair BOOST_MOVE_I impl_value_type>::value
, typename dtl::enable_if_c<dtl::is_convertible<Pair BOOST_MOVE_I dtl_pair_t>::value
BOOST_MOVE_I iterator>::type)
insert(const_iterator p, BOOST_FWD_REF(Pair) x)
{
@@ -1777,17 +1807,24 @@ class flat_multimap
#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
BOOST_COPYABLE_AND_MOVABLE(flat_multimap)
typedef std::pair<Key, T> std_pair_t;
typedef dtl::flat_tree<
std::pair<Key, T>,
std_pair_t,
dtl::select1st<Key>,
Compare,
AllocatorOrContainer> tree_t;
//This is the real tree stored here. It's based on a movable pair
typedef dtl::pair<Key, T> dtl_pair_t;
#ifdef BOOST_CONTAINER_STD_PAIR_IS_MOVABLE
typedef std_pair_t impl_pair_t;
#else
typedef dtl_pair_t impl_pair_t;
#endif
typedef dtl::flat_tree<
dtl::pair<Key, T>,
impl_pair_t,
dtl::select1st<Key>,
Compare,
typename dtl::container_or_allocator_rebind<AllocatorOrContainer, dtl::pair<Key, T> >::type
typename dtl::container_or_allocator_rebind<AllocatorOrContainer, impl_pair_t >::type
> impl_tree_t;
impl_tree_t m_flat_tree; // flat tree representing flat_map
@@ -2388,7 +2425,7 @@ class flat_multimap
//! @copydoc ::boost::container::flat_set::nth(size_type) const
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
{ return dtl::force_copy<iterator>(m_flat_tree.nth(n)); }
{ return dtl::force_copy<const_iterator>(m_flat_tree.nth(n)); }
//! @copydoc ::boost::container::flat_set::index_of(iterator)
BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
@@ -2477,7 +2514,7 @@ class flat_multimap
template<class Pair>
inline BOOST_CONTAINER_DOC1ST
( iterator
, typename dtl::enable_if_c<dtl::is_convertible<Pair BOOST_MOVE_I impl_value_type>::value
, typename dtl::enable_if_c<dtl::is_convertible<Pair BOOST_MOVE_I dtl_pair_t>::value
BOOST_MOVE_I iterator >::type)
insert(BOOST_FWD_REF(Pair) x)
{ return dtl::force_copy<iterator>(m_flat_tree.emplace_equal(boost::forward<Pair>(x))); }
@@ -2514,7 +2551,7 @@ class flat_multimap
template<class Pair>
inline BOOST_CONTAINER_DOC1ST
( iterator
, typename dtl::enable_if_c<dtl::is_convertible<Pair BOOST_MOVE_I impl_value_type>::value
, typename dtl::enable_if_c<dtl::is_convertible<Pair BOOST_MOVE_I dtl_pair_t>::value
BOOST_MOVE_I iterator>::type)
insert(const_iterator p, BOOST_FWD_REF(Pair) x)
{