diff --git a/.gitignore b/.gitignore index 8dbcd63..737a4de 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/include/boost/container/allocator_traits.hpp b/include/boost/container/allocator_traits.hpp index cdb6683..8e2fafa 100644 --- a/include/boost/container/allocator_traits.hpp +++ b/include/boost/container/allocator_traits.hpp @@ -32,6 +32,8 @@ #include #include //is_empty #include +#include +#include #ifndef BOOST_CONTAINER_DETAIL_STD_FWD_HPP #include #endif @@ -81,6 +83,144 @@ namespace boost { namespace container { +namespace dtl { + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + +template +BOOST_CONTAINER_FORCEINLINE void construct_type(T *p, BOOST_FWD_REF(Args) ...args) +{ + ::new((void*)p, boost_container_new_t()) T(::boost::forward(args)...); +} + +template < class Pair, class KeyType, class ... Args> +typename dtl::enable_if< dtl::is_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(k)); + BOOST_CONTAINER_TRY{ + construct_type(dtl::addressof(p->second), ::boost::forward(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\ +BOOST_CONTAINER_FORCEINLINE \ + typename dtl::disable_if_c::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, 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(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 +inline +typename dtl::enable_if, 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 +inline +typename dtl::enable_if_c + < dtl::is_pair::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 +inline +typename dtl::enable_if_c + < dtl::is_pair::type>::value && + !boost::move_detail::is_reference::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 +inline +typename dtl::enable_if, 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(x)); + BOOST_CONTAINER_TRY{ + dtl::construct_type(dtl::addressof(p->second), ::boost::forward(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 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)...); } + { dtl::construct_type(p, ::boost::forward(args)...); } #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) public: @@ -450,7 +590,7 @@ struct allocator_traits \ template\ 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 diff --git a/include/boost/container/deque.hpp b/include/boost/container/deque.hpp index 157c900..e599581 100644 --- a/include/boost/container/deque.hpp +++ b/include/boost/container/deque.hpp @@ -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 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 deque_iterator +{ + public: + typedef std::random_access_iterator_tag iterator_category; + typedef typename boost::intrusive::pointer_traits::element_type value_type; + typedef typename boost::intrusive::pointer_traits::difference_type difference_type; + typedef typename boost::intrusive::pointer_traits::size_type size_type; + typedef typename if_c + < IsConst + , typename boost::intrusive::pointer_traits::template + rebind_pointer::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; } + + 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 + , nat>::type nonconst_iterator; + + typedef Pointer val_alloc_ptr; + typedef typename boost::intrusive::pointer_traits:: + template rebind_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 deque_iterator +{ + public: + typedef std::random_access_iterator_tag iterator_category; + typedef typename boost::intrusive::pointer_traits::element_type value_type; + typedef typename boost::intrusive::pointer_traits::difference_type difference_type; + typedef typename boost::intrusive::pointer_traits::size_type size_type; + typedef typename if_c + < IsConst + , typename boost::intrusive::pointer_traits::template + rebind_pointer::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)); + return deque_block_size::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 + , nat>::type nonconst_iterator; + + typedef Pointer val_alloc_ptr; + typedef typename boost::intrusive::pointer_traits:: + template rebind_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 @@ -360,15 +805,20 @@ class deque_base typedef typename get_deque_opt::type options_type; protected: + #if BOOST_CONTAINER_DEQUE_LIGHTER_ITERATOR_LEVEL == 0 typedef dtl::deque_iterator iterator; - typedef dtl::deque_iterator const_iterator; + typedef dtl::deque_iterator const_iterator; + #else + typedef dtl::deque_iterator iterator; + typedef dtl::deque_iterator 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::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 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::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::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::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::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::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::type, } template - 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(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 + iterator priv_insert_aux_impl(const_iterator p, size_type n, InsertProxy proxy) + { + iterator pos(p.unconst()); + const size_type elemsbefore = static_cast(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 iterator priv_insert_back_aux_impl(size_type n, InsertProxy proxy) { @@ -2146,8 +2629,14 @@ class deque : protected deque_base::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::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::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::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::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::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::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 deque(InputIterator, InputIterator, Allocator const&) -> deque::value_type, Allocator>; #endif -}} +} //namespace container +} //namespace boost #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED diff --git a/include/boost/container/detail/construct_in_place.hpp b/include/boost/container/detail/construct_in_place.hpp index d824d81..bfdf05c 100644 --- a/include/boost/container/detail/construct_in_place.hpp +++ b/include/boost/container/detail/construct_in_place.hpp @@ -24,6 +24,7 @@ #include #include #include +#include namespace boost { namespace container { @@ -62,9 +63,42 @@ BOOST_CONTAINER_FORCEINLINE void construct_in_place(Allocator &a, T *dest, empla //Assignment +template +BOOST_CONTAINER_FORCEINLINE + typename dtl::disable_if_c + < dtl::is_pair::type>::value + && dtl::is_pair::type>::value + , void>::type +assign_in_place_ref(T &t, BOOST_FWD_REF(U) u) +{ t = ::boost::forward(u); } + +template +BOOST_CONTAINER_FORCEINLINE + typename dtl::enable_if_c + < dtl::is_pair::type>::value + && dtl::is_pair::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 +BOOST_CONTAINER_FORCEINLINE + typename dtl::enable_if_c + < dtl::is_pair::type>::value + && dtl::is_pair::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 BOOST_CONTAINER_FORCEINLINE void assign_in_place(DstIt dest, InpIt source) -{ *dest = *source; } +{ assign_in_place_ref(*dest, *source); } template BOOST_CONTAINER_FORCEINLINE void assign_in_place(DstIt dest, value_init_construct_iterator) diff --git a/include/boost/container/flat_map.hpp b/include/boost/container/flat_map.hpp index b092fb2..e4843f5 100644 --- a/include/boost/container/flat_map.hpp +++ b/include/boost/container/flat_map.hpp @@ -48,6 +48,11 @@ #include #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 BOOST_CONTAINER_FORCEINLINE static D &force(S &s) -{ return *move_detail::force_ptr(&s); } +{ return s; } template BOOST_CONTAINER_FORCEINLINE static const D &force(const S &s) -{ return *move_detail::force_ptr(&s); } +{ return s; } + +template +BOOST_CONTAINER_FORCEINLINE static D force_copy(D s) +{ return s; } + +#else //!BOOST_CONTAINER_DOXYGEN_INVOKED + +template +BOOST_CONTAINER_FORCEINLINE static D &force(S &s) +{ return *move_detail::launder_cast(&s); } + +template +BOOST_CONTAINER_FORCEINLINE static const D &force(const S &s) +{ return *move_detail::launder_cast(&s); } template BOOST_CONTAINER_FORCEINLINE static D force_copy(const S &s) { - const D *const vp = move_detail::force_ptr(&s); + const D *const vp = move_detail::launder_cast(&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 std_pair_t; typedef dtl::flat_tree< - std::pair, + std_pair_t, dtl::select1st, Compare, AllocatorOrContainer> tree_t; //This is the real tree stored here. It's based on a movable pair + typedef dtl::pair 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, + impl_pair_t, dtl::select1st, Compare, - typename dtl::container_or_allocator_rebind >::type + typename dtl::container_or_allocator_rebind::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(m_flat_tree.nth(n)); } + { return dtl::force_copy(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 inline BOOST_CONTAINER_DOC1ST ( std::pair - , typename dtl::enable_if_c::value + , typename dtl::enable_if_c::value BOOST_MOVE_I std::pair >::type) insert(BOOST_FWD_REF(Pair) x) { @@ -1153,7 +1183,7 @@ class flat_map template inline BOOST_CONTAINER_DOC1ST ( iterator - , typename dtl::enable_if_c::value + , typename dtl::enable_if_c::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 std_pair_t; typedef dtl::flat_tree< - std::pair, + std_pair_t, dtl::select1st, Compare, AllocatorOrContainer> tree_t; //This is the real tree stored here. It's based on a movable pair + typedef dtl::pair 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, + impl_pair_t, dtl::select1st, Compare, - typename dtl::container_or_allocator_rebind >::type + typename dtl::container_or_allocator_rebind::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(m_flat_tree.nth(n)); } + { return dtl::force_copy(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 inline BOOST_CONTAINER_DOC1ST ( iterator - , typename dtl::enable_if_c::value + , typename dtl::enable_if_c::value BOOST_MOVE_I iterator >::type) insert(BOOST_FWD_REF(Pair) x) { return dtl::force_copy(m_flat_tree.emplace_equal(boost::forward(x))); } @@ -2514,7 +2551,7 @@ class flat_multimap template inline BOOST_CONTAINER_DOC1ST ( iterator - , typename dtl::enable_if_c::value + , typename dtl::enable_if_c::value BOOST_MOVE_I iterator>::type) insert(const_iterator p, BOOST_FWD_REF(Pair) x) {