diff options
Diffstat (limited to 'boost/container')
25 files changed, 2296 insertions, 1231 deletions
diff --git a/boost/container/allocator_traits.hpp b/boost/container/allocator_traits.hpp index d6621f614a..b08f601461 100644 --- a/boost/container/allocator_traits.hpp +++ b/boost/container/allocator_traits.hpp @@ -347,7 +347,7 @@ struct allocator_traits #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) //! <b>Effects</b>: calls <code>a.construct(p, std::forward<Args>(args)...)</code> if that call is well-formed; - //! otherwise, invokes <code>::new (static_cast<void*>(p)) T(std::forward<Args>(args)...)</code> + //! otherwise, invokes <code>`placement new` (static_cast<void*>(p)) T(std::forward<Args>(args)...)</code> template <class T, class ...Args> BOOST_CONTAINER_FORCEINLINE static void construct(Allocator & a, T* p, BOOST_FWD_REF(Args)... args) { diff --git a/boost/container/deque.hpp b/boost/container/deque.hpp index 255cd9399d..b838f6e4eb 100644 --- a/boost/container/deque.hpp +++ b/boost/container/deque.hpp @@ -31,11 +31,11 @@ #include <boost/container/detail/alloc_helpers.hpp> #include <boost/container/detail/copy_move_algo.hpp> #include <boost/container/detail/iterator.hpp> -#include <boost/container/detail/iterator_to_raw_pointer.hpp> +#include <boost/move/detail/iterator_to_raw_pointer.hpp> #include <boost/container/detail/iterators.hpp> #include <boost/container/detail/min_max.hpp> #include <boost/container/detail/mpl.hpp> -#include <boost/container/detail/to_raw_pointer.hpp> +#include <boost/move/detail/to_raw_pointer.hpp> #include <boost/container/detail/type_traits.hpp> // move #include <boost/move/adl_move_swap.hpp> @@ -1649,7 +1649,7 @@ class deque : protected deque_base<Allocator> if (this->members_.m_start.m_cur != this->members_.m_start.m_last - 1) { allocator_traits_type::destroy ( this->alloc() - , container_detail::to_raw_pointer(this->members_.m_start.m_cur) + , boost::movelib::to_raw_pointer(this->members_.m_start.m_cur) ); ++this->members_.m_start.m_cur; } @@ -1669,7 +1669,7 @@ class deque : protected deque_base<Allocator> --this->members_.m_finish.m_cur; allocator_traits_type::destroy ( this->alloc() - , container_detail::to_raw_pointer(this->members_.m_finish.m_cur) + , boost::movelib::to_raw_pointer(this->members_.m_finish.m_cur) ); } else @@ -1916,7 +1916,7 @@ class deque : protected deque_base<Allocator> T *priv_push_back_simple_pos() const { - return container_detail::to_raw_pointer(this->members_.m_finish.m_cur); + return boost::movelib::to_raw_pointer(this->members_.m_finish.m_cur); } void priv_push_back_simple_commit() @@ -1931,7 +1931,7 @@ class deque : protected deque_base<Allocator> } T *priv_push_front_simple_pos() const - { return container_detail::to_raw_pointer(this->members_.m_start.m_cur) - 1; } + { return boost::movelib::to_raw_pointer(this->members_.m_start.m_cur) - 1; } void priv_push_front_simple_commit() { --this->members_.m_start.m_cur; } @@ -1940,7 +1940,7 @@ class deque : protected deque_base<Allocator> { if(!Base::traits_t::trivial_dctr){ for(;p != p2; ++p){ - allocator_traits_type::destroy(this->alloc(), container_detail::iterator_to_raw_pointer(p)); + allocator_traits_type::destroy(this->alloc(), boost::movelib::iterator_to_raw_pointer(p)); } } } @@ -1949,7 +1949,7 @@ class deque : protected deque_base<Allocator> { if(!Base::traits_t::trivial_dctr){ for(;p != p2; ++p){ - allocator_traits_type::destroy(this->alloc(), container_detail::iterator_to_raw_pointer(p)); + allocator_traits_type::destroy(this->alloc(), boost::movelib::iterator_to_raw_pointer(p)); } } } @@ -2133,7 +2133,7 @@ class deque : protected deque_base<Allocator> this->members_.m_finish.m_cur = this->members_.m_finish.m_last - 1; allocator_traits_type::destroy ( this->alloc() - , container_detail::to_raw_pointer(this->members_.m_finish.m_cur) + , boost::movelib::to_raw_pointer(this->members_.m_finish.m_cur) ); } @@ -2145,7 +2145,7 @@ class deque : protected deque_base<Allocator> { allocator_traits_type::destroy ( this->alloc() - , container_detail::to_raw_pointer(this->members_.m_start.m_cur) + , boost::movelib::to_raw_pointer(this->members_.m_start.m_cur) ); this->priv_deallocate_node(this->members_.m_start.m_first); this->members_.m_start.priv_set_node(this->members_.m_start.m_node + 1); diff --git a/boost/container/detail/adaptive_node_pool_impl.hpp b/boost/container/detail/adaptive_node_pool_impl.hpp index 24c81dda3b..54db19dff2 100644 --- a/boost/container/detail/adaptive_node_pool_impl.hpp +++ b/boost/container/detail/adaptive_node_pool_impl.hpp @@ -28,10 +28,10 @@ // container/detail #include <boost/container/detail/pool_common.hpp> #include <boost/container/detail/iterator.hpp> -#include <boost/container/detail/iterator_to_raw_pointer.hpp> +#include <boost/move/detail/iterator_to_raw_pointer.hpp> #include <boost/container/detail/math_functions.hpp> #include <boost/container/detail/mpl.hpp> -#include <boost/container/detail/to_raw_pointer.hpp> +#include <boost/move/detail/to_raw_pointer.hpp> #include <boost/container/detail/type_traits.hpp> // intrusive #include <boost/intrusive/pointer_traits.hpp> @@ -378,7 +378,7 @@ class private_adaptive_node_pool_impl //!Returns the segment manager. Never throws segment_manager_base_type* get_segment_manager_base()const - { return container_detail::to_raw_pointer(mp_segment_mngr_base); } + { return boost::movelib::to_raw_pointer(mp_segment_mngr_base); } //!Allocates array of count elements. Can throw void *allocate_node() @@ -390,7 +390,7 @@ class private_adaptive_node_pool_impl free_nodes_t &free_nodes = m_block_container.begin()->free_nodes; BOOST_ASSERT(!free_nodes.empty()); const size_type free_nodes_count = free_nodes.size(); - void *first_node = container_detail::to_raw_pointer(free_nodes.pop_front()); + void *first_node = boost::movelib::to_raw_pointer(free_nodes.pop_front()); if(free_nodes.empty()){ block_container_traits_t::erase_first(m_block_container); } @@ -401,7 +401,7 @@ class private_adaptive_node_pool_impl else{ multiallocation_chain chain; this->priv_append_from_new_blocks(1, chain, IsAlignOnly()); - return container_detail::to_raw_pointer(chain.pop_front()); + return boost::movelib::to_raw_pointer(chain.pop_front()); } } @@ -492,7 +492,7 @@ class private_adaptive_node_pool_impl free_nodes_iterator itf(nodes.begin()), itbf(itbb); size_type splice_node_count = size_type(-1); while(itf != ite){ - void *pElem = container_detail::to_raw_pointer(container_detail::iterator_to_raw_pointer(itf)); + void *pElem = boost::movelib::to_raw_pointer(boost::movelib::iterator_to_raw_pointer(itf)); block_info_t &block_info = *this->priv_block_from_node(pElem); BOOST_ASSERT(block_info.free_nodes.size() < m_real_num_node); ++splice_node_count; @@ -631,7 +631,7 @@ class private_adaptive_node_pool_impl BOOST_ASSERT(to_deallocate->free_nodes.size() == mp_impl->m_real_num_node); BOOST_ASSERT(0 == to_deallocate->hdr_offset); hdr_offset_holder *hdr_off_holder = - mp_impl->priv_first_subblock_from_block(container_detail::to_raw_pointer(to_deallocate)); + mp_impl->priv_first_subblock_from_block(boost::movelib::to_raw_pointer(to_deallocate)); m_chain.push_back(hdr_off_holder); } @@ -763,7 +763,7 @@ class private_adaptive_node_pool_impl //First add all possible nodes to the chain const size_type left = total_elements - chain.size(); const size_type max_chain = (num_node < left) ? num_node : left; - mem_address = static_cast<char *>(container_detail::to_raw_pointer + mem_address = static_cast<char *>(boost::movelib::to_raw_pointer (chain.incorporate_after(chain.last(), void_pointer(mem_address), m_real_node_size, max_chain))); //Now store remaining nodes in the free list if(const size_type max_free = num_node - max_chain){ diff --git a/boost/container/detail/advanced_insert_int.hpp b/boost/container/detail/advanced_insert_int.hpp index 1050857c46..20adb523a6 100644 --- a/boost/container/detail/advanced_insert_int.hpp +++ b/boost/container/detail/advanced_insert_int.hpp @@ -31,7 +31,7 @@ #include <boost/container/detail/type_traits.hpp> #include <boost/container/detail/iterator.hpp> #include <boost/container/detail/iterators.hpp> -#include <boost/container/detail/iterator_to_raw_pointer.hpp> +#include <boost/move/detail/iterator_to_raw_pointer.hpp> #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) #include <boost/move/detail/fwd_macros.hpp> #endif @@ -157,7 +157,7 @@ struct insert_copy_proxy void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const { BOOST_ASSERT(n == 1); (void)n; - alloc_traits::construct( a, iterator_to_raw_pointer(p), v_); + alloc_traits::construct( a, boost::movelib::iterator_to_raw_pointer(p), v_); } void copy_n_and_update(Allocator &, Iterator p, size_type n) const @@ -184,7 +184,7 @@ struct insert_move_proxy void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const { BOOST_ASSERT(n == 1); (void)n; - alloc_traits::construct( a, iterator_to_raw_pointer(p), ::boost::move(v_) ); + alloc_traits::construct( a, boost::movelib::iterator_to_raw_pointer(p), ::boost::move(v_) ); } void copy_n_and_update(Allocator &, Iterator p, size_type n) const @@ -240,7 +240,7 @@ struct insert_nonmovable_emplace_proxy void priv_uninitialized_copy_some_and_update(Allocator &a, const index_tuple<IdxPack...>&, Iterator p, size_type n) { BOOST_ASSERT(n == 1); (void)n; - alloc_traits::construct( a, iterator_to_raw_pointer(p), ::boost::forward<Args>(get<IdxPack>(this->args_))... ); + alloc_traits::construct( a, boost::movelib::iterator_to_raw_pointer(p), ::boost::forward<Args>(get<IdxPack>(this->args_))... ); } protected: @@ -354,7 +354,7 @@ struct insert_nonmovable_emplace_proxy##N\ void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n)\ {\ BOOST_ASSERT(n == 1); (void)n;\ - alloc_traits::construct(a, iterator_to_raw_pointer(p) BOOST_MOVE_I##N BOOST_MOVE_MFWD##N);\ + alloc_traits::construct(a, boost::movelib::iterator_to_raw_pointer(p) BOOST_MOVE_I##N BOOST_MOVE_MFWD##N);\ }\ \ void copy_n_and_update(Allocator &, Iterator, size_type)\ diff --git a/boost/container/detail/algorithm.hpp b/boost/container/detail/algorithm.hpp index 67e7876345..11844220e1 100644 --- a/boost/container/detail/algorithm.hpp +++ b/boost/container/detail/algorithm.hpp @@ -29,6 +29,128 @@ namespace container { using boost::intrusive::algo_equal; using boost::intrusive::algo_lexicographical_compare; +template<class Func> +class binder1st +{ + public: + typedef typename Func::second_argument_type argument_type; + typedef typename Func::result_type result_type; + + binder1st(const Func& func, const typename Func::first_argument_type& arg) + : op(func), value(arg) + {} + + result_type operator()(const argument_type& arg) const + { return op(value, arg); } + + result_type operator()(argument_type& arg) const + { return op(value, arg); } + + private: + Func op; + typename Func::first_argument_type value; +}; + +template<class Func, class T> +inline binder1st<Func> bind1st(const Func& func, const T& arg) +{ return boost::container::binder1st<Func>(func, arg); } + +template<class Func> +class binder2nd +{ + public: + typedef typename Func::first_argument_type argument_type; + typedef typename Func::result_type result_type; + + binder2nd(const Func& func, const typename Func::second_argument_type& arg) + : op(func), value(arg) + {} + + result_type operator()(const argument_type& arg) const + { return op(arg, value); } + + result_type operator()(argument_type& arg) const + { return op(arg, value); } + + private: + Func op; + typename Func::second_argument_type value; +}; + +template<class Func, class T> +inline binder2nd<Func> bind2nd(const Func& func, const T& arg) +{ + return (boost::container::binder2nd<Func>(func, arg)); +} + +template<class Func> +class unary_negate +{ + public: + typedef typename Func::argument_type argument_type; + typedef typename Func::result_type result_type; + + explicit unary_negate(const Func& func) + : m_func(func) + {} + + bool operator()(const typename Func::argument_type& arg) const + { return !m_func(arg); } + + private: + Func m_func; +}; + +template<class Func> inline +unary_negate<Func> not1(const Func& func) +{ + return boost::container::unary_negate<Func>(func); +} + +template<class InputIt, class UnaryPredicate> +InputIt find_if(InputIt first, InputIt last, UnaryPredicate p) +{ + for (; first != last; ++first) { + if (p(*first)) { + return first; + } + } + return last; +} + +template<class InputIt, class ForwardIt, class BinaryPredicate> +InputIt find_first_of(InputIt first1, InputIt last1, ForwardIt first2, ForwardIt last2, BinaryPredicate p) +{ + for (; first1 != last1; ++first1) { + for (ForwardIt it = first2; it != last2; ++it) { + if (p(*first1, *it)) { + return first1; + } + } + } + return last1; +} + +template<class ForwardIt1, class ForwardIt2, class BinaryPredicate> +ForwardIt1 search(ForwardIt1 first1, ForwardIt1 last1, + ForwardIt2 first2, ForwardIt2 last2, BinaryPredicate p) +{ + for (; ; ++first1) { + ForwardIt1 it = first1; + for (ForwardIt2 it2 = first2; ; ++it, ++it2) { + if (it2 == last2) { + return first1; + } + if (it == last1) { + return last1; + } + if (!p(*it, *it2)) { + break; + } + } + } +} + } //namespace container { } //namespace boost { diff --git a/boost/container/detail/copy_move_algo.hpp b/boost/container/detail/copy_move_algo.hpp index dda311aa33..9044960e79 100644 --- a/boost/container/detail/copy_move_algo.hpp +++ b/boost/container/detail/copy_move_algo.hpp @@ -22,7 +22,7 @@ #include <boost/container/allocator_traits.hpp> // container/detail #include <boost/container/detail/iterator.hpp> -#include <boost/container/detail/iterator_to_raw_pointer.hpp> +#include <boost/move/detail/iterator_to_raw_pointer.hpp> #include <boost/container/detail/mpl.hpp> #include <boost/container/detail/type_traits.hpp> #include <boost/container/detail/construct_in_place.hpp> @@ -178,7 +178,7 @@ inline F memmove(I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW typedef typename boost::container::iterator_traits<I>::value_type value_type; typename boost::container::iterator_traits<I>::difference_type n = boost::container::iterator_distance(f, l); if(n){ - std::memmove((iterator_to_raw_pointer)(r), (iterator_to_raw_pointer)(f), sizeof(value_type)*n); + std::memmove(boost::movelib::iterator_to_raw_pointer(r), boost::movelib::iterator_to_raw_pointer(f), sizeof(value_type)*n); boost::container::iterator_advance(r, n); } return r; @@ -192,7 +192,7 @@ F memmove_n(I f, U n, F r) BOOST_NOEXCEPT_OR_NOTHROW { typedef typename boost::container::iterator_traits<I>::value_type value_type; if(n){ - std::memmove((iterator_to_raw_pointer)(r), (iterator_to_raw_pointer)(f), sizeof(value_type)*n); + std::memmove(boost::movelib::iterator_to_raw_pointer(r), boost::movelib::iterator_to_raw_pointer(f), sizeof(value_type)*n); boost::container::iterator_advance(r, n); } return r; @@ -206,7 +206,7 @@ I memmove_n_source(I f, U n, F r) BOOST_NOEXCEPT_OR_NOTHROW { if(n){ typedef typename boost::container::iterator_traits<I>::value_type value_type; - std::memmove((iterator_to_raw_pointer)(r), (iterator_to_raw_pointer)(f), sizeof(value_type)*n); + std::memmove(boost::movelib::iterator_to_raw_pointer(r), boost::movelib::iterator_to_raw_pointer(f), sizeof(value_type)*n); boost::container::iterator_advance(f, n); } return f; @@ -220,7 +220,7 @@ I memmove_n_source_dest(I f, U n, F &r) BOOST_NOEXCEPT_OR_NOTHROW { typedef typename boost::container::iterator_traits<I>::value_type value_type; if(n){ - std::memmove((iterator_to_raw_pointer)(r), (iterator_to_raw_pointer)(f), sizeof(value_type)*n); + std::memmove(boost::movelib::iterator_to_raw_pointer(r), boost::movelib::iterator_to_raw_pointer(f), sizeof(value_type)*n); boost::container::iterator_advance(f, n); boost::container::iterator_advance(r, n); } @@ -295,13 +295,13 @@ inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F F back = r; BOOST_TRY{ while (f != l) { - allocator_traits<Allocator>::construct(a, container_detail::iterator_to_raw_pointer(r), boost::move(*f)); + allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r), boost::move(*f)); ++f; ++r; } } BOOST_CATCH(...){ for (; back != r; ++back){ - allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(back)); + allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back)); } BOOST_RETHROW; } @@ -340,13 +340,13 @@ inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F F back = r; BOOST_TRY{ while (n--) { - allocator_traits<Allocator>::construct(a, container_detail::iterator_to_raw_pointer(r), boost::move(*f)); + allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r), boost::move(*f)); ++f; ++r; } } BOOST_CATCH(...){ for (; back != r; ++back){ - allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(back)); + allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back)); } BOOST_RETHROW; } @@ -385,13 +385,13 @@ inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F F back = r; BOOST_TRY{ while (n--) { - allocator_traits<Allocator>::construct(a, container_detail::iterator_to_raw_pointer(r), boost::move(*f)); + allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r), boost::move(*f)); ++f; ++r; } } BOOST_CATCH(...){ for (; back != r; ++back){ - allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(back)); + allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back)); } BOOST_RETHROW; } @@ -430,13 +430,13 @@ inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F F back = r; BOOST_TRY{ while (f != l) { - allocator_traits<Allocator>::construct(a, container_detail::iterator_to_raw_pointer(r), *f); + allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r), *f); ++f; ++r; } } BOOST_CATCH(...){ for (; back != r; ++back){ - allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(back)); + allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back)); } BOOST_RETHROW; } @@ -475,13 +475,13 @@ inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F F back = r; BOOST_TRY{ while (n--) { - allocator_traits<Allocator>::construct(a, container_detail::iterator_to_raw_pointer(r), *f); + allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r), *f); ++f; ++r; } } BOOST_CATCH(...){ for (; back != r; ++back){ - allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(back)); + allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back)); } BOOST_RETHROW; } @@ -520,13 +520,13 @@ inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F F back = r; BOOST_TRY{ while (n--) { - boost::container::construct_in_place(a, container_detail::iterator_to_raw_pointer(r), f); + boost::container::construct_in_place(a, boost::movelib::iterator_to_raw_pointer(r), f); ++f; ++r; } } BOOST_CATCH(...){ for (; back != r; ++back){ - allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(back)); + allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back)); } BOOST_RETHROW; } @@ -564,13 +564,13 @@ inline typename container_detail::disable_if_memzero_initializable<F, F>::type F back = r; BOOST_TRY{ while (n--) { - allocator_traits<Allocator>::construct(a, container_detail::iterator_to_raw_pointer(r)); + allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r)); ++r; } } BOOST_CATCH(...){ for (; back != r; ++back){ - allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(back)); + allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back)); } BOOST_RETHROW; } @@ -585,7 +585,7 @@ inline typename container_detail::enable_if_memzero_initializable<F, F>::type uninitialized_value_init_alloc_n(Allocator &, typename boost::container::allocator_traits<Allocator>::size_type n, F r) { typedef typename boost::container::iterator_traits<F>::value_type value_type; - std::memset((void*)container_detail::iterator_to_raw_pointer(r), 0, sizeof(value_type)*n); + std::memset((void*)boost::movelib::iterator_to_raw_pointer(r), 0, sizeof(value_type)*n); boost::container::iterator_advance(r, n); return r; } @@ -611,13 +611,13 @@ inline F uninitialized_default_init_alloc_n(Allocator &a, typename boost::contai F back = r; BOOST_TRY{ while (n--) { - allocator_traits<Allocator>::construct(a, container_detail::iterator_to_raw_pointer(r), default_init); + allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r), default_init); ++r; } } BOOST_CATCH(...){ for (; back != r; ++back){ - allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(back)); + allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back)); } BOOST_RETHROW; } @@ -647,13 +647,13 @@ inline void uninitialized_fill_alloc(Allocator &a, F f, F l, const T &t) F back = f; BOOST_TRY{ while (f != l) { - allocator_traits<Allocator>::construct(a, container_detail::iterator_to_raw_pointer(f), t); + allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(f), t); ++f; } } BOOST_CATCH(...){ for (; back != l; ++back){ - allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(back)); + allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back)); } BOOST_RETHROW; } @@ -683,13 +683,13 @@ inline F uninitialized_fill_alloc_n(Allocator &a, const T &v, typename boost::co F back = r; BOOST_TRY{ while (n--) { - allocator_traits<Allocator>::construct(a, container_detail::iterator_to_raw_pointer(r), v); + allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r), v); ++r; } } BOOST_CATCH(...){ for (; back != r; ++back){ - allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(back)); + allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back)); } BOOST_RETHROW; } @@ -890,7 +890,7 @@ inline typename container_detail::enable_if_memtransfer_copy_assignable<I, F, F> typedef typename boost::container::iterator_traits<I>::value_type value_type; const typename boost::container::iterator_traits<I>::difference_type n = boost::container::iterator_distance(f, l); r -= n; - std::memmove((container_detail::iterator_to_raw_pointer)(r), (container_detail::iterator_to_raw_pointer)(f), sizeof(value_type)*n); + std::memmove((boost::movelib::iterator_to_raw_pointer)(r), (boost::movelib::iterator_to_raw_pointer)(f), sizeof(value_type)*n); return r; } @@ -963,8 +963,9 @@ template inline typename container_detail::disable_if_trivially_destructible<I, void>::type destroy_alloc_n(Allocator &a, I f, U n) { - while(n--){ - allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(f)); + while(n){ + --n; + allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(f)); ++f; } } @@ -1021,9 +1022,9 @@ inline typename container_detail::enable_if_c storage_type storage; const std::size_t n_i_bytes = sizeof(value_type)*n_i; - void *const large_ptr = static_cast<void*>(container_detail::iterator_to_raw_pointer(large_range_f)); - void *const short_ptr = static_cast<void*>(container_detail::iterator_to_raw_pointer(short_range_f)); - void *const stora_ptr = static_cast<void*>(container_detail::iterator_to_raw_pointer(storage)); + void *const large_ptr = static_cast<void*>(boost::movelib::iterator_to_raw_pointer(large_range_f)); + void *const short_ptr = static_cast<void*>(boost::movelib::iterator_to_raw_pointer(short_range_f)); + void *const stora_ptr = static_cast<void*>(boost::movelib::iterator_to_raw_pointer(storage)); std::memcpy(stora_ptr, large_ptr, n_i_bytes); std::memcpy(large_ptr, short_ptr, n_i_bytes); std::memcpy(short_ptr, stora_ptr, n_i_bytes); @@ -1052,8 +1053,8 @@ inline typename container_detail::enable_if_c const std::size_t sizeof_storage = sizeof(storage); std::size_t n_i_bytes = sizeof(value_type)*n_i; - char *large_ptr = static_cast<char*>(static_cast<void*>(container_detail::iterator_to_raw_pointer(large_range_f))); - char *short_ptr = static_cast<char*>(static_cast<void*>(container_detail::iterator_to_raw_pointer(short_range_f))); + char *large_ptr = static_cast<char*>(static_cast<void*>(boost::movelib::iterator_to_raw_pointer(large_range_f))); + char *short_ptr = static_cast<char*>(static_cast<void*>(boost::movelib::iterator_to_raw_pointer(short_range_f))); char *stora_ptr = static_cast<char*>(static_cast<void*>(&storage)); std::size_t szt_times = n_i_bytes/sizeof_storage; diff --git a/boost/container/detail/destroyers.hpp b/boost/container/detail/destroyers.hpp index 52b44c0363..b110561a4a 100644 --- a/boost/container/detail/destroyers.hpp +++ b/boost/container/detail/destroyers.hpp @@ -25,7 +25,7 @@ #include <boost/container/detail/workaround.hpp> #include <boost/container/allocator_traits.hpp> -#include <boost/container/detail/to_raw_pointer.hpp> +#include <boost/move/detail/to_raw_pointer.hpp> #include <boost/container/detail/version_type.hpp> namespace boost { @@ -152,7 +152,7 @@ struct scoped_destroy_deallocator ~scoped_destroy_deallocator() { if(m_ptr){ - AllocTraits::destroy(m_alloc, container_detail::to_raw_pointer(m_ptr)); + AllocTraits::destroy(m_alloc, boost::movelib::to_raw_pointer(m_ptr)); priv_deallocate(m_ptr, alloc_version()); } } @@ -202,7 +202,7 @@ struct scoped_destructor_n ~scoped_destructor_n() { if(!m_p) return; - value_type *raw_ptr = container_detail::to_raw_pointer(m_p); + value_type *raw_ptr = boost::movelib::to_raw_pointer(m_p); while(m_n--){ AllocTraits::destroy(m_a, raw_ptr++); } @@ -317,7 +317,7 @@ class allocator_destroyer void operator()(const pointer &p) { - AllocTraits::destroy(a_, container_detail::to_raw_pointer(p)); + AllocTraits::destroy(a_, boost::movelib::to_raw_pointer(p)); this->priv_deallocate(p, alloc_version()); } }; @@ -339,7 +339,7 @@ class allocator_destroyer_and_chain_builder void operator()(const typename Allocator::pointer &p) { - allocator_traits<Allocator>::destroy(a_, container_detail::to_raw_pointer(p)); + allocator_traits<Allocator>::destroy(a_, boost::movelib::to_raw_pointer(p)); c_.push_back(p); } }; diff --git a/boost/container/detail/flat_tree.hpp b/boost/container/detail/flat_tree.hpp index 93984d18e5..9aab87308a 100644 --- a/boost/container/detail/flat_tree.hpp +++ b/boost/container/detail/flat_tree.hpp @@ -28,25 +28,30 @@ #include <boost/container/detail/pair.hpp> #include <boost/container/vector.hpp> +#include <boost/container/allocator_traits.hpp> + #include <boost/container/detail/value_init.hpp> #include <boost/container/detail/destroyers.hpp> #include <boost/container/detail/algorithm.hpp> //algo_equal(), algo_lexicographical_compare #include <boost/container/detail/iterator.hpp> #include <boost/container/detail/is_sorted.hpp> -#include <boost/container/allocator_traits.hpp> +#include <boost/container/detail/type_traits.hpp> +#include <boost/container/detail/iterators.hpp> + #ifdef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER #include <boost/intrusive/pointer_traits.hpp> #endif -#include <boost/container/detail/type_traits.hpp> -#include <boost/container/detail/iterators.hpp> +#include <boost/intrusive/detail/minimal_pair_header.hpp> //pair + #include <boost/move/make_unique.hpp> +#include <boost/move/iterator.hpp> #include <boost/move/adl_move_swap.hpp> +#include <boost/move/algo/adaptive_sort.hpp> + #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) #include <boost/move/detail/fwd_macros.hpp> #endif -#include <boost/intrusive/detail/minimal_pair_header.hpp> //pair -#include <boost/move/iterator.hpp> namespace boost { namespace container { @@ -105,14 +110,17 @@ template <class Value, class KeyOfValue, class Compare, class Allocator> class flat_tree { - typedef boost::container::vector<Value, Allocator> vector_t; + public: + typedef boost::container::vector<Value, Allocator> sequence_type; + + private: typedef Allocator allocator_t; typedef allocator_traits<Allocator> allocator_traits_type; public: typedef flat_tree_value_compare<Compare, Value, KeyOfValue> value_compare; - private: + private: struct Data //Inherit from value_compare to do EBO : public value_compare @@ -121,48 +129,48 @@ class flat_tree public: Data() - : value_compare(), m_vect() + : value_compare(), m_seq() {} - explicit Data(const Data &d) - : value_compare(static_cast<const value_compare&>(d)), m_vect(d.m_vect) + explicit Data(const allocator_t &alloc) + : value_compare(), m_seq(alloc) {} - Data(BOOST_RV_REF(Data) d) - : value_compare(boost::move(static_cast<value_compare&>(d))), m_vect(boost::move(d.m_vect)) + explicit Data(const Compare &comp) + : value_compare(comp), m_seq() {} - Data(const Data &d, const Allocator &a) - : value_compare(static_cast<const value_compare&>(d)), m_vect(d.m_vect, a) + Data(const Compare &comp, const allocator_t &alloc) + : value_compare(comp), m_seq(alloc) {} - Data(BOOST_RV_REF(Data) d, const Allocator &a) - : value_compare(boost::move(static_cast<value_compare&>(d))), m_vect(boost::move(d.m_vect), a) + explicit Data(const Data &d) + : value_compare(static_cast<const value_compare&>(d)), m_seq(d.m_seq) {} - explicit Data(const Compare &comp) - : value_compare(comp), m_vect() + Data(BOOST_RV_REF(Data) d) + : value_compare(boost::move(static_cast<value_compare&>(d))), m_seq(boost::move(d.m_seq)) {} - Data(const Compare &comp, const allocator_t &alloc) - : value_compare(comp), m_vect(alloc) + Data(const Data &d, const Allocator &a) + : value_compare(static_cast<const value_compare&>(d)), m_seq(d.m_seq, a) {} - explicit Data(const allocator_t &alloc) - : value_compare(), m_vect(alloc) + Data(BOOST_RV_REF(Data) d, const Allocator &a) + : value_compare(boost::move(static_cast<value_compare&>(d))), m_seq(boost::move(d.m_seq), a) {} Data& operator=(BOOST_COPY_ASSIGN_REF(Data) d) { this->value_compare::operator=(d); - m_vect = d.m_vect; + m_seq = d.m_seq; return *this; } Data& operator=(BOOST_RV_REF(Data) d) { this->value_compare::operator=(boost::move(static_cast<value_compare &>(d))); - m_vect = boost::move(d.m_vect); + m_seq = boost::move(d.m_seq); return *this; } @@ -170,10 +178,10 @@ class flat_tree { value_compare& mycomp = *this, & othercomp = d; boost::adl_move_swap(mycomp, othercomp); - this->m_vect.swap(d.m_vect); + this->m_seq.swap(d.m_seq); } - vector_t m_vect; + sequence_type m_seq; }; Data m_data; @@ -181,23 +189,23 @@ class flat_tree public: - typedef typename vector_t::value_type value_type; - typedef typename vector_t::pointer pointer; - typedef typename vector_t::const_pointer const_pointer; - typedef typename vector_t::reference reference; - typedef typename vector_t::const_reference const_reference; - typedef typename KeyOfValue::type key_type; - typedef Compare key_compare; - typedef typename vector_t::allocator_type allocator_type; - typedef typename vector_t::size_type size_type; - typedef typename vector_t::difference_type difference_type; - typedef typename vector_t::iterator iterator; - typedef typename vector_t::const_iterator const_iterator; - typedef typename vector_t::reverse_iterator reverse_iterator; - typedef typename vector_t::const_reverse_iterator const_reverse_iterator; + typedef typename sequence_type::value_type value_type; + typedef typename sequence_type::pointer pointer; + typedef typename sequence_type::const_pointer const_pointer; + typedef typename sequence_type::reference reference; + typedef typename sequence_type::const_reference const_reference; + typedef typename KeyOfValue::type key_type; + typedef Compare key_compare; + typedef typename sequence_type::allocator_type allocator_type; + typedef typename sequence_type::size_type size_type; + typedef typename sequence_type::difference_type difference_type; + typedef typename sequence_type::iterator iterator; + typedef typename sequence_type::const_iterator const_iterator; + typedef typename sequence_type::reverse_iterator reverse_iterator; + typedef typename sequence_type::const_reverse_iterator const_reverse_iterator; //!Standard extension - typedef allocator_type stored_allocator_type; + typedef allocator_type stored_allocator_type; private: typedef allocator_traits<stored_allocator_type> stored_allocator_traits; @@ -211,14 +219,14 @@ class flat_tree : m_data(comp) { } - BOOST_CONTAINER_FORCEINLINE flat_tree(const Compare& comp, const allocator_type& a) - : m_data(comp, a) - { } - BOOST_CONTAINER_FORCEINLINE explicit flat_tree(const allocator_type& a) : m_data(a) { } + BOOST_CONTAINER_FORCEINLINE flat_tree(const Compare& comp, const allocator_type& a) + : m_data(comp, a) + { } + BOOST_CONTAINER_FORCEINLINE flat_tree(const flat_tree& x) : m_data(x.m_data) { } @@ -237,46 +245,92 @@ class flat_tree { } template <class InputIterator> - flat_tree( ordered_range_t, InputIterator first, InputIterator last - , const Compare& comp = Compare() - , const allocator_type& a = allocator_type()) + BOOST_CONTAINER_FORCEINLINE + flat_tree( ordered_range_t, InputIterator first, InputIterator last) + : m_data() + { + this->m_data.m_seq.insert(this->m_data.m_seq.end(), first, last); + BOOST_ASSERT((is_sorted)(this->m_data.m_seq.cbegin(), this->m_data.m_seq.cend(), this->priv_value_comp())); + } + + template <class InputIterator> + BOOST_CONTAINER_FORCEINLINE + flat_tree( ordered_range_t, InputIterator first, InputIterator last, const Compare& comp) + : m_data(comp) + { + this->m_data.m_seq.insert(this->m_data.m_seq.end(), first, last); + BOOST_ASSERT((is_sorted)(this->m_data.m_seq.cbegin(), this->m_data.m_seq.cend(), this->priv_value_comp())); + } + + template <class InputIterator> + BOOST_CONTAINER_FORCEINLINE + flat_tree( ordered_range_t, InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a) : m_data(comp, a) { - this->m_data.m_vect.insert(this->m_data.m_vect.end(), first, last); - BOOST_ASSERT((is_sorted)(this->m_data.m_vect.cbegin(), this->m_data.m_vect.cend(), this->priv_value_comp())); + this->m_data.m_seq.insert(this->m_data.m_seq.end(), first, last); + BOOST_ASSERT((is_sorted)(this->m_data.m_seq.cbegin(), this->m_data.m_seq.cend(), this->priv_value_comp())); + } + + template <class InputIterator> + BOOST_CONTAINER_FORCEINLINE + flat_tree( ordered_unique_range_t, InputIterator first, InputIterator last) + : m_data() + { + this->m_data.m_seq.insert(this->m_data.m_seq.end(), first, last); + BOOST_ASSERT((is_sorted_and_unique)(this->m_data.m_seq.cbegin(), this->m_data.m_seq.cend(), this->priv_value_comp())); } template <class InputIterator> - flat_tree( ordered_unique_range_t, InputIterator first, InputIterator last - , const Compare& comp = Compare() - , const allocator_type& a = allocator_type()) + BOOST_CONTAINER_FORCEINLINE + flat_tree( ordered_unique_range_t, InputIterator first, InputIterator last, const Compare& comp) + : m_data(comp) + { + this->m_data.m_seq.insert(this->m_data.m_seq.end(), first, last); + BOOST_ASSERT((is_sorted_and_unique)(this->m_data.m_seq.cbegin(), this->m_data.m_seq.cend(), this->priv_value_comp())); + } + + template <class InputIterator> + BOOST_CONTAINER_FORCEINLINE + flat_tree( ordered_unique_range_t, InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a) : m_data(comp, a) { - this->m_data.m_vect.insert(this->m_data.m_vect.end(), first, last); - BOOST_ASSERT((is_sorted_and_unique)(this->m_data.m_vect.cbegin(), this->m_data.m_vect.cend(), this->priv_value_comp())); + this->m_data.m_seq.insert(this->m_data.m_seq.end(), first, last); + BOOST_ASSERT((is_sorted_and_unique)(this->m_data.m_seq.cbegin(), this->m_data.m_seq.cend(), this->priv_value_comp())); } template <class InputIterator> - flat_tree( bool unique_insertion - , InputIterator first, InputIterator last - , const Compare& comp = Compare() - , const allocator_type& a = allocator_type()) + BOOST_CONTAINER_FORCEINLINE + flat_tree( bool unique_insertion, InputIterator first, InputIterator last) + : m_data() + { + this->priv_range_insertion_construct(unique_insertion, first, last); + } + + template <class InputIterator> + BOOST_CONTAINER_FORCEINLINE + flat_tree( bool unique_insertion, InputIterator first, InputIterator last + , const Compare& comp) + : m_data(comp) + { + this->priv_range_insertion_construct(unique_insertion, first, last); + } + + template <class InputIterator> + BOOST_CONTAINER_FORCEINLINE + flat_tree( bool unique_insertion, InputIterator first, InputIterator last + , const allocator_type& a) + : m_data(a) + { + this->priv_range_insertion_construct(unique_insertion, first, last); + } + + template <class InputIterator> + BOOST_CONTAINER_FORCEINLINE + flat_tree( bool unique_insertion, InputIterator first, InputIterator last + , const Compare& comp, const allocator_type& a) : m_data(comp, a) { - //Use cend() as hint to achieve linear time for - //ordered ranges as required by the standard - //for the constructor - //Call end() every iteration as reallocation might have invalidated iterators - if(unique_insertion){ - for ( ; first != last; ++first){ - this->insert_unique(this->cend(), *first); - } - } - else{ - for ( ; first != last; ++first){ - this->insert_equal(this->cend(), *first); - } - } + this->priv_range_insertion_construct(unique_insertion, first, last); } BOOST_CONTAINER_FORCEINLINE ~flat_tree() @@ -312,31 +366,31 @@ class flat_tree { return this->m_data; } BOOST_CONTAINER_FORCEINLINE allocator_type get_allocator() const - { return this->m_data.m_vect.get_allocator(); } + { return this->m_data.m_seq.get_allocator(); } BOOST_CONTAINER_FORCEINLINE const stored_allocator_type &get_stored_allocator() const - { return this->m_data.m_vect.get_stored_allocator(); } + { return this->m_data.m_seq.get_stored_allocator(); } BOOST_CONTAINER_FORCEINLINE stored_allocator_type &get_stored_allocator() - { return this->m_data.m_vect.get_stored_allocator(); } + { return this->m_data.m_seq.get_stored_allocator(); } BOOST_CONTAINER_FORCEINLINE iterator begin() - { return this->m_data.m_vect.begin(); } + { return this->m_data.m_seq.begin(); } BOOST_CONTAINER_FORCEINLINE const_iterator begin() const { return this->cbegin(); } BOOST_CONTAINER_FORCEINLINE const_iterator cbegin() const - { return this->m_data.m_vect.begin(); } + { return this->m_data.m_seq.begin(); } BOOST_CONTAINER_FORCEINLINE iterator end() - { return this->m_data.m_vect.end(); } + { return this->m_data.m_seq.end(); } BOOST_CONTAINER_FORCEINLINE const_iterator end() const { return this->cend(); } BOOST_CONTAINER_FORCEINLINE const_iterator cend() const - { return this->m_data.m_vect.end(); } + { return this->m_data.m_seq.end(); } BOOST_CONTAINER_FORCEINLINE reverse_iterator rbegin() { return reverse_iterator(this->end()); } @@ -357,13 +411,13 @@ class flat_tree { return const_reverse_iterator(this->cbegin()); } BOOST_CONTAINER_FORCEINLINE bool empty() const - { return this->m_data.m_vect.empty(); } + { return this->m_data.m_seq.empty(); } BOOST_CONTAINER_FORCEINLINE size_type size() const - { return this->m_data.m_vect.size(); } + { return this->m_data.m_seq.size(); } BOOST_CONTAINER_FORCEINLINE size_type max_size() const - { return this->m_data.m_vect.max_size(); } + { return this->m_data.m_seq.max_size(); } BOOST_CONTAINER_FORCEINLINE void swap(flat_tree& other) BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value @@ -395,14 +449,14 @@ class flat_tree iterator insert_equal(const value_type& val) { iterator i = this->upper_bound(KeyOfValue()(val)); - i = this->m_data.m_vect.insert(i, val); + i = this->m_data.m_seq.insert(i, val); return i; } iterator insert_equal(BOOST_RV_REF(value_type) mval) { iterator i = this->upper_bound(KeyOfValue()(mval)); - i = this->m_data.m_vect.insert(i, boost::move(mval)); + i = this->m_data.m_seq.insert(i, boost::move(mval)); return i; } @@ -509,7 +563,7 @@ class flat_tree >::type * = 0 #endif ) - { this->m_data.m_vect.merge(first, last, static_cast<const value_compare &>(this->m_data)); } + { this->m_data.m_seq.merge(first, last, static_cast<const value_compare &>(this->m_data)); } template <class InIt> void insert_unique(ordered_unique_range_t, InIt first, InIt last @@ -538,7 +592,7 @@ class flat_tree >::type * = 0 #endif ) - { this->m_data.m_vect.merge_unique(first, last, static_cast<const value_compare &>(this->m_data)); } + { this->m_data.m_seq.merge_unique(first, last, static_cast<const value_compare &>(this->m_data)); } #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) @@ -606,7 +660,7 @@ class flat_tree typedef typename emplace_functor_type<try_emplace_t, KeyType, Args...>::type func_t; typedef emplace_iterator<value_type, func_t, difference_type> it_t; func_t func(try_emplace_t(), ::boost::forward<KeyType>(key), ::boost::forward<Args>(args)...); - ret.first = this->m_data.m_vect.insert(data.position, it_t(func), it_t()); + ret.first = this->m_data.m_seq.insert(data.position, it_t(func), it_t()); } return ret; } @@ -675,7 +729,7 @@ class flat_tree typedef typename emplace_functor_type<try_emplace_t, KeyType BOOST_MOVE_I##N BOOST_MOVE_TARG##N>::type func_t;\ typedef emplace_iterator<value_type, func_t, difference_type> it_t;\ func_t func(try_emplace_t(), ::boost::forward<KeyType>(key) BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\ - ret.first = this->m_data.m_vect.insert(data.position, it_t(func), it_t());\ + ret.first = this->m_data.m_seq.insert(data.position, it_t(func), it_t());\ }\ return ret;\ }\ @@ -702,29 +756,29 @@ class flat_tree typedef typename emplace_functor_type<KeyType, M>::type func_t; typedef emplace_iterator<value_type, func_t, difference_type> it_t; func_t func(boost::forward<KeyType>(key), boost::forward<M>(obj)); - ret.first = this->m_data.m_vect.insert(data.position, it_t(func), it_t()); + ret.first = this->m_data.m_seq.insert(data.position, it_t(func), it_t()); } return ret; } BOOST_CONTAINER_FORCEINLINE iterator erase(const_iterator position) - { return this->m_data.m_vect.erase(position); } + { return this->m_data.m_seq.erase(position); } size_type erase(const key_type& k) { std::pair<iterator,iterator > itp = this->equal_range(k); size_type ret = static_cast<size_type>(itp.second-itp.first); if (ret){ - this->m_data.m_vect.erase(itp.first, itp.second); + this->m_data.m_seq.erase(itp.first, itp.second); } return ret; } BOOST_CONTAINER_FORCEINLINE iterator erase(const_iterator first, const_iterator last) - { return this->m_data.m_vect.erase(first, last); } + { return this->m_data.m_seq.erase(first, last); } BOOST_CONTAINER_FORCEINLINE void clear() - { this->m_data.m_vect.clear(); } + { this->m_data.m_seq.clear(); } //! <b>Effects</b>: Tries to deallocate the excess of memory created // with previous allocations. The size of the vector is unchanged @@ -733,19 +787,19 @@ class flat_tree //! //! <b>Complexity</b>: Linear to size(). BOOST_CONTAINER_FORCEINLINE void shrink_to_fit() - { this->m_data.m_vect.shrink_to_fit(); } + { this->m_data.m_seq.shrink_to_fit(); } BOOST_CONTAINER_FORCEINLINE iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW - { return this->m_data.m_vect.nth(n); } + { return this->m_data.m_seq.nth(n); } BOOST_CONTAINER_FORCEINLINE const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW - { return this->m_data.m_vect.nth(n); } + { return this->m_data.m_seq.nth(n); } BOOST_CONTAINER_FORCEINLINE size_type index_of(iterator p) BOOST_NOEXCEPT_OR_NOTHROW - { return this->m_data.m_vect.index_of(p); } + { return this->m_data.m_seq.index_of(p); } BOOST_CONTAINER_FORCEINLINE size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW - { return this->m_data.m_vect.index_of(p); } + { return this->m_data.m_seq.index_of(p); } // set operations: iterator find(const key_type& k) @@ -793,7 +847,7 @@ class flat_tree void merge_unique(flat_tree& source) { - this->m_data.m_vect.merge_unique + this->m_data.m_seq.merge_unique ( boost::make_move_iterator(source.begin()) , boost::make_move_iterator(source.end()) , static_cast<const value_compare &>(this->m_data)); @@ -801,7 +855,7 @@ class flat_tree void merge_equal(flat_tree& source) { - this->m_data.m_vect.merge + this->m_data.m_seq.merge ( boost::make_move_iterator(source.begin()) , boost::make_move_iterator(source.end()) , static_cast<const value_compare &>(this->m_data)); @@ -832,10 +886,61 @@ class flat_tree { return this->priv_lower_bound_range(this->cbegin(), this->cend(), k); } BOOST_CONTAINER_FORCEINLINE size_type capacity() const - { return this->m_data.m_vect.capacity(); } + { return this->m_data.m_seq.capacity(); } BOOST_CONTAINER_FORCEINLINE void reserve(size_type cnt) - { this->m_data.m_vect.reserve(cnt); } + { this->m_data.m_seq.reserve(cnt); } + + BOOST_CONTAINER_FORCEINLINE sequence_type extract_sequence() + { + return boost::move(m_data.m_seq); + } + + BOOST_CONTAINER_FORCEINLINE sequence_type &get_sequence_ref() + { + return m_data.m_seq; + } + + void adopt_sequence_equal(BOOST_RV_REF(sequence_type) seq) + { + sequence_type &tseq = m_data.m_seq; + boost::movelib::adaptive_sort + ( boost::movelib::iterator_to_raw_pointer(seq.begin()) + , boost::movelib::iterator_to_raw_pointer(seq.end()) + , this->priv_value_comp() + , boost::movelib::iterator_to_raw_pointer(tseq.begin() + tseq.size()) + , tseq.capacity() - tseq.size()); + tseq = boost::move(seq); + } + + void adopt_sequence_equal(ordered_range_t, BOOST_RV_REF(sequence_type) seq) + { + BOOST_ASSERT((is_sorted)(seq.cbegin(), seq.cend(), this->priv_value_comp())); + sequence_type &tseq = m_data.m_seq; + tseq = boost::move(seq); + } + + void adopt_sequence_unique(BOOST_RV_REF(sequence_type) seq) + { + sequence_type &tseq = m_data.m_seq; + boost::movelib::adaptive_sort + ( boost::movelib::iterator_to_raw_pointer(seq.begin()) + , boost::movelib::iterator_to_raw_pointer(seq.end()) + , this->priv_value_comp() + , boost::movelib::iterator_to_raw_pointer(tseq.begin() + tseq.size()) + , tseq.capacity() - tseq.size()); + seq.erase( boost::movelib::unique + (seq.begin(), seq.end(), boost::movelib::negate<value_compare>(this->m_data.get_comp())) + , seq.cend()); + tseq = boost::move(seq); + } + + void adopt_sequence_unique(ordered_unique_range_t, BOOST_RV_REF(sequence_type) seq) + { + BOOST_ASSERT((is_sorted_and_unique)(seq.cbegin(), seq.cend(), this->priv_value_comp())); + sequence_type &tseq = m_data.m_seq; + tseq = boost::move(seq); + } BOOST_CONTAINER_FORCEINLINE friend bool operator==(const flat_tree& x, const flat_tree& y) { @@ -864,6 +969,25 @@ class flat_tree private: + template <class InputIterator> + void priv_range_insertion_construct( bool unique_insertion, InputIterator first, InputIterator last) + { + //Use cend() as hint to achieve linear time for + //ordered ranges as required by the standard + //for the constructor + //Call end() every iteration as reallocation might have invalidated iterators + if(unique_insertion){ + for ( ; first != last; ++first){ + this->insert_unique(this->cend(), *first); + } + } + else{ + for ( ; first != last; ++first){ + this->insert_equal(this->cend(), *first); + } + } + } + BOOST_CONTAINER_FORCEINLINE bool priv_in_range_or_end(const_iterator pos) const { return (this->begin() <= pos) && (pos <= this->end()); @@ -963,7 +1087,7 @@ class flat_tree BOOST_CONTAINER_FORCEINLINE iterator priv_insert_commit (insert_commit_data &commit_data, BOOST_FWD_REF(Convertible) convertible) { - return this->m_data.m_vect.insert + return this->m_data.m_seq.insert ( commit_data.position , boost::forward<Convertible>(convertible)); } diff --git a/boost/container/detail/iterator_to_raw_pointer.hpp b/boost/container/detail/iterator_to_raw_pointer.hpp index 83736d8bb1..8c7c880035 100644 --- a/boost/container/detail/iterator_to_raw_pointer.hpp +++ b/boost/container/detail/iterator_to_raw_pointer.hpp @@ -18,38 +18,13 @@ # pragma once #endif -#include <boost/container/detail/iterator.hpp> -#include <boost/container/detail/to_raw_pointer.hpp> -#include <boost/intrusive/pointer_traits.hpp> +#include <boost/move/detail/iterator_to_raw_pointer.hpp> namespace boost { namespace container { namespace container_detail { -template <class T> -inline T* iterator_to_pointer(T* i) -{ return i; } - -template <class Iterator> -inline typename boost::container::iterator_traits<Iterator>::pointer - iterator_to_pointer(const Iterator &i) -{ return i.operator->(); } - -template <class Iterator> -struct iterator_to_element_ptr -{ - typedef typename boost::container::iterator_traits<Iterator>::pointer pointer; - typedef typename boost::intrusive::pointer_traits<pointer>::element_type element_type; - typedef element_type* type; -}; - -template <class Iterator> -inline typename iterator_to_element_ptr<Iterator>::type - iterator_to_raw_pointer(const Iterator &i) -{ - return ::boost::intrusive::detail::to_raw_pointer - ( ::boost::container::container_detail::iterator_to_pointer(i) ); -} +using ::boost::movelib::iterator_to_raw_pointer; } //namespace container_detail { } //namespace container { diff --git a/boost/container/detail/multiallocation_chain.hpp b/boost/container/detail/multiallocation_chain.hpp index 32f87c8ae9..bce1b8651f 100644 --- a/boost/container/detail/multiallocation_chain.hpp +++ b/boost/container/detail/multiallocation_chain.hpp @@ -24,7 +24,7 @@ // container #include <boost/container/container_fwd.hpp> // container/detail -#include <boost/container/detail/to_raw_pointer.hpp> +#include <boost/move/detail/to_raw_pointer.hpp> #include <boost/container/detail/transform_iterator.hpp> #include <boost/container/detail/type_traits.hpp> // intrusive @@ -63,7 +63,7 @@ class basic_multiallocation_chain pointer_traits<node_ptr> node_ptr_traits; static node & to_node(const VoidPointer &p) - { return *static_cast<node*>(static_cast<void*>(container_detail::to_raw_pointer(p))); } + { return *static_cast<node*>(static_cast<void*>(boost::movelib::to_raw_pointer(p))); } static VoidPointer from_node(node &n) { return node_ptr_traits::pointer_to(n); } @@ -152,7 +152,7 @@ class basic_multiallocation_chain char_ptr prev_elem = elem; elem += unit_bytes; for(size_type i = 0; i != num_units-1; ++i, elem += unit_bytes){ - ::new (container_detail::to_raw_pointer(prev_elem)) void_pointer(elem); + ::new (boost::movelib::to_raw_pointer(prev_elem)) void_pointer(elem); prev_elem = elem; } slist_impl_.incorporate_after(after_this, to_node_ptr(b), to_node_ptr(prev_elem), num_units); diff --git a/boost/container/detail/node_alloc_holder.hpp b/boost/container/detail/node_alloc_holder.hpp index 7ef5d2883e..b6e602e884 100644 --- a/boost/container/detail/node_alloc_holder.hpp +++ b/boost/container/detail/node_alloc_holder.hpp @@ -30,10 +30,10 @@ #include <boost/container/detail/allocator_version_traits.hpp> #include <boost/container/detail/construct_in_place.hpp> #include <boost/container/detail/destroyers.hpp> -#include <boost/container/detail/iterator_to_raw_pointer.hpp> +#include <boost/move/detail/iterator_to_raw_pointer.hpp> #include <boost/container/detail/mpl.hpp> #include <boost/container/detail/placement_new.hpp> -#include <boost/container/detail/to_raw_pointer.hpp> +#include <boost/move/detail/to_raw_pointer.hpp> #include <boost/container/detail/type_traits.hpp> #include <boost/container/detail/version_type.hpp> // intrusive @@ -106,23 +106,23 @@ struct node_alloc_holder : members_(a) {} + //Constructors for associative containers + node_alloc_holder(const value_compare &c, const ValAlloc &a) + : members_(a, c) + {} + explicit node_alloc_holder(const node_alloc_holder &x) : members_(NodeAllocTraits::select_on_container_copy_construction(x.node_alloc())) {} + node_alloc_holder(const node_alloc_holder &x, const value_compare &c) + : members_(NodeAllocTraits::select_on_container_copy_construction(x.node_alloc()), c) + {} + explicit node_alloc_holder(BOOST_RV_REF(node_alloc_holder) x) : members_(boost::move(x.node_alloc())) { this->icont().swap(x.icont()); } - //Constructors for associative containers - explicit node_alloc_holder(const value_compare &c, const ValAlloc &a) - : members_(a, c) - {} - - explicit node_alloc_holder(const value_compare &c, const node_alloc_holder &x) - : members_(NodeAllocTraits::select_on_container_copy_construction(x.node_alloc()), c) - {} - explicit node_alloc_holder(const value_compare &c) : members_(c) {} @@ -171,7 +171,7 @@ struct node_alloc_holder node_deallocator.release(); //This does not throw typedef typename Node::hook_type hook_type; - ::new(static_cast<hook_type*>(container_detail::to_raw_pointer(p)), boost_container_new_t()) hook_type; + ::new(static_cast<hook_type*>(boost::movelib::to_raw_pointer(p)), boost_container_new_t()) hook_type; return (p); } @@ -189,7 +189,7 @@ struct node_alloc_holder BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\ node_deallocator.release();\ typedef typename Node::hook_type hook_type;\ - ::new(static_cast<hook_type*>(container_detail::to_raw_pointer(p)), boost_container_new_t()) hook_type;\ + ::new(static_cast<hook_type*>(boost::movelib::to_raw_pointer(p)), boost_container_new_t()) hook_type;\ return (p);\ }\ // @@ -207,7 +207,7 @@ struct node_alloc_holder node_deallocator.release(); //This does not throw typedef typename Node::hook_type hook_type; - ::new(static_cast<hook_type*>(container_detail::to_raw_pointer(p)), boost_container_new_t()) hook_type; + ::new(static_cast<hook_type*>(boost::movelib::to_raw_pointer(p)), boost_container_new_t()) hook_type; return (p); } @@ -230,13 +230,13 @@ struct node_alloc_holder node_deallocator.release(); //This does not throw typedef typename Node::hook_type hook_type; - ::new(static_cast<hook_type*>(container_detail::to_raw_pointer(p)), boost_container_new_t()) hook_type; + ::new(static_cast<hook_type*>(boost::movelib::to_raw_pointer(p)), boost_container_new_t()) hook_type; return (p); } void destroy_node(const NodePtr &nodep) { - allocator_traits<NodeAlloc>::destroy(this->node_alloc(), container_detail::to_raw_pointer(nodep)); + allocator_traits<NodeAlloc>::destroy(this->node_alloc(), boost::movelib::to_raw_pointer(nodep)); this->deallocate_one(nodep); } @@ -266,7 +266,7 @@ struct node_alloc_holder Deallocator node_deallocator(NodePtr(), nalloc); container_detail::scoped_destructor<NodeAlloc> sdestructor(nalloc, 0); while(n--){ - p = container_detail::iterator_to_raw_pointer(itbeg); + p = boost::movelib::iterator_to_raw_pointer(itbeg); node_deallocator.set(p); ++itbeg; //This can throw diff --git a/boost/container/detail/node_pool_impl.hpp b/boost/container/detail/node_pool_impl.hpp index 4febf19e90..024bf306c5 100644 --- a/boost/container/detail/node_pool_impl.hpp +++ b/boost/container/detail/node_pool_impl.hpp @@ -25,7 +25,7 @@ #include <boost/container/detail/math_functions.hpp> #include <boost/container/detail/mpl.hpp> #include <boost/container/detail/pool_common.hpp> -#include <boost/container/detail/to_raw_pointer.hpp> +#include <boost/move/detail/to_raw_pointer.hpp> #include <boost/container/detail/type_traits.hpp> #include <boost/intrusive/pointer_traits.hpp> @@ -92,7 +92,7 @@ class private_node_pool_impl //!Returns the segment manager. Never throws segment_manager_base_type* get_segment_manager_base()const - { return container_detail::to_raw_pointer(mp_segment_mngr_base); } + { return boost::movelib::to_raw_pointer(mp_segment_mngr_base); } void *allocate_node() { return this->priv_alloc_node(); } diff --git a/boost/container/detail/pair.hpp b/boost/container/detail/pair.hpp index 4abff4b4d8..4755e569b2 100644 --- a/boost/container/detail/pair.hpp +++ b/boost/container/detail/pair.hpp @@ -35,16 +35,62 @@ #include <boost/intrusive/detail/minimal_pair_header.hpp> //pair #include <boost/move/utility_core.hpp> -#include<boost/move/detail/fwd_macros.hpp> +#include <boost/move/detail/fwd_macros.hpp> namespace boost { namespace tuples { struct null_type; +template < + class T0, class T1, class T2, + class T3, class T4, class T5, + class T6, class T7, class T8, + class T9> +class tuple; + } //namespace tuples { } //namespace boost { +namespace boost { +namespace container { +namespace pair_impl { + +template <class TupleClass> +struct is_boost_tuple +{ + static const bool value = false; +}; + +template < + class T0, class T1, class T2, + class T3, class T4, class T5, + class T6, class T7, class T8, + class T9> +struct is_boost_tuple< boost::tuples::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> > +{ + static const bool value = true; +}; + +template<class Tuple> +struct disable_if_boost_tuple + : boost::container::container_detail::disable_if< is_boost_tuple<Tuple> > +{}; + +template<class T> +struct is_tuple_null +{ + static const bool value = false; +}; + +template<> +struct is_tuple_null<boost::tuples::null_type> +{ + static const bool value = true; +}; + +}}} + #if defined(BOOST_MSVC) && (_CPPLIB_VER == 520) //MSVC 2010 tuple marker namespace std { namespace tr1 { struct _Nil; }} @@ -236,7 +282,12 @@ struct pair BOOST_MOVE_I_IF(BOOST_MOVE_OR(N,M)) BOOST_MOVE_CLASS##N BOOST_MOVE_I_IF(BOOST_MOVE_AND(N,M)) BOOST_MOVE_CLASSQ##M > \ pair( piecewise_construct_t\ , BoostTuple<BOOST_MOVE_TARG##N BOOST_MOVE_I##N BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,N),::boost::tuples::null_type)> p\ - , BoostTuple<BOOST_MOVE_TARGQ##M BOOST_MOVE_I##M BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,M),::boost::tuples::null_type)> q)\ + , BoostTuple<BOOST_MOVE_TARGQ##M BOOST_MOVE_I##M BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,M),::boost::tuples::null_type)> q\ + , typename container_detail::enable_if_c\ + < pair_impl::is_boost_tuple< BoostTuple<BOOST_MOVE_TARG##N BOOST_MOVE_I##N BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,N),::boost::tuples::null_type)> >::value &&\ + !(pair_impl::is_tuple_null<BOOST_MOVE_LAST_TARG##N>::value || pair_impl::is_tuple_null<BOOST_MOVE_LAST_TARGQ##M>::value) \ + >::type* = 0\ + )\ : first(BOOST_MOVE_TMPL_GET##N), second(BOOST_MOVE_TMPL_GETQ##M)\ { (void)p; (void)q; }\ // @@ -254,7 +305,8 @@ struct pair { (void) t1; (void)t2; } public: - template<template<class ...> class Tuple, class... Args1, class... Args2> + template< template<class ...> class Tuple, class... Args1, class... Args2 + , class = typename pair_impl::disable_if_boost_tuple< Tuple<Args1...> >::type> pair(piecewise_construct_t, Tuple<Args1...> t1, Tuple<Args2...> t2) : pair(t1, t2, typename build_number_seq<sizeof...(Args1)>::type(), typename build_number_seq<sizeof...(Args2)>::type()) {} @@ -270,7 +322,8 @@ struct pair { (void)t; return T(::boost::forward<Args>(get<Indexes>(t))...); } public: - template<template<class ...> class Tuple, class... Args1, class... Args2> + template< template<class ...> class Tuple, class... Args1, class... Args2 + , class = typename pair_impl::disable_if_boost_tuple< Tuple<Args1...> >::type> pair(piecewise_construct_t, Tuple<Args1...> t1, Tuple<Args2...> t2) : first (build_from_args<first_type> (::boost::move(t1))) , second (build_from_args<second_type>(::boost::move(t2))) diff --git a/boost/container/detail/pair_key_mapped_of_value.hpp b/boost/container/detail/pair_key_mapped_of_value.hpp new file mode 100644 index 0000000000..6112b87826 --- /dev/null +++ b/boost/container/detail/pair_key_mapped_of_value.hpp @@ -0,0 +1,55 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/container for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#ifndef BOOST_CONTAINER_PAIR_KEY_MAPPED_OF_VALUE_HPP +#define BOOST_CONTAINER_PAIR_KEY_MAPPED_OF_VALUE_HPP + +#ifndef BOOST_CONFIG_HPP +# include <boost/config.hpp> +#endif + +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include <boost/container/detail/config_begin.hpp> +#include <boost/container/detail/workaround.hpp> + +namespace boost { +namespace container { + +template<class Key, class Mapped> +struct pair_key_mapped_of_value +{ + typedef Key key_type; + typedef Mapped mapped_type; + + template<class Pair> + const key_type & key_of_value(const Pair &p) const + { return p.first; } + + template<class Pair> + const mapped_type & mapped_of_value(const Pair &p) const + { return p.second; } + + template<class Pair> + key_type & key_of_value(Pair &p) const + { return const_cast<key_type&>(p.first); } + + template<class Pair> + mapped_type & mapped_of_value(Pair &p) const + { return p.second; } + +}; + +}} + +#include <boost/container/detail/config_end.hpp> + +#endif // BOOST_CONTAINER_PAIR_KEY_MAPPED_OF_VALUE_HPP diff --git a/boost/container/detail/to_raw_pointer.hpp b/boost/container/detail/to_raw_pointer.hpp deleted file mode 100644 index 0b4445a942..0000000000 --- a/boost/container/detail/to_raw_pointer.hpp +++ /dev/null @@ -1,33 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2014-2015. Distributed under the Boost -// Software License, Version 1.0. (See accompanying file -// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/container for documentation. -// -////////////////////////////////////////////////////////////////////////////// -#ifndef BOOST_CONTAINER_DETAIL_TO_RAW_POINTER_HPP -#define BOOST_CONTAINER_DETAIL_TO_RAW_POINTER_HPP - -#ifndef BOOST_CONFIG_HPP -# include <boost/config.hpp> -#endif - -#if defined(BOOST_HAS_PRAGMA_ONCE) -# pragma once -#endif - -#include <boost/intrusive/detail/to_raw_pointer.hpp> - -namespace boost { -namespace container { -namespace container_detail { - -using ::boost::intrusive::detail::to_raw_pointer; - -} //namespace container_detail { -} //namespace container { -} //namespace boost { - -#endif //#ifndef BOOST_CONTAINER_DETAIL_TO_RAW_POINTER_HPP diff --git a/boost/container/detail/tree.hpp b/boost/container/detail/tree.hpp index 853d0ad843..99baf3a257 100644 --- a/boost/container/detail/tree.hpp +++ b/boost/container/detail/tree.hpp @@ -493,7 +493,7 @@ class tree typedef boost::container::reverse_iterator <const_iterator> const_reverse_iterator; typedef node_handle - < Node, value_type, allocator_type, void> node_type; + < NodeAlloc, void> node_type; typedef insert_return_type_base <iterator, node_type> insert_return_type; @@ -509,7 +509,11 @@ class tree : AllocHolder() {} - BOOST_CONTAINER_FORCEINLINE explicit tree(const key_compare& comp, const allocator_type& a = allocator_type()) + BOOST_CONTAINER_FORCEINLINE explicit tree(const key_compare& comp) + : AllocHolder(ValComp(comp)) + {} + + BOOST_CONTAINER_FORCEINLINE explicit tree(const key_compare& comp, const allocator_type& a) : AllocHolder(ValComp(comp), a) {} @@ -518,85 +522,110 @@ class tree {} template <class InputIterator> - tree(bool unique_insertion, InputIterator first, InputIterator last, const key_compare& comp, - const allocator_type& a - #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) - , typename container_detail::enable_if_or - < void - , container_detail::is_same<alloc_version, version_1> - , container_detail::is_input_iterator<InputIterator> - >::type * = 0 - #endif - ) + tree(bool unique_insertion, InputIterator first, InputIterator last) + : AllocHolder(value_compare(key_compare())) + { + this->tree_construct(unique_insertion, first, last); + //AllocHolder clears in case of exception + } + + template <class InputIterator> + tree(bool unique_insertion, InputIterator first, InputIterator last, const key_compare& comp) + : AllocHolder(value_compare(comp)) + { + this->tree_construct(unique_insertion, first, last); + //AllocHolder clears in case of exception + } + + template <class InputIterator> + tree(bool unique_insertion, InputIterator first, InputIterator last, const key_compare& comp, const allocator_type& a) : AllocHolder(value_compare(comp), a) { + this->tree_construct(unique_insertion, first, last); + //AllocHolder clears in case of exception + } + + //construct with ordered range + template <class InputIterator> + tree( ordered_range_t, InputIterator first, InputIterator last) + : AllocHolder(value_compare(key_compare())) + { + this->tree_construct(ordered_range_t(), first, last); + } + + template <class InputIterator> + tree( ordered_range_t, InputIterator first, InputIterator last, const key_compare& comp) + : AllocHolder(value_compare(comp)) + { + this->tree_construct(ordered_range_t(), first, last); + } + + template <class InputIterator> + tree( ordered_range_t, InputIterator first, InputIterator last + , const key_compare& comp, const allocator_type& a) + : AllocHolder(value_compare(comp), a) + { + this->tree_construct(ordered_range_t(), first, last); + } + + private: + + template <class InputIterator> + void tree_construct(bool unique_insertion, InputIterator first, InputIterator last) + { //Use cend() as hint to achieve linear time for //ordered ranges as required by the standard //for the constructor - const const_iterator end_it(this->cend()); if(unique_insertion){ + const const_iterator end_it(this->cend()); for ( ; first != last; ++first){ this->insert_unique_convertible(end_it, *first); } } else{ - for ( ; first != last; ++first){ - this->insert_equal_convertible(end_it, *first); - } + this->tree_construct_non_unique(first, last); } } template <class InputIterator> - tree(bool unique_insertion, InputIterator first, InputIterator last, const key_compare& comp, - const allocator_type& a + void tree_construct_non_unique(InputIterator first, InputIterator last #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) - , typename container_detail::disable_if_or + , typename container_detail::enable_if_or < void , container_detail::is_same<alloc_version, version_1> , container_detail::is_input_iterator<InputIterator> >::type * = 0 #endif ) - : AllocHolder(value_compare(comp), a) { - if(unique_insertion){ - //Use cend() as hint to achieve linear time for - //ordered ranges as required by the standard - //for the constructor - const const_iterator end_it(this->cend()); - for ( ; first != last; ++first){ - this->insert_unique_convertible(end_it, *first); - } - } - else{ - //Optimized allocation and construction - this->allocate_many_and_construct - ( first, boost::container::iterator_distance(first, last) - , insert_equal_end_hint_functor<Node, Icont>(this->icont())); + //Use cend() as hint to achieve linear time for + //ordered ranges as required by the standard + //for the constructor + const const_iterator end_it(this->cend()); + for ( ; first != last; ++first){ + this->insert_equal_convertible(end_it, *first); } } template <class InputIterator> - tree( ordered_range_t, InputIterator first, InputIterator last - , const key_compare& comp = key_compare(), const allocator_type& a = allocator_type() - #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) - , typename container_detail::enable_if_or + void tree_construct_non_unique(InputIterator first, InputIterator last + #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + , typename container_detail::disable_if_or < void , container_detail::is_same<alloc_version, version_1> , container_detail::is_input_iterator<InputIterator> >::type * = 0 - #endif + #endif ) - : AllocHolder(value_compare(comp), a) { - for ( ; first != last; ++first){ - this->push_back_impl(*first); - } + //Optimized allocation and construction + this->allocate_many_and_construct + ( first, boost::container::iterator_distance(first, last) + , insert_equal_end_hint_functor<Node, Icont>(this->icont())); } template <class InputIterator> - tree( ordered_range_t, InputIterator first, InputIterator last - , const key_compare& comp = key_compare(), const allocator_type& a = allocator_type() + void tree_construct( ordered_range_t, InputIterator first, InputIterator last #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) , typename container_detail::disable_if_or < void @@ -605,16 +634,34 @@ class tree >::type * = 0 #endif ) - : AllocHolder(value_compare(comp), a) { //Optimized allocation and construction this->allocate_many_and_construct ( first, boost::container::iterator_distance(first, last) , container_detail::push_back_functor<Node, Icont>(this->icont())); + //AllocHolder clears in case of exception + } + + template <class InputIterator> + void tree_construct( ordered_range_t, InputIterator first, InputIterator last + #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + , typename container_detail::enable_if_or + < void + , container_detail::is_same<alloc_version, version_1> + , container_detail::is_input_iterator<InputIterator> + >::type * = 0 + #endif + ) + { + for ( ; first != last; ++first){ + this->push_back_impl(*first); + } } + public: + BOOST_CONTAINER_FORCEINLINE tree(const tree& x) - : AllocHolder(x.value_comp(), x) + : AllocHolder(x, x.value_comp()) { this->icont().clone_from (x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc())); @@ -630,6 +677,7 @@ class tree { this->icont().clone_from (x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc())); + //AllocHolder clears in case of exception } tree(BOOST_RV_REF(tree) x, const allocator_type &a) @@ -642,6 +690,7 @@ class tree this->icont().clone_from (boost::move(x.icont()), typename AllocHolder::move_cloner(*this), Destroyer(this->node_alloc())); } + //AllocHolder clears in case of exception } BOOST_CONTAINER_FORCEINLINE ~tree() @@ -1142,7 +1191,7 @@ class tree this->insert_unique_check(hint, KeyOfValue()(nh.value()), data); if(ret.second){ irt.inserted = true; - irt.position = iterator(this->icont().insert_unique_commit(*nh.get_node_pointer(), data)); + irt.position = iterator(this->icont().insert_unique_commit(*nh.get(), data)); nh.release(); } else{ diff --git a/boost/container/flat_map.hpp b/boost/container/flat_map.hpp index b842101feb..56f12ecbe8 100644 --- a/boost/container/flat_map.hpp +++ b/boost/container/flat_map.hpp @@ -59,14 +59,15 @@ class flat_multimap; namespace container_detail{ template<class D, class S> -BOOST_CONTAINER_FORCEINLINE static D &force(const S &s) -{ return *const_cast<D*>((reinterpret_cast<const D*>(&s))); } +BOOST_CONTAINER_FORCEINLINE static D &force(S &s) +{ return *reinterpret_cast<D*>(&s); } template<class D, class S> -BOOST_CONTAINER_FORCEINLINE static D force_copy(S s) +BOOST_CONTAINER_FORCEINLINE static D force_copy(const S &s) { - D *vp = reinterpret_cast<D *>(&s); - return D(*vp); + const D *const vp = reinterpret_cast<const D *>(&s); + D ret_val(*vp); + return ret_val; } } //namespace container_detail{ @@ -144,13 +145,15 @@ class flat_map <typename allocator_traits<Allocator>::pointer>::reverse_iterator reverse_iterator_impl; typedef typename container_detail::get_flat_tree_iterators <typename allocator_traits<Allocator>::pointer>::const_reverse_iterator const_reverse_iterator_impl; + public: typedef typename impl_tree_t::stored_allocator_type impl_stored_allocator_type; + typedef typename impl_tree_t::sequence_type impl_sequence_type; - impl_tree_t &tree() + BOOST_CONTAINER_FORCEINLINE impl_tree_t &tree() { return m_flat_tree; } - const impl_tree_t &tree() const + BOOST_CONTAINER_FORCEINLINE const impl_tree_t &tree() const { return m_flat_tree; } private: @@ -182,8 +185,11 @@ class flat_map typedef BOOST_CONTAINER_IMPDEF(reverse_iterator_impl) reverse_iterator; typedef BOOST_CONTAINER_IMPDEF(const_reverse_iterator_impl) const_reverse_iterator; typedef BOOST_CONTAINER_IMPDEF(impl_value_type) movable_value_type; + typedef typename BOOST_CONTAINER_IMPDEF(tree_t::sequence_type) sequence_type; + + //Allocator::value_type must be std::pair<Key, T> + BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); - public: ////////////////////////////////////////////// // // construct/copy/destroy @@ -193,106 +199,183 @@ class flat_map //! <b>Effects</b>: Default constructs an empty flat_map. //! //! <b>Complexity</b>: Constant. - flat_map() BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value && - container_detail::is_nothrow_default_constructible<Compare>::value) + flat_map() BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value && + container_detail::is_nothrow_default_constructible<Compare>::value) : m_flat_tree() - { - //value_type must be std::pair<Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); - } + {} + + //! <b>Effects</b>: Constructs an empty flat_map using the specified allocator. + //! + //! <b>Complexity</b>: Constant. + BOOST_CONTAINER_FORCEINLINE explicit flat_map(const allocator_type& a) + : m_flat_tree(container_detail::force<const impl_allocator_type>(a)) + {} //! <b>Effects</b>: Constructs an empty flat_map using the specified - //! comparison object and allocator. + //! comparison object. //! //! <b>Complexity</b>: Constant. - explicit flat_map(const Compare& comp, const allocator_type& a = allocator_type()) - : m_flat_tree(comp, container_detail::force<impl_allocator_type>(a)) - { - //value_type must be std::pair<Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); - } + BOOST_CONTAINER_FORCEINLINE explicit flat_map(const Compare& comp) + : m_flat_tree(comp) + {} - //! <b>Effects</b>: Constructs an empty flat_map using the specified allocator. + //! <b>Effects</b>: Constructs an empty flat_map using the specified + //! comparison object and allocator. //! //! <b>Complexity</b>: Constant. - explicit flat_map(const allocator_type& a) - : m_flat_tree(container_detail::force<impl_allocator_type>(a)) - { - //value_type must be std::pair<Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); - } + BOOST_CONTAINER_FORCEINLINE flat_map(const Compare& comp, const allocator_type& a) + : m_flat_tree(comp, container_detail::force<const impl_allocator_type>(a)) + {} - //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and - //! allocator, and inserts elements from the range [first ,last ). + //! <b>Effects</b>: Constructs an empty flat_map and + //! and inserts elements from the range [first ,last ). //! //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using - //! comp and otherwise N logN, where N is last - first. + //! the predicate and otherwise N logN, where N is last - first. template <class InputIterator> - flat_map(InputIterator first, InputIterator last, const Compare& comp = Compare(), - const allocator_type& a = allocator_type()) - : m_flat_tree(true, first, last, comp, container_detail::force<impl_allocator_type>(a)) - { - //value_type must be std::pair<Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); - } + BOOST_CONTAINER_FORCEINLINE flat_map(InputIterator first, InputIterator last) + : m_flat_tree(true, first, last) + {} //! <b>Effects</b>: Constructs an empty flat_map using the specified //! allocator, and inserts elements from the range [first ,last ). //! //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using - //! comp and otherwise N logN, where N is last - first. + //! the predicate and otherwise N logN, where N is last - first. template <class InputIterator> - flat_map(InputIterator first, InputIterator last, const allocator_type& a) - : m_flat_tree(true, first, last, Compare(), container_detail::force<impl_allocator_type>(a)) - { - //value_type must be std::pair<Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); - } + BOOST_CONTAINER_FORCEINLINE flat_map(InputIterator first, InputIterator last, const allocator_type& a) + : m_flat_tree(true, first, last, container_detail::force<const impl_allocator_type>(a)) + {} + + //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and + //! and inserts elements from the range [first ,last ). + //! + //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using + //! the predicate and otherwise N logN, where N is last - first. + template <class InputIterator> + BOOST_CONTAINER_FORCEINLINE flat_map(InputIterator first, InputIterator last, const Compare& comp) + : m_flat_tree(true, first, last, comp) + {} //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and - //! allocator, and inserts elements from the ordered unique range [first ,last). This function + //! allocator, and inserts elements from the range [first ,last ). + //! + //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using + //! the predicate and otherwise N logN, where N is last - first. + template <class InputIterator> + BOOST_CONTAINER_FORCEINLINE flat_map(InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a) + : m_flat_tree(true, first, last, comp, container_detail::force<const impl_allocator_type>(a)) + {} + + //! <b>Effects</b>: Constructs an empty flat_map + //! and inserts elements from the ordered range [first ,last). This function //! is more efficient than the normal range creation for ordered ranges. //! - //! <b>Requires</b>: [first ,last) must be ordered according to the predicate and must be - //! unique values. + //! <b>Requires</b>: [first ,last) must be ordered according to the predicate. //! //! <b>Complexity</b>: Linear in N. //! //! <b>Note</b>: Non-standard extension. template <class InputIterator> - flat_map( ordered_unique_range_t, InputIterator first, InputIterator last - , const Compare& comp = Compare(), const allocator_type& a = allocator_type()) - : m_flat_tree(ordered_unique_range, first, last, comp, a) - { - //value_type must be std::pair<Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); - } + BOOST_CONTAINER_FORCEINLINE + flat_map(ordered_unique_range_t, InputIterator first, InputIterator last) + : m_flat_tree(ordered_range, first, last) + {} -#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and - //! allocator, and inserts elements from the range [il.begin() ,il.end()). + //! inserts elements from the ordered range [first ,last). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! <b>Requires</b>: [first ,last) must be ordered according to the predicate. + //! + //! <b>Complexity</b>: Linear in N. + //! + //! <b>Note</b>: Non-standard extension. + template <class InputIterator> + BOOST_CONTAINER_FORCEINLINE + flat_map(ordered_unique_range_t, InputIterator first, InputIterator last, const Compare& comp) + : m_flat_tree(ordered_range, first, last, comp) + {} + + //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and + //! allocator, and inserts elements from the ordered range [first ,last). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! <b>Requires</b>: [first ,last) must be ordered according to the predicate. + //! + //! <b>Complexity</b>: Linear in N. + //! + //! <b>Note</b>: Non-standard extension. + template <class InputIterator> + BOOST_CONTAINER_FORCEINLINE + flat_map(ordered_unique_range_t, InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a) + : m_flat_tree(ordered_range, first, last, comp, a) + {} + +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + //! <b>Effects</b>: Constructs an empty flat_map and + //! inserts elements from the range [il.begin() ,il.end()). //! //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using - //! comp and otherwise N logN, where N is last - first. - flat_map(std::initializer_list<value_type> il, const Compare& comp = Compare(), - const allocator_type& a = allocator_type()) - : m_flat_tree(true, il.begin(), il.end(), comp, container_detail::force<impl_allocator_type>(a)) - { - //value_type must be std::pair<Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); - } + //! the predicate and otherwise N logN, where N is last - first. + BOOST_CONTAINER_FORCEINLINE flat_map(std::initializer_list<value_type> il) + : m_flat_tree(true, il.begin(), il.end()) + {} //! <b>Effects</b>: Constructs an empty flat_map using the specified //! allocator, and inserts elements from the range [il.begin() ,il.end()). //! //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using - //! comp and otherwise N logN, where N is last - first. - flat_map(std::initializer_list<value_type> il, const allocator_type& a) - : m_flat_tree(true, il.begin(), il.end(), Compare(), container_detail::force<impl_allocator_type>(a)) - { - //value_type must be std::pair<Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); - } + //! the predicate and otherwise N logN, where N is last - first. + BOOST_CONTAINER_FORCEINLINE flat_map(std::initializer_list<value_type> il, const allocator_type& a) + : m_flat_tree(true, il.begin(), il.end(), container_detail::force<const impl_allocator_type>(a)) + {} + + //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and + //! inserts elements from the range [il.begin() ,il.end()). + //! + //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using + //! the predicate and otherwise N logN, where N is last - first. + BOOST_CONTAINER_FORCEINLINE flat_map(std::initializer_list<value_type> il, const Compare& comp) + : m_flat_tree(true, il.begin(), il.end(), comp) + {} + + //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and + //! allocator, and inserts elements from the range [il.begin() ,il.end()). + //! + //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using + //! the predicate and otherwise N logN, where N is last - first. + BOOST_CONTAINER_FORCEINLINE flat_map(std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a) + : m_flat_tree(true, il.begin(), il.end(), comp, container_detail::force<const impl_allocator_type>(a)) + {} + + //! <b>Effects</b>: Constructs an empty flat_map using and + //! inserts elements from the ordered unique range [il.begin(), il.end()). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be + //! unique values. + //! + //! <b>Complexity</b>: Linear in N. + //! + //! <b>Note</b>: Non-standard extension. + BOOST_CONTAINER_FORCEINLINE flat_map(ordered_unique_range_t, std::initializer_list<value_type> il) + : m_flat_tree(ordered_unique_range, il.begin(), il.end()) + {} + + //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and + //! inserts elements from the ordered unique range [il.begin(), il.end()). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be + //! unique values. + //! + //! <b>Complexity</b>: Linear in N. + //! + //! <b>Note</b>: Non-standard extension. + BOOST_CONTAINER_FORCEINLINE flat_map(ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp) + : m_flat_tree(ordered_unique_range, il.begin(), il.end(), comp) + {} //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and //! allocator, and inserts elements from the ordered unique range [il.begin(), il.end()). This function @@ -304,24 +387,17 @@ class flat_map //! <b>Complexity</b>: Linear in N. //! //! <b>Note</b>: Non-standard extension. - flat_map(ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp = Compare(), - const allocator_type& a = allocator_type()) + BOOST_CONTAINER_FORCEINLINE flat_map(ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a) : m_flat_tree(ordered_unique_range, il.begin(), il.end(), comp, a) - { - //value_type must be std::pair<Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); - } + {} #endif //! <b>Effects</b>: Copy constructs a flat_map. //! //! <b>Complexity</b>: Linear in x.size(). - flat_map(const flat_map& x) + BOOST_CONTAINER_FORCEINLINE flat_map(const flat_map& x) : m_flat_tree(x.m_flat_tree) - { - //value_type must be std::pair<Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); - } + {} //! <b>Effects</b>: Move constructs a flat_map. //! Constructs *this using x's resources. @@ -329,39 +405,30 @@ class flat_map //! <b>Complexity</b>: Constant. //! //! <b>Postcondition</b>: x is emptied. - flat_map(BOOST_RV_REF(flat_map) x) + BOOST_CONTAINER_FORCEINLINE flat_map(BOOST_RV_REF(flat_map) x) BOOST_NOEXCEPT_IF(boost::container::container_detail::is_nothrow_move_constructible<Compare>::value) : m_flat_tree(boost::move(x.m_flat_tree)) - { - //value_type must be std::pair<Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); - } + {} //! <b>Effects</b>: Copy constructs a flat_map using the specified allocator. //! //! <b>Complexity</b>: Linear in x.size(). - flat_map(const flat_map& x, const allocator_type &a) + BOOST_CONTAINER_FORCEINLINE flat_map(const flat_map& x, const allocator_type &a) : m_flat_tree(x.m_flat_tree, a) - { - //value_type must be std::pair<Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); - } + {} //! <b>Effects</b>: Move constructs a flat_map using the specified allocator. //! Constructs *this using x's resources. //! //! <b>Complexity</b>: Constant if x.get_allocator() == a, linear otherwise. - flat_map(BOOST_RV_REF(flat_map) x, const allocator_type &a) + BOOST_CONTAINER_FORCEINLINE flat_map(BOOST_RV_REF(flat_map) x, const allocator_type &a) : m_flat_tree(boost::move(x.m_flat_tree), a) - { - //value_type must be std::pair<Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); - } + {} //! <b>Effects</b>: Makes *this a copy of x. //! //! <b>Complexity</b>: Linear in x.size(). - flat_map& operator=(BOOST_COPY_ASSIGN_REF(flat_map) x) + BOOST_CONTAINER_FORCEINLINE flat_map& operator=(BOOST_COPY_ASSIGN_REF(flat_map) x) { m_flat_tree = x.m_flat_tree; return *this; } //! <b>Effects</b>: Move constructs a flat_map. @@ -373,7 +440,7 @@ class flat_map //! <b>Complexity</b>: Constant if allocator_traits_type:: //! propagate_on_container_move_assignment is true or //! this->get>allocator() == x.get_allocator(). Linear otherwise. - flat_map& operator=(BOOST_RV_REF(flat_map) x) + BOOST_CONTAINER_FORCEINLINE flat_map& operator=(BOOST_RV_REF(flat_map) x) BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value || allocator_traits_type::is_always_equal::value) && boost::container::container_detail::is_nothrow_move_assignable<Compare>::value) @@ -393,7 +460,7 @@ class flat_map //! was passed to the object's constructor. //! //! <b>Complexity</b>: Constant. - allocator_type get_allocator() const BOOST_NOEXCEPT_OR_NOTHROW + BOOST_CONTAINER_FORCEINLINE allocator_type get_allocator() const BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::force_copy<allocator_type>(m_flat_tree.get_allocator()); } //! <b>Effects</b>: Returns a reference to the internal allocator. @@ -403,7 +470,7 @@ class flat_map //! <b>Complexity</b>: Constant. //! //! <b>Note</b>: Non-standard extension. - stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW + BOOST_CONTAINER_FORCEINLINE stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::force<stored_allocator_type>(m_flat_tree.get_stored_allocator()); } //! <b>Effects</b>: Returns a reference to the internal allocator. @@ -413,8 +480,8 @@ class flat_map //! <b>Complexity</b>: Constant. //! //! <b>Note</b>: Non-standard extension. - const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW - { return container_detail::force<stored_allocator_type>(m_flat_tree.get_stored_allocator()); } + BOOST_CONTAINER_FORCEINLINE const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW + { return container_detail::force<const stored_allocator_type>(m_flat_tree.get_stored_allocator()); } ////////////////////////////////////////////// // @@ -427,7 +494,7 @@ class flat_map //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - iterator begin() BOOST_NOEXCEPT_OR_NOTHROW + BOOST_CONTAINER_FORCEINLINE iterator begin() BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::force_copy<iterator>(m_flat_tree.begin()); } //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container. @@ -435,7 +502,7 @@ class flat_map //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW + BOOST_CONTAINER_FORCEINLINE const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::force_copy<const_iterator>(m_flat_tree.begin()); } //! <b>Effects</b>: Returns an iterator to the end of the container. @@ -443,7 +510,7 @@ class flat_map //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - iterator end() BOOST_NOEXCEPT_OR_NOTHROW + BOOST_CONTAINER_FORCEINLINE iterator end() BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::force_copy<iterator>(m_flat_tree.end()); } //! <b>Effects</b>: Returns a const_iterator to the end of the container. @@ -451,7 +518,7 @@ class flat_map //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW + BOOST_CONTAINER_FORCEINLINE const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::force_copy<const_iterator>(m_flat_tree.end()); } //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning @@ -460,7 +527,7 @@ class flat_map //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW + BOOST_CONTAINER_FORCEINLINE reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::force_copy<reverse_iterator>(m_flat_tree.rbegin()); } //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning @@ -469,7 +536,7 @@ class flat_map //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW + BOOST_CONTAINER_FORCEINLINE const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::force_copy<const_reverse_iterator>(m_flat_tree.rbegin()); } //! <b>Effects</b>: Returns a reverse_iterator pointing to the end @@ -478,7 +545,7 @@ class flat_map //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW + BOOST_CONTAINER_FORCEINLINE reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::force_copy<reverse_iterator>(m_flat_tree.rend()); } //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end @@ -487,7 +554,7 @@ class flat_map //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW + BOOST_CONTAINER_FORCEINLINE const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::force_copy<const_reverse_iterator>(m_flat_tree.rend()); } //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container. @@ -495,7 +562,7 @@ class flat_map //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW + BOOST_CONTAINER_FORCEINLINE const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::force_copy<const_iterator>(m_flat_tree.cbegin()); } //! <b>Effects</b>: Returns a const_iterator to the end of the container. @@ -503,7 +570,7 @@ class flat_map //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW + BOOST_CONTAINER_FORCEINLINE const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::force_copy<const_iterator>(m_flat_tree.cend()); } //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning @@ -512,7 +579,7 @@ class flat_map //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW + BOOST_CONTAINER_FORCEINLINE const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::force_copy<const_reverse_iterator>(m_flat_tree.crbegin()); } //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end @@ -521,7 +588,7 @@ class flat_map //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW + BOOST_CONTAINER_FORCEINLINE const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::force_copy<const_reverse_iterator>(m_flat_tree.crend()); } ////////////////////////////////////////////// @@ -535,7 +602,7 @@ class flat_map //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - bool empty() const BOOST_NOEXCEPT_OR_NOTHROW + BOOST_CONTAINER_FORCEINLINE bool empty() const BOOST_NOEXCEPT_OR_NOTHROW { return m_flat_tree.empty(); } //! <b>Effects</b>: Returns the number of the elements contained in the container. @@ -543,7 +610,7 @@ class flat_map //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - size_type size() const BOOST_NOEXCEPT_OR_NOTHROW + BOOST_CONTAINER_FORCEINLINE size_type size() const BOOST_NOEXCEPT_OR_NOTHROW { return m_flat_tree.size(); } //! <b>Effects</b>: Returns the largest possible size of the container. @@ -551,7 +618,7 @@ class flat_map //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW + BOOST_CONTAINER_FORCEINLINE size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW { return m_flat_tree.max_size(); } //! <b>Effects</b>: Number of elements for which memory has been allocated. @@ -560,7 +627,7 @@ class flat_map //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW + BOOST_CONTAINER_FORCEINLINE size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW { return m_flat_tree.capacity(); } //! <b>Effects</b>: If n is less than or equal to capacity(), this call has no @@ -572,7 +639,7 @@ class flat_map //! //! <b>Note</b>: If capacity() is less than "cnt", iterators and references to //! to values might be invalidated. - void reserve(size_type cnt) + BOOST_CONTAINER_FORCEINLINE void reserve(size_type cnt) { m_flat_tree.reserve(cnt); } //! <b>Effects</b>: Tries to deallocate the excess of memory created @@ -581,7 +648,7 @@ class flat_map //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws. //! //! <b>Complexity</b>: Linear to size(). - void shrink_to_fit() + BOOST_CONTAINER_FORCEINLINE void shrink_to_fit() { m_flat_tree.shrink_to_fit(); } ////////////////////////////////////////////// @@ -608,8 +675,8 @@ class flat_map mapped_type &operator[](key_type &&k) ; #elif defined(BOOST_MOVE_HELPERS_RETURN_SFINAE_BROKEN) //in compilers like GCC 3.4, we can't catch temporaries - mapped_type& operator[](const key_type &k) { return this->priv_subscript(k); } - mapped_type& operator[](BOOST_RV_REF(key_type) k) { return this->priv_subscript(::boost::move(k)); } + BOOST_CONTAINER_FORCEINLINE mapped_type& operator[](const key_type &k) { return this->priv_subscript(k); } + BOOST_CONTAINER_FORCEINLINE mapped_type& operator[](BOOST_RV_REF(key_type) k) { return this->priv_subscript(::boost::move(k)); } #else BOOST_MOVE_CONVERSION_AWARE_CATCH( operator[] , key_type, mapped_type&, this->priv_subscript) #endif @@ -705,19 +772,19 @@ class flat_map } //! @copydoc ::boost::container::flat_set::nth(size_type) - iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW + BOOST_CONTAINER_FORCEINLINE iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::force_copy<iterator>(m_flat_tree.nth(n)); } //! @copydoc ::boost::container::flat_set::nth(size_type) const - const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW + BOOST_CONTAINER_FORCEINLINE const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::force_copy<iterator>(m_flat_tree.nth(n)); } //! @copydoc ::boost::container::flat_set::index_of(iterator) - size_type index_of(iterator p) BOOST_NOEXCEPT_OR_NOTHROW + BOOST_CONTAINER_FORCEINLINE size_type index_of(iterator p) BOOST_NOEXCEPT_OR_NOTHROW { return m_flat_tree.index_of(container_detail::force_copy<impl_iterator>(p)); } //! @copydoc ::boost::container::flat_set::index_of(const_iterator) const - size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW + BOOST_CONTAINER_FORCEINLINE size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW { return m_flat_tree.index_of(container_detail::force_copy<impl_const_iterator>(p)); } //! Returns: A reference to the element whose key is equivalent to x. @@ -769,7 +836,7 @@ class flat_map //! //! <b>Note</b>: If an element is inserted it might invalidate elements. template <class... Args> - std::pair<iterator,bool> emplace(BOOST_FWD_REF(Args)... args) + BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> emplace(BOOST_FWD_REF(Args)... args) { return container_detail::force_copy< std::pair<iterator, bool> >(m_flat_tree.emplace_unique(boost::forward<Args>(args)...)); } //! <b>Effects</b>: Inserts an object of type T constructed with @@ -785,7 +852,7 @@ class flat_map //! //! <b>Note</b>: If an element is inserted it might invalidate elements. template <class... Args> - iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args) + BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args) { return container_detail::force_copy<iterator> (m_flat_tree.emplace_hint_unique( container_detail::force_copy<impl_const_iterator>(hint) @@ -869,14 +936,14 @@ class flat_map #define BOOST_CONTAINER_FLAT_MAP_EMPLACE_CODE(N) \ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ - std::pair<iterator,bool> emplace(BOOST_MOVE_UREF##N)\ + BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> emplace(BOOST_MOVE_UREF##N)\ {\ return container_detail::force_copy< std::pair<iterator, bool> >\ (m_flat_tree.emplace_unique(BOOST_MOVE_FWD##N));\ }\ \ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ - iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ + BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ {\ return container_detail::force_copy<iterator>(m_flat_tree.emplace_hint_unique\ (container_detail::force_copy<impl_const_iterator>(hint) BOOST_MOVE_I##N BOOST_MOVE_FWD##N));\ @@ -921,9 +988,9 @@ class flat_map //! to the elements with bigger keys than x. //! //! <b>Note</b>: If an element is inserted it might invalidate elements. - std::pair<iterator,bool> insert(const value_type& x) + BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> insert(const value_type& x) { return container_detail::force_copy<std::pair<iterator,bool> >( - m_flat_tree.insert_unique(container_detail::force<impl_value_type>(x))); } + m_flat_tree.insert_unique(container_detail::force<const impl_value_type>(x))); } //! <b>Effects</b>: Inserts a new value_type move constructed from the pair if and //! only if there is no element in the container with key equivalent to the key of x. @@ -936,7 +1003,7 @@ class flat_map //! to the elements with bigger keys than x. //! //! <b>Note</b>: If an element is inserted it might invalidate elements. - std::pair<iterator,bool> insert(BOOST_RV_REF(value_type) x) + BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> insert(BOOST_RV_REF(value_type) x) { return container_detail::force_copy<std::pair<iterator,bool> >( m_flat_tree.insert_unique(boost::move(container_detail::force<impl_value_type>(x)))); } @@ -951,7 +1018,7 @@ class flat_map //! to the elements with bigger keys than x. //! //! <b>Note</b>: If an element is inserted it might invalidate elements. - std::pair<iterator,bool> insert(BOOST_RV_REF(movable_value_type) x) + BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> insert(BOOST_RV_REF(movable_value_type) x) { return container_detail::force_copy<std::pair<iterator,bool> > (m_flat_tree.insert_unique(boost::move(x))); @@ -968,11 +1035,11 @@ class flat_map //! right before p) plus insertion linear to the elements with bigger keys than x. //! //! <b>Note</b>: If an element is inserted it might invalidate elements. - iterator insert(const_iterator p, const value_type& x) + BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, const value_type& x) { return container_detail::force_copy<iterator>( m_flat_tree.insert_unique( container_detail::force_copy<impl_const_iterator>(p) - , container_detail::force<impl_value_type>(x))); + , container_detail::force<const impl_value_type>(x))); } //! <b>Effects</b>: Inserts an element move constructed from x in the container. @@ -984,7 +1051,7 @@ class flat_map //! right before p) plus insertion linear to the elements with bigger keys than x. //! //! <b>Note</b>: If an element is inserted it might invalidate elements. - iterator insert(const_iterator p, BOOST_RV_REF(value_type) x) + BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(value_type) x) { return container_detail::force_copy<iterator> (m_flat_tree.insert_unique( container_detail::force_copy<impl_const_iterator>(p) @@ -1000,7 +1067,7 @@ class flat_map //! right before p) plus insertion linear to the elements with bigger keys than x. //! //! <b>Note</b>: If an element is inserted it might invalidate elements. - iterator insert(const_iterator p, BOOST_RV_REF(movable_value_type) x) + BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(movable_value_type) x) { return container_detail::force_copy<iterator>( m_flat_tree.insert_unique(container_detail::force_copy<impl_const_iterator>(p), boost::move(x))); @@ -1016,7 +1083,7 @@ class flat_map //! //! <b>Note</b>: If an element is inserted it might invalidate elements. template <class InputIterator> - void insert(InputIterator first, InputIterator last) + BOOST_CONTAINER_FORCEINLINE void insert(InputIterator first, InputIterator last) { m_flat_tree.insert_unique(first, last); } //! <b>Requires</b>: first, last are not iterators into *this. @@ -1035,7 +1102,7 @@ class flat_map //! //! <b>Note</b>: Non-standard extension. template <class InputIterator> - void insert(ordered_unique_range_t, InputIterator first, InputIterator last) + BOOST_CONTAINER_FORCEINLINE void insert(ordered_unique_range_t, InputIterator first, InputIterator last) { m_flat_tree.insert_unique(ordered_unique_range, first, last); } #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) @@ -1046,7 +1113,7 @@ class flat_map //! search time plus N*size() insertion time. //! //! <b>Note</b>: If an element is inserted it might invalidate elements. - void insert(std::initializer_list<value_type> il) + BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il) { m_flat_tree.insert_unique(il.begin(), il.end()); } //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be @@ -1062,7 +1129,7 @@ class flat_map //! <b>Note</b>: If an element is inserted it might invalidate elements. //! //! <b>Note</b>: Non-standard extension. - void insert(ordered_unique_range_t, std::initializer_list<value_type> il) + BOOST_CONTAINER_FORCEINLINE void insert(ordered_unique_range_t, std::initializer_list<value_type> il) { m_flat_tree.insert_unique(ordered_unique_range, il.begin(), il.end()); } #endif @@ -1109,7 +1176,7 @@ class flat_map //! //! <b>Note</b>: Invalidates elements with keys //! not less than the erased element. - iterator erase(const_iterator p) + BOOST_CONTAINER_FORCEINLINE iterator erase(const_iterator p) { return container_detail::force_copy<iterator> (m_flat_tree.erase(container_detail::force_copy<impl_const_iterator>(p))); @@ -1121,7 +1188,7 @@ class flat_map //! //! <b>Complexity</b>: Logarithmic search time plus erasure time //! linear to the elements with bigger keys. - size_type erase(const key_type& x) + BOOST_CONTAINER_FORCEINLINE size_type erase(const key_type& x) { return m_flat_tree.erase(x); } //! <b>Effects</b>: Erases all the elements in the range [first, last). @@ -1132,7 +1199,7 @@ class flat_map //! //! <b>Complexity</b>: Logarithmic search time plus erasure time //! linear to the elements with bigger keys. - iterator erase(const_iterator first, const_iterator last) + BOOST_CONTAINER_FORCEINLINE iterator erase(const_iterator first, const_iterator last) { return container_detail::force_copy<iterator>( m_flat_tree.erase( container_detail::force_copy<impl_const_iterator>(first) @@ -1144,7 +1211,7 @@ class flat_map //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - void swap(flat_map& x) + BOOST_CONTAINER_FORCEINLINE void swap(flat_map& x) BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value && boost::container::container_detail::is_nothrow_swappable<Compare>::value ) { m_flat_tree.swap(x.m_flat_tree); } @@ -1154,7 +1221,7 @@ class flat_map //! <b>Postcondition</b>: size() == 0. //! //! <b>Complexity</b>: linear in size(). - void clear() BOOST_NOEXCEPT_OR_NOTHROW + BOOST_CONTAINER_FORCEINLINE void clear() BOOST_NOEXCEPT_OR_NOTHROW { m_flat_tree.clear(); } ////////////////////////////////////////////// @@ -1167,14 +1234,14 @@ class flat_map //! of which a was constructed. //! //! <b>Complexity</b>: Constant. - key_compare key_comp() const + BOOST_CONTAINER_FORCEINLINE key_compare key_comp() const { return container_detail::force_copy<key_compare>(m_flat_tree.key_comp()); } //! <b>Effects</b>: Returns an object of value_compare constructed out //! of the comparison object. //! //! <b>Complexity</b>: Constant. - value_compare value_comp() const + BOOST_CONTAINER_FORCEINLINE value_compare value_comp() const { return value_compare(container_detail::force_copy<key_compare>(m_flat_tree.key_comp())); } ////////////////////////////////////////////// @@ -1187,102 +1254,135 @@ class flat_map //! equivalent to x, or end() if such an element is not found. //! //! <b>Complexity</b>: Logarithmic. - iterator find(const key_type& x) + BOOST_CONTAINER_FORCEINLINE iterator find(const key_type& x) { return container_detail::force_copy<iterator>(m_flat_tree.find(x)); } //! <b>Returns</b>: A const_iterator pointing to an element with the key //! equivalent to x, or end() if such an element is not found. //! //! <b>Complexity</b>: Logarithmic. - const_iterator find(const key_type& x) const + BOOST_CONTAINER_FORCEINLINE const_iterator find(const key_type& x) const { return container_detail::force_copy<const_iterator>(m_flat_tree.find(x)); } //! <b>Returns</b>: The number of elements with key equivalent to x. //! //! <b>Complexity</b>: log(size())+count(k) - size_type count(const key_type& x) const + BOOST_CONTAINER_FORCEINLINE size_type count(const key_type& x) const { return static_cast<size_type>(m_flat_tree.find(x) != m_flat_tree.end()); } //! <b>Returns</b>: An iterator pointing to the first element with key not less //! than k, or a.end() if such an element is not found. //! //! <b>Complexity</b>: Logarithmic. - iterator lower_bound(const key_type& x) + BOOST_CONTAINER_FORCEINLINE iterator lower_bound(const key_type& x) { return container_detail::force_copy<iterator>(m_flat_tree.lower_bound(x)); } //! <b>Returns</b>: A const iterator pointing to the first element with key not //! less than k, or a.end() if such an element is not found. //! //! <b>Complexity</b>: Logarithmic. - const_iterator lower_bound(const key_type& x) const + BOOST_CONTAINER_FORCEINLINE const_iterator lower_bound(const key_type& x) const { return container_detail::force_copy<const_iterator>(m_flat_tree.lower_bound(x)); } //! <b>Returns</b>: An iterator pointing to the first element with key not less //! than x, or end() if such an element is not found. //! //! <b>Complexity</b>: Logarithmic. - iterator upper_bound(const key_type& x) + BOOST_CONTAINER_FORCEINLINE iterator upper_bound(const key_type& x) { return container_detail::force_copy<iterator>(m_flat_tree.upper_bound(x)); } //! <b>Returns</b>: A const iterator pointing to the first element with key not //! less than x, or end() if such an element is not found. //! //! <b>Complexity</b>: Logarithmic. - const_iterator upper_bound(const key_type& x) const + BOOST_CONTAINER_FORCEINLINE const_iterator upper_bound(const key_type& x) const { return container_detail::force_copy<const_iterator>(m_flat_tree.upper_bound(x)); } //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). //! //! <b>Complexity</b>: Logarithmic. - std::pair<iterator,iterator> equal_range(const key_type& x) + BOOST_CONTAINER_FORCEINLINE std::pair<iterator,iterator> equal_range(const key_type& x) { return container_detail::force_copy<std::pair<iterator,iterator> >(m_flat_tree.lower_bound_range(x)); } //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). //! //! <b>Complexity</b>: Logarithmic. - std::pair<const_iterator,const_iterator> equal_range(const key_type& x) const + BOOST_CONTAINER_FORCEINLINE std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const { return container_detail::force_copy<std::pair<const_iterator,const_iterator> >(m_flat_tree.lower_bound_range(x)); } + //! <b>Effects</b>: Extracts the internal sequence container. + //! + //! <b>Complexity</b>: Same as the move constructor of sequence_type, usually constant. + //! + //! <b>Postcondition</b>: this->empty() + //! + //! <b>Throws</b>: If secuence_type's move constructor throws + BOOST_CONTAINER_FORCEINLINE sequence_type extract_sequence() + { + return boost::move(container_detail::force<sequence_type>(m_flat_tree.get_sequence_ref())); + } + + //! <b>Effects</b>: Discards the internally hold sequence container and adopts the + //! one passed externally using the move assignment. Erases non-unique elements. + //! + //! <b>Complexity</b>: Assuming O(1) move assignment, O(NlogN) with N = seq.size() + //! + //! <b>Throws</b>: If the comparison or the move constructor throws + BOOST_CONTAINER_FORCEINLINE void adopt_sequence(BOOST_RV_REF(sequence_type) seq) + { this->m_flat_tree.adopt_sequence_unique(boost::move(container_detail::force<impl_sequence_type>(seq))); } + + //! <b>Requires</b>: seq shall be ordered according to this->compare() + //! and shall contain unique elements. + //! + //! <b>Effects</b>: Discards the internally hold sequence container and adopts the + //! one passed externally using the move assignment. + //! + //! <b>Complexity</b>: Assuming O(1) move assignment, O(1) + //! + //! <b>Throws</b>: If the move assignment throws + BOOST_CONTAINER_FORCEINLINE void adopt_sequence(ordered_unique_range_t, BOOST_RV_REF(sequence_type) seq) + { this->m_flat_tree.adopt_sequence_unique(ordered_unique_range_t(), boost::move(container_detail::force<impl_sequence_type>(seq))); } + //! <b>Effects</b>: Returns true if x and y are equal //! //! <b>Complexity</b>: Linear to the number of elements in the container. - friend bool operator==(const flat_map& x, const flat_map& y) + BOOST_CONTAINER_FORCEINLINE friend bool operator==(const flat_map& x, const flat_map& y) { return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin()); } //! <b>Effects</b>: Returns true if x and y are unequal //! //! <b>Complexity</b>: Linear to the number of elements in the container. - friend bool operator!=(const flat_map& x, const flat_map& y) + BOOST_CONTAINER_FORCEINLINE friend bool operator!=(const flat_map& x, const flat_map& y) { return !(x == y); } //! <b>Effects</b>: Returns true if x is less than y //! //! <b>Complexity</b>: Linear to the number of elements in the container. - friend bool operator<(const flat_map& x, const flat_map& y) + BOOST_CONTAINER_FORCEINLINE friend bool operator<(const flat_map& x, const flat_map& y) { return ::boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } //! <b>Effects</b>: Returns true if x is greater than y //! //! <b>Complexity</b>: Linear to the number of elements in the container. - friend bool operator>(const flat_map& x, const flat_map& y) + BOOST_CONTAINER_FORCEINLINE friend bool operator>(const flat_map& x, const flat_map& y) { return y < x; } //! <b>Effects</b>: Returns true if x is equal or less than y //! //! <b>Complexity</b>: Linear to the number of elements in the container. - friend bool operator<=(const flat_map& x, const flat_map& y) + BOOST_CONTAINER_FORCEINLINE friend bool operator<=(const flat_map& x, const flat_map& y) { return !(y < x); } //! <b>Effects</b>: Returns true if x is equal or greater than y //! //! <b>Complexity</b>: Linear to the number of elements in the container. - friend bool operator>=(const flat_map& x, const flat_map& y) + BOOST_CONTAINER_FORCEINLINE friend bool operator>=(const flat_map& x, const flat_map& y) { return !(x < y); } //! <b>Effects</b>: x.swap(y) //! //! <b>Complexity</b>: Constant. - friend void swap(flat_map& x, flat_map& y) + BOOST_CONTAINER_FORCEINLINE friend void swap(flat_map& x, flat_map& y) { x.swap(y); } #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED @@ -1401,11 +1501,12 @@ class flat_multimap <typename allocator_traits<Allocator>::pointer>::const_reverse_iterator const_reverse_iterator_impl; public: typedef typename impl_tree_t::stored_allocator_type impl_stored_allocator_type; + typedef typename impl_tree_t::sequence_type impl_sequence_type; - impl_tree_t &tree() + BOOST_CONTAINER_FORCEINLINE impl_tree_t &tree() { return m_flat_tree; } - const impl_tree_t &tree() const + BOOST_CONTAINER_FORCEINLINE const impl_tree_t &tree() const { return m_flat_tree; } private: @@ -1437,6 +1538,10 @@ class flat_multimap typedef BOOST_CONTAINER_IMPDEF(reverse_iterator_impl) reverse_iterator; typedef BOOST_CONTAINER_IMPDEF(const_reverse_iterator_impl) const_reverse_iterator; typedef BOOST_CONTAINER_IMPDEF(impl_value_type) movable_value_type; + typedef typename BOOST_CONTAINER_IMPDEF(tree_t::sequence_type) sequence_type; + + //Allocator::value_type must be std::pair<Key, T> + BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); ////////////////////////////////////////////// // @@ -1447,63 +1552,109 @@ class flat_multimap //! <b>Effects</b>: Default constructs an empty flat_map. //! //! <b>Complexity</b>: Constant. - flat_multimap() BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value && - container_detail::is_nothrow_default_constructible<Compare>::value) + BOOST_CONTAINER_FORCEINLINE flat_multimap() + BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value && + container_detail::is_nothrow_default_constructible<Compare>::value) : m_flat_tree() - { - //value_type must be std::pair<Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); - } + {} + + //! <b>Effects</b>: Constructs an empty flat_multimap using the specified allocator. + //! + //! <b>Complexity</b>: Constant. + BOOST_CONTAINER_FORCEINLINE explicit flat_multimap(const allocator_type& a) + : m_flat_tree(container_detail::force<const impl_allocator_type>(a)) + {} //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison - //! object and allocator. + //! object . //! //! <b>Complexity</b>: Constant. - explicit flat_multimap(const Compare& comp, - const allocator_type& a = allocator_type()) - : m_flat_tree(comp, container_detail::force<impl_allocator_type>(a)) - { - //value_type must be std::pair<Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); - } + BOOST_CONTAINER_FORCEINLINE explicit flat_multimap(const Compare& comp) + : m_flat_tree(comp) + {} - //! <b>Effects</b>: Constructs an empty flat_multimap using the specified allocator. + //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison + //! object and allocator. //! //! <b>Complexity</b>: Constant. - explicit flat_multimap(const allocator_type& a) - : m_flat_tree(container_detail::force<impl_allocator_type>(a)) - { - //value_type must be std::pair<Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); - } + BOOST_CONTAINER_FORCEINLINE + flat_multimap(const Compare& comp, const allocator_type& a) + : m_flat_tree(comp, container_detail::force<const impl_allocator_type>(a)) + {} - //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object - //! and allocator, and inserts elements from the range [first ,last ). + //! <b>Effects</b>: Constructs an empty flat_multimap + //! and inserts elements from the range [first ,last ). //! //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using - //! comp and otherwise N logN, where N is last - first. + //! the predicate and otherwise N logN, where N is last - first. template <class InputIterator> - flat_multimap(InputIterator first, InputIterator last, - const Compare& comp = Compare(), - const allocator_type& a = allocator_type()) - : m_flat_tree(false, first, last, comp, container_detail::force<impl_allocator_type>(a)) - { - //value_type must be std::pair<Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); - } + BOOST_CONTAINER_FORCEINLINE + flat_multimap(InputIterator first, InputIterator last) + : m_flat_tree(false, first, last) + {} //! <b>Effects</b>: Constructs an empty flat_multimap using the specified //! allocator, and inserts elements from the range [first ,last ). //! //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using - //! comp and otherwise N logN, where N is last - first. + //! the predicate and otherwise N logN, where N is last - first. template <class InputIterator> + BOOST_CONTAINER_FORCEINLINE flat_multimap(InputIterator first, InputIterator last, const allocator_type& a) - : m_flat_tree(false, first, last, Compare(), container_detail::force<impl_allocator_type>(a)) - { - //value_type must be std::pair<Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); - } + : m_flat_tree(false, first, last, container_detail::force<const impl_allocator_type>(a)) + {} + + //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object + //! and inserts elements from the range [first ,last ). + //! + //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using + //! the predicate and otherwise N logN, where N is last - first. + template <class InputIterator> + BOOST_CONTAINER_FORCEINLINE + flat_multimap(InputIterator first, InputIterator last, const Compare& comp) + : m_flat_tree(false, first, last, comp) + {} + + //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object + //! and allocator, and inserts elements from the range [first ,last ). + //! + //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using + //! the predicate and otherwise N logN, where N is last - first. + template <class InputIterator> + BOOST_CONTAINER_FORCEINLINE + flat_multimap(InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a) + : m_flat_tree(false, first, last, comp, container_detail::force<const impl_allocator_type>(a)) + {} + + //! <b>Effects</b>: Constructs an empty flat_multimap + //! and inserts elements from the ordered range [first ,last). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! <b>Requires</b>: [first ,last) must be ordered according to the predicate. + //! + //! <b>Complexity</b>: Linear in N. + //! + //! <b>Note</b>: Non-standard extension. + template <class InputIterator> + BOOST_CONTAINER_FORCEINLINE + flat_multimap(ordered_range_t, InputIterator first, InputIterator last) + : m_flat_tree(ordered_range, first, last) + {} + + //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object and + //! inserts elements from the ordered range [first ,last). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! <b>Requires</b>: [first ,last) must be ordered according to the predicate. + //! + //! <b>Complexity</b>: Linear in N. + //! + //! <b>Note</b>: Non-standard extension. + template <class InputIterator> + BOOST_CONTAINER_FORCEINLINE + flat_multimap(ordered_range_t, InputIterator first, InputIterator last, const Compare& comp) + : m_flat_tree(ordered_range, first, last, comp) + {} //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object and //! allocator, and inserts elements from the ordered range [first ,last). This function @@ -1515,39 +1666,79 @@ class flat_multimap //! //! <b>Note</b>: Non-standard extension. template <class InputIterator> - flat_multimap(ordered_range_t, InputIterator first, InputIterator last, - const Compare& comp = Compare(), - const allocator_type& a = allocator_type()) + BOOST_CONTAINER_FORCEINLINE + flat_multimap(ordered_range_t, InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a) : m_flat_tree(ordered_range, first, last, comp, a) - { - //value_type must be std::pair<Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); - } + {} #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) - //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and - //! allocator, and inserts elements from the range [il.begin(), il.end()). + //! <b>Effects</b>: Constructs an empty flat_map and + //! inserts elements from the range [il.begin(), il.end()). //! //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using - //! comp and otherwise N logN, where N is last - first. - flat_multimap(std::initializer_list<value_type> il, const Compare& comp = Compare(), const allocator_type& a = allocator_type()) - : m_flat_tree(false, il.begin(), il.end(), comp, container_detail::force<impl_allocator_type>(a)) - { - //value_type must be std::pair<Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); - } + //! the predicate and otherwise N logN, where N is last - first. + BOOST_CONTAINER_FORCEINLINE + flat_multimap(std::initializer_list<value_type> il) + : m_flat_tree(false, il.begin(), il.end()) + {} //! <b>Effects</b>: Constructs an empty flat_map using the specified //! allocator, and inserts elements from the range [il.begin(), il.end()). //! //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using - //! comp and otherwise N logN, where N is last - first. + //! the predicate and otherwise N logN, where N is last - first. + BOOST_CONTAINER_FORCEINLINE flat_multimap(std::initializer_list<value_type> il, const allocator_type& a) - : m_flat_tree(false, il.begin(), il.end(), Compare(), container_detail::force<impl_allocator_type>(a)) - { - //value_type must be std::pair<Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); - } + : m_flat_tree(false, il.begin(), il.end(), container_detail::force<const impl_allocator_type>(a)) + {} + + //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and + //! inserts elements from the range [il.begin(), il.end()). + //! + //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using + //! the predicate and otherwise N logN, where N is last - first. + BOOST_CONTAINER_FORCEINLINE + flat_multimap(std::initializer_list<value_type> il, const Compare& comp) + : m_flat_tree(false, il.begin(), il.end(), comp) + {} + + //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and + //! allocator, and inserts elements from the range [il.begin(), il.end()). + //! + //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using + //! the predicate and otherwise N logN, where N is last - first. + BOOST_CONTAINER_FORCEINLINE + flat_multimap(std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a) + : m_flat_tree(false, il.begin(), il.end(), comp, container_detail::force<const impl_allocator_type>(a)) + {} + + //! <b>Effects</b>: Constructs an empty flat_multimap and + //! inserts elements from the ordered range [il.begin(), il.end()). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate. + //! + //! <b>Complexity</b>: Linear in N. + //! + //! <b>Note</b>: Non-standard extension. + BOOST_CONTAINER_FORCEINLINE + flat_multimap(ordered_range_t, std::initializer_list<value_type> il) + : m_flat_tree(ordered_range, il.begin(), il.end()) + {} + + //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object and + //! inserts elements from the ordered range [il.begin(), il.end()). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate. + //! + //! <b>Complexity</b>: Linear in N. + //! + //! <b>Note</b>: Non-standard extension. + BOOST_CONTAINER_FORCEINLINE + flat_multimap(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp) + : m_flat_tree(ordered_range, il.begin(), il.end(), comp) + {} //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object and //! allocator, and inserts elements from the ordered range [il.begin(), il.end()). This function @@ -1558,68 +1749,59 @@ class flat_multimap //! <b>Complexity</b>: Linear in N. //! //! <b>Note</b>: Non-standard extension. - flat_multimap(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp = Compare(), - const allocator_type& a = allocator_type()) + BOOST_CONTAINER_FORCEINLINE + flat_multimap(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a) : m_flat_tree(ordered_range, il.begin(), il.end(), comp, a) - { - //value_type must be std::pair<Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); - } + {} #endif //! <b>Effects</b>: Copy constructs a flat_multimap. //! //! <b>Complexity</b>: Linear in x.size(). + BOOST_CONTAINER_FORCEINLINE flat_multimap(const flat_multimap& x) : m_flat_tree(x.m_flat_tree) - { - //value_type must be std::pair<Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); - } + {} //! <b>Effects</b>: Move constructs a flat_multimap. Constructs *this using x's resources. //! //! <b>Complexity</b>: Constant. //! //! <b>Postcondition</b>: x is emptied. + BOOST_CONTAINER_FORCEINLINE flat_multimap(BOOST_RV_REF(flat_multimap) x) BOOST_NOEXCEPT_IF(boost::container::container_detail::is_nothrow_move_constructible<Compare>::value) : m_flat_tree(boost::move(x.m_flat_tree)) - { - //value_type must be std::pair<Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); - } + {} //! <b>Effects</b>: Copy constructs a flat_multimap using the specified allocator. //! //! <b>Complexity</b>: Linear in x.size(). + BOOST_CONTAINER_FORCEINLINE flat_multimap(const flat_multimap& x, const allocator_type &a) : m_flat_tree(x.m_flat_tree, a) - { - //value_type must be std::pair<Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); - } + {} //! <b>Effects</b>: Move constructs a flat_multimap using the specified allocator. //! Constructs *this using x's resources. //! //! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise. + BOOST_CONTAINER_FORCEINLINE flat_multimap(BOOST_RV_REF(flat_multimap) x, const allocator_type &a) : m_flat_tree(boost::move(x.m_flat_tree), a) - { - //value_type must be std::pair<Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); - } + {} //! <b>Effects</b>: Makes *this a copy of x. //! //! <b>Complexity</b>: Linear in x.size(). + BOOST_CONTAINER_FORCEINLINE flat_multimap& operator=(BOOST_COPY_ASSIGN_REF(flat_multimap) x) { m_flat_tree = x.m_flat_tree; return *this; } //! <b>Effects</b>: this->swap(x.get()). //! //! <b>Complexity</b>: Constant. + BOOST_CONTAINER_FORCEINLINE flat_multimap& operator=(BOOST_RV_REF(flat_multimap) x) BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value || allocator_traits_type::is_always_equal::value) && @@ -1630,6 +1812,7 @@ class flat_multimap //! <b>Effects</b>: Assign content of il to *this //! //! <b>Complexity</b>: Linear in il.size(). + BOOST_CONTAINER_FORCEINLINE flat_multimap& operator=(std::initializer_list<value_type> il) { this->clear(); @@ -1642,6 +1825,7 @@ class flat_multimap //! was passed to the object's constructor. //! //! <b>Complexity</b>: Constant. + BOOST_CONTAINER_FORCEINLINE allocator_type get_allocator() const BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::force_copy<allocator_type>(m_flat_tree.get_allocator()); } @@ -1652,6 +1836,7 @@ class flat_multimap //! <b>Complexity</b>: Constant. //! //! <b>Note</b>: Non-standard extension. + BOOST_CONTAINER_FORCEINLINE stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::force<stored_allocator_type>(m_flat_tree.get_stored_allocator()); } @@ -1662,8 +1847,9 @@ class flat_multimap //! <b>Complexity</b>: Constant. //! //! <b>Note</b>: Non-standard extension. + BOOST_CONTAINER_FORCEINLINE const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW - { return container_detail::force<stored_allocator_type>(m_flat_tree.get_stored_allocator()); } + { return container_detail::force<const stored_allocator_type>(m_flat_tree.get_stored_allocator()); } ////////////////////////////////////////////// // @@ -1676,6 +1862,7 @@ class flat_multimap //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. + BOOST_CONTAINER_FORCEINLINE iterator begin() BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::force_copy<iterator>(m_flat_tree.begin()); } @@ -1684,6 +1871,7 @@ class flat_multimap //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. + BOOST_CONTAINER_FORCEINLINE const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::force_copy<const_iterator>(m_flat_tree.begin()); } @@ -1692,6 +1880,7 @@ class flat_multimap //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. + BOOST_CONTAINER_FORCEINLINE iterator end() BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::force_copy<iterator>(m_flat_tree.end()); } @@ -1700,6 +1889,7 @@ class flat_multimap //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. + BOOST_CONTAINER_FORCEINLINE const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::force_copy<const_iterator>(m_flat_tree.end()); } @@ -1709,6 +1899,7 @@ class flat_multimap //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. + BOOST_CONTAINER_FORCEINLINE reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::force_copy<reverse_iterator>(m_flat_tree.rbegin()); } @@ -1718,6 +1909,7 @@ class flat_multimap //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. + BOOST_CONTAINER_FORCEINLINE const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::force_copy<const_reverse_iterator>(m_flat_tree.rbegin()); } @@ -1727,6 +1919,7 @@ class flat_multimap //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. + BOOST_CONTAINER_FORCEINLINE reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::force_copy<reverse_iterator>(m_flat_tree.rend()); } @@ -1736,6 +1929,7 @@ class flat_multimap //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. + BOOST_CONTAINER_FORCEINLINE const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::force_copy<const_reverse_iterator>(m_flat_tree.rend()); } @@ -1744,6 +1938,7 @@ class flat_multimap //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. + BOOST_CONTAINER_FORCEINLINE const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::force_copy<const_iterator>(m_flat_tree.cbegin()); } @@ -1752,6 +1947,7 @@ class flat_multimap //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. + BOOST_CONTAINER_FORCEINLINE const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::force_copy<const_iterator>(m_flat_tree.cend()); } @@ -1761,6 +1957,7 @@ class flat_multimap //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. + BOOST_CONTAINER_FORCEINLINE const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::force_copy<const_reverse_iterator>(m_flat_tree.crbegin()); } @@ -1770,6 +1967,7 @@ class flat_multimap //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. + BOOST_CONTAINER_FORCEINLINE const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::force_copy<const_reverse_iterator>(m_flat_tree.crend()); } @@ -1784,6 +1982,7 @@ class flat_multimap //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. + BOOST_CONTAINER_FORCEINLINE bool empty() const BOOST_NOEXCEPT_OR_NOTHROW { return m_flat_tree.empty(); } @@ -1792,6 +1991,7 @@ class flat_multimap //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. + BOOST_CONTAINER_FORCEINLINE size_type size() const BOOST_NOEXCEPT_OR_NOTHROW { return m_flat_tree.size(); } @@ -1800,6 +2000,7 @@ class flat_multimap //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. + BOOST_CONTAINER_FORCEINLINE size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW { return m_flat_tree.max_size(); } @@ -1809,6 +2010,7 @@ class flat_multimap //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. + BOOST_CONTAINER_FORCEINLINE size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW { return m_flat_tree.capacity(); } @@ -1821,6 +2023,7 @@ class flat_multimap //! //! <b>Note</b>: If capacity() is less than "cnt", iterators and references to //! to values might be invalidated. + BOOST_CONTAINER_FORCEINLINE void reserve(size_type cnt) { m_flat_tree.reserve(cnt); } @@ -1830,22 +2033,27 @@ class flat_multimap //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws. //! //! <b>Complexity</b>: Linear to size(). + BOOST_CONTAINER_FORCEINLINE void shrink_to_fit() { m_flat_tree.shrink_to_fit(); } //! @copydoc ::boost::container::flat_set::nth(size_type) + BOOST_CONTAINER_FORCEINLINE iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::force_copy<iterator>(m_flat_tree.nth(n)); } //! @copydoc ::boost::container::flat_set::nth(size_type) const + BOOST_CONTAINER_FORCEINLINE const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::force_copy<iterator>(m_flat_tree.nth(n)); } //! @copydoc ::boost::container::flat_set::index_of(iterator) + BOOST_CONTAINER_FORCEINLINE size_type index_of(iterator p) BOOST_NOEXCEPT_OR_NOTHROW { return m_flat_tree.index_of(container_detail::force_copy<impl_iterator>(p)); } //! @copydoc ::boost::container::flat_set::index_of(const_iterator) const + BOOST_CONTAINER_FORCEINLINE size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW { return m_flat_tree.index_of(container_detail::force_copy<impl_const_iterator>(p)); } @@ -1860,6 +2068,7 @@ class flat_multimap //! //! <b>Note</b>: If an element is inserted it might invalidate elements. template <class... Args> + BOOST_CONTAINER_FORCEINLINE iterator emplace(BOOST_FWD_REF(Args)... args) { return container_detail::force_copy<iterator>(m_flat_tree.emplace_equal(boost::forward<Args>(args)...)); } @@ -1876,6 +2085,7 @@ class flat_multimap //! //! <b>Note</b>: If an element is inserted it might invalidate elements. template <class... Args> + BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args) { return container_detail::force_copy<iterator>(m_flat_tree.emplace_hint_equal @@ -1886,11 +2096,11 @@ class flat_multimap #define BOOST_CONTAINER_FLAT_MULTIMAP_EMPLACE_CODE(N) \ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ - iterator emplace(BOOST_MOVE_UREF##N)\ + BOOST_CONTAINER_FORCEINLINE iterator emplace(BOOST_MOVE_UREF##N)\ { return container_detail::force_copy<iterator>(m_flat_tree.emplace_equal(BOOST_MOVE_FWD##N)); }\ \ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ - iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ + BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ {\ return container_detail::force_copy<iterator>(m_flat_tree.emplace_hint_equal\ (container_detail::force_copy<impl_const_iterator>(hint) BOOST_MOVE_I##N BOOST_MOVE_FWD##N));\ @@ -1908,10 +2118,10 @@ class flat_multimap //! to the elements with bigger keys than x. //! //! <b>Note</b>: If an element is inserted it might invalidate elements. - iterator insert(const value_type& x) + BOOST_CONTAINER_FORCEINLINE iterator insert(const value_type& x) { return container_detail::force_copy<iterator>( - m_flat_tree.insert_equal(container_detail::force<impl_value_type>(x))); + m_flat_tree.insert_equal(container_detail::force<const impl_value_type>(x))); } //! <b>Effects</b>: Inserts a new value move-constructed from x and returns @@ -1921,7 +2131,7 @@ class flat_multimap //! to the elements with bigger keys than x. //! //! <b>Note</b>: If an element is inserted it might invalidate elements. - iterator insert(BOOST_RV_REF(value_type) x) + BOOST_CONTAINER_FORCEINLINE iterator insert(BOOST_RV_REF(value_type) x) { return container_detail::force_copy<iterator>(m_flat_tree.insert_equal(boost::move(x))); } //! <b>Effects</b>: Inserts a new value move-constructed from x and returns @@ -1931,7 +2141,7 @@ class flat_multimap //! to the elements with bigger keys than x. //! //! <b>Note</b>: If an element is inserted it might invalidate elements. - iterator insert(BOOST_RV_REF(impl_value_type) x) + BOOST_CONTAINER_FORCEINLINE iterator insert(BOOST_RV_REF(impl_value_type) x) { return container_detail::force_copy<iterator>(m_flat_tree.insert_equal(boost::move(x))); } //! <b>Effects</b>: Inserts a copy of x in the container. @@ -1945,11 +2155,11 @@ class flat_multimap //! to the elements with bigger keys than x. //! //! <b>Note</b>: If an element is inserted it might invalidate elements. - iterator insert(const_iterator p, const value_type& x) + BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, const value_type& x) { return container_detail::force_copy<iterator> (m_flat_tree.insert_equal( container_detail::force_copy<impl_const_iterator>(p) - , container_detail::force<impl_value_type>(x))); + , container_detail::force<const impl_value_type>(x))); } //! <b>Effects</b>: Inserts a value move constructed from x in the container. @@ -1963,7 +2173,7 @@ class flat_multimap //! to the elements with bigger keys than x. //! //! <b>Note</b>: If an element is inserted it might invalidate elements. - iterator insert(const_iterator p, BOOST_RV_REF(value_type) x) + BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(value_type) x) { return container_detail::force_copy<iterator> (m_flat_tree.insert_equal(container_detail::force_copy<impl_const_iterator>(p) @@ -1981,7 +2191,7 @@ class flat_multimap //! to the elements with bigger keys than x. //! //! <b>Note</b>: If an element is inserted it might invalidate elements. - iterator insert(const_iterator p, BOOST_RV_REF(impl_value_type) x) + BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(impl_value_type) x) { return container_detail::force_copy<iterator>( m_flat_tree.insert_equal(container_detail::force_copy<impl_const_iterator>(p), boost::move(x))); @@ -1996,7 +2206,7 @@ class flat_multimap //! //! <b>Note</b>: If an element is inserted it might invalidate elements. template <class InputIterator> - void insert(InputIterator first, InputIterator last) + BOOST_CONTAINER_FORCEINLINE void insert(InputIterator first, InputIterator last) { m_flat_tree.insert_equal(first, last); } //! <b>Requires</b>: first, last are not iterators into *this. @@ -2014,7 +2224,7 @@ class flat_multimap //! //! <b>Note</b>: Non-standard extension. template <class InputIterator> - void insert(ordered_range_t, InputIterator first, InputIterator last) + BOOST_CONTAINER_FORCEINLINE void insert(ordered_range_t, InputIterator first, InputIterator last) { m_flat_tree.insert_equal(ordered_range, first, last); } #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) @@ -2024,7 +2234,7 @@ class flat_multimap //! search time plus N*size() insertion time. //! //! <b>Note</b>: If an element is inserted it might invalidate elements. - void insert(std::initializer_list<value_type> il) + BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il) { m_flat_tree.insert_equal(il.begin(), il.end()); } //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate. @@ -2039,7 +2249,7 @@ class flat_multimap //! <b>Note</b>: If an element is inserted it might invalidate elements. //! //! <b>Note</b>: Non-standard extension. - void insert(ordered_range_t, std::initializer_list<value_type> il) + BOOST_CONTAINER_FORCEINLINE void insert(ordered_range_t, std::initializer_list<value_type> il) { m_flat_tree.insert_equal(ordered_range, il.begin(), il.end()); } #endif @@ -2057,22 +2267,22 @@ class flat_multimap //! //! <b>Complexity</b>: N log(a.size() + N) (N has the value source.size()) template<class C2> - void merge(flat_multimap<Key, T, C2, Allocator>& source) + BOOST_CONTAINER_FORCEINLINE void merge(flat_multimap<Key, T, C2, Allocator>& source) { m_flat_tree.merge_equal(source.tree()); } //! @copydoc ::boost::container::flat_multimap::merge(flat_multimap<Key, T, C2, Allocator>&) template<class C2> - void merge(BOOST_RV_REF_BEG flat_multimap<Key, T, C2, Allocator> BOOST_RV_REF_END source) + BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_multimap<Key, T, C2, Allocator> BOOST_RV_REF_END source) { return this->merge(static_cast<flat_multimap<Key, T, C2, Allocator>&>(source)); } //! @copydoc ::boost::container::flat_multimap::merge(flat_multimap<Key, T, C2, Allocator>&) template<class C2> - void merge(flat_map<Key, T, C2, Allocator>& source) + BOOST_CONTAINER_FORCEINLINE void merge(flat_map<Key, T, C2, Allocator>& source) { m_flat_tree.merge_equal(source.tree()); } - //! @copydoc ::boost::container::flat_multimap::merge(flat_multimap<Key, T, C2, Allocator>&) + //! @copydoc ::boost::container::flat_multimap::merge(flat_map<Key, T, C2, Allocator>&) template<class C2> - void merge(BOOST_RV_REF_BEG flat_map<Key, T, C2, Allocator> BOOST_RV_REF_END source) + BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_map<Key, T, C2, Allocator> BOOST_RV_REF_END source) { return this->merge(static_cast<flat_map<Key, T, C2, Allocator>&>(source)); } //! <b>Effects</b>: Erases the element pointed to by p. @@ -2085,7 +2295,7 @@ class flat_multimap //! //! <b>Note</b>: Invalidates elements with keys //! not less than the erased element. - iterator erase(const_iterator p) + BOOST_CONTAINER_FORCEINLINE iterator erase(const_iterator p) { return container_detail::force_copy<iterator>( m_flat_tree.erase(container_detail::force_copy<impl_const_iterator>(p))); @@ -2097,7 +2307,7 @@ class flat_multimap //! //! <b>Complexity</b>: Logarithmic search time plus erasure time //! linear to the elements with bigger keys. - size_type erase(const key_type& x) + BOOST_CONTAINER_FORCEINLINE size_type erase(const key_type& x) { return m_flat_tree.erase(x); } //! <b>Effects</b>: Erases all the elements in the range [first, last). @@ -2108,7 +2318,7 @@ class flat_multimap //! //! <b>Complexity</b>: Logarithmic search time plus erasure time //! linear to the elements with bigger keys. - iterator erase(const_iterator first, const_iterator last) + BOOST_CONTAINER_FORCEINLINE iterator erase(const_iterator first, const_iterator last) { return container_detail::force_copy<iterator> (m_flat_tree.erase( container_detail::force_copy<impl_const_iterator>(first) @@ -2120,7 +2330,7 @@ class flat_multimap //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - void swap(flat_multimap& x) + BOOST_CONTAINER_FORCEINLINE void swap(flat_multimap& x) BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value && boost::container::container_detail::is_nothrow_swappable<Compare>::value ) { m_flat_tree.swap(x.m_flat_tree); } @@ -2130,7 +2340,7 @@ class flat_multimap //! <b>Postcondition</b>: size() == 0. //! //! <b>Complexity</b>: linear in size(). - void clear() BOOST_NOEXCEPT_OR_NOTHROW + BOOST_CONTAINER_FORCEINLINE void clear() BOOST_NOEXCEPT_OR_NOTHROW { m_flat_tree.clear(); } ////////////////////////////////////////////// @@ -2143,14 +2353,14 @@ class flat_multimap //! of which a was constructed. //! //! <b>Complexity</b>: Constant. - key_compare key_comp() const + BOOST_CONTAINER_FORCEINLINE key_compare key_comp() const { return container_detail::force_copy<key_compare>(m_flat_tree.key_comp()); } //! <b>Effects</b>: Returns an object of value_compare constructed out //! of the comparison object. //! //! <b>Complexity</b>: Constant. - value_compare value_comp() const + BOOST_CONTAINER_FORCEINLINE value_compare value_comp() const { return value_compare(container_detail::force_copy<key_compare>(m_flat_tree.key_comp())); } ////////////////////////////////////////////// @@ -2163,102 +2373,134 @@ class flat_multimap //! equivalent to x, or end() if such an element is not found. //! //! <b>Complexity</b>: Logarithmic. - iterator find(const key_type& x) + BOOST_CONTAINER_FORCEINLINE iterator find(const key_type& x) { return container_detail::force_copy<iterator>(m_flat_tree.find(x)); } //! <b>Returns</b>: An const_iterator pointing to an element with the key //! equivalent to x, or end() if such an element is not found. //! //! <b>Complexity</b>: Logarithmic. - const_iterator find(const key_type& x) const + BOOST_CONTAINER_FORCEINLINE const_iterator find(const key_type& x) const { return container_detail::force_copy<const_iterator>(m_flat_tree.find(x)); } //! <b>Returns</b>: The number of elements with key equivalent to x. //! //! <b>Complexity</b>: log(size())+count(k) - size_type count(const key_type& x) const + BOOST_CONTAINER_FORCEINLINE size_type count(const key_type& x) const { return m_flat_tree.count(x); } //! <b>Returns</b>: An iterator pointing to the first element with key not less //! than k, or a.end() if such an element is not found. //! //! <b>Complexity</b>: Logarithmic - iterator lower_bound(const key_type& x) + BOOST_CONTAINER_FORCEINLINE iterator lower_bound(const key_type& x) { return container_detail::force_copy<iterator>(m_flat_tree.lower_bound(x)); } //! <b>Returns</b>: A const iterator pointing to the first element with key //! not less than k, or a.end() if such an element is not found. //! //! <b>Complexity</b>: Logarithmic - const_iterator lower_bound(const key_type& x) const + BOOST_CONTAINER_FORCEINLINE const_iterator lower_bound(const key_type& x) const { return container_detail::force_copy<const_iterator>(m_flat_tree.lower_bound(x)); } //! <b>Returns</b>: An iterator pointing to the first element with key not less //! than x, or end() if such an element is not found. //! //! <b>Complexity</b>: Logarithmic - iterator upper_bound(const key_type& x) + BOOST_CONTAINER_FORCEINLINE iterator upper_bound(const key_type& x) {return container_detail::force_copy<iterator>(m_flat_tree.upper_bound(x)); } //! <b>Returns</b>: A const iterator pointing to the first element with key //! not less than x, or end() if such an element is not found. //! //! <b>Complexity</b>: Logarithmic - const_iterator upper_bound(const key_type& x) const + BOOST_CONTAINER_FORCEINLINE const_iterator upper_bound(const key_type& x) const { return container_detail::force_copy<const_iterator>(m_flat_tree.upper_bound(x)); } //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). //! //! <b>Complexity</b>: Logarithmic - std::pair<iterator,iterator> equal_range(const key_type& x) + BOOST_CONTAINER_FORCEINLINE std::pair<iterator,iterator> equal_range(const key_type& x) { return container_detail::force_copy<std::pair<iterator,iterator> >(m_flat_tree.equal_range(x)); } //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). //! //! <b>Complexity</b>: Logarithmic - std::pair<const_iterator,const_iterator> equal_range(const key_type& x) const + BOOST_CONTAINER_FORCEINLINE std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const { return container_detail::force_copy<std::pair<const_iterator,const_iterator> >(m_flat_tree.equal_range(x)); } + //! <b>Effects</b>: Extracts the internal sequence container. + //! + //! <b>Complexity</b>: Same as the move constructor of sequence_type, usually constant. + //! + //! <b>Postcondition</b>: this->empty() + //! + //! <b>Throws</b>: If secuence_type's move constructor throws + BOOST_CONTAINER_FORCEINLINE sequence_type extract_sequence() + { + return boost::move(container_detail::force<sequence_type>(m_flat_tree.get_sequence_ref())); + } + + //! <b>Effects</b>: Discards the internally hold sequence container and adopts the + //! one passed externally using the move assignment. + //! + //! <b>Complexity</b>: Assuming O(1) move assignment, O(NlogN) with N = seq.size() + //! + //! <b>Throws</b>: If the comparison or the move constructor throws + BOOST_CONTAINER_FORCEINLINE void adopt_sequence(BOOST_RV_REF(sequence_type) seq) + { this->m_flat_tree.adopt_sequence_equal(boost::move(container_detail::force<impl_sequence_type>(seq))); } + + //! <b>Requires</b>: seq shall be ordered according to this->compare(). + //! + //! <b>Effects</b>: Discards the internally hold sequence container and adopts the + //! one passed externally using the move assignment. + //! + //! <b>Complexity</b>: Assuming O(1) move assignment, O(1) + //! + //! <b>Throws</b>: If the move assignment throws + BOOST_CONTAINER_FORCEINLINE void adopt_sequence(ordered_range_t, BOOST_RV_REF(sequence_type) seq) + { this->m_flat_tree.adopt_sequence_equal(ordered_range_t(), boost::move(container_detail::force<impl_sequence_type>(seq))); } + //! <b>Effects</b>: Returns true if x and y are equal //! //! <b>Complexity</b>: Linear to the number of elements in the container. - friend bool operator==(const flat_multimap& x, const flat_multimap& y) + BOOST_CONTAINER_FORCEINLINE friend bool operator==(const flat_multimap& x, const flat_multimap& y) { return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin()); } //! <b>Effects</b>: Returns true if x and y are unequal //! //! <b>Complexity</b>: Linear to the number of elements in the container. - friend bool operator!=(const flat_multimap& x, const flat_multimap& y) + BOOST_CONTAINER_FORCEINLINE friend bool operator!=(const flat_multimap& x, const flat_multimap& y) { return !(x == y); } //! <b>Effects</b>: Returns true if x is less than y //! //! <b>Complexity</b>: Linear to the number of elements in the container. - friend bool operator<(const flat_multimap& x, const flat_multimap& y) + BOOST_CONTAINER_FORCEINLINE friend bool operator<(const flat_multimap& x, const flat_multimap& y) { return ::boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } //! <b>Effects</b>: Returns true if x is greater than y //! //! <b>Complexity</b>: Linear to the number of elements in the container. - friend bool operator>(const flat_multimap& x, const flat_multimap& y) + BOOST_CONTAINER_FORCEINLINE friend bool operator>(const flat_multimap& x, const flat_multimap& y) { return y < x; } //! <b>Effects</b>: Returns true if x is equal or less than y //! //! <b>Complexity</b>: Linear to the number of elements in the container. - friend bool operator<=(const flat_multimap& x, const flat_multimap& y) + BOOST_CONTAINER_FORCEINLINE friend bool operator<=(const flat_multimap& x, const flat_multimap& y) { return !(y < x); } //! <b>Effects</b>: Returns true if x is equal or greater than y //! //! <b>Complexity</b>: Linear to the number of elements in the container. - friend bool operator>=(const flat_multimap& x, const flat_multimap& y) + BOOST_CONTAINER_FORCEINLINE friend bool operator>=(const flat_multimap& x, const flat_multimap& y) { return !(x < y); } //! <b>Effects</b>: x.swap(y) //! //! <b>Complexity</b>: Constant. - friend void swap(flat_multimap& x, flat_multimap& y) + BOOST_CONTAINER_FORCEINLINE friend void swap(flat_multimap& x, flat_multimap& y) { x.swap(y); } }; diff --git a/boost/container/flat_set.hpp b/boost/container/flat_set.hpp index fa27006177..9e39be8e78 100644 --- a/boost/container/flat_set.hpp +++ b/boost/container/flat_set.hpp @@ -114,6 +114,7 @@ class flat_set typedef typename BOOST_CONTAINER_IMPDEF(base_t::const_iterator) const_iterator; typedef typename BOOST_CONTAINER_IMPDEF(base_t::reverse_iterator) reverse_iterator; typedef typename BOOST_CONTAINER_IMPDEF(base_t::const_reverse_iterator) const_reverse_iterator; + typedef typename BOOST_CONTAINER_IMPDEF(base_t::sequence_type) sequence_type; public: ////////////////////////////////////////////// @@ -125,37 +126,47 @@ class flat_set //! <b>Effects</b>: Default constructs an empty container. //! //! <b>Complexity</b>: Constant. + BOOST_CONTAINER_FORCEINLINE explicit flat_set() BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value && container_detail::is_nothrow_default_constructible<Compare>::value) : base_t() {} //! <b>Effects</b>: Constructs an empty container using the specified - //! comparison object and allocator. + //! comparison object. //! //! <b>Complexity</b>: Constant. - explicit flat_set(const Compare& comp, - const allocator_type& a = allocator_type()) - : base_t(comp, a) + BOOST_CONTAINER_FORCEINLINE + explicit flat_set(const Compare& comp) + : base_t(comp) {} //! <b>Effects</b>: Constructs an empty container using the specified allocator. //! //! <b>Complexity</b>: Constant. + BOOST_CONTAINER_FORCEINLINE explicit flat_set(const allocator_type& a) : base_t(a) {} - //! <b>Effects</b>: Constructs an empty container using the specified comparison object and - //! allocator, and inserts elements from the range [first ,last ). + //! <b>Effects</b>: Constructs an empty container using the specified + //! comparison object and allocator. + //! + //! <b>Complexity</b>: Constant. + BOOST_CONTAINER_FORCEINLINE + flat_set(const Compare& comp, const allocator_type& a) + : base_t(comp, a) + {} + + //! <b>Effects</b>: Constructs an empty container and + //! inserts elements from the range [first ,last ). //! //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using //! comp and otherwise N logN, where N is last - first. template <class InputIterator> - flat_set(InputIterator first, InputIterator last, - const Compare& comp = Compare(), - const allocator_type& a = allocator_type()) - : base_t(true, first, last, comp, a) + BOOST_CONTAINER_FORCEINLINE + flat_set(InputIterator first, InputIterator last) + : base_t(true, first, last) {} //! <b>Effects</b>: Constructs an empty container using the specified @@ -164,8 +175,63 @@ class flat_set //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using //! comp and otherwise N logN, where N is last - first. template <class InputIterator> + BOOST_CONTAINER_FORCEINLINE flat_set(InputIterator first, InputIterator last, const allocator_type& a) - : base_t(true, first, last, Compare(), a) + : base_t(true, first, last, a) + {} + + //! <b>Effects</b>: Constructs an empty container using the specified comparison object and + //! inserts elements from the range [first ,last ). + //! + //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using + //! comp and otherwise N logN, where N is last - first. + template <class InputIterator> + BOOST_CONTAINER_FORCEINLINE + flat_set(InputIterator first, InputIterator last, const Compare& comp) + : base_t(true, first, last, comp) + {} + + //! <b>Effects</b>: Constructs an empty container using the specified comparison object and + //! allocator, and inserts elements from the range [first ,last ). + //! + //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using + //! comp and otherwise N logN, where N is last - first. + template <class InputIterator> + BOOST_CONTAINER_FORCEINLINE + flat_set(InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a) + : base_t(true, first, last, comp, a) + {} + + //! <b>Effects</b>: Constructs an empty container and + //! inserts elements from the ordered unique range [first ,last). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! <b>Requires</b>: [first ,last) must be ordered according to the predicate and must be + //! unique values. + //! + //! <b>Complexity</b>: Linear in N. + //! + //! <b>Note</b>: Non-standard extension. + template <class InputIterator> + BOOST_CONTAINER_FORCEINLINE + flat_set(ordered_unique_range_t, InputIterator first, InputIterator last) + : base_t(ordered_unique_range, first, last) + {} + + //! <b>Effects</b>: Constructs an empty container using the specified comparison object and + //! inserts elements from the ordered unique range [first ,last). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! <b>Requires</b>: [first ,last) must be ordered according to the predicate and must be + //! unique values. + //! + //! <b>Complexity</b>: Linear in N. + //! + //! <b>Note</b>: Non-standard extension. + template <class InputIterator> + BOOST_CONTAINER_FORCEINLINE + flat_set(ordered_unique_range_t, InputIterator first, InputIterator last, const Compare& comp) + : base_t(ordered_unique_range, first, last, comp) {} //! <b>Effects</b>: Constructs an empty container using the specified comparison object and @@ -179,21 +245,19 @@ class flat_set //! //! <b>Note</b>: Non-standard extension. template <class InputIterator> - flat_set(ordered_unique_range_t, InputIterator first, InputIterator last, - const Compare& comp = Compare(), - const allocator_type& a = allocator_type()) + BOOST_CONTAINER_FORCEINLINE + flat_set(ordered_unique_range_t, InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a) : base_t(ordered_unique_range, first, last, comp, a) {} #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) - //! <b>Effects</b>: Constructs an empty container using the specified comparison object and - //! allocator, and inserts elements from the range [il.begin(), il.end()). + //! <b>Effects</b>: Constructs an empty container and + //! inserts elements from the range [il.begin(), il.end()). //! //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using //! comp and otherwise N logN, where N is il.begin() - il.end(). - flat_set(std::initializer_list<value_type> il, const Compare& comp = Compare(), - const allocator_type& a = allocator_type()) - : base_t(true, il.begin(), il.end(), comp, a) + BOOST_CONTAINER_FORCEINLINE flat_set(std::initializer_list<value_type> il) + : base_t(true, il.begin(), il.end()) {} //! <b>Effects</b>: Constructs an empty container using the specified @@ -201,8 +265,54 @@ class flat_set //! //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using //! comp and otherwise N logN, where N is il.begin() - il.end(). - flat_set(std::initializer_list<value_type> il, const allocator_type& a) - : base_t(true, il.begin(), il.end(), Compare(), a) + BOOST_CONTAINER_FORCEINLINE flat_set(std::initializer_list<value_type> il, const allocator_type& a) + : base_t(true, il.begin(), il.end(), a) + {} + + //! <b>Effects</b>: Constructs an empty container using the specified comparison object and + //! inserts elements from the range [il.begin(), il.end()). + //! + //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using + //! comp and otherwise N logN, where N is il.begin() - il.end(). + BOOST_CONTAINER_FORCEINLINE flat_set(std::initializer_list<value_type> il, const Compare& comp) + : base_t(true, il.begin(), il.end(), comp) + {} + + //! <b>Effects</b>: Constructs an empty container using the specified comparison object and + //! allocator, and inserts elements from the range [il.begin(), il.end()). + //! + //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using + //! comp and otherwise N logN, where N is il.begin() - il.end(). + BOOST_CONTAINER_FORCEINLINE flat_set(std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a) + : base_t(true, il.begin(), il.end(), comp, a) + {} + + //! <b>Effects</b>: Constructs an empty container using the specified comparison object and + //! inserts elements from the ordered unique range [il.begin(), il.end()). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be + //! unique values. + //! + //! <b>Complexity</b>: Linear in N. + //! + //! <b>Note</b>: Non-standard extension. + BOOST_CONTAINER_FORCEINLINE flat_set(ordered_unique_range_t, std::initializer_list<value_type> il) + : base_t(ordered_unique_range, il.begin(), il.end()) + {} + + //! <b>Effects</b>: Constructs an empty container using the specified comparison object and + //! inserts elements from the ordered unique range [il.begin(), il.end()). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be + //! unique values. + //! + //! <b>Complexity</b>: Linear in N. + //! + //! <b>Note</b>: Non-standard extension. + BOOST_CONTAINER_FORCEINLINE flat_set(ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp) + : base_t(ordered_unique_range, il.begin(), il.end(), comp) {} //! <b>Effects</b>: Constructs an empty container using the specified comparison object and @@ -215,8 +325,7 @@ class flat_set //! <b>Complexity</b>: Linear in N. //! //! <b>Note</b>: Non-standard extension. - flat_set(ordered_unique_range_t, std::initializer_list<value_type> il, - const Compare& comp = Compare(), const allocator_type& a = allocator_type()) + BOOST_CONTAINER_FORCEINLINE flat_set(ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a) : base_t(ordered_unique_range, il.begin(), il.end(), comp, a) {} #endif @@ -224,7 +333,7 @@ class flat_set //! <b>Effects</b>: Copy constructs the container. //! //! <b>Complexity</b>: Linear in x.size(). - flat_set(const flat_set& x) + BOOST_CONTAINER_FORCEINLINE flat_set(const flat_set& x) : base_t(static_cast<const base_t&>(x)) {} @@ -233,7 +342,7 @@ class flat_set //! <b>Complexity</b>: Constant. //! //! <b>Postcondition</b>: x is emptied. - flat_set(BOOST_RV_REF(flat_set) x) + BOOST_CONTAINER_FORCEINLINE flat_set(BOOST_RV_REF(flat_set) x) BOOST_NOEXCEPT_IF(boost::container::container_detail::is_nothrow_move_constructible<Compare>::value) : base_t(BOOST_MOVE_BASE(base_t, x)) {} @@ -241,7 +350,7 @@ class flat_set //! <b>Effects</b>: Copy constructs a container using the specified allocator. //! //! <b>Complexity</b>: Linear in x.size(). - flat_set(const flat_set& x, const allocator_type &a) + BOOST_CONTAINER_FORCEINLINE flat_set(const flat_set& x, const allocator_type &a) : base_t(static_cast<const base_t&>(x), a) {} @@ -249,14 +358,14 @@ class flat_set //! Constructs *this using x's resources. //! //! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise - flat_set(BOOST_RV_REF(flat_set) x, const allocator_type &a) + BOOST_CONTAINER_FORCEINLINE flat_set(BOOST_RV_REF(flat_set) x, const allocator_type &a) : base_t(BOOST_MOVE_BASE(base_t, x), a) {} //! <b>Effects</b>: Makes *this a copy of x. //! //! <b>Complexity</b>: Linear in x.size(). - flat_set& operator=(BOOST_COPY_ASSIGN_REF(flat_set) x) + BOOST_CONTAINER_FORCEINLINE flat_set& operator=(BOOST_COPY_ASSIGN_REF(flat_set) x) { return static_cast<flat_set&>(this->base_t::operator=(static_cast<const base_t&>(x))); } //! <b>Throws</b>: If allocator_traits_type::propagate_on_container_move_assignment @@ -265,7 +374,7 @@ class flat_set //! <b>Complexity</b>: Constant if allocator_traits_type:: //! propagate_on_container_move_assignment is true or //! this->get>allocator() == x.get_allocator(). Linear otherwise. - flat_set& operator=(BOOST_RV_REF(flat_set) x) + BOOST_CONTAINER_FORCEINLINE flat_set& operator=(BOOST_RV_REF(flat_set) x) BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value || allocator_traits_type::is_always_equal::value) && boost::container::container_detail::is_nothrow_move_assignable<Compare>::value) @@ -469,7 +578,7 @@ class flat_set //! //! <b>Note</b>: If an element is inserted it might invalidate elements. template <class... Args> - std::pair<iterator,bool> emplace(BOOST_FWD_REF(Args)... args) + BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> emplace(BOOST_FWD_REF(Args)... args) { return this->base_t::emplace_unique(boost::forward<Args>(args)...); } //! <b>Effects</b>: Inserts an object of type Key constructed with @@ -485,18 +594,18 @@ class flat_set //! //! <b>Note</b>: If an element is inserted it might invalidate elements. template <class... Args> - iterator emplace_hint(const_iterator p, BOOST_FWD_REF(Args)... args) + BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator p, BOOST_FWD_REF(Args)... args) { return this->base_t::emplace_hint_unique(p, boost::forward<Args>(args)...); } #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) #define BOOST_CONTAINER_FLAT_SET_EMPLACE_CODE(N) \ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ - std::pair<iterator,bool> emplace(BOOST_MOVE_UREF##N)\ + BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> emplace(BOOST_MOVE_UREF##N)\ { return this->base_t::emplace_unique(BOOST_MOVE_FWD##N); }\ \ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ - iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ + BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ { return this->base_t::emplace_hint_unique(hint BOOST_MOVE_I##N BOOST_MOVE_FWD##N); }\ // BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_FLAT_SET_EMPLACE_CODE) @@ -575,7 +684,7 @@ class flat_set //! //! <b>Note</b>: If an element is inserted it might invalidate elements. template <class InputIterator> - void insert(InputIterator first, InputIterator last) + BOOST_CONTAINER_FORCEINLINE void insert(InputIterator first, InputIterator last) { this->base_t::insert_unique(first, last); } //! <b>Requires</b>: first, last are not iterators into *this and @@ -590,7 +699,7 @@ class flat_set //! //! <b>Note</b>: Non-standard extension. If an element is inserted it might invalidate elements. template <class InputIterator> - void insert(ordered_unique_range_t, InputIterator first, InputIterator last) + BOOST_CONTAINER_FORCEINLINE void insert(ordered_unique_range_t, InputIterator first, InputIterator last) { this->base_t::insert_unique(ordered_unique_range, first, last); } #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) @@ -601,7 +710,7 @@ class flat_set //! search time plus N*size() insertion time. //! //! <b>Note</b>: If an element is inserted it might invalidate elements. - void insert(std::initializer_list<value_type> il) + BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il) { this->base_t::insert_unique(il.begin(), il.end()); } //! <b>Requires</b>: Range [il.begin(), il.end()) must be ordered according to the predicate @@ -614,7 +723,7 @@ class flat_set //! search time plus N*size() insertion time. //! //! <b>Note</b>: Non-standard extension. If an element is inserted it might invalidate elements. - void insert(ordered_unique_range_t, std::initializer_list<value_type> il) + BOOST_CONTAINER_FORCEINLINE void insert(ordered_unique_range_t, std::initializer_list<value_type> il) { this->base_t::insert_unique(ordered_unique_range, il.begin(), il.end()); } #endif @@ -623,7 +732,7 @@ class flat_set BOOST_CONTAINER_FORCEINLINE void merge(flat_set<Key, C2, Allocator>& source) { this->base_t::merge_unique(source.tree()); } - //! @copydoc ::boost::container::flat_map::merge(flat_set<Key, C2, Allocator>&) + //! @copydoc ::boost::container::flat_set::merge(flat_set<Key, C2, Allocator>&) template<class C2> BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_set<Key, C2, Allocator> BOOST_RV_REF_END source) { return this->merge(static_cast<flat_set<Key, C2, Allocator>&>(source)); } @@ -633,7 +742,7 @@ class flat_set BOOST_CONTAINER_FORCEINLINE void merge(flat_multiset<Key, C2, Allocator>& source) { this->base_t::merge_unique(source.tree()); } - //! @copydoc ::boost::container::flat_map::merge(flat_multiset<Key, C2, Allocator>&) + //! @copydoc ::boost::container::flat_set::merge(flat_multiset<Key, C2, Allocator>&) template<class C2> BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_multiset<Key, C2, Allocator> BOOST_RV_REF_END source) { return this->merge(static_cast<flat_multiset<Key, C2, Allocator>&>(source)); } @@ -765,7 +874,7 @@ class flat_set //! <b>Returns</b>: The number of elements with key equivalent to x. //! //! <b>Complexity</b>: log(size())+count(k) - size_type count(const key_type& x) const + BOOST_CONTAINER_FORCEINLINE size_type count(const key_type& x) const { return static_cast<size_type>(this->base_t::find(x) != this->base_t::cend()); } #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) @@ -798,13 +907,13 @@ class flat_set //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). //! //! <b>Complexity</b>: Logarithmic - std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const + BOOST_CONTAINER_FORCEINLINE std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const { return this->base_t::lower_bound_range(x); } //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). //! //! <b>Complexity</b>: Logarithmic - std::pair<iterator,iterator> equal_range(const key_type& x) + BOOST_CONTAINER_FORCEINLINE std::pair<iterator,iterator> equal_range(const key_type& x) { return this->base_t::lower_bound_range(x); } #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) @@ -844,16 +953,46 @@ class flat_set //! <b>Complexity</b>: Constant. friend void swap(flat_set& x, flat_set& y); + //! <b>Effects</b>: Extracts the internal sequence container. + //! + //! <b>Complexity</b>: Same as the move constructor of sequence_type, usually constant. + //! + //! <b>Postcondition</b>: this->empty() + //! + //! <b>Throws</b>: If secuence_type's move constructor throws + sequence_type extract_sequence(); + #endif //#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED + //! <b>Effects</b>: Discards the internally hold sequence container and adopts the + //! one passed externally using the move assignment. Erases non-unique elements. + //! + //! <b>Complexity</b>: Assuming O(1) move assignment, O(NlogN) with N = seq.size() + //! + //! <b>Throws</b>: If the comparison or the move constructor throws + BOOST_CONTAINER_FORCEINLINE void adopt_sequence(BOOST_RV_REF(sequence_type) seq) + { this->base_t::adopt_sequence_unique(boost::move(seq)); } + + //! <b>Requires</b>: seq shall be ordered according to this->compare() + //! and shall contain unique elements. + //! + //! <b>Effects</b>: Discards the internally hold sequence container and adopts the + //! one passed externally using the move assignment. + //! + //! <b>Complexity</b>: Assuming O(1) move assignment, O(1) + //! + //! <b>Throws</b>: If the move assignment throws + BOOST_CONTAINER_FORCEINLINE void adopt_sequence(ordered_unique_range_t, BOOST_RV_REF(sequence_type) seq) + { this->base_t::adopt_sequence_unique(ordered_unique_range_t(), boost::move(seq)); } + #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED private: template<class KeyType> - std::pair<iterator, bool> priv_insert(BOOST_FWD_REF(KeyType) x) + BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> priv_insert(BOOST_FWD_REF(KeyType) x) { return this->base_t::insert_unique(::boost::forward<KeyType>(x)); } template<class KeyType> - iterator priv_insert(const_iterator p, BOOST_FWD_REF(KeyType) x) + BOOST_CONTAINER_FORCEINLINE iterator priv_insert(const_iterator p, BOOST_FWD_REF(KeyType) x) { return this->base_t::insert_unique(p, ::boost::forward<KeyType>(x)); } #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED }; @@ -939,40 +1078,83 @@ class flat_multiset typedef typename BOOST_CONTAINER_IMPDEF(base_t::const_iterator) const_iterator; typedef typename BOOST_CONTAINER_IMPDEF(base_t::reverse_iterator) reverse_iterator; typedef typename BOOST_CONTAINER_IMPDEF(base_t::const_reverse_iterator) const_reverse_iterator; + typedef typename BOOST_CONTAINER_IMPDEF(base_t::sequence_type) sequence_type; //! @copydoc ::boost::container::flat_set::flat_set() - explicit flat_multiset() BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value && + BOOST_CONTAINER_FORCEINLINE explicit flat_multiset() BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value && container_detail::is_nothrow_default_constructible<Compare>::value) : base_t() {} - //! @copydoc ::boost::container::flat_set::flat_set(const Compare&, const allocator_type&) - explicit flat_multiset(const Compare& comp, - const allocator_type& a = allocator_type()) - : base_t(comp, a) + //! @copydoc ::boost::container::flat_set::flat_set(const Compare&) + BOOST_CONTAINER_FORCEINLINE explicit flat_multiset(const Compare& comp) + : base_t(comp) {} //! @copydoc ::boost::container::flat_set::flat_set(const allocator_type&) - explicit flat_multiset(const allocator_type& a) + BOOST_CONTAINER_FORCEINLINE explicit flat_multiset(const allocator_type& a) : base_t(a) {} + //! @copydoc ::boost::container::flat_set::flat_set(const Compare&, const allocator_type&) + BOOST_CONTAINER_FORCEINLINE flat_multiset(const Compare& comp, const allocator_type& a) + : base_t(comp, a) + {} + + //! @copydoc ::boost::container::flat_set::flat_set(InputIterator, InputIterator) + template <class InputIterator> + BOOST_CONTAINER_FORCEINLINE flat_multiset(InputIterator first, InputIterator last) + : base_t(false, first, last) + {} + + //! @copydoc ::boost::container::flat_set::flat_set(InputIterator, InputIterator, const allocator_type&) + template <class InputIterator> + BOOST_CONTAINER_FORCEINLINE flat_multiset(InputIterator first, InputIterator last, const allocator_type& a) + : base_t(false, first, last, a) + {} + + //! @copydoc ::boost::container::flat_set::flat_set(InputIterator, InputIterator, const Compare& comp) + template <class InputIterator> + BOOST_CONTAINER_FORCEINLINE flat_multiset(InputIterator first, InputIterator last, const Compare& comp) + : base_t(false, first, last, comp) + {} + //! @copydoc ::boost::container::flat_set::flat_set(InputIterator, InputIterator, const Compare& comp, const allocator_type&) template <class InputIterator> - flat_multiset(InputIterator first, InputIterator last, - const Compare& comp = Compare(), - const allocator_type& a = allocator_type()) + BOOST_CONTAINER_FORCEINLINE flat_multiset(InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a) : base_t(false, first, last, comp, a) {} - //! @copydoc ::boost::container::flat_set::flat_set(InputIterator, InputIterator, const allocator_type&) + //! <b>Effects</b>: Constructs an empty flat_multiset and + //! inserts elements from the ordered range [first ,last ). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! <b>Requires</b>: [first ,last) must be ordered according to the predicate. + //! + //! <b>Complexity</b>: Linear in N. + //! + //! <b>Note</b>: Non-standard extension. + template <class InputIterator> + BOOST_CONTAINER_FORCEINLINE flat_multiset(ordered_range_t, InputIterator first, InputIterator last) + : base_t(ordered_range, first, last) + {} + + //! <b>Effects</b>: Constructs an empty flat_multiset using the specified comparison object and + //! inserts elements from the ordered range [first ,last ). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! <b>Requires</b>: [first ,last) must be ordered according to the predicate. + //! + //! <b>Complexity</b>: Linear in N. + //! + //! <b>Note</b>: Non-standard extension. template <class InputIterator> - flat_multiset(InputIterator first, InputIterator last, const allocator_type& a) - : base_t(false, first, last, Compare(), a) + BOOST_CONTAINER_FORCEINLINE flat_multiset(ordered_range_t, InputIterator first, InputIterator last, const Compare& comp) + : base_t(ordered_range, first, last, comp) {} //! <b>Effects</b>: Constructs an empty flat_multiset using the specified comparison object and - //! allocator, and inserts elements from the ordered range [first ,last ). This function + //! allocator, and inserts elements from the ordered range [first, last ). This function //! is more efficient than the normal range creation for ordered ranges. //! //! <b>Requires</b>: [first ,last) must be ordered according to the predicate. @@ -981,22 +1163,55 @@ class flat_multiset //! //! <b>Note</b>: Non-standard extension. template <class InputIterator> - flat_multiset(ordered_range_t, InputIterator first, InputIterator last, - const Compare& comp = Compare(), - const allocator_type& a = allocator_type()) + BOOST_CONTAINER_FORCEINLINE flat_multiset(ordered_range_t, InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a) : base_t(ordered_range, first, last, comp, a) {} #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + //! @copydoc ::boost::container::flat_set::flat_set(std::initializer_list<value_type) + BOOST_CONTAINER_FORCEINLINE flat_multiset(std::initializer_list<value_type> il) + : base_t(false, il.begin(), il.end()) + {} + + //! @copydoc ::boost::container::flat_set::flat_set(std::initializer_list<value_type>, const allocator_type&) + BOOST_CONTAINER_FORCEINLINE flat_multiset(std::initializer_list<value_type> il, const allocator_type& a) + : base_t(false, il.begin(), il.end(), a) + {} + + //! @copydoc ::boost::container::flat_set::flat_set(std::initializer_list<value_type>, const Compare& comp) + BOOST_CONTAINER_FORCEINLINE flat_multiset(std::initializer_list<value_type> il, const Compare& comp) + : base_t(false, il.begin(), il.end(), comp) + {} + //! @copydoc ::boost::container::flat_set::flat_set(std::initializer_list<value_type>, const Compare& comp, const allocator_type&) - flat_multiset(std::initializer_list<value_type> il, const Compare& comp = Compare(), - const allocator_type& a = allocator_type()) + BOOST_CONTAINER_FORCEINLINE flat_multiset(std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a) : base_t(false, il.begin(), il.end(), comp, a) {} - //! @copydoc ::boost::container::flat_set::flat_set(std::initializer_list<value_type>, const allocator_type&) - flat_multiset(std::initializer_list<value_type> il, const allocator_type& a) - : base_t(false, il.begin(), il.end(), Compare(), a) + //! <b>Effects</b>: Constructs an empty containerand + //! inserts elements from the ordered unique range [il.begin(), il.end()). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate. + //! + //! <b>Complexity</b>: Linear in N. + //! + //! <b>Note</b>: Non-standard extension. + BOOST_CONTAINER_FORCEINLINE flat_multiset(ordered_range_t, std::initializer_list<value_type> il) + : base_t(ordered_range, il.begin(), il.end()) + {} + + //! <b>Effects</b>: Constructs an empty container using the specified comparison object and + //! inserts elements from the ordered unique range [il.begin(), il.end()). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate. + //! + //! <b>Complexity</b>: Linear in N. + //! + //! <b>Note</b>: Non-standard extension. + BOOST_CONTAINER_FORCEINLINE flat_multiset(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp) + : base_t(ordered_range, il.begin(), il.end(), comp) {} //! <b>Effects</b>: Constructs an empty container using the specified comparison object and @@ -1008,39 +1223,38 @@ class flat_multiset //! <b>Complexity</b>: Linear in N. //! //! <b>Note</b>: Non-standard extension. - flat_multiset(ordered_range_t, std::initializer_list<value_type> il, - const Compare& comp = Compare(), const allocator_type& a = allocator_type()) + BOOST_CONTAINER_FORCEINLINE flat_multiset(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a) : base_t(ordered_range, il.begin(), il.end(), comp, a) {} #endif //! @copydoc ::boost::container::flat_set::flat_set(const flat_set &) - flat_multiset(const flat_multiset& x) + BOOST_CONTAINER_FORCEINLINE flat_multiset(const flat_multiset& x) : base_t(static_cast<const base_t&>(x)) {} //! @copydoc ::boost::container::flat_set::flat_set(flat_set &&) - flat_multiset(BOOST_RV_REF(flat_multiset) x) + BOOST_CONTAINER_FORCEINLINE flat_multiset(BOOST_RV_REF(flat_multiset) x) BOOST_NOEXCEPT_IF(boost::container::container_detail::is_nothrow_move_constructible<Compare>::value) : base_t(boost::move(static_cast<base_t&>(x))) {} //! @copydoc ::boost::container::flat_set::flat_set(const flat_set &, const allocator_type &) - flat_multiset(const flat_multiset& x, const allocator_type &a) + BOOST_CONTAINER_FORCEINLINE flat_multiset(const flat_multiset& x, const allocator_type &a) : base_t(static_cast<const base_t&>(x), a) {} //! @copydoc ::boost::container::flat_set::flat_set(flat_set &&, const allocator_type &) - flat_multiset(BOOST_RV_REF(flat_multiset) x, const allocator_type &a) + BOOST_CONTAINER_FORCEINLINE flat_multiset(BOOST_RV_REF(flat_multiset) x, const allocator_type &a) : base_t(BOOST_MOVE_BASE(base_t, x), a) {} //! @copydoc ::boost::container::flat_set::operator=(const flat_set &) - flat_multiset& operator=(BOOST_COPY_ASSIGN_REF(flat_multiset) x) + BOOST_CONTAINER_FORCEINLINE flat_multiset& operator=(BOOST_COPY_ASSIGN_REF(flat_multiset) x) { return static_cast<flat_multiset&>(this->base_t::operator=(static_cast<const base_t&>(x))); } //! @copydoc ::boost::container::flat_set::operator=(flat_set &&) - flat_multiset& operator=(BOOST_RV_REF(flat_multiset) x) + BOOST_CONTAINER_FORCEINLINE flat_multiset& operator=(BOOST_RV_REF(flat_multiset) x) BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value || allocator_traits_type::is_always_equal::value) && boost::container::container_detail::is_nothrow_move_assignable<Compare>::value) @@ -1140,7 +1354,7 @@ class flat_multiset //! //! <b>Note</b>: If an element is inserted it might invalidate elements. template <class... Args> - iterator emplace(BOOST_FWD_REF(Args)... args) + BOOST_CONTAINER_FORCEINLINE iterator emplace(BOOST_FWD_REF(Args)... args) { return this->base_t::emplace_equal(boost::forward<Args>(args)...); } //! <b>Effects</b>: Inserts an object of type Key constructed with @@ -1155,18 +1369,18 @@ class flat_multiset //! //! <b>Note</b>: If an element is inserted it might invalidate elements. template <class... Args> - iterator emplace_hint(const_iterator p, BOOST_FWD_REF(Args)... args) + BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator p, BOOST_FWD_REF(Args)... args) { return this->base_t::emplace_hint_equal(p, boost::forward<Args>(args)...); } #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) #define BOOST_CONTAINER_FLAT_MULTISET_EMPLACE_CODE(N) \ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ - iterator emplace(BOOST_MOVE_UREF##N)\ + BOOST_CONTAINER_FORCEINLINE iterator emplace(BOOST_MOVE_UREF##N)\ { return this->base_t::emplace_equal(BOOST_MOVE_FWD##N); }\ \ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ - iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ + BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ { return this->base_t::emplace_hint_equal(hint BOOST_MOVE_I##N BOOST_MOVE_FWD##N); }\ // BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_FLAT_MULTISET_EMPLACE_CODE) @@ -1233,7 +1447,7 @@ class flat_multiset //! //! <b>Note</b>: If an element is inserted it might invalidate elements. template <class InputIterator> - void insert(InputIterator first, InputIterator last) + BOOST_CONTAINER_FORCEINLINE void insert(InputIterator first, InputIterator last) { this->base_t::insert_equal(first, last); } //! <b>Requires</b>: first, last are not iterators into *this and @@ -1247,7 +1461,7 @@ class flat_multiset //! //! <b>Note</b>: Non-standard extension. If an element is inserted it might invalidate elements. template <class InputIterator> - void insert(ordered_range_t, InputIterator first, InputIterator last) + BOOST_CONTAINER_FORCEINLINE void insert(ordered_range_t, InputIterator first, InputIterator last) { this->base_t::insert_equal(ordered_range, first, last); } #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) @@ -1257,7 +1471,7 @@ class flat_multiset //! search time plus N*size() insertion time. //! //! <b>Note</b>: If an element is inserted it might invalidate elements. - void insert(std::initializer_list<value_type> il) + BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il) { this->base_t::insert_equal(il.begin(), il.end()); } //! <b>Requires</b>: Range [il.begin(), il.end()) must be ordered according to the predicate. @@ -1269,7 +1483,7 @@ class flat_multiset //! search time plus N*size() insertion time. //! //! <b>Note</b>: Non-standard extension. If an element is inserted it might invalidate elements. - void insert(ordered_range_t, std::initializer_list<value_type> il) + BOOST_CONTAINER_FORCEINLINE void insert(ordered_range_t, std::initializer_list<value_type> il) { this->base_t::insert_equal(ordered_range, il.begin(), il.end()); } #endif @@ -1392,16 +1606,45 @@ class flat_multiset //! <b>Complexity</b>: Constant. friend void swap(flat_multiset& x, flat_multiset& y); + //! <b>Effects</b>: Extracts the internal sequence container. + //! + //! <b>Complexity</b>: Same as the move constructor of sequence_type, usually constant. + //! + //! <b>Postcondition</b>: this->empty() + //! + //! <b>Throws</b>: If secuence_type's move constructor throws + sequence_type extract_sequence(); + #endif //#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED + //! <b>Effects</b>: Discards the internally hold sequence container and adopts the + //! one passed externally using the move assignment. + //! + //! <b>Complexity</b>: Assuming O(1) move assignment, O(NlogN) with N = seq.size() + //! + //! <b>Throws</b>: If the comparison or the move constructor throws + BOOST_CONTAINER_FORCEINLINE void adopt_sequence(BOOST_RV_REF(sequence_type) seq) + { this->base_t::adopt_sequence_equal(boost::move(seq)); } + + //! <b>Requires</b>: seq shall be ordered according to this->compare() + //! + //! <b>Effects</b>: Discards the internally hold sequence container and adopts the + //! one passed externally using the move assignment. + //! + //! <b>Complexity</b>: Assuming O(1) move assignment, O(1) + //! + //! <b>Throws</b>: If the move assignment throws + BOOST_CONTAINER_FORCEINLINE void adopt_sequence(ordered_range_t, BOOST_RV_REF(sequence_type) seq) + { this->base_t::adopt_sequence_equal(ordered_range_t(), boost::move(seq)); } + #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED private: template <class KeyType> - iterator priv_insert(BOOST_FWD_REF(KeyType) x) + BOOST_CONTAINER_FORCEINLINE iterator priv_insert(BOOST_FWD_REF(KeyType) x) { return this->base_t::insert_equal(::boost::forward<KeyType>(x)); } template <class KeyType> - iterator priv_insert(const_iterator p, BOOST_FWD_REF(KeyType) x) + BOOST_CONTAINER_FORCEINLINE iterator priv_insert(const_iterator p, BOOST_FWD_REF(KeyType) x) { return this->base_t::insert_equal(p, ::boost::forward<KeyType>(x)); } #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED }; diff --git a/boost/container/map.hpp b/boost/container/map.hpp index 5520fb45ba..33e0331eb0 100644 --- a/boost/container/map.hpp +++ b/boost/container/map.hpp @@ -31,6 +31,8 @@ #include <boost/container/detail/type_traits.hpp> #include <boost/container/detail/value_init.hpp> #include <boost/container/detail/pair.hpp> +#include <boost/container/detail/pair_key_mapped_of_value.hpp> + // move #include <boost/move/traits.hpp> #include <boost/move/utility_core.hpp> @@ -53,34 +55,6 @@ namespace boost { namespace container { -///@cond - -template<class Key, class Mapped> -struct pair_key_mapped_of_value -{ - typedef Key key_type; - typedef Mapped mapped_type; - - template<class Pair> - const key_type & key_of_value(const Pair &p) const - { return p.first; } - - template<class Pair> - const mapped_type & mapped_of_value(const Pair &p) const - { return p.second; } - - template<class Pair> - key_type & key_of_value(Pair &p) const - { return const_cast<key_type&>(p.first); } - - template<class Pair> - mapped_type & mapped_of_value(Pair &p) const - { return p.second; } - -}; - -///@endcond - #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED //! A map is a kind of associative container that supports unique keys (contains at @@ -132,7 +106,7 @@ class map typedef Key key_type; typedef ::boost::container::allocator_traits<Allocator> allocator_traits_type; typedef T mapped_type; - typedef std::pair<const Key, T> value_type; + typedef typename boost::container::allocator_traits<Allocator>::value_type value_type; typedef typename boost::container::allocator_traits<Allocator>::pointer pointer; typedef typename boost::container::allocator_traits<Allocator>::const_pointer const_pointer; typedef typename boost::container::allocator_traits<Allocator>::reference reference; @@ -150,14 +124,15 @@ class map typedef std::pair<key_type, mapped_type> nonconst_value_type; typedef BOOST_CONTAINER_IMPDEF(movable_value_type_impl) movable_value_type; typedef BOOST_CONTAINER_IMPDEF(node_handle< - typename base_t::node_type::container_node_type - BOOST_MOVE_I value_type - BOOST_MOVE_I allocator_type + typename base_t::stored_allocator_type BOOST_MOVE_I pair_key_mapped_of_value <key_type BOOST_MOVE_I mapped_type> >) node_type; typedef BOOST_CONTAINER_IMPDEF (insert_return_type_base<iterator BOOST_MOVE_I node_type>) insert_return_type; + //allocator_type::value_type type must be std::pair<CONST Key, T> + BOOST_STATIC_ASSERT((container_detail::is_same<typename allocator_type::value_type, std::pair<const Key, T> >::value)); + ////////////////////////////////////////////// // // construct/copy/destroy @@ -171,62 +146,99 @@ class map map() BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value && container_detail::is_nothrow_default_constructible<Compare>::value) : base_t() - { - //A type must be std::pair<CONST Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); - } + {} //! <b>Effects</b>: Constructs an empty map using the specified comparison object //! and allocator. //! //! <b>Complexity</b>: Constant. - BOOST_CONTAINER_FORCEINLINE - explicit map(const Compare& comp, const allocator_type& a = allocator_type()) + BOOST_CONTAINER_FORCEINLINE map(const Compare& comp, const allocator_type& a) : base_t(comp, a) - { - //A type must be std::pair<CONST Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); - } + {} + + //! <b>Effects</b>: Constructs an empty map using the specified comparison object. + //! + //! <b>Complexity</b>: Constant. + BOOST_CONTAINER_FORCEINLINE explicit map(const Compare& comp) + : base_t(comp) + {} //! <b>Effects</b>: Constructs an empty map using the specified allocator. //! //! <b>Complexity</b>: Constant. - BOOST_CONTAINER_FORCEINLINE - explicit map(const allocator_type& a) + BOOST_CONTAINER_FORCEINLINE explicit map(const allocator_type& a) : base_t(a) - { - //A type must be std::pair<CONST Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); - } + {} - //! <b>Effects</b>: Constructs an empty map using the specified comparison object and - //! allocator, and inserts elements from the range [first ,last ). + //! <b>Effects</b>: Constructs an empty map and + //! inserts elements from the range [first ,last ). //! //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using - //! comp and otherwise N logN, where N is last - first. + //! the predicate and otherwise N logN, where N is last - first. template <class InputIterator> - BOOST_CONTAINER_FORCEINLINE - map(InputIterator first, InputIterator last, const Compare& comp = Compare(), - const allocator_type& a = allocator_type()) - : base_t(true, first, last, comp, a) - { - //A type must be std::pair<CONST Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); - } + BOOST_CONTAINER_FORCEINLINE map(InputIterator first, InputIterator last) + : base_t(true, first, last) + {} //! <b>Effects</b>: Constructs an empty map using the specified //! allocator, and inserts elements from the range [first ,last ). //! //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using - //! comp and otherwise N logN, where N is last - first. + //! the predicate and otherwise N logN, where N is last - first. template <class InputIterator> - BOOST_CONTAINER_FORCEINLINE - map(InputIterator first, InputIterator last, const allocator_type& a) + BOOST_CONTAINER_FORCEINLINE map(InputIterator first, InputIterator last, const allocator_type& a) : base_t(true, first, last, Compare(), a) - { - //A type must be std::pair<CONST Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); - } + {} + + //! <b>Effects</b>: Constructs an empty map using the specified comparison object and + //! inserts elements from the range [first ,last ). + //! + //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using + //! the predicate and otherwise N logN, where N is last - first. + template <class InputIterator> + BOOST_CONTAINER_FORCEINLINE map(InputIterator first, InputIterator last, const Compare& comp) + : base_t(true, first, last, comp) + {} + + //! <b>Effects</b>: Constructs an empty map using the specified comparison object and + //! allocator, and inserts elements from the range [first ,last ). + //! + //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using + //! the predicate and otherwise N logN, where N is last - first. + template <class InputIterator> + BOOST_CONTAINER_FORCEINLINE map(InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a) + : base_t(true, first, last, comp, a) + {} + + //! <b>Effects</b>: Constructs an empty map and + //! inserts elements from the ordered unique range [first ,last). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! <b>Requires</b>: [first ,last) must be ordered according to the predicate and must be + //! unique values. + //! + //! <b>Complexity</b>: Linear in N. + //! + //! <b>Note</b>: Non-standard extension. + template <class InputIterator> + BOOST_CONTAINER_FORCEINLINE map( ordered_unique_range_t, InputIterator first, InputIterator last) + : base_t(ordered_range, first, last) + {} + + //! <b>Effects</b>: Constructs an empty map using the specified comparison object and + //! inserts elements from the ordered unique range [first ,last). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! <b>Requires</b>: [first ,last) must be ordered according to the predicate and must be + //! unique values. + //! + //! <b>Complexity</b>: Linear in N. + //! + //! <b>Note</b>: Non-standard extension. + template <class InputIterator> + BOOST_CONTAINER_FORCEINLINE map( ordered_unique_range_t, InputIterator first, InputIterator last, const Compare& comp) + : base_t(ordered_range, first, last, comp) + {} //! <b>Effects</b>: Constructs an empty map using the specified comparison object and //! allocator, and inserts elements from the ordered unique range [first ,last). This function @@ -239,43 +251,76 @@ class map //! //! <b>Note</b>: Non-standard extension. template <class InputIterator> - BOOST_CONTAINER_FORCEINLINE - map( ordered_unique_range_t, InputIterator first, InputIterator last - , const Compare& comp = Compare(), const allocator_type& a = allocator_type()) + BOOST_CONTAINER_FORCEINLINE map( ordered_unique_range_t, InputIterator first, InputIterator last + , const Compare& comp, const allocator_type& a) : base_t(ordered_range, first, last, comp, a) - { - //A type must be std::pair<CONST Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); - } + {} #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + //! <b>Effects</b>: Constructs an empty map and + //! inserts elements from the range [il.begin(), il.end()). + //! + //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted according + //! to the predicate and otherwise N logN, where N is il.first() - il.end(). + BOOST_CONTAINER_FORCEINLINE map(std::initializer_list<value_type> il) + : base_t(true, il.begin(), il.end()) + {} + //! <b>Effects</b>: Constructs an empty map using the specified comparison object and - //! allocator, and inserts elements from the range [il.begin(), il.end()). + //! inserts elements from the range [il.begin(), il.end()). //! //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using - //! comp and otherwise N logN, where N is il.first() - il.end(). - BOOST_CONTAINER_FORCEINLINE - map(std::initializer_list<value_type> il, const Compare& comp = Compare(), const allocator_type& a = allocator_type()) - : base_t(true, il.begin(), il.end(), comp, a) - { - //A type must be std::pair<CONST Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); - } + //! the predicate and otherwise N logN, where N is il.first() - il.end(). + BOOST_CONTAINER_FORCEINLINE map(std::initializer_list<value_type> il, const Compare& comp) + : base_t(true, il.begin(), il.end(), comp) + {} //! <b>Effects</b>: Constructs an empty map using the specified //! allocator, and inserts elements from the range [il.begin(), il.end()). //! //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using - //! comp and otherwise N logN, where N is il.first() - il.end(). - BOOST_CONTAINER_FORCEINLINE - map(std::initializer_list<value_type> il, const allocator_type& a) + //! the predicate and otherwise N logN, where N is il.first() - il.end(). + BOOST_CONTAINER_FORCEINLINE map(std::initializer_list<value_type> il, const allocator_type& a) : base_t(true, il.begin(), il.end(), Compare(), a) - { - //A type must be std::pair<CONST Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); - } + {} - //! <b>Effects</b>: Constructs an empty set using the specified comparison object and + //! <b>Effects</b>: Constructs an empty map using the specified comparison object and + //! allocator, and inserts elements from the range [il.begin(), il.end()). + //! + //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using + //! the predicate and otherwise N logN, where N is il.first() - il.end(). + BOOST_CONTAINER_FORCEINLINE map(std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a) + : base_t(true, il.begin(), il.end(), comp, a) + {} + + //! <b>Effects</b>: Constructs an empty map and inserts elements from the ordered unique range [il.begin(), il.end()). + //! This function is more efficient than the normal range creation for ordered ranges. + //! + //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be + //! unique values. + //! + //! <b>Complexity</b>: Linear in N. + //! + //! <b>Note</b>: Non-standard extension. + BOOST_CONTAINER_FORCEINLINE map(ordered_unique_range_t, std::initializer_list<value_type> il) + : base_t(ordered_range, il.begin(), il.end()) + {} + + //! <b>Effects</b>: Constructs an empty map using the specified comparison object, + //! and inserts elements from the ordered unique range [il.begin(), il.end()). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be + //! unique values. + //! + //! <b>Complexity</b>: Linear in N. + //! + //! <b>Note</b>: Non-standard extension. + BOOST_CONTAINER_FORCEINLINE map(ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp) + : base_t(ordered_range, il.begin(), il.end(), comp) + {} + + //! <b>Effects</b>: Constructs an empty map using the specified comparison object and //! allocator, and inserts elements from the ordered unique range [il.begin(), il.end()). This function //! is more efficient than the normal range creation for ordered ranges. //! @@ -285,51 +330,36 @@ class map //! <b>Complexity</b>: Linear in N. //! //! <b>Note</b>: Non-standard extension. - BOOST_CONTAINER_FORCEINLINE - map(ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp = Compare(), - const allocator_type& a = allocator_type()) + BOOST_CONTAINER_FORCEINLINE map( ordered_unique_range_t, std::initializer_list<value_type> il + , const Compare& comp, const allocator_type& a) : base_t(ordered_range, il.begin(), il.end(), comp, a) - { - //A type must be std::pair<CONST Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); - } + {} + #endif //! <b>Effects</b>: Copy constructs a map. //! //! <b>Complexity</b>: Linear in x.size(). - BOOST_CONTAINER_FORCEINLINE - map(const map& x) + BOOST_CONTAINER_FORCEINLINE map(const map& x) : base_t(static_cast<const base_t&>(x)) - { - //A type must be std::pair<CONST Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); - } + {} //! <b>Effects</b>: Move constructs a map. Constructs *this using x's resources. //! //! <b>Complexity</b>: Constant. //! //! <b>Postcondition</b>: x is emptied. - BOOST_CONTAINER_FORCEINLINE - map(BOOST_RV_REF(map) x) + BOOST_CONTAINER_FORCEINLINE map(BOOST_RV_REF(map) x) BOOST_NOEXCEPT_IF(boost::container::container_detail::is_nothrow_move_constructible<Compare>::value) : base_t(BOOST_MOVE_BASE(base_t, x)) - { - //A type must be std::pair<CONST Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); - } + {} //! <b>Effects</b>: Copy constructs a map using the specified allocator. //! //! <b>Complexity</b>: Linear in x.size(). - BOOST_CONTAINER_FORCEINLINE - map(const map& x, const allocator_type &a) + BOOST_CONTAINER_FORCEINLINE map(const map& x, const allocator_type &a) : base_t(static_cast<const base_t&>(x), a) - { - //A type must be std::pair<CONST Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); - } + {} //! <b>Effects</b>: Move constructs a map using the specified allocator. //! Constructs *this using x's resources. @@ -337,19 +367,14 @@ class map //! <b>Complexity</b>: Constant if x == x.get_allocator(), linear otherwise. //! //! <b>Postcondition</b>: x is emptied. - BOOST_CONTAINER_FORCEINLINE - map(BOOST_RV_REF(map) x, const allocator_type &a) + BOOST_CONTAINER_FORCEINLINE map(BOOST_RV_REF(map) x, const allocator_type &a) : base_t(BOOST_MOVE_BASE(base_t, x), a) - { - //A type must be std::pair<CONST Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); - } + {} //! <b>Effects</b>: Makes *this a copy of x. //! //! <b>Complexity</b>: Linear in x.size(). - BOOST_CONTAINER_FORCEINLINE - map& operator=(BOOST_COPY_ASSIGN_REF(map) x) + BOOST_CONTAINER_FORCEINLINE map& operator=(BOOST_COPY_ASSIGN_REF(map) x) { return static_cast<map&>(this->base_t::operator=(static_cast<const base_t&>(x))); } //! <b>Effects</b>: this->swap(x.get()). @@ -360,8 +385,7 @@ class map //! <b>Complexity</b>: Constant if allocator_traits_type:: //! propagate_on_container_move_assignment is true or //! this->get>allocator() == x.get_allocator(). Linear otherwise. - BOOST_CONTAINER_FORCEINLINE - map& operator=(BOOST_RV_REF(map) x) + BOOST_CONTAINER_FORCEINLINE map& operator=(BOOST_RV_REF(map) x) BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value || allocator_traits_type::is_always_equal::value) && boost::container::container_detail::is_nothrow_move_assignable<Compare>::value) @@ -370,8 +394,7 @@ class map #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) //! <b>Effects</b>: Assign content of il to *this. //! - BOOST_CONTAINER_FORCEINLINE - map& operator=(std::initializer_list<value_type> il) + BOOST_CONTAINER_FORCEINLINE map& operator=(std::initializer_list<value_type> il) { this->clear(); insert(il.begin(), il.end()); @@ -716,7 +739,7 @@ class map //! //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t //! is inserted right before p. - iterator insert(const_iterator p, BOOST_RV_REF(nonconst_value_type) x) + BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(nonconst_value_type) x) { return this->try_emplace(p, boost::move(x.first), boost::move(x.second)); } //! <b>Effects</b>: Move constructs a new value from x if and only if there is @@ -728,7 +751,7 @@ class map //! //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t //! is inserted right before p. - iterator insert(const_iterator p, BOOST_RV_REF(movable_value_type) x) + BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(movable_value_type) x) { return this->try_emplace(p, boost::move(x.first), boost::move(x.second)); } //! <b>Effects</b>: Inserts a copy of x in the container. @@ -746,7 +769,7 @@ class map //! <b>Returns</b>: An iterator pointing to the element with key equivalent to the key of x. //! //! <b>Complexity</b>: Logarithmic. - iterator insert(const_iterator p, BOOST_RV_REF(value_type) x) + BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(value_type) x) { return this->base_t::insert_unique(p, boost::move(x)); } //! <b>Requires</b>: first, last are not iterators into *this. @@ -1225,7 +1248,7 @@ class multimap typedef Key key_type; typedef T mapped_type; - typedef std::pair<const Key, T> value_type; + typedef typename boost::container::allocator_traits<Allocator>::value_type value_type; typedef typename boost::container::allocator_traits<Allocator>::pointer pointer; typedef typename boost::container::allocator_traits<Allocator>::const_pointer const_pointer; typedef typename boost::container::allocator_traits<Allocator>::reference reference; @@ -1243,12 +1266,13 @@ class multimap typedef std::pair<key_type, mapped_type> nonconst_value_type; typedef BOOST_CONTAINER_IMPDEF(movable_value_type_impl) movable_value_type; typedef BOOST_CONTAINER_IMPDEF(node_handle< - typename base_t::node_type::container_node_type - BOOST_MOVE_I value_type - BOOST_MOVE_I allocator_type + typename base_t::stored_allocator_type BOOST_MOVE_I pair_key_mapped_of_value <key_type BOOST_MOVE_I mapped_type> >) node_type; + //allocator_type::value_type type must be std::pair<CONST Key, T> + BOOST_STATIC_ASSERT((container_detail::is_same<typename allocator_type::value_type, std::pair<const Key, T> >::value)); + ////////////////////////////////////////////// // // construct/copy/destroy @@ -1258,66 +1282,102 @@ class multimap //! <b>Effects</b>: Default constructs an empty multimap. //! //! <b>Complexity</b>: Constant. - BOOST_CONTAINER_FORCEINLINE - multimap() BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value && - container_detail::is_nothrow_default_constructible<Compare>::value) + BOOST_CONTAINER_FORCEINLINE multimap() + BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value && + container_detail::is_nothrow_default_constructible<Compare>::value) : base_t() - { - //A type must be std::pair<CONST Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); - } + {} - //! <b>Effects</b>: Constructs an empty multimap using the specified allocator. + //! <b>Effects</b>: Constructs an empty multimap using the specified allocator + //! object and allocator. //! //! <b>Complexity</b>: Constant. - BOOST_CONTAINER_FORCEINLINE - explicit multimap(const Compare& comp, const allocator_type& a = allocator_type()) - : base_t(comp, a) - { - //A type must be std::pair<CONST Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); - } + BOOST_CONTAINER_FORCEINLINE explicit multimap(const allocator_type& a) + : base_t(a) + {} - //! <b>Effects</b>: Constructs an empty multimap using the specified comparison - //! object and allocator. + //! <b>Effects</b>: Constructs an empty multimap using the specified comparison. //! //! <b>Complexity</b>: Constant. - BOOST_CONTAINER_FORCEINLINE - explicit multimap(const allocator_type& a) - : base_t(a) - { - //A type must be std::pair<CONST Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); - } + BOOST_CONTAINER_FORCEINLINE explicit multimap(const Compare& comp) + : base_t(comp) + {} - //! <b>Effects</b>: Constructs an empty multimap using the specified comparison object - //! and allocator, and inserts elements from the range [first ,last ). + //! <b>Effects</b>: Constructs an empty multimap using the specified comparison and allocator. + //! + //! <b>Complexity</b>: Constant. + BOOST_CONTAINER_FORCEINLINE multimap(const Compare& comp, const allocator_type& a) + : base_t(comp, a) + {} + + //! <b>Effects</b>: Constructs an empty multimap and + //! inserts elements from the range [first ,last ). //! //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using - //! comp and otherwise N logN, where N is last - first. + //! the predicate and otherwise N logN, where N is last - first. template <class InputIterator> - BOOST_CONTAINER_FORCEINLINE - multimap(InputIterator first, InputIterator last, - const Compare& comp = Compare(), - const allocator_type& a = allocator_type()) - : base_t(false, first, last, comp, a) - { - //A type must be std::pair<CONST Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); - } + BOOST_CONTAINER_FORCEINLINE multimap(InputIterator first, InputIterator last) + : base_t(false, first, last) + {} //! <b>Effects</b>: Constructs an empty multimap using the specified //! allocator, and inserts elements from the range [first ,last ). //! //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using - //! comp and otherwise N logN, where N is last - first. + //! the predicate and otherwise N logN, where N is last - first. template <class InputIterator> BOOST_CONTAINER_FORCEINLINE multimap(InputIterator first, InputIterator last, const allocator_type& a) : base_t(false, first, last, Compare(), a) - { - //A type must be std::pair<CONST Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); - } + {} + + //! <b>Effects</b>: Constructs an empty multimap using the specified comparison object and + //! inserts elements from the range [first ,last ). + //! + //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using + //! the predicate and otherwise N logN, where N is last - first. + template <class InputIterator> + BOOST_CONTAINER_FORCEINLINE multimap(InputIterator first, InputIterator last, const Compare& comp) + : base_t(false, first, last, comp) + {} + + //! <b>Effects</b>: Constructs an empty multimap using the specified comparison object + //! and allocator, and inserts elements from the range [first ,last ). + //! + //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using + //! the predicate and otherwise N logN, where N is last - first. + template <class InputIterator> + BOOST_CONTAINER_FORCEINLINE multimap(InputIterator first, InputIterator last, + const Compare& comp, const allocator_type& a) + : base_t(false, first, last, comp, a) + {} + + //! <b>Effects</b>: Constructs an empty multimap and + //! inserts elements from the ordered range [first ,last). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! <b>Requires</b>: [first ,last) must be ordered according to the predicate. + //! + //! <b>Complexity</b>: Linear in N. + //! + //! <b>Note</b>: Non-standard extension. + template <class InputIterator> + BOOST_CONTAINER_FORCEINLINE multimap(ordered_range_t, InputIterator first, InputIterator last) + : base_t(ordered_range, first, last) + {} + + //! <b>Effects</b>: Constructs an empty multimap using the specified comparison object and + //! inserts elements from the ordered range [first ,last). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! <b>Requires</b>: [first ,last) must be ordered according to the predicate. + //! + //! <b>Complexity</b>: Linear in N. + //! + //! <b>Note</b>: Non-standard extension. + template <class InputIterator> + BOOST_CONTAINER_FORCEINLINE multimap(ordered_range_t, InputIterator first, InputIterator last, const Compare& comp) + : base_t(ordered_range, first, last, comp) + {} //! <b>Effects</b>: Constructs an empty multimap using the specified comparison object and //! allocator, and inserts elements from the ordered range [first ,last). This function @@ -1329,41 +1389,51 @@ class multimap //! //! <b>Note</b>: Non-standard extension. template <class InputIterator> - BOOST_CONTAINER_FORCEINLINE multimap(ordered_range_t, InputIterator first, InputIterator last, const Compare& comp = Compare(), - const allocator_type& a = allocator_type()) + BOOST_CONTAINER_FORCEINLINE multimap(ordered_range_t, InputIterator first, InputIterator last, const Compare& comp, + const allocator_type& a) : base_t(ordered_range, first, last, comp, a) {} #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) - //! <b>Effects</b>: Constructs an empty multimap using the specified comparison object and - //! allocator, and inserts elements from the range [il.begin(), il.end()). + //! <b>Effects</b>: Constructs an empty multimap and + //! and inserts elements from the range [il.begin(), il.end()). //! //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using - //! comp and otherwise N logN, where N is il.first() - il.end(). - BOOST_CONTAINER_FORCEINLINE - multimap(std::initializer_list<value_type> il, const Compare& comp = Compare(), - const allocator_type& a = allocator_type()) - : base_t(false, il.begin(), il.end(), comp, a) - { - //A type must be std::pair<CONST Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); - } + //! the predicate and otherwise N logN, where N is il.first() - il.end(). + BOOST_CONTAINER_FORCEINLINE multimap(std::initializer_list<value_type> il) + : base_t(false, il.begin(), il.end()) + {} //! <b>Effects</b>: Constructs an empty multimap using the specified //! allocator, and inserts elements from the range [il.begin(), il.end()). //! //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using - //! comp and otherwise N logN, where N is il.first() - il.end(). - BOOST_CONTAINER_FORCEINLINE - multimap(std::initializer_list<value_type> il, const allocator_type& a) + //! the predicate and otherwise N logN, where N is il.first() - il.end(). + BOOST_CONTAINER_FORCEINLINE multimap(std::initializer_list<value_type> il, const allocator_type& a) : base_t(false, il.begin(), il.end(), Compare(), a) - { - //A type must be std::pair<CONST Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); - } + {} + + //! <b>Effects</b>: Constructs an empty multimap using the specified comparison object and + //! inserts elements from the range [il.begin(), il.end()). + //! + //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using + //! the predicate and otherwise N logN, where N is il.first() - il.end(). + BOOST_CONTAINER_FORCEINLINE multimap(std::initializer_list<value_type> il, const Compare& comp) + : base_t(false, il.begin(), il.end(), comp) + {} - //! <b>Effects</b>: Constructs an empty set using the specified comparison object and - //! allocator, and inserts elements from the ordered range [il.begin(), il.end()). This function + //! <b>Effects</b>: Constructs an empty multimap using the specified comparison object and + //! allocator, and inserts elements from the range [il.begin(), il.end()). + //! + //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using + //! the predicate and otherwise N logN, where N is il.first() - il.end(). + BOOST_CONTAINER_FORCEINLINE multimap(std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a) + : base_t(false, il.begin(), il.end(), comp, a) + {} + + + //! <b>Effects</b>: Constructs an empty map and + //! inserts elements from the ordered range [il.begin(), il.end()). This function //! is more efficient than the normal range creation for ordered ranges. //! //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate. @@ -1371,14 +1441,36 @@ class multimap //! <b>Complexity</b>: Linear in N. //! //! <b>Note</b>: Non-standard extension. - BOOST_CONTAINER_FORCEINLINE - multimap(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp = Compare(), - const allocator_type& a = allocator_type()) + BOOST_CONTAINER_FORCEINLINE multimap(ordered_range_t, std::initializer_list<value_type> il) + : base_t(ordered_range, il.begin(), il.end()) + {} + + //! <b>Effects</b>: Constructs an empty map using the specified comparison object and + //! inserts elements from the ordered range [il.begin(), il.end()). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate. + //! + //! <b>Complexity</b>: Linear in N. + //! + //! <b>Note</b>: Non-standard extension. + BOOST_CONTAINER_FORCEINLINE multimap(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp) + : base_t(ordered_range, il.begin(), il.end(), comp) + {} + + //! <b>Effects</b>: Constructs an empty map and + //! inserts elements from the ordered range [il.begin(), il.end()). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate. + //! + //! <b>Complexity</b>: Linear in N. + //! + //! <b>Note</b>: Non-standard extension. + BOOST_CONTAINER_FORCEINLINE multimap(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a) : base_t(ordered_range, il.begin(), il.end(), comp, a) - { - //A type must be std::pair<CONST Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); - } + {} + #endif //! <b>Effects</b>: Copy constructs a multimap. @@ -1386,10 +1478,7 @@ class multimap //! <b>Complexity</b>: Linear in x.size(). BOOST_CONTAINER_FORCEINLINE multimap(const multimap& x) : base_t(static_cast<const base_t&>(x)) - { - //A type must be std::pair<CONST Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); - } + {} //! <b>Effects</b>: Move constructs a multimap. Constructs *this using x's resources. //! @@ -1399,20 +1488,14 @@ class multimap BOOST_CONTAINER_FORCEINLINE multimap(BOOST_RV_REF(multimap) x) BOOST_NOEXCEPT_IF(boost::container::container_detail::is_nothrow_move_constructible<Compare>::value) : base_t(BOOST_MOVE_BASE(base_t, x)) - { - //A type must be std::pair<CONST Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); - } + {} //! <b>Effects</b>: Copy constructs a multimap. //! //! <b>Complexity</b>: Linear in x.size(). BOOST_CONTAINER_FORCEINLINE multimap(const multimap& x, const allocator_type &a) : base_t(static_cast<const base_t&>(x), a) - { - //A type must be std::pair<CONST Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); - } + {} //! <b>Effects</b>: Move constructs a multimap using the specified allocator. //! Constructs *this using x's resources. @@ -1421,10 +1504,7 @@ class multimap //! <b>Postcondition</b>: x is emptied. BOOST_CONTAINER_FORCEINLINE multimap(BOOST_RV_REF(multimap) x, const allocator_type &a) : base_t(BOOST_MOVE_BASE(base_t, x), a) - { - //A type must be std::pair<CONST Key, T> - BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value)); - } + {} //! <b>Effects</b>: Makes *this a copy of x. //! @@ -1708,7 +1788,7 @@ class multimap //! //! <b>Complexity</b>: N log(a.size() + N) (N has the value source.size()) template<class C2> - void merge(multimap<Key, T, C2, Allocator, Options>& source) + BOOST_CONTAINER_FORCEINLINE void merge(multimap<Key, T, C2, Allocator, Options>& source) { typedef container_detail::tree <value_type_impl, select_1st_t, C2, Allocator, Options> base2_t; @@ -1717,12 +1797,12 @@ class multimap //! @copydoc ::boost::container::multimap::merge(multimap<Key, T, C2, Allocator, Options>&) template<class C2> - void merge(BOOST_RV_REF_BEG multimap<Key, T, C2, Allocator, Options> BOOST_RV_REF_END source) + BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG multimap<Key, T, C2, Allocator, Options> BOOST_RV_REF_END source) { return this->merge(static_cast<multimap<Key, T, C2, Allocator, Options>&>(source)); } //! @copydoc ::boost::container::multimap::merge(multimap<Key, T, C2, Allocator, Options>&) template<class C2> - void merge(map<Key, T, C2, Allocator, Options>& source) + BOOST_CONTAINER_FORCEINLINE void merge(map<Key, T, C2, Allocator, Options>& source) { typedef container_detail::tree <value_type_impl, select_1st_t, C2, Allocator, Options> base2_t; @@ -1731,7 +1811,7 @@ class multimap //! @copydoc ::boost::container::multimap::merge(multimap<Key, T, C2, Allocator, Options>&) template<class C2> - void merge(BOOST_RV_REF_BEG map<Key, T, C2, Allocator, Options> BOOST_RV_REF_END source) + BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG map<Key, T, C2, Allocator, Options> BOOST_RV_REF_END source) { return this->merge(static_cast<map<Key, T, C2, Allocator, Options>&>(source)); } #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) diff --git a/boost/container/node_handle.hpp b/boost/container/node_handle.hpp index c46313cc4f..594a09c99e 100644 --- a/boost/container/node_handle.hpp +++ b/boost/container/node_handle.hpp @@ -23,7 +23,7 @@ #include <boost/container/detail/workaround.hpp> #include <boost/static_assert.hpp> #include <boost/container/detail/placement_new.hpp> -#include <boost/container/detail/to_raw_pointer.hpp> +#include <boost/move/detail/to_raw_pointer.hpp> #include <boost/container/allocator_traits.hpp> #include <boost/container/detail/mpl.hpp> @@ -40,20 +40,34 @@ namespace container { ///@cond -template<class Value, class KeyMapped, bool keymapped_is_void = container_detail::is_same<KeyMapped, void>::value> +template<class Value, class KeyMapped> struct node_handle_keymapped_traits { + typedef typename KeyMapped::key_type key_type; + typedef typename KeyMapped::mapped_type mapped_type; +}; + +template<class Value> +struct node_handle_keymapped_traits<Value, void> +{ typedef Value key_type; typedef Value mapped_type; }; -template<class Value, class KeyMapped> -struct node_handle_keymapped_traits<Value, KeyMapped, false> +class node_handle_friend { - typedef typename KeyMapped::key_type key_type; - typedef typename KeyMapped::mapped_type mapped_type; + public: + + template<class NH> + BOOST_CONTAINER_FORCEINLINE static void destroy_alloc(NH &nh) BOOST_NOEXCEPT + { nh.destroy_alloc(); } + + template<class NH> + BOOST_CONTAINER_FORCEINLINE static typename NH::node_pointer &get_node_pointer(NH &nh) BOOST_NOEXCEPT + { return nh.get_node_pointer(); } }; + ///@endcond //! A node_handle is an object that accepts ownership of a single element from an associative container. @@ -73,76 +87,63 @@ struct node_handle_keymapped_traits<Value, KeyMapped, false> //! //! If a node handle is not empty, then it contains an allocator that is equal to the allocator of the container //! when the element was extracted. If a node handle is empty, it contains no allocator. -template <class NodeType, class Value, class Allocator, class KeyMapped = void> +template <class NodeAllocator, class KeyMapped = void> class node_handle { - typedef node_handle_keymapped_traits<Value, KeyMapped> keymapped_t; + typedef NodeAllocator nallocator_type; + typedef allocator_traits<NodeAllocator> nator_traits; + typedef typename nator_traits::value_type priv_node_t; + typedef typename priv_node_t::value_type priv_value_t; + typedef node_handle_keymapped_traits<priv_value_t, KeyMapped> keymapped_t; public: - typedef Value value_type; + typedef priv_value_t value_type; typedef typename keymapped_t::key_type key_type; typedef typename keymapped_t::mapped_type mapped_type; - typedef Allocator allocator_type; - typedef NodeType container_node_type; + typedef typename nator_traits::template portable_rebind_alloc + <value_type>::type allocator_type; + + typedef priv_node_t container_node_type; + friend class node_handle_friend; ///@cond private: BOOST_MOVABLE_BUT_NOT_COPYABLE(node_handle) - typedef allocator_traits<allocator_type> ator_traits; - typedef typename ator_traits::template portable_rebind_alloc - <container_node_type>::type nallocator_type; - typedef allocator_traits<nallocator_type> node_ator_traits; - typedef typename node_ator_traits::pointer node_pointer; + typedef typename nator_traits::pointer node_pointer; typedef ::boost::aligned_storage - <sizeof(allocator_type), boost::alignment_of<nallocator_type>::value> nalloc_storage_t; + < sizeof(nallocator_type) + , boost::alignment_of<nallocator_type>::value> nalloc_storage_t; node_pointer m_ptr; nalloc_storage_t m_nalloc_storage; void move_construct_alloc(nallocator_type &al) - { ::new(m_nalloc_storage.address(), boost_container_new_t()) allocator_type(::boost::move(al)); } + { ::new(m_nalloc_storage.address(), boost_container_new_t()) nallocator_type(::boost::move(al)); } - void destroy_node() + void destroy_deallocate_node() { - node_ator_traits::destroy(this->node_alloc(), container_detail::to_raw_pointer(m_ptr)); - node_ator_traits::deallocate(this->node_alloc(), m_ptr, 1u); + nator_traits::destroy(this->node_alloc(), boost::movelib::to_raw_pointer(m_ptr)); + nator_traits::deallocate(this->node_alloc(), m_ptr, 1u); } template<class OtherNodeHandle> void move_construct_end(OtherNodeHandle &nh) { if(m_ptr){ - ::new (m_nalloc_storage.address(), boost_container_new_t()) allocator_type(::boost::move(nh.node_alloc())); - nh.destroy_alloc(); - nh.get_node_pointer() = node_pointer(); + ::new (m_nalloc_storage.address(), boost_container_new_t()) nallocator_type(::boost::move(nh.node_alloc())); + node_handle_friend::destroy_alloc(nh); + node_handle_friend::get_node_pointer(nh) = node_pointer(); } BOOST_ASSERT(nh.empty()); } - public: - - void destroy_alloc() - { static_cast<allocator_type*>(m_nalloc_storage.address())->~allocator_type(); } + void destroy_alloc() BOOST_NOEXCEPT + { static_cast<nallocator_type*>(m_nalloc_storage.address())->~nallocator_type(); } - node_pointer &get_node_pointer() + node_pointer &get_node_pointer() BOOST_NOEXCEPT { return m_ptr; } - nallocator_type &node_alloc() - { return *static_cast<nallocator_type*>(m_nalloc_storage.address()); } - - const nallocator_type &node_alloc() const - { return *static_cast<const nallocator_type*>(m_nalloc_storage.address()); } - - node_pointer release() - { - node_pointer p(m_ptr); - m_ptr = node_pointer(); - if(p) - this->destroy_alloc(); - return p; - } - ///@endcond public: @@ -150,13 +151,13 @@ class node_handle //! //! <b>Postcondition</b>: this->empty() BOOST_CXX14_CONSTEXPR node_handle() BOOST_NOEXCEPT - : m_ptr(), m_nalloc_storage() - { BOOST_ASSERT(this->empty()); } + : m_ptr() + { } //! <b>Effects</b>: Constructs a node_handle object initializing internal pointer with p. - //! If p != nullptr copy constructs internal allocator al. + //! If p != nullptr copy constructs internal allocator from al. node_handle(node_pointer p, const nallocator_type &al) BOOST_NOEXCEPT - : m_ptr(p), m_nalloc_storage() + : m_ptr(p) { if(m_ptr){ ::new (m_nalloc_storage.address(), boost_container_new_t()) nallocator_type(al); @@ -172,12 +173,12 @@ class node_handle //! <b>Note</b>: Two node_handle's are related if only one of KeyMapped template parameter //! of a node handle is void. template<class KeyMapped2> - node_handle( BOOST_RV_REF_BEG node_handle<NodeType, Value, Allocator, KeyMapped2> BOOST_RV_REF_END nh + node_handle( BOOST_RV_REF_BEG node_handle<NodeAllocator, KeyMapped2> BOOST_RV_REF_END nh , typename container_detail::enable_if_c < ((unsigned)container_detail::is_same<KeyMapped, void>::value + (unsigned)container_detail::is_same<KeyMapped2, void>::value) == 1u - >::type* = 0) - : m_ptr(nh.get_node_pointer()), m_nalloc_storage() + >::type* = 0) BOOST_NOEXCEPT + : m_ptr(nh.get()) { this->move_construct_end(nh); } //! <b>Effects</b>: Constructs a node_handle object initializing internal pointer with nh's internal pointer @@ -186,43 +187,44 @@ class node_handle //! //! <b>Postcondition</b>: nh.empty() node_handle (BOOST_RV_REF(node_handle) nh) BOOST_NOEXCEPT - : m_ptr(nh.m_ptr), m_nalloc_storage() + : m_ptr(nh.m_ptr) { this->move_construct_end(nh); } //! <b>Effects</b>: If !this->empty(), destroys the value_type subobject in the container_node_type object //! pointed to by c by calling allocator_traits<impl_defined>::destroy, then deallocates m_ptr by calling - //! ator_traits::rebind_traits<container_node_type>::deallocate. - ~node_handle () BOOST_NOEXCEPT + //! nator_traits::rebind_traits<container_node_type>::deallocate. + ~node_handle() BOOST_NOEXCEPT { if(!this->empty()){ - this->destroy_node(); + this->destroy_deallocate_node(); this->destroy_alloc(); } } - //! <b>Requires</b>: Either this->empty(), or ator_traits::propagate_on_container_move_assignment is true, or + //! <b>Requires</b>: Either this->empty(), or nator_traits::propagate_on_container_move_assignment is true, or //! node_alloc() == nh.node_alloc(). //! //! <b>Effects</b>: If m_ptr != nullptr, destroys the value_type subobject in the container_node_type object - //! pointed to by m_ptr by calling ator_traits::destroy, then deallocates m_ptr by calling ator_- - //! traits::rebind_traits<container_node_type>::deallocate. Assigns nh.m_ptr to m_ptr. If this->empty() - //! or ator_traits::propagate_on_container_move_assignment is true, move assigns nh.node_alloc() to + //! pointed to by m_ptr by calling nator_traits::destroy, then deallocates m_ptr by calling + //! nator_traits::deallocate. Assigns nh.m_ptr to m_ptr. If this->empty() + //! or nator_traits::propagate_on_container_move_assignment is true, move assigns nh.node_alloc() to //! node_alloc(). Assigns nullptr to nh.m_ptr and assigns nullopt to nh.node_alloc(). + //! //! <b>Returns</b>: *this. //! //! <b>Throws</b>: Nothing. - node_handle & operator=(BOOST_RV_REF(node_handle) nh) + node_handle & operator=(BOOST_RV_REF(node_handle) nh) BOOST_NOEXCEPT { - BOOST_ASSERT(this->empty() || nh.empty() || ator_traits::propagate_on_container_move_assignment::value - || ator_traits::equal(node_alloc(), nh.node_alloc())); + BOOST_ASSERT(this->empty() || nator_traits::propagate_on_container_move_assignment::value + || nator_traits::equal(node_alloc(), nh.node_alloc())); bool const was_this_non_null = !this->empty(); bool const was_nh_non_null = !nh.empty(); if(was_nh_non_null){ if(was_this_non_null){ - this->destroy_node(); - if(ator_traits::propagate_on_container_move_assignment::value){ + this->destroy_deallocate_node(); + if(nator_traits::propagate_on_container_move_assignment::value){ this->node_alloc() = ::boost::move(nh.node_alloc()); } } @@ -234,7 +236,7 @@ class node_handle nh.destroy_alloc(); } else if(was_this_non_null){ - this->destroy_node(); + this->destroy_deallocate_node(); this->destroy_alloc(); m_ptr = node_pointer(); } @@ -310,23 +312,23 @@ class node_handle return !this->m_ptr; } - //! <b>Requires</b>: this->empty(), or nh.empty(), or ator_traits::propagate_on_container_swap is true, or + //! <b>Requires</b>: this->empty(), or nh.empty(), or nator_traits::propagate_on_container_swap is true, or //! node_alloc() == nh.node_alloc(). //! - //! <b>Effects</b>: Calls swap(m_ptr, nh.m_ptr). If this->empty(), or nh.empty(), or ator_traits::propagate_on_- + //! <b>Effects</b>: Calls swap(m_ptr, nh.m_ptr). If this->empty(), or nh.empty(), or nator_traits::propagate_on_- //! container_swap is true calls swap(node_alloc(), nh.node_alloc()). void swap(node_handle &nh) - BOOST_NOEXCEPT_IF(ator_traits::propagate_on_container_swap::value || ator_traits::is_always_equal::value) + BOOST_NOEXCEPT_IF(nator_traits::propagate_on_container_swap::value || nator_traits::is_always_equal::value) { - BOOST_ASSERT(this->empty() || nh.empty() || ator_traits::propagate_on_container_swap::value - || ator_traits::equal(node_alloc(), nh.node_alloc())); + BOOST_ASSERT(this->empty() || nh.empty() || nator_traits::propagate_on_container_swap::value + || nator_traits::equal(node_alloc(), nh.node_alloc())); bool const was_this_non_null = !this->empty(); bool const was_nh_non_null = !nh.empty(); if(was_nh_non_null){ if(was_this_non_null){ - if(ator_traits::propagate_on_container_swap::value){ + if(nator_traits::propagate_on_container_swap::value){ ::boost::adl_move_swap(this->node_alloc(), nh.node_alloc()); } } @@ -337,11 +339,53 @@ class node_handle } else if(was_this_non_null){ nh.move_construct_alloc(this->node_alloc()); - nh.destroy_alloc(); + this->destroy_alloc(); } ::boost::adl_move_swap(m_ptr, nh.m_ptr); } + //! <b>Effects</b>: If this->empty() returns nullptr, otherwise returns m_ptr + //! resets m_ptr to nullptr and destroys the internal allocator. + //! + //! <b>Postcondition</b>: this->empty() + //! + //! <b>Note</b>: Non-standard extensions + node_pointer release() BOOST_NOEXCEPT + { + node_pointer p(m_ptr); + m_ptr = node_pointer(); + if(p) + this->destroy_alloc(); + return p; + } + + //! <b>Effects</b>: Returns m_ptr. + //! + //! <b>Note</b>: Non-standard extensions + node_pointer get() const BOOST_NOEXCEPT + { + return m_ptr; + } + + //! <b>Effects</b>: Returns a reference to the internal node allocator. + //! + //! <b>Note</b>: Non-standard extensions + nallocator_type &node_alloc() BOOST_NOEXCEPT + { + BOOST_ASSERT(!empty()); + return *static_cast<nallocator_type*>(m_nalloc_storage.address()); + } + + + //! <b>Effects</b>: Returns a reference to the internal node allocator. + //! + //! <b>Note</b>: Non-standard extensions + const nallocator_type &node_alloc() const BOOST_NOEXCEPT + { + BOOST_ASSERT(!empty()); + return *static_cast<const nallocator_type*>(m_nalloc_storage.address()); + } + //! <b>Effects</b>: x.swap(y). //! friend void swap(node_handle & x, node_handle & y) BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT(x.swap(y))) diff --git a/boost/container/set.hpp b/boost/container/set.hpp index 5cf0f964a5..8730b1c89a 100644 --- a/boost/container/set.hpp +++ b/boost/container/set.hpp @@ -112,46 +112,103 @@ class set //! <b>Effects</b>: Default constructs an empty set. //! //! <b>Complexity</b>: Constant. - set() BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value && - container_detail::is_nothrow_default_constructible<Compare>::value) + + BOOST_CONTAINER_FORCEINLINE set() + BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value && + container_detail::is_nothrow_default_constructible<Compare>::value) : base_t() {} + //! <b>Effects</b>: Constructs an empty set using the specified allocator object. + //! + //! <b>Complexity</b>: Constant. + BOOST_CONTAINER_FORCEINLINE explicit set(const allocator_type& a) + : base_t(a) + {} + + //! <b>Effects</b>: Constructs an empty set using the specified comparison object. + //! + //! <b>Complexity</b>: Constant. + BOOST_CONTAINER_FORCEINLINE explicit set(const Compare& comp) + : base_t(comp) + {} + //! <b>Effects</b>: Constructs an empty set using the specified comparison object //! and allocator. //! //! <b>Complexity</b>: Constant. - explicit set(const Compare& comp, - const allocator_type& a = allocator_type()) + BOOST_CONTAINER_FORCEINLINE set(const Compare& comp, const allocator_type& a) : base_t(comp, a) {} - //! <b>Effects</b>: Constructs an empty set using the specified allocator object. + //! <b>Effects</b>: Constructs an empty set using and + //! inserts elements from the range [first ,last ). //! - //! <b>Complexity</b>: Constant. - explicit set(const allocator_type& a) - : base_t(a) + //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using + //! the predicate and otherwise N logN, where N is last - first. + template <class InputIterator> + BOOST_CONTAINER_FORCEINLINE set(InputIterator first, InputIterator last) + : base_t(true, first, last) {} - //! <b>Effects</b>: Constructs an empty set using the specified comparison object and + //! <b>Effects</b>: Constructs an empty set using the specified //! allocator, and inserts elements from the range [first ,last ). //! //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using - //! comp and otherwise N logN, where N is last - first. + //! the predicate and otherwise N logN, where N is last - first. template <class InputIterator> - set(InputIterator first, InputIterator last, const Compare& comp = Compare(), - const allocator_type& a = allocator_type()) - : base_t(true, first, last, comp, a) + BOOST_CONTAINER_FORCEINLINE set(InputIterator first, InputIterator last, const allocator_type& a) + : base_t(true, first, last, key_compare(), a) {} - //! <b>Effects</b>: Constructs an empty set using the specified + //! <b>Effects</b>: Constructs an empty set using the specified comparison object and + //! inserts elements from the range [first ,last ). + //! + //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using + //! the predicate and otherwise N logN, where N is last - first. + template <class InputIterator> + BOOST_CONTAINER_FORCEINLINE set(InputIterator first, InputIterator last, const Compare& comp) + : base_t(true, first, last, comp) + {} + + //! <b>Effects</b>: Constructs an empty set using the specified comparison object and //! allocator, and inserts elements from the range [first ,last ). //! //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using - //! comp and otherwise N logN, where N is last - first. + //! the predicate and otherwise N logN, where N is last - first. template <class InputIterator> - set(InputIterator first, InputIterator last, const allocator_type& a) - : base_t(true, first, last, key_compare(), a) + BOOST_CONTAINER_FORCEINLINE set(InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a) + : base_t(true, first, last, comp, a) + {} + + //! <b>Effects</b>: Constructs an empty set and + //! inserts elements from the ordered unique range [first ,last). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! <b>Requires</b>: [first ,last) must be ordered according to the predicate and must be + //! unique values. + //! + //! <b>Complexity</b>: Linear in N. + //! + //! <b>Note</b>: Non-standard extension. + template <class InputIterator> + BOOST_CONTAINER_FORCEINLINE set( ordered_unique_range_t, InputIterator first, InputIterator last) + : base_t(ordered_range, first, last) + {} + + //! <b>Effects</b>: Constructs an empty set using the specified comparison object and + //! inserts elements from the ordered unique range [first ,last). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! <b>Requires</b>: [first ,last) must be ordered according to the predicate and must be + //! unique values. + //! + //! <b>Complexity</b>: Linear in N. + //! + //! <b>Note</b>: Non-standard extension. + template <class InputIterator> + BOOST_CONTAINER_FORCEINLINE set( ordered_unique_range_t, InputIterator first, InputIterator last, const Compare& comp ) + : base_t(ordered_range, first, last, comp) {} //! <b>Effects</b>: Constructs an empty set using the specified comparison object and @@ -165,31 +222,77 @@ class set //! //! <b>Note</b>: Non-standard extension. template <class InputIterator> - set( ordered_unique_range_t, InputIterator first, InputIterator last - , const Compare& comp = Compare(), const allocator_type& a = allocator_type()) + BOOST_CONTAINER_FORCEINLINE set( ordered_unique_range_t, InputIterator first, InputIterator last + , const Compare& comp, const allocator_type& a) : base_t(ordered_range, first, last, comp, a) {} #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) - //! <b>Effects</b>: Constructs an empty set using the specified comparison object and - //! allocator, and inserts elements from the range [il.begin(), il.end()). + //! <b>Effects</b>: Constructs an empty set and + //! inserts elements from the range [il.begin(), il.end()). //! //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using - //! comp and otherwise N logN, where N is il.begin() - il.end(). - set(std::initializer_list<value_type> il, const Compare& comp = Compare(), const allocator_type& a = allocator_type()) - : base_t(true, il.begin(), il.end(), comp, a) + //! the predicate and otherwise N logN, where N is il.begin() - il.end(). + BOOST_CONTAINER_FORCEINLINE set(std::initializer_list<value_type> il) + : base_t(true, il.begin(), il.end()) {} //! <b>Effects</b>: Constructs an empty set using the specified //! allocator, and inserts elements from the range [il.begin(), il.end()). //! //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using - //! comp and otherwise N logN, where N is il.begin() - il.end(). - set(std::initializer_list<value_type> il, const allocator_type& a) + //! the predicate and otherwise N logN, where N is il.begin() - il.end(). + BOOST_CONTAINER_FORCEINLINE set(std::initializer_list<value_type> il, const allocator_type& a) : base_t(true, il.begin(), il.end(), Compare(), a) {} //! <b>Effects</b>: Constructs an empty set using the specified comparison object and + //! inserts elements from the range [il.begin(), il.end()). + //! + //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using + //! the predicate and otherwise N logN, where N is il.begin() - il.end(). + BOOST_CONTAINER_FORCEINLINE set(std::initializer_list<value_type> il, const Compare& comp ) + : base_t(true, il.begin(), il.end(), comp) + {} + + //! <b>Effects</b>: Constructs an empty set using the specified comparison object and + //! allocator, and inserts elements from the range [il.begin(), il.end()). + //! + //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using + //! the predicate and otherwise N logN, where N is il.begin() - il.end(). + BOOST_CONTAINER_FORCEINLINE set(std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a) + : base_t(true, il.begin(), il.end(), comp, a) + {} + + //! <b>Effects</b>: Constructs an empty set and + //! inserts elements from the ordered unique range [il.begin(), il.end()). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be + //! unique values. + //! + //! <b>Complexity</b>: Linear in N. + //! + //! <b>Note</b>: Non-standard extension. + BOOST_CONTAINER_FORCEINLINE set( ordered_unique_range_t, std::initializer_list<value_type> il) + : base_t(ordered_range, il.begin(), il.end()) + {} + + //! <b>Effects</b>: Constructs an empty set using the specified comparison object and + //! inserts elements from the ordered unique range [il.begin(), il.end()). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be + //! unique values. + //! + //! <b>Complexity</b>: Linear in N. + //! + //! <b>Note</b>: Non-standard extension. + BOOST_CONTAINER_FORCEINLINE set( ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp) + : base_t(ordered_range, il.begin(), il.end(), comp) + {} + + //! <b>Effects</b>: Constructs an empty set using the specified comparison object and //! allocator, and inserts elements from the ordered unique range [il.begin(), il.end()). This function //! is more efficient than the normal range creation for ordered ranges. //! @@ -199,8 +302,7 @@ class set //! <b>Complexity</b>: Linear in N. //! //! <b>Note</b>: Non-standard extension. - set( ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp = Compare() - , const allocator_type& a = allocator_type()) + BOOST_CONTAINER_FORCEINLINE set( ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a) : base_t(ordered_range, il.begin(), il.end(), comp, a) {} #endif @@ -208,7 +310,7 @@ class set //! <b>Effects</b>: Copy constructs a set. //! //! <b>Complexity</b>: Linear in x.size(). - set(const set& x) + BOOST_CONTAINER_FORCEINLINE set(const set& x) : base_t(static_cast<const base_t&>(x)) {} @@ -217,7 +319,7 @@ class set //! <b>Complexity</b>: Constant. //! //! <b>Postcondition</b>: x is emptied. - set(BOOST_RV_REF(set) x) + BOOST_CONTAINER_FORCEINLINE set(BOOST_RV_REF(set) x) BOOST_NOEXCEPT_IF(boost::container::container_detail::is_nothrow_move_constructible<Compare>::value) : base_t(BOOST_MOVE_BASE(base_t, x)) {} @@ -225,7 +327,7 @@ class set //! <b>Effects</b>: Copy constructs a set using the specified allocator. //! //! <b>Complexity</b>: Linear in x.size(). - set(const set& x, const allocator_type &a) + BOOST_CONTAINER_FORCEINLINE set(const set& x, const allocator_type &a) : base_t(static_cast<const base_t&>(x), a) {} @@ -233,14 +335,14 @@ class set //! Constructs *this using x's resources. //! //! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise. - set(BOOST_RV_REF(set) x, const allocator_type &a) + BOOST_CONTAINER_FORCEINLINE set(BOOST_RV_REF(set) x, const allocator_type &a) : base_t(BOOST_MOVE_BASE(base_t, x), a) {} //! <b>Effects</b>: Makes *this a copy of x. //! //! <b>Complexity</b>: Linear in x.size(). - set& operator=(BOOST_COPY_ASSIGN_REF(set) x) + BOOST_CONTAINER_FORCEINLINE set& operator=(BOOST_COPY_ASSIGN_REF(set) x) { return static_cast<set&>(this->base_t::operator=(static_cast<const base_t&>(x))); } //! <b>Effects</b>: this->swap(x.get()). @@ -251,7 +353,7 @@ class set //! <b>Complexity</b>: Constant if allocator_traits_type:: //! propagate_on_container_move_assignment is true or //! this->get>allocator() == x.get_allocator(). Linear otherwise. - set& operator=(BOOST_RV_REF(set) x) + BOOST_CONTAINER_FORCEINLINE set& operator=(BOOST_RV_REF(set) x) BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value || allocator_traits_type::is_always_equal::value) && boost::container::container_detail::is_nothrow_move_assignable<Compare>::value) @@ -424,7 +526,7 @@ class set //! //! <b>Complexity</b>: Logarithmic. template <class... Args> - std::pair<iterator,bool> emplace(BOOST_FWD_REF(Args)... args) + BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> emplace(BOOST_FWD_REF(Args)... args) { return this->base_t::emplace_unique(boost::forward<Args>(args)...); } //! <b>Effects</b>: Inserts an object of type Key constructed with @@ -437,18 +539,18 @@ class set //! //! <b>Complexity</b>: Logarithmic. template <class... Args> - iterator emplace_hint(const_iterator p, BOOST_FWD_REF(Args)... args) + BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator p, BOOST_FWD_REF(Args)... args) { return this->base_t::emplace_hint_unique(p, boost::forward<Args>(args)...); } #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) #define BOOST_CONTAINER_SET_EMPLACE_CODE(N) \ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ - std::pair<iterator,bool> emplace(BOOST_MOVE_UREF##N)\ + BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> emplace(BOOST_MOVE_UREF##N)\ { return this->base_t::emplace_unique(BOOST_MOVE_FWD##N); }\ \ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ - iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ + BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ { return this->base_t::emplace_hint_unique(hint BOOST_MOVE_I##N BOOST_MOVE_FWD##N); }\ // BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SET_EMPLACE_CODE) @@ -513,7 +615,7 @@ class set //! //! <b>Complexity</b>: At most N log(size()+N) (N is the distance from first to last) template <class InputIterator> - void insert(InputIterator first, InputIterator last) + BOOST_CONTAINER_FORCEINLINE void insert(InputIterator first, InputIterator last) { this->base_t::insert_unique(first, last); } #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) @@ -521,16 +623,16 @@ class set //! if there is no element with key equivalent to the key of that element. //! //! <b>Complexity</b>: At most N log(size()+N) (N is the distance from il.begin() to il.end()) - void insert(std::initializer_list<value_type> il) + BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il) { this->base_t::insert_unique(il.begin(), il.end()); } #endif //! @copydoc ::boost::container::map::insert(node_type&&) - insert_return_type insert(BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh) + BOOST_CONTAINER_FORCEINLINE insert_return_type insert(BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh) { return this->base_t::insert_unique_node(boost::move(nh)); } //! @copydoc ::boost::container::map::insert(const_iterator, node_type&&) - insert_return_type insert(const_iterator hint, BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh) + BOOST_CONTAINER_FORCEINLINE insert_return_type insert(const_iterator hint, BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh) { return this->base_t::insert_unique_node(hint, boost::move(nh)); } //! @copydoc ::boost::container::map::merge(map<Key, T, C2, Allocator, Options>&) @@ -586,6 +688,12 @@ class set //! <b>Complexity</b>: log(size())+N where N is the distance from first to last. iterator erase(const_iterator first, const_iterator last); + //! @copydoc ::boost::container::map::extract(const_iterator) + node_type extract(const_iterator p); + + //! @copydoc ::boost::container::map::extract(const key_type&) + node_type extract(const key_type& x); + //! <b>Effects</b>: Swaps the contents of *this and x. //! //! <b>Throws</b>: Nothing. @@ -631,13 +739,13 @@ class set //! <b>Returns</b>: The number of elements with key equivalent to x. //! //! <b>Complexity</b>: log(size())+count(k) - size_type count(const key_type& x) const + BOOST_CONTAINER_FORCEINLINE size_type count(const key_type& x) const { return static_cast<size_type>(this->base_t::find(x) != this->base_t::cend()); } //! <b>Returns</b>: The number of elements with key equivalent to x. //! //! <b>Complexity</b>: log(size())+count(k) - size_type count(const key_type& x) + BOOST_CONTAINER_FORCEINLINE size_type count(const key_type& x) { return static_cast<size_type>(this->base_t::find(x) != this->base_t::end()); } #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) @@ -671,13 +779,13 @@ class set //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). //! //! <b>Complexity</b>: Logarithmic - std::pair<iterator,iterator> equal_range(const key_type& x) + BOOST_CONTAINER_FORCEINLINE std::pair<iterator,iterator> equal_range(const key_type& x) { return this->base_t::lower_bound_range(x); } //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)). //! //! <b>Complexity</b>: Logarithmic - std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const + BOOST_CONTAINER_FORCEINLINE std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const { return this->base_t::lower_bound_range(x); } #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) @@ -737,11 +845,11 @@ class set #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED private: template <class KeyType> - std::pair<iterator, bool> priv_insert(BOOST_FWD_REF(KeyType) x) + BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> priv_insert(BOOST_FWD_REF(KeyType) x) { return this->base_t::insert_unique(::boost::forward<KeyType>(x)); } template <class KeyType> - iterator priv_insert(const_iterator p, BOOST_FWD_REF(KeyType) x) + BOOST_CONTAINER_FORCEINLINE iterator priv_insert(const_iterator p, BOOST_FWD_REF(KeyType) x) { return this->base_t::insert_unique(p, ::boost::forward<KeyType>(x)); } #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED }; @@ -829,34 +937,77 @@ class multiset ////////////////////////////////////////////// //! @copydoc ::boost::container::set::set() - multiset() BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value && - container_detail::is_nothrow_default_constructible<Compare>::value) + BOOST_CONTAINER_FORCEINLINE multiset() + BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value && + container_detail::is_nothrow_default_constructible<Compare>::value) : base_t() {} + //! @copydoc ::boost::container::set::set(const allocator_type&) + BOOST_CONTAINER_FORCEINLINE explicit multiset(const allocator_type& a) + : base_t(a) + {} + + //! @copydoc ::boost::container::set::set(const Compare&) + BOOST_CONTAINER_FORCEINLINE explicit multiset(const Compare& comp) + : base_t(comp) + {} + //! @copydoc ::boost::container::set::set(const Compare&, const allocator_type&) - explicit multiset(const Compare& comp, - const allocator_type& a = allocator_type()) + BOOST_CONTAINER_FORCEINLINE multiset(const Compare& comp, const allocator_type& a) : base_t(comp, a) {} - //! @copydoc ::boost::container::set::set(const allocator_type&) - explicit multiset(const allocator_type& a) - : base_t(a) + //! @copydoc ::boost::container::set::set(InputIterator, InputIterator) + template <class InputIterator> + BOOST_CONTAINER_FORCEINLINE multiset(InputIterator first, InputIterator last) + : base_t(false, first, last) + {} + + //! @copydoc ::boost::container::set::set(InputIterator, InputIterator, const allocator_type&) + template <class InputIterator> + BOOST_CONTAINER_FORCEINLINE multiset(InputIterator first, InputIterator last, const allocator_type& a) + : base_t(false, first, last, key_compare(), a) {} - //! @copydoc ::boost::container::set::set(InputIterator, InputIterator, const Compare& comp, const allocator_type&) + //! @copydoc ::boost::container::set::set(InputIterator, InputIterator, const Compare&) template <class InputIterator> - multiset(InputIterator first, InputIterator last, - const Compare& comp = Compare(), - const allocator_type& a = allocator_type()) + BOOST_CONTAINER_FORCEINLINE multiset(InputIterator first, InputIterator last, const Compare& comp) + : base_t(false, first, last, comp) + {} + + //! @copydoc ::boost::container::set::set(InputIterator, InputIterator, const Compare&, const allocator_type&) + template <class InputIterator> + BOOST_CONTAINER_FORCEINLINE multiset(InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a) : base_t(false, first, last, comp, a) {} - //! @copydoc ::boost::container::set::set(InputIterator, InputIterator, const allocator_type&) + //! <b>Effects</b>: Constructs an empty multiset and + //! and inserts elements from the ordered range [first ,last ). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! <b>Requires</b>: [first ,last) must be ordered according to the predicate. + //! + //! <b>Complexity</b>: Linear in N. + //! + //! <b>Note</b>: Non-standard extension. template <class InputIterator> - multiset(InputIterator first, InputIterator last, const allocator_type& a) - : base_t(false, first, last, key_compare(), a) + BOOST_CONTAINER_FORCEINLINE multiset( ordered_range_t, InputIterator first, InputIterator last ) + : base_t(ordered_range, first, last) + {} + + //! <b>Effects</b>: Constructs an empty multiset using the specified comparison object and + //! inserts elements from the ordered range [first ,last ). This function + //! is more efficient than the normal range creation for ordered ranges. + //! + //! <b>Requires</b>: [first ,last) must be ordered according to the predicate. + //! + //! <b>Complexity</b>: Linear in N. + //! + //! <b>Note</b>: Non-standard extension. + template <class InputIterator> + BOOST_CONTAINER_FORCEINLINE multiset( ordered_range_t, InputIterator first, InputIterator last, const Compare& comp) + : base_t(ordered_range, first, last, comp) {} //! <b>Effects</b>: Constructs an empty multiset using the specified comparison object and @@ -869,56 +1020,74 @@ class multiset //! //! <b>Note</b>: Non-standard extension. template <class InputIterator> - multiset( ordered_range_t, InputIterator first, InputIterator last - , const Compare& comp = Compare() - , const allocator_type& a = allocator_type()) + BOOST_CONTAINER_FORCEINLINE multiset( ordered_range_t, InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a) : base_t(ordered_range, first, last, comp, a) {} #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) - //! @copydoc ::boost::container::set::set(std::initializer_list<value_type>, const Compare& comp, const allocator_type&) - multiset(std::initializer_list<value_type> il, const Compare& comp = Compare(), const allocator_type& a = allocator_type()) - : base_t(false, il.begin(), il.end(), comp, a) + //! @copydoc ::boost::container::set::set(std::initializer_list<value_type>) + BOOST_CONTAINER_FORCEINLINE multiset(std::initializer_list<value_type> il) + : base_t(false, il.begin(), il.end()) {} //! @copydoc ::boost::container::set::set(std::initializer_list<value_type>, const allocator_type&) - multiset(std::initializer_list<value_type> il, const allocator_type& a) + BOOST_CONTAINER_FORCEINLINE multiset(std::initializer_list<value_type> il, const allocator_type& a) : base_t(false, il.begin(), il.end(), Compare(), a) {} - //! @copydoc ::boost::container::set::set(ordered_unique_range_t, std::initializer_list<value_type>, const Compare& comp, const allocator_type&) - multiset(ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp = Compare(), const allocator_type& a = allocator_type()) + //! @copydoc ::boost::container::set::set(std::initializer_list<value_type>, const Compare&) + BOOST_CONTAINER_FORCEINLINE multiset(std::initializer_list<value_type> il, const Compare& comp) + : base_t(false, il.begin(), il.end(), comp) + {} + + //! @copydoc ::boost::container::set::set(std::initializer_list<value_type>, const Compare&, const allocator_type&) + BOOST_CONTAINER_FORCEINLINE multiset(std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a) + : base_t(false, il.begin(), il.end(), comp, a) + {} + + //! @copydoc ::boost::container::set::set(ordered_unique_range_t, std::initializer_list<value_type>) + BOOST_CONTAINER_FORCEINLINE multiset(ordered_range_t, std::initializer_list<value_type> il) + : base_t(ordered_range, il.begin(), il.end()) + {} + + //! @copydoc ::boost::container::set::set(ordered_unique_range_t, std::initializer_list<value_type>, const Compare&) + BOOST_CONTAINER_FORCEINLINE multiset(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp) + : base_t(ordered_range, il.begin(), il.end(), comp) + {} + + //! @copydoc ::boost::container::set::set(ordered_unique_range_t, std::initializer_list<value_type>, const Compare&, const allocator_type&) + BOOST_CONTAINER_FORCEINLINE multiset(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a) : base_t(ordered_range, il.begin(), il.end(), comp, a) {} #endif //! @copydoc ::boost::container::set::set(const set &) - multiset(const multiset& x) + BOOST_CONTAINER_FORCEINLINE multiset(const multiset& x) : base_t(static_cast<const base_t&>(x)) {} //! @copydoc ::boost::container::set::set(set &&) - multiset(BOOST_RV_REF(multiset) x) + BOOST_CONTAINER_FORCEINLINE multiset(BOOST_RV_REF(multiset) x) BOOST_NOEXCEPT_IF(boost::container::container_detail::is_nothrow_move_constructible<Compare>::value) : base_t(BOOST_MOVE_BASE(base_t, x)) {} //! @copydoc ::boost::container::set::set(const set &, const allocator_type &) - multiset(const multiset& x, const allocator_type &a) + BOOST_CONTAINER_FORCEINLINE multiset(const multiset& x, const allocator_type &a) : base_t(static_cast<const base_t&>(x), a) {} //! @copydoc ::boost::container::set::set(set &&, const allocator_type &) - multiset(BOOST_RV_REF(multiset) x, const allocator_type &a) + BOOST_CONTAINER_FORCEINLINE multiset(BOOST_RV_REF(multiset) x, const allocator_type &a) : base_t(BOOST_MOVE_BASE(base_t, x), a) {} //! @copydoc ::boost::container::set::operator=(const set &) - multiset& operator=(BOOST_COPY_ASSIGN_REF(multiset) x) + BOOST_CONTAINER_FORCEINLINE multiset& operator=(BOOST_COPY_ASSIGN_REF(multiset) x) { return static_cast<multiset&>(this->base_t::operator=(static_cast<const base_t&>(x))); } //! @copydoc ::boost::container::set::operator=(set &&) - multiset& operator=(BOOST_RV_REF(multiset) x) + BOOST_CONTAINER_FORCEINLINE multiset& operator=(BOOST_RV_REF(multiset) x) BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value || allocator_traits_type::is_always_equal::value) && boost::container::container_detail::is_nothrow_move_assignable<Compare>::value) @@ -999,7 +1168,7 @@ class multiset //! //! <b>Complexity</b>: Logarithmic. template <class... Args> - iterator emplace(BOOST_FWD_REF(Args)... args) + BOOST_CONTAINER_FORCEINLINE iterator emplace(BOOST_FWD_REF(Args)... args) { return this->base_t::emplace_equal(boost::forward<Args>(args)...); } //! <b>Effects</b>: Inserts an object of type Key constructed with @@ -1011,18 +1180,18 @@ class multiset //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t //! is inserted right before p. template <class... Args> - iterator emplace_hint(const_iterator p, BOOST_FWD_REF(Args)... args) + BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator p, BOOST_FWD_REF(Args)... args) { return this->base_t::emplace_hint_equal(p, boost::forward<Args>(args)...); } #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) #define BOOST_CONTAINER_MULTISET_EMPLACE_CODE(N) \ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ - iterator emplace(BOOST_MOVE_UREF##N)\ + BOOST_CONTAINER_FORCEINLINE iterator emplace(BOOST_MOVE_UREF##N)\ { return this->base_t::emplace_equal(BOOST_MOVE_FWD##N); }\ \ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ - iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ + BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ { return this->base_t::emplace_hint_equal(hint BOOST_MOVE_I##N BOOST_MOVE_FWD##N); }\ // BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_MULTISET_EMPLACE_CODE) @@ -1079,21 +1248,21 @@ class multiset //! //! <b>Complexity</b>: At most N log(size()+N) (N is the distance from first to last) template <class InputIterator> - void insert(InputIterator first, InputIterator last) + BOOST_CONTAINER_FORCEINLINE void insert(InputIterator first, InputIterator last) { this->base_t::insert_equal(first, last); } #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) //! @copydoc ::boost::container::set::insert(std::initializer_list<value_type>) - void insert(std::initializer_list<value_type> il) + BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il) { this->base_t::insert_equal(il.begin(), il.end()); } #endif //! @copydoc ::boost::container::multimap::insert(node_type&&) - iterator insert(BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh) + BOOST_CONTAINER_FORCEINLINE iterator insert(BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh) { return this->base_t::insert_equal_node(boost::move(nh)); } //! @copydoc ::boost::container::multimap::insert(const_iterator, node_type&&) - iterator insert(const_iterator hint, BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh) + BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator hint, BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh) { return this->base_t::insert_equal_node(hint, boost::move(nh)); } //! @copydoc ::boost::container::multimap::merge(multimap<Key, T, C2, Allocator, Options>&) @@ -1135,6 +1304,12 @@ class multiset //! @copydoc ::boost::container::set::erase(const_iterator,const_iterator) iterator erase(const_iterator first, const_iterator last); + //! @copydoc ::boost::container::multimap::extract(const_iterator) + node_type extract(const_iterator p); + + //! @copydoc ::boost::container::multimap::extract(const key_type&) + node_type extract(const key_type& x); + //! @copydoc ::boost::container::set::swap void swap(multiset& x) BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value @@ -1219,11 +1394,11 @@ class multiset #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED private: template <class KeyType> - iterator priv_insert(BOOST_FWD_REF(KeyType) x) + BOOST_CONTAINER_FORCEINLINE iterator priv_insert(BOOST_FWD_REF(KeyType) x) { return this->base_t::insert_equal(::boost::forward<KeyType>(x)); } template <class KeyType> - iterator priv_insert(const_iterator p, BOOST_FWD_REF(KeyType) x) + BOOST_CONTAINER_FORCEINLINE iterator priv_insert(const_iterator p, BOOST_FWD_REF(KeyType) x) { return this->base_t::insert_equal(p, ::boost::forward<KeyType>(x)); } #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED diff --git a/boost/container/small_vector.hpp b/boost/container/small_vector.hpp index 14446247ac..804740cc72 100644 --- a/boost/container/small_vector.hpp +++ b/boost/container/small_vector.hpp @@ -387,8 +387,8 @@ class small_vector_base this->steal_resources(x); } else{ - this->assign( boost::make_move_iterator(container_detail::iterator_to_raw_pointer(x.begin())) - , boost::make_move_iterator(container_detail::iterator_to_raw_pointer(x.end ())) + this->assign( boost::make_move_iterator(boost::movelib::iterator_to_raw_pointer(x.begin())) + , boost::make_move_iterator(boost::movelib::iterator_to_raw_pointer(x.end ())) ); } } diff --git a/boost/container/stable_vector.hpp b/boost/container/stable_vector.hpp index 5d6dc0f228..cf156e04de 100644 --- a/boost/container/stable_vector.hpp +++ b/boost/container/stable_vector.hpp @@ -44,7 +44,7 @@ #include <boost/container/detail/iterator.hpp> #include <boost/container/detail/iterators.hpp> #include <boost/container/detail/placement_new.hpp> -#include <boost/container/detail/to_raw_pointer.hpp> +#include <boost/move/detail/to_raw_pointer.hpp> #include <boost/container/detail/type_traits.hpp> // intrusive #include <boost/intrusive/pointer_traits.hpp> @@ -1975,7 +1975,7 @@ class stable_vector , container_detail::addressof(p->value) , it); //This does not throw - ::new(static_cast<node_base_type*>(container_detail::to_raw_pointer(p)), boost_container_new_t()) + ::new(static_cast<node_base_type*>(boost::movelib::to_raw_pointer(p)), boost_container_new_t()) node_base_type(index_traits_type::ptr_to_node_base_ptr(*up_index)); } @@ -1988,7 +1988,7 @@ class stable_vector , container_detail::addressof(p->value) , ::boost::forward<ValueConvertible>(value_convertible)); //This does not throw - ::new(static_cast<node_base_type*>(container_detail::to_raw_pointer(p)), boost_container_new_t()) node_base_type; + ::new(static_cast<node_base_type*>(boost::movelib::to_raw_pointer(p)), boost_container_new_t()) node_base_type; } void priv_swap_members(stable_vector &x) diff --git a/boost/container/string.hpp b/boost/container/string.hpp index 7b780fd588..24056781c9 100644 --- a/boost/container/string.hpp +++ b/boost/container/string.hpp @@ -35,10 +35,11 @@ #include <boost/container/detail/min_max.hpp> #include <boost/container/detail/mpl.hpp> #include <boost/container/detail/next_capacity.hpp> -#include <boost/container/detail/to_raw_pointer.hpp> +#include <boost/move/detail/to_raw_pointer.hpp> #include <boost/container/detail/version_type.hpp> #include <boost/container/detail/type_traits.hpp> #include <boost/container/detail/minimal_char_traits_header.hpp> +#include <boost/container/detail/algorithm.hpp> #include <boost/intrusive/pointer_traits.hpp> @@ -51,7 +52,6 @@ #include <boost/functional/hash.hpp> #include <algorithm> -#include <functional> //bind2nd, etc. #include <iosfwd> #include <istream> #include <ostream> @@ -308,14 +308,14 @@ class basic_string_base { allocator_traits_type::construct ( this->alloc() - , container_detail::to_raw_pointer(p) + , boost::movelib::to_raw_pointer(p) , value ); } void destroy(pointer p, size_type n) { - value_type *raw_p = container_detail::to_raw_pointer(p); + value_type *raw_p = boost::movelib::to_raw_pointer(p); for(; n--; ++raw_p){ allocator_traits_type::destroy( this->alloc(), raw_p); } @@ -325,7 +325,7 @@ class basic_string_base { allocator_traits_type::destroy ( this->alloc() - , container_detail::to_raw_pointer(p) + , boost::movelib::to_raw_pointer(p) ); } @@ -541,8 +541,8 @@ class basic_string bool operator()(const typename Tr::char_type& x) const { - return std::find_if(m_first, m_last, - std::bind1st(Eq_traits<Tr>(), x)) == m_last; + return boost::container::find_if(m_first, m_last, + boost::container::bind1st(Eq_traits<Tr>(), x)) == m_last; } }; #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED @@ -1158,8 +1158,8 @@ class basic_string size_type long_storage = this->priv_long_storage(); size_type long_size = this->priv_long_size(); //Shrink from allocated buffer to the internal one, including trailing null - Traits::copy( container_detail::to_raw_pointer(this->priv_short_addr()) - , container_detail::to_raw_pointer(long_addr) + Traits::copy( boost::movelib::to_raw_pointer(this->priv_short_addr()) + , boost::movelib::to_raw_pointer(long_addr) , long_size+1); this->is_short(true); this->alloc().deallocate(long_addr, long_storage); @@ -1492,7 +1492,7 @@ class basic_string { size_type n = static_cast<size_type>(last - first); this->reserve(n); - CharT* ptr = container_detail::to_raw_pointer(this->priv_addr()); + CharT* ptr = boost::movelib::to_raw_pointer(this->priv_addr()); Traits::copy(ptr, first, n); this->priv_construct_null(ptr + n); this->priv_size(n); @@ -1511,7 +1511,7 @@ class basic_string { size_type cur = 0; const pointer addr = this->priv_addr(); - CharT *ptr = container_detail::to_raw_pointer(addr); + CharT *ptr = boost::movelib::to_raw_pointer(addr); const size_type old_size = this->priv_size(); while (first != last && cur != old_size) { Traits::assign(*ptr, *first); @@ -1570,7 +1570,7 @@ class basic_string size_type len = container_detail::min_value(n, str_size - pos2); if (sz > this->max_size() - len) throw_length_error("basic_string::insert max_size() exceeded"); - const CharT *beg_ptr = container_detail::to_raw_pointer(s.begin()) + pos2; + const CharT *beg_ptr = boost::movelib::to_raw_pointer(s.begin()) + pos2; const CharT *end_ptr = beg_ptr + len; this->insert(this->priv_addr() + pos1, beg_ptr, end_ptr); return *this; @@ -1730,10 +1730,10 @@ class basic_string pointer_past_last, pointer_past_last); this->priv_size(old_size+n); - Traits::move(const_cast<CharT*>(container_detail::to_raw_pointer(p + n)), - container_detail::to_raw_pointer(p), + Traits::move(const_cast<CharT*>(boost::movelib::to_raw_pointer(p + n)), + boost::movelib::to_raw_pointer(p), (elems_after - n) + 1); - this->priv_copy(first, last, const_cast<CharT*>(container_detail::to_raw_pointer(p))); + this->priv_copy(first, last, const_cast<CharT*>(boost::movelib::to_raw_pointer(p))); } else { ForwardIter mid = first; @@ -1746,7 +1746,7 @@ class basic_string (p, const_iterator(old_start + old_length + 1), old_start + newer_size); this->priv_size(newer_size + elems_after); - this->priv_copy(first, mid, const_cast<CharT*>(container_detail::to_raw_pointer(p))); + this->priv_copy(first, mid, const_cast<CharT*>(boost::movelib::to_raw_pointer(p))); } } else{ @@ -1773,9 +1773,9 @@ class basic_string else{ //value_type is POD, so backwards expansion is much easier //than with vector<T> - value_type * const oldbuf = container_detail::to_raw_pointer(old_start); - value_type * const newbuf = container_detail::to_raw_pointer(new_start); - const value_type *const pos = container_detail::to_raw_pointer(p); + value_type * const oldbuf = boost::movelib::to_raw_pointer(old_start); + value_type * const newbuf = boost::movelib::to_raw_pointer(new_start); + const value_type *const pos = boost::movelib::to_raw_pointer(p); const size_type before = pos - oldbuf; //First move old data @@ -1847,10 +1847,10 @@ class basic_string iterator erase(const_iterator p) BOOST_NOEXCEPT_OR_NOTHROW { // The move includes the terminating null. - CharT * const ptr = const_cast<CharT*>(container_detail::to_raw_pointer(p)); + CharT * const ptr = const_cast<CharT*>(boost::movelib::to_raw_pointer(p)); const size_type old_size = this->priv_size(); Traits::move(ptr, - container_detail::to_raw_pointer(p + 1), + boost::movelib::to_raw_pointer(p + 1), old_size - (p - this->priv_addr())); this->priv_size(old_size-1); return iterator(ptr); @@ -1866,12 +1866,12 @@ class basic_string //! the other elements being erased. If no such element exists, end() is returned. iterator erase(const_iterator first, const_iterator last) BOOST_NOEXCEPT_OR_NOTHROW { - CharT * f = const_cast<CharT*>(container_detail::to_raw_pointer(first)); + CharT * f = const_cast<CharT*>(boost::movelib::to_raw_pointer(first)); if (first != last) { // The move includes the terminating null. const size_type num_erased = last - first; const size_type old_size = this->priv_size(); Traits::move(f, - container_detail::to_raw_pointer(last), + boost::movelib::to_raw_pointer(last), (old_size + 1)-(last - this->priv_addr())); const size_type new_length = old_size - num_erased; this->priv_size(new_length); @@ -2059,11 +2059,11 @@ class basic_string { const size_type len = static_cast<size_type>(i2 - i1); if (len >= n) { - Traits::assign(const_cast<CharT*>(container_detail::to_raw_pointer(i1)), n, c); + Traits::assign(const_cast<CharT*>(boost::movelib::to_raw_pointer(i1)), n, c); erase(i1 + n, i2); } else { - Traits::assign(const_cast<CharT*>(container_detail::to_raw_pointer(i1)), len, c); + Traits::assign(const_cast<CharT*>(boost::movelib::to_raw_pointer(i1)), len, c); insert(i2, n - len, c); } return *this; @@ -2088,7 +2088,7 @@ class basic_string ) { for ( ; i1 != i2 && j1 != j2; ++i1, ++j1){ - Traits::assign(*const_cast<CharT*>(container_detail::to_raw_pointer(i1)), *j1); + Traits::assign(*const_cast<CharT*>(boost::movelib::to_raw_pointer(i1)), *j1); } if (j1 == j2) @@ -2111,13 +2111,13 @@ class basic_string difference_type n = boost::container::iterator_distance(j1, j2); const difference_type len = i2 - i1; if (len >= n) { - this->priv_copy(j1, j2, const_cast<CharT*>(container_detail::to_raw_pointer(i1))); + this->priv_copy(j1, j2, const_cast<CharT*>(boost::movelib::to_raw_pointer(i1))); this->erase(i1 + n, i2); } else { ForwardIter m = j1; boost::container::iterator_advance(m, len); - this->priv_copy(j1, m, const_cast<CharT*>(container_detail::to_raw_pointer(i1))); + this->priv_copy(j1, m, const_cast<CharT*>(boost::movelib::to_raw_pointer(i1))); this->insert(i2, m, j2); } return *this; @@ -2128,7 +2128,7 @@ class basic_string //! //! <b>Effects</b>: Calls `replace(i1 - begin(), i2 - i1, sv).`. //! - //! <bReturns</b>: *this. + //! <b>Returns</b>: *this. template<template <class, class> class BasicStringView> basic_string& replace(const_iterator i1, const_iterator i2, BasicStringView<CharT, Traits> sv) { @@ -2141,7 +2141,7 @@ class basic_string //! //! <b>Effects</b>: Calls replace(i1 - begin(), i2 - i1, il.begin(), il.size()). //! - //! <bReturns</b>: *this. + //! <b>Returns</b>: *this. basic_string& replace(const_iterator i1, const_iterator i2, std::initializer_list<CharT> il) { return this->replace( static_cast<size_type>(i1 - this->cbegin()) @@ -2166,7 +2166,7 @@ class basic_string if (pos > this->size()) throw_out_of_range("basic_string::copy out of range position"); const size_type len = container_detail::min_value(n, this->size() - pos); - Traits::copy(s, container_detail::to_raw_pointer(this->priv_addr() + pos), len); + Traits::copy(s, boost::movelib::to_raw_pointer(this->priv_addr() + pos), len); return len; } @@ -2195,7 +2195,7 @@ class basic_string //! //! <b>Complexity</b>: constant time. const CharT* c_str() const BOOST_NOEXCEPT_OR_NOTHROW - { return container_detail::to_raw_pointer(this->priv_addr()); } + { return boost::movelib::to_raw_pointer(this->priv_addr()); } //! <b>Requires</b>: The program shall not alter any of the values stored in the character array. //! @@ -2203,13 +2203,13 @@ class basic_string //! //! <b>Complexity</b>: constant time. const CharT* data() const BOOST_NOEXCEPT_OR_NOTHROW - { return container_detail::to_raw_pointer(this->priv_addr()); } + { return boost::movelib::to_raw_pointer(this->priv_addr()); } //! <b>Returns</b>: A pointer p such that p + i == &operator[](i) for each i in [0,size()]. //! //! <b>Complexity</b>: constant time. CharT* data() BOOST_NOEXCEPT_OR_NOTHROW - { return container_detail::to_raw_pointer(this->priv_addr()); } + { return boost::movelib::to_raw_pointer(this->priv_addr()); } #ifndef BOOST_CONTAINER_TEMPLATED_CONVERSION_OPERATOR_BROKEN //! <b>Returns</b>: a string_view to the characters in the string. @@ -2272,8 +2272,8 @@ class basic_string const pointer addr = this->priv_addr(); pointer finish = addr + this->priv_size(); const const_iterator result = - std::search(container_detail::to_raw_pointer(addr + pos), - container_detail::to_raw_pointer(finish), + boost::container::search(boost::movelib::to_raw_pointer(addr + pos), + boost::movelib::to_raw_pointer(finish), s, s + n, Eq_traits<Traits>()); return result != finish ? result - begin() : npos; } @@ -2299,8 +2299,8 @@ class basic_string const pointer addr = this->priv_addr(); pointer finish = addr + sz; const const_iterator result = - std::find_if(addr + pos, finish, - std::bind2nd(Eq_traits<Traits>(), c)); + boost::container::find_if(addr + pos, finish, + boost::container::bind2nd(Eq_traits<Traits>(), c)); return result != finish ? result - begin() : npos; } } @@ -2371,8 +2371,8 @@ class basic_string else { const const_iterator last = begin() + container_detail::min_value(len - 1, pos) + 1; const_reverse_iterator rresult = - std::find_if(const_reverse_iterator(last), rend(), - std::bind2nd(Eq_traits<Traits>(), c)); + boost::container::find_if(const_reverse_iterator(last), rend(), + boost::container::bind2nd(Eq_traits<Traits>(), c)); return rresult != rend() ? (rresult.base() - 1) - begin() : npos; } } @@ -2385,7 +2385,7 @@ class basic_string //! //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos. size_type find_first_of(const basic_string& str, size_type pos = 0) const - { return find_first_of(str.c_str(), pos, str.size()); } + { return this->find_first_of(str.c_str(), pos, str.size()); } //! <b>Effects</b>: Determines the lowest position xpos, if possible, such that both of the //! following conditions obtain: a) pos <= xpos and xpos < size(); @@ -2396,7 +2396,7 @@ class basic_string //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos. template<template <class, class> class BasicStringView> size_type find_first_of(BasicStringView<CharT, Traits> sv, size_type pos = 0) const - { return find_first_of(sv.data(), pos, sv.size()); } + { return this->find_first_of(sv.data(), pos, sv.size()); } //! <b>Requires</b>: s points to an array of at least n elements of CharT. //! @@ -2411,7 +2411,7 @@ class basic_string else { const pointer addr = this->priv_addr(); pointer finish = addr + sz; - const_iterator result = std::find_first_of + const_iterator result = boost::container::find_first_of (addr + pos, finish, s, s + n, Eq_traits<Traits>()); return result != finish ? result - this->begin() : npos; } @@ -2423,7 +2423,7 @@ class basic_string //! //! <b>Returns</b>: find_first_of(basic_string(s), pos). size_type find_first_of(const CharT* s, size_type pos = 0) const - { return find_first_of(s, pos, Traits::length(s)); } + { return this->find_first_of(s, pos, Traits::length(s)); } //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT. //! @@ -2431,7 +2431,7 @@ class basic_string //! //! <b>Returns</b>: find_first_of(basic_string<CharT,traits,Allocator>(1,c), pos). size_type find_first_of(CharT c, size_type pos = 0) const - { return find(c, pos); } + { return this->find(c, pos); } //! <b>Effects</b>: Determines the highest position xpos, if possible, such that both of //! the following conditions obtain: a) xpos <= pos and xpos < size(); b) @@ -2441,7 +2441,7 @@ class basic_string //! //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos. size_type find_last_of(const basic_string& str, size_type pos = npos) const - { return find_last_of(str.c_str(), pos, str.size()); } + { return this->find_last_of(str.c_str(), pos, str.size()); } //! <b>Effects</b>: Determines the highest position xpos, if possible, such that both of //! the following conditions obtain: a) xpos <= pos and xpos < size(); b) @@ -2452,7 +2452,7 @@ class basic_string //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos. template<template <class, class> class BasicStringView> size_type find_last_of(BasicStringView<CharT, Traits> sv, size_type pos = npos) const - { return find_last_of(sv.data(), pos, sv.size()); } + { return this->find_last_of(sv.data(), pos, sv.size()); } //! <b>Requires</b>: s points to an array of at least n elements of CharT. //! @@ -2469,7 +2469,7 @@ class basic_string const pointer addr = this->priv_addr(); const const_iterator last = addr + container_detail::min_value(len - 1, pos) + 1; const const_reverse_iterator rresult = - std::find_first_of(const_reverse_iterator(last), rend(), + boost::container::find_first_of(const_reverse_iterator(last), rend(), s, s + n, Eq_traits<Traits>()); return rresult != rend() ? (rresult.base() - 1) - addr : npos; } @@ -2524,7 +2524,7 @@ class basic_string else { const pointer addr = this->priv_addr(); const pointer finish = addr + this->priv_size(); - const const_iterator result = std::find_if + const const_iterator result = boost::container::find_if (addr + pos, finish, Not_within_traits<Traits>(s, s + n)); return result != finish ? result - addr : npos; } @@ -2549,8 +2549,8 @@ class basic_string const pointer addr = this->priv_addr(); const pointer finish = addr + this->priv_size(); const const_iterator result - = std::find_if(addr + pos, finish, - std::not1(std::bind2nd(Eq_traits<Traits>(), c))); + = boost::container::find_if(addr + pos, finish, + boost::container::not1(boost::container::bind2nd(Eq_traits<Traits>(), c))); return result != finish ? result - begin() : npos; } } @@ -2590,7 +2590,7 @@ class basic_string else { const const_iterator last = begin() + container_detail::min_value(len - 1, pos) + 1; const const_reverse_iterator rresult = - std::find_if(const_reverse_iterator(last), rend(), + boost::container::find_if(const_reverse_iterator(last), rend(), Not_within_traits<Traits>(s, s + n)); return rresult != rend() ? (rresult.base() - 1) - begin() : npos; } @@ -2616,8 +2616,8 @@ class basic_string else { const const_iterator last = begin() + container_detail::min_value(len - 1, pos) + 1; const const_reverse_iterator rresult = - std::find_if(const_reverse_iterator(last), rend(), - std::not1(std::bind2nd(Eq_traits<Traits>(), c))); + boost::container::find_if(const_reverse_iterator(last), rend(), + boost::container::not1(boost::container::bind2nd(Eq_traits<Traits>(), c))); return rresult != rend() ? (rresult.base() - 1) - begin() : npos; } } @@ -2804,8 +2804,8 @@ class basic_string { const difference_type n1 = l1 - f1; const difference_type n2 = l2 - f2; - const int cmp = Traits::compare(container_detail::to_raw_pointer(f1), - container_detail::to_raw_pointer(f2), + const int cmp = Traits::compare(boost::movelib::to_raw_pointer(f1), + boost::movelib::to_raw_pointer(f2), container_detail::min_value(n1, n2)); return cmp != 0 ? cmp : (n1 < n2 ? -1 : (n1 > n2 ? 1 : 0)); } @@ -2826,8 +2826,8 @@ class basic_string real_cap = long_size+1; const pointer ret = this->allocation_command(allocate_new, long_size+1, real_cap, reuse); //Copy and update - Traits::copy( container_detail::to_raw_pointer(ret) - , container_detail::to_raw_pointer(this->priv_long_addr()) + Traits::copy( boost::movelib::to_raw_pointer(ret) + , boost::movelib::to_raw_pointer(this->priv_long_addr()) , long_size+1); this->priv_long_addr(ret); this->priv_storage(real_cap); diff --git a/boost/container/vector.hpp b/boost/container/vector.hpp index 336d616007..5ec669ba99 100644 --- a/boost/container/vector.hpp +++ b/boost/container/vector.hpp @@ -36,10 +36,10 @@ #include <boost/container/detail/destroyers.hpp> #include <boost/container/detail/iterator.hpp> #include <boost/container/detail/iterators.hpp> -#include <boost/container/detail/iterator_to_raw_pointer.hpp> +#include <boost/move/detail/iterator_to_raw_pointer.hpp> #include <boost/container/detail/mpl.hpp> #include <boost/container/detail/next_capacity.hpp> -#include <boost/container/detail/to_raw_pointer.hpp> +#include <boost/move/detail/to_raw_pointer.hpp> #include <boost/container/detail/type_traits.hpp> #include <boost/container/detail/version_type.hpp> // intrusive @@ -54,6 +54,10 @@ #include <boost/move/detail/fwd_macros.hpp> #endif #include <boost/move/detail/move_helpers.hpp> +// move/algo +#include <boost/move/algo/adaptive_merge.hpp> +#include <boost/move/algo/unique.hpp> +#include <boost/move/algo/predicate.hpp> // other #include <boost/core/no_exceptions_support.hpp> #include <boost/assert.hpp> @@ -609,7 +613,7 @@ struct vector_alloc_holder<Allocator, version_0> , m_size(holder.m_size) //Size is initialized here so vector should only call uninitialized_xxx after this { ::boost::container::uninitialized_move_alloc_n - (this->alloc(), container_detail::to_raw_pointer(holder.start()), m_size, container_detail::to_raw_pointer(this->start())); + (this->alloc(), boost::movelib::to_raw_pointer(holder.start()), m_size, boost::movelib::to_raw_pointer(this->start())); } template<class OtherAllocator, class OtherAllocatorVersion> @@ -621,7 +625,7 @@ struct vector_alloc_holder<Allocator, version_0> const size_type n = holder.m_size; this->priv_first_allocation(n); ::boost::container::uninitialized_move_alloc_n - (this->alloc(), container_detail::to_raw_pointer(holder.start()), n, container_detail::to_raw_pointer(this->start())); + (this->alloc(), boost::movelib::to_raw_pointer(holder.start()), n, boost::movelib::to_raw_pointer(this->start())); } BOOST_CONTAINER_FORCEINLINE void priv_first_allocation(size_type cap) @@ -675,8 +679,8 @@ struct vector_alloc_holder<Allocator, version_0> void priv_deep_swap(vector_alloc_holder<OtherAllocator, OtherAllocatorVersion> &x) { const size_type MaxTmpStorage = sizeof(value_type)*Allocator::internal_capacity; - value_type *const first_this = container_detail::to_raw_pointer(this->start()); - value_type *const first_x = container_detail::to_raw_pointer(x.start()); + value_type *const first_this = boost::movelib::to_raw_pointer(this->start()); + value_type *const first_x = boost::movelib::to_raw_pointer(x.start()); if(this->m_size < x.m_size){ boost::container::deep_swap_alloc_n<MaxTmpStorage>(this->alloc(), first_this, this->m_size, first_x, x.m_size); @@ -1186,7 +1190,7 @@ class vector if (first == last){ //There are no more elements in the sequence, erase remaining T* const end_pos = this->priv_raw_end(); - const size_type n = static_cast<size_type>(end_pos - container_detail::iterator_to_raw_pointer(cur)); + const size_type n = static_cast<size_type>(end_pos - boost::movelib::iterator_to_raw_pointer(cur)); this->priv_destroy_last_n(n); } else{ @@ -2005,7 +2009,7 @@ class vector { BOOST_ASSERT(this->priv_in_range(position)); const pointer p = vector_iterator_get_ptr(position); - T *const pos_ptr = container_detail::to_raw_pointer(p); + T *const pos_ptr = boost::movelib::to_raw_pointer(p); T *const beg_ptr = this->priv_raw_begin(); T *const new_end_ptr = ::boost::container::move(pos_ptr + 1, beg_ptr + this->m_holder.m_size, pos_ptr); //Move elements forward and destroy last @@ -2025,9 +2029,9 @@ class vector (first < last && this->priv_in_range(first) && this->priv_in_range_or_end(last))); if (first != last){ T* const old_end_ptr = this->priv_raw_end(); - T* const first_ptr = container_detail::to_raw_pointer(vector_iterator_get_ptr(first)); - T* const last_ptr = container_detail::to_raw_pointer(vector_iterator_get_ptr(last)); - T* const ptr = container_detail::to_raw_pointer(boost::container::move(last_ptr, old_end_ptr, first_ptr)); + T* const first_ptr = boost::movelib::to_raw_pointer(vector_iterator_get_ptr(first)); + T* const last_ptr = boost::movelib::to_raw_pointer(vector_iterator_get_ptr(last)); + T* const ptr = boost::movelib::to_raw_pointer(boost::container::move(last_ptr, old_end_ptr, first_ptr)); this->priv_destroy_last_n(old_end_ptr - ptr); } return iterator(vector_iterator_get_ptr(first)); @@ -2240,37 +2244,15 @@ class vector p = this->m_holder.allocation_command(allocate_new, new_size, new_cap, p); this->priv_merge_in_new_buffer(UniqueBool(), first, n, comp, p, new_cap); } - else if(!UniqueBool::value && free_c >= n){ - typedef container_detail::vector_merge_cursor<T, size_type, BidirIt, Compare> inserter_t; - T* const pbeg = this->priv_raw_begin(); - return this->priv_insert_ordered_at(n, inserter_t(pbeg, pbeg + s, last, comp)); - } - else{ //UniqueBool::value == true and free_c >= n - std::size_t remaining = n; - static const std::size_t PosCount = 64u; - size_type positions[PosCount]; - size_type *indexes = 0; - while(remaining){ - //Query for room to store indexes in the remaining buffer - boost::uintptr_t const szt_align_mask = container_detail::alignment_of<size_type>::value - 1; - boost::uintptr_t const addr = boost::uintptr_t(this->priv_raw_begin() + s + n); - boost::uintptr_t const capaddr = boost::uintptr_t(this->priv_raw_begin() + c); - boost::uintptr_t const aligned_addr = (addr + szt_align_mask) & ~szt_align_mask; - indexes = reinterpret_cast<size_type *>(aligned_addr); - std::size_t index_capacity = (aligned_addr >= capaddr) ? 0u : (capaddr - aligned_addr)/sizeof(size_type); - - //Capacity is constant, we're not going to change it - if(index_capacity < PosCount){ - indexes = positions; - index_capacity = PosCount; - } - if(index_capacity > remaining) - index_capacity = remaining; - BidirIt limit = first; - boost::container::iterator_advance(limit, index_capacity); - this->priv_insert_ordered_range(UniqueBool(), index_capacity, first, limit, indexes, comp); - first = limit; - remaining -= index_capacity; + else{ + T *raw_pos = boost::movelib::iterator_to_raw_pointer(this->insert(this->cend(), first, last)); + T *raw_beg = this->priv_raw_begin(); + T *raw_end = this->priv_raw_end(); + boost::movelib::adaptive_merge(raw_beg, raw_pos, raw_end, comp, raw_end, free_c - n); + if(UniqueBool::value){ + size_type const count = + static_cast<size_type>(raw_end - boost::movelib::unique(raw_beg, raw_end, boost::movelib::negate<Compare>(comp))); + this->priv_destroy_last_n(count); } } } @@ -2279,53 +2261,6 @@ class vector } } - template <class UniqueBool, class BidirIt, class Compare> - void priv_insert_ordered_range - (UniqueBool, size_type const n, BidirIt first, BidirIt const last, size_type positions[], Compare comp) - { - //Linear: at most N + M -1 comparisons - //Log: MlogN - //Average - //Linear: N + M - 2 - //Log: MlogN - //N+M - 2 - //N - //(N+M)/2 < MlogN - //(N/M+1)/2 <= logN - //bool const linear = !s || !n || (s <= n) || ((s+n)/n/2 < logN); - size_type const s = this->size(); - size_type remaining = n; - T* const pbeg = this->priv_raw_begin(); - T* const pend = pbeg + s; - T* pcur = pbeg; - size_type *position = positions; - size_type added_in_middle = 0; - if(first != last && pcur != pend){ - while(1){ - //maintain stability moving external values only if they are strictly less - if(comp(*first, *pcur)) { - *position = static_cast<size_type>(pcur - pbeg); - BOOST_ASSERT((position == positions) || (*(position-1) == size_type(-1)) || (*(position-1) <= *position)); - ++position; - ++added_in_middle; - --remaining; - if(++first == last) break; - } - else if(UniqueBool::value && !comp(*pcur, *first)){ - *position = size_type(-1); - ++position; - --remaining; - if(++first == last) break; - } - else{ - if(++pcur == pend) break; - } - } - } - this->insert_ordered_at(added_in_middle, position, first); - this->insert(this->cend(), remaining, first, last); - } - template<class UniqueBool, class FwdIt, class Compare> void priv_merge_in_new_buffer (UniqueBool, FwdIt first, size_type n, Compare comp, pointer new_storage, size_type const new_cap) @@ -2337,7 +2272,7 @@ class vector T* pbeg = this->priv_raw_begin(); size_type const old_size = this->size(); T* const pend = pbeg + old_size; - T* d_first = container_detail::to_raw_pointer(new_storage); + T* d_first = boost::movelib::to_raw_pointer(new_storage); size_type added = n; //Merge in new buffer loop while(1){ @@ -2373,7 +2308,7 @@ class vector //Nothrow operations pointer const old_p = this->m_holder.start(); size_type const old_cap = this->m_holder.capacity(); - boost::container::destroy_alloc_n(a, container_detail::to_raw_pointer(old_p), old_size); + boost::container::destroy_alloc_n(a, boost::movelib::to_raw_pointer(old_p), old_size); a.deallocate(old_p, old_cap); this->m_holder.m_size = old_size + added; this->m_holder.start(new_storage); @@ -2444,8 +2379,8 @@ class vector } //Else do a one by one move else{ - this->assign( boost::make_move_iterator(container_detail::iterator_to_raw_pointer(x.begin())) - , boost::make_move_iterator(container_detail::iterator_to_raw_pointer(x.end() )) + this->assign( boost::make_move_iterator(boost::movelib::iterator_to_raw_pointer(x.begin())) + , boost::make_move_iterator(boost::movelib::iterator_to_raw_pointer(x.end() )) ); } //Move allocator if needed @@ -2514,8 +2449,8 @@ class vector } //... and move-insert the remaining range sml.insert( sml.cend() - , boost::make_move_iterator(container_detail::iterator_to_raw_pointer(big.nth(common_elements))) - , boost::make_move_iterator(container_detail::iterator_to_raw_pointer(big.end())) + , boost::make_move_iterator(boost::movelib::iterator_to_raw_pointer(big.nth(common_elements))) + , boost::make_move_iterator(boost::movelib::iterator_to_raw_pointer(big.end())) ); //Destroy remaining elements big.erase(big.nth(common_elements), big.cend()); @@ -2540,7 +2475,7 @@ class vector pointer const p = allocator_traits_type::allocate(this->m_holder.alloc(), new_cap, this->m_holder.m_start); //We will reuse insert code, so create a dummy input iterator this->priv_forward_range_insert_new_allocation - ( container_detail::to_raw_pointer(p), new_cap, this->priv_raw_end(), 0, this->priv_dummy_empty_proxy()); + ( boost::movelib::to_raw_pointer(p), new_cap, this->priv_raw_end(), 0, this->priv_dummy_empty_proxy()); } void priv_reserve_no_capacity(size_type new_cap, version_2) @@ -2561,7 +2496,7 @@ class vector this->m_holder.capacity(real_cap); } else{ //If there is no forward expansion, move objects, we will reuse insertion code - T * const new_mem = container_detail::to_raw_pointer(ret); + T * const new_mem = boost::movelib::to_raw_pointer(ret); T * const ins_pos = this->priv_raw_end(); if(reuse){ //Backwards (and possibly forward) expansion #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS @@ -2691,7 +2626,7 @@ class vector ++this->num_alloc; #endif this->priv_forward_range_insert_new_allocation - ( container_detail::to_raw_pointer(p), sz + ( boost::movelib::to_raw_pointer(p), sz , this->priv_raw_begin(), 0, this->priv_dummy_empty_proxy()); } } @@ -2735,11 +2670,11 @@ class vector { //Check if we have enough memory or try to expand current memory const size_type n_pos = pos - this->m_holder.start(); - T *const raw_pos = container_detail::to_raw_pointer(pos); + T *const raw_pos = boost::movelib::to_raw_pointer(pos); const size_type new_cap = this->m_holder.next_capacity(n); //Pass the hint so that allocators can take advantage of this. - T * const new_buf = container_detail::to_raw_pointer + T * const new_buf = boost::movelib::to_raw_pointer (allocator_traits_type::allocate(this->m_holder.alloc(), new_cap, this->m_holder.m_start)); #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS ++this->num_alloc; @@ -2754,7 +2689,7 @@ class vector (const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy, version_2) { //Check if we have enough memory or try to expand current memory - T *const raw_pos = container_detail::to_raw_pointer(pos); + T *const raw_pos = boost::movelib::to_raw_pointer(pos); const size_type n_pos = raw_pos - this->priv_raw_begin(); //There is not enough memory, allocate a new @@ -2781,7 +2716,7 @@ class vector ++this->num_expand_bwd; #endif this->priv_forward_range_insert_expand_backwards - (container_detail::to_raw_pointer(ret), real_cap, raw_pos, n, insert_range_proxy); + (boost::movelib::to_raw_pointer(ret), real_cap, raw_pos, n, insert_range_proxy); } } //New buffer @@ -2790,7 +2725,7 @@ class vector ++this->num_alloc; #endif this->priv_forward_range_insert_new_allocation - ( container_detail::to_raw_pointer(ret), real_cap, raw_pos, n, insert_range_proxy); + ( boost::movelib::to_raw_pointer(ret), real_cap, raw_pos, n, insert_range_proxy); } return iterator(this->m_holder.start() + n_pos); @@ -2810,7 +2745,7 @@ class vector } else{ //Expand forward - T *const raw_pos = container_detail::to_raw_pointer(pos); + T *const raw_pos = boost::movelib::to_raw_pointer(pos); const size_type n_pos = raw_pos - this->priv_raw_begin(); this->priv_forward_range_insert_expand_forward(raw_pos, n, insert_range_proxy); return iterator(this->m_holder.start() + n_pos); @@ -2926,10 +2861,10 @@ class vector } private: - T *priv_raw_begin() const - { return container_detail::to_raw_pointer(m_holder.start()); } + BOOST_CONTAINER_FORCEINLINE T *priv_raw_begin() const + { return boost::movelib::to_raw_pointer(m_holder.start()); } - T* priv_raw_end() const + BOOST_CONTAINER_FORCEINLINE T* priv_raw_end() const { return this->priv_raw_begin() + this->m_holder.m_size; } template <class InsertionProxy> |