diff options
Diffstat (limited to 'boost/container')
70 files changed, 6052 insertions, 4667 deletions
diff --git a/boost/container/adaptive_pool.hpp b/boost/container/adaptive_pool.hpp index c12d511c65..1f6b6667e9 100644 --- a/boost/container/adaptive_pool.hpp +++ b/boost/container/adaptive_pool.hpp @@ -11,7 +11,11 @@ #ifndef BOOST_CONTAINER_ADAPTIVE_POOL_HPP #define BOOST_CONTAINER_ADAPTIVE_POOL_HPP -#if defined(_MSC_VER) && (_MSC_VER >= 1200) +#ifndef BOOST_CONFIG_HPP +# include <boost/config.hpp> +#endif + +#if defined(BOOST_HAS_PRAGMA_ONCE) # pragma once #endif @@ -25,15 +29,11 @@ #include <boost/container/detail/mpl.hpp> #include <boost/container/detail/alloc_lib_auto_link.hpp> #include <boost/container/detail/singleton.hpp> - #include <boost/container/detail/placement_new.hpp> #include <boost/assert.hpp> -#include <boost/utility/addressof.hpp> #include <boost/static_assert.hpp> #include <boost/move/utility_core.hpp> -#include <memory> -#include <algorithm> #include <cstddef> @@ -57,7 +57,7 @@ template < class T , std::size_t NodesPerBlock BOOST_CONTAINER_DOCONLY(= ADP_nodes_per_block) , std::size_t MaxFreeBlocks BOOST_CONTAINER_DOCONLY(= ADP_max_free_blocks) , std::size_t OverheadPercent BOOST_CONTAINER_DOCONLY(= ADP_overhead_percent) - BOOST_CONTAINER_DOCIGN(BOOST_CONTAINER_I unsigned Version) + BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I unsigned Version) > class adaptive_pool { @@ -67,7 +67,7 @@ class adaptive_pool typedef unsigned int allocation_type; typedef adaptive_pool <T, NodesPerBlock, MaxFreeBlocks, OverheadPercent - BOOST_CONTAINER_DOCIGN(BOOST_CONTAINER_I Version) + BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I Version) > self_t; static const std::size_t nodes_per_block = NodesPerBlock; @@ -110,7 +110,7 @@ class adaptive_pool , NodesPerBlock , MaxFreeBlocks , OverheadPercent - BOOST_CONTAINER_DOCIGN(BOOST_CONTAINER_I Version) + BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I Version) > other; }; @@ -127,34 +127,34 @@ class adaptive_pool public: //!Default constructor - adaptive_pool() BOOST_CONTAINER_NOEXCEPT + adaptive_pool() BOOST_NOEXCEPT_OR_NOTHROW {} //!Copy constructor from other adaptive_pool. - adaptive_pool(const adaptive_pool &) BOOST_CONTAINER_NOEXCEPT + adaptive_pool(const adaptive_pool &) BOOST_NOEXCEPT_OR_NOTHROW {} //!Copy constructor from related adaptive_pool. template<class T2> adaptive_pool (const adaptive_pool<T2, NodesPerBlock, MaxFreeBlocks, OverheadPercent - BOOST_CONTAINER_DOCIGN(BOOST_CONTAINER_I Version)> &) BOOST_CONTAINER_NOEXCEPT + BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I Version)> &) BOOST_NOEXCEPT_OR_NOTHROW {} //!Destructor - ~adaptive_pool() BOOST_CONTAINER_NOEXCEPT + ~adaptive_pool() BOOST_NOEXCEPT_OR_NOTHROW {} //!Returns the number of elements that could be allocated. //!Never throws - size_type max_size() const BOOST_CONTAINER_NOEXCEPT + size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW { return size_type(-1)/sizeof(T); } //!Allocate memory for an array of count elements. //!Throws std::bad_alloc if there is no enough memory pointer allocate(size_type count, const void * = 0) { - if(count > this->max_size()) + if(BOOST_UNLIKELY(count > this->max_size())) boost::container::throw_bad_alloc(); if(Version == 1 && count == 1){ @@ -170,7 +170,7 @@ class adaptive_pool //!Deallocate allocated memory. //!Never throws - void deallocate(const pointer &ptr, size_type count) BOOST_CONTAINER_NOEXCEPT + void deallocate(const pointer &ptr, size_type count) BOOST_NOEXCEPT_OR_NOTHROW { (void)count; if(Version == 1 && count == 1){ @@ -184,22 +184,20 @@ class adaptive_pool } } - std::pair<pointer, bool> - allocation_command(allocation_type command, + pointer allocation_command(allocation_type command, size_type limit_size, - size_type preferred_size, - size_type &received_size, pointer reuse = pointer()) + size_type &prefer_in_recvd_out_size, + pointer &reuse) { - std::pair<pointer, bool> ret = - this->priv_allocation_command(command, limit_size, preferred_size, received_size, reuse); - if(!ret.first && !(command & BOOST_CONTAINER_NOTHROW_ALLOCATION)) + pointer ret = this->priv_allocation_command(command, limit_size, prefer_in_recvd_out_size, reuse); + if(BOOST_UNLIKELY(!ret && !(command & BOOST_CONTAINER_NOTHROW_ALLOCATION))) boost::container::throw_bad_alloc(); return ret; } //!Returns maximum the number of objects the previously allocated memory //!pointed by p can hold. - size_type size(pointer p) const BOOST_CONTAINER_NOEXCEPT + size_type size(pointer p) const BOOST_NOEXCEPT_OR_NOTHROW { return boost_cont_size(p); } //!Allocates just one object. Memory allocated with this function @@ -230,7 +228,7 @@ class adaptive_pool //!Deallocates memory previously allocated with allocate_one(). //!You should never use deallocate_one to deallocate memory allocated //!with other functions different from allocate_one(). Never throws - void deallocate_one(pointer p) BOOST_CONTAINER_NOEXCEPT + void deallocate_one(pointer p) BOOST_NOEXCEPT_OR_NOTHROW { typedef container_detail::shared_adaptive_node_pool <sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t; @@ -238,7 +236,7 @@ class adaptive_pool singleton_t::instance().deallocate_node(p); } - void deallocate_individual(multiallocation_chain &chain) BOOST_CONTAINER_NOEXCEPT + void deallocate_individual(multiallocation_chain &chain) BOOST_NOEXCEPT_OR_NOTHROW { typedef container_detail::shared_adaptive_node_pool <sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t; @@ -255,14 +253,15 @@ class adaptive_pool BOOST_STATIC_ASSERT(( Version > 1 ));/* boost_cont_memchain ch; BOOST_CONTAINER_MEMCHAIN_INIT(&ch); - if(!boost_cont_multialloc_nodes(n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch)){ + if(BOOST_UNLIKELY(!boost_cont_multialloc_nodes(n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch))){ boost::container::throw_bad_alloc(); } chain.incorporate_after(chain.before_begin() ,(T*)BOOST_CONTAINER_MEMCHAIN_FIRSTMEM(&ch) ,(T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch) ,BOOST_CONTAINER_MEMCHAIN_SIZE(&ch) );*/ - if(!boost_cont_multialloc_nodes(n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, reinterpret_cast<boost_cont_memchain *>(&chain))){ + if(BOOST_UNLIKELY(!boost_cont_multialloc_nodes + (n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, reinterpret_cast<boost_cont_memchain *>(&chain)))){ boost::container::throw_bad_alloc(); } } @@ -274,19 +273,20 @@ class adaptive_pool BOOST_STATIC_ASSERT(( Version > 1 ));/* boost_cont_memchain ch; BOOST_CONTAINER_MEMCHAIN_INIT(&ch); - if(!boost_cont_multialloc_arrays(n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch)){ + if(BOOST_UNLIKELY(!boost_cont_multialloc_arrays(n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch))){ boost::container::throw_bad_alloc(); } chain.incorporate_after(chain.before_begin() ,(T*)BOOST_CONTAINER_MEMCHAIN_FIRSTMEM(&ch) ,(T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch) ,BOOST_CONTAINER_MEMCHAIN_SIZE(&ch) );*/ - if(!boost_cont_multialloc_arrays(n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, reinterpret_cast<boost_cont_memchain *>(&chain))){ + if(BOOST_UNLIKELY(!boost_cont_multialloc_arrays + (n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, reinterpret_cast<boost_cont_memchain *>(&chain)))){ boost::container::throw_bad_alloc(); } } - void deallocate_many(multiallocation_chain &chain) BOOST_CONTAINER_NOEXCEPT + void deallocate_many(multiallocation_chain &chain) BOOST_NOEXCEPT_OR_NOTHROW {/* boost_cont_memchain ch; void *beg(&*chain.begin()), *last(&*chain.last()); @@ -297,7 +297,7 @@ class adaptive_pool } //!Deallocates all free blocks of the pool - static void deallocate_free_blocks() BOOST_CONTAINER_NOEXCEPT + static void deallocate_free_blocks() BOOST_NOEXCEPT_OR_NOTHROW { typedef container_detail::shared_adaptive_node_pool <sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t; @@ -307,37 +307,39 @@ class adaptive_pool //!Swaps allocators. Does not throw. If each allocator is placed in a //!different memory segment, the result is undefined. - friend void swap(adaptive_pool &, adaptive_pool &) BOOST_CONTAINER_NOEXCEPT + friend void swap(adaptive_pool &, adaptive_pool &) BOOST_NOEXCEPT_OR_NOTHROW {} //!An allocator always compares to true, as memory allocated with one //!instance can be deallocated by another instance - friend bool operator==(const adaptive_pool &, const adaptive_pool &) BOOST_CONTAINER_NOEXCEPT + friend bool operator==(const adaptive_pool &, const adaptive_pool &) BOOST_NOEXCEPT_OR_NOTHROW { return true; } //!An allocator always compares to false, as memory allocated with one //!instance can be deallocated by another instance - friend bool operator!=(const adaptive_pool &, const adaptive_pool &) BOOST_CONTAINER_NOEXCEPT + friend bool operator!=(const adaptive_pool &, const adaptive_pool &) BOOST_NOEXCEPT_OR_NOTHROW { return false; } private: - std::pair<pointer, bool> priv_allocation_command + pointer priv_allocation_command (allocation_type command, std::size_t limit_size - ,std::size_t preferred_size,std::size_t &received_size, void *reuse_ptr) + ,size_type &prefer_in_recvd_out_size, pointer &reuse_ptr) { + std::size_t const preferred_size = prefer_in_recvd_out_size; boost_cont_command_ret_t ret = {0 , 0}; - if(limit_size > this->max_size() || preferred_size > this->max_size()){ -// ret.first = 0; - return std::pair<pointer, bool>(pointer(), false); + if(BOOST_UNLIKELY(limit_size > this->max_size() || preferred_size > this->max_size())){ + return pointer(); } std::size_t l_size = limit_size*sizeof(T); std::size_t p_size = preferred_size*sizeof(T); std::size_t r_size; { - ret = boost_cont_allocation_command(command, sizeof(T), l_size, p_size, &r_size, reuse_ptr); + void* reuse_ptr_void = reuse_ptr; + ret = boost_cont_allocation_command(command, sizeof(T), l_size, p_size, &r_size, reuse_ptr_void); + reuse_ptr = ret.second ? static_cast<T*>(reuse_ptr_void) : 0; } - received_size = r_size/sizeof(T); - return std::pair<pointer, bool>(static_cast<pointer>(ret.first), !!ret.second); + prefer_in_recvd_out_size = r_size/sizeof(T); + return (pointer)ret.first; } }; diff --git a/boost/container/allocator.hpp b/boost/container/allocator.hpp index 14d56452b6..9f757c73e8 100644 --- a/boost/container/allocator.hpp +++ b/boost/container/allocator.hpp @@ -11,7 +11,11 @@ #ifndef BOOST_CONTAINER_ALLOCATOR_HPP #define BOOST_CONTAINER_ALLOCATOR_HPP -#if defined(_MSC_VER) && (_MSC_VER >= 1200) +#ifndef BOOST_CONFIG_HPP +# include <boost/config.hpp> +#endif + +#if defined(BOOST_HAS_PRAGMA_ONCE) # pragma once #endif @@ -25,7 +29,6 @@ #include <boost/static_assert.hpp> #include <cstddef> #include <cassert> -#include <new> namespace boost { namespace container { @@ -156,12 +159,12 @@ class allocator //!Default constructor //!Never throws - allocator() BOOST_CONTAINER_NOEXCEPT + allocator() BOOST_NOEXCEPT_OR_NOTHROW {} //!Constructor from other allocator. //!Never throws - allocator(const allocator &) BOOST_CONTAINER_NOEXCEPT + allocator(const allocator &) BOOST_NOEXCEPT_OR_NOTHROW {} //!Constructor from related allocator. @@ -171,7 +174,7 @@ class allocator #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED , Version, AllocationDisableMask #endif - > &) BOOST_CONTAINER_NOEXCEPT + > &) BOOST_NOEXCEPT_OR_NOTHROW {} //!Allocates memory for an array of count elements. @@ -191,45 +194,43 @@ class allocator //!Deallocates previously allocated memory. //!Never throws - void deallocate(pointer ptr, size_type) BOOST_CONTAINER_NOEXCEPT + void deallocate(pointer ptr, size_type) BOOST_NOEXCEPT_OR_NOTHROW { boost_cont_free(ptr); } //!Returns the maximum number of elements that could be allocated. //!Never throws - size_type max_size() const BOOST_CONTAINER_NOEXCEPT + size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW { return size_type(-1)/sizeof(T); } //!Swaps two allocators, does nothing //!because this allocator is stateless - friend void swap(self_t &, self_t &) BOOST_CONTAINER_NOEXCEPT + friend void swap(self_t &, self_t &) BOOST_NOEXCEPT_OR_NOTHROW {} //!An allocator always compares to true, as memory allocated with one //!instance can be deallocated by another instance - friend bool operator==(const allocator &, const allocator &) BOOST_CONTAINER_NOEXCEPT + friend bool operator==(const allocator &, const allocator &) BOOST_NOEXCEPT_OR_NOTHROW { return true; } //!An allocator always compares to false, as memory allocated with one //!instance can be deallocated by another instance - friend bool operator!=(const allocator &, const allocator &) BOOST_CONTAINER_NOEXCEPT + friend bool operator!=(const allocator &, const allocator &) BOOST_NOEXCEPT_OR_NOTHROW { return false; } //!An advanced function that offers in-place expansion shrink to fit and new allocation //!capabilities. Memory allocated with this function can only be deallocated with deallocate() //!or deallocate_many(). //!This function is available only with Version == 2 - std::pair<pointer, bool> - allocation_command(allocation_type command, + pointer allocation_command(allocation_type command, size_type limit_size, - size_type preferred_size, - size_type &received_size, pointer reuse = pointer()) + size_type &prefer_in_recvd_out_size, + pointer &reuse) { BOOST_STATIC_ASSERT(( Version > 1 )); const allocation_type mask(AllocationDisableMask); command &= ~mask; - std::pair<pointer, bool> ret = - priv_allocation_command(command, limit_size, preferred_size, received_size, reuse); - if(!ret.first && !(command & BOOST_CONTAINER_NOTHROW_ALLOCATION)) + pointer ret = this->priv_allocation_command(command, limit_size, prefer_in_recvd_out_size, reuse); + if(!ret && !(command & BOOST_CONTAINER_NOTHROW_ALLOCATION)) boost::container::throw_bad_alloc(); return ret; } @@ -239,7 +240,7 @@ class allocator //!Memory must not have been allocated with //!allocate_one or allocate_individual. //!This function is available only with Version == 2 - size_type size(pointer p) const BOOST_CONTAINER_NOEXCEPT + size_type size(pointer p) const BOOST_NOEXCEPT_OR_NOTHROW { BOOST_STATIC_ASSERT(( Version > 1 )); return boost_cont_size(p); @@ -268,7 +269,7 @@ class allocator //!You should never use deallocate_one to deallocate memory allocated //!with other functions different from allocate_one() or allocate_individual. //Never throws - void deallocate_one(pointer p) BOOST_CONTAINER_NOEXCEPT + void deallocate_one(pointer p) BOOST_NOEXCEPT_OR_NOTHROW { BOOST_STATIC_ASSERT(( Version > 1 )); return this->deallocate(p, 1); @@ -276,7 +277,7 @@ class allocator //!Deallocates memory allocated with allocate_one() or allocate_individual(). //!This function is available only with Version == 2 - void deallocate_individual(multiallocation_chain &chain) BOOST_CONTAINER_NOEXCEPT + void deallocate_individual(multiallocation_chain &chain) BOOST_NOEXCEPT_OR_NOTHROW { BOOST_STATIC_ASSERT(( Version > 1 )); return this->deallocate_many(chain); @@ -326,7 +327,7 @@ class allocator //!Deallocates several elements allocated by //!allocate_many(), allocate(), or allocation_command(). //!This function is available only with Version == 2 - void deallocate_many(multiallocation_chain &chain) BOOST_CONTAINER_NOEXCEPT + void deallocate_many(multiallocation_chain &chain) BOOST_NOEXCEPT_OR_NOTHROW { BOOST_STATIC_ASSERT(( Version > 1 )); boost_cont_memchain ch; @@ -339,22 +340,26 @@ class allocator private: - std::pair<pointer, bool> priv_allocation_command - (allocation_type command, std::size_t limit_size - ,std::size_t preferred_size,std::size_t &received_size, void *reuse_ptr) + pointer priv_allocation_command + (allocation_type command, std::size_t limit_size + ,size_type &prefer_in_recvd_out_size + ,pointer &reuse_ptr) { + std::size_t const preferred_size = prefer_in_recvd_out_size; boost_cont_command_ret_t ret = {0 , 0}; if((limit_size > this->max_size()) | (preferred_size > this->max_size())){ - return std::pair<pointer, bool>(pointer(), false); + return pointer(); } std::size_t l_size = limit_size*sizeof(T); std::size_t p_size = preferred_size*sizeof(T); std::size_t r_size; { - ret = boost_cont_allocation_command(command, sizeof(T), l_size, p_size, &r_size, reuse_ptr); + void* reuse_ptr_void = reuse_ptr; + ret = boost_cont_allocation_command(command, sizeof(T), l_size, p_size, &r_size, reuse_ptr_void); + reuse_ptr = ret.second ? static_cast<T*>(reuse_ptr_void) : 0; } - received_size = r_size/sizeof(T); - return std::pair<pointer, bool>(static_cast<pointer>(ret.first), !!ret.second); + prefer_in_recvd_out_size = r_size/sizeof(T); + return (pointer)ret.first; } }; diff --git a/boost/container/allocator_traits.hpp b/boost/container/allocator_traits.hpp index a85831f984..cdaf2eacf0 100644 --- a/boost/container/allocator_traits.hpp +++ b/boost/container/allocator_traits.hpp @@ -13,43 +13,82 @@ // See http://www.boost.org/libs/container for documentation. // ////////////////////////////////////////////////////////////////////////////// - #ifndef BOOST_CONTAINER_ALLOCATOR_ALLOCATOR_TRAITS_HPP #define BOOST_CONTAINER_ALLOCATOR_ALLOCATOR_TRAITS_HPP -#if defined(_MSC_VER) +#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> + +// container #include <boost/container/container_fwd.hpp> -#include <boost/intrusive/pointer_traits.hpp> -#include <boost/intrusive/detail/memory_util.hpp> -#include <boost/container/detail/memory_util.hpp> #include <boost/container/detail/mpl.hpp> +#include <boost/container/detail/type_traits.hpp> //is_empty #include <boost/container/detail/placement_new.hpp> +#ifndef BOOST_CONTAINER_DETAIL_STD_FWD_HPP +#include <boost/container/detail/std_fwd.hpp> +#endif +// intrusive +#include <boost/intrusive/pointer_traits.hpp> +#include <boost/intrusive/detail/mpl.hpp> +// move #include <boost/move/utility_core.hpp> - +// move/detail #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) -#include <boost/container/detail/preprocessor.hpp> +#include <boost/move/detail/fwd_macros.hpp> #endif +// other boost +#include <boost/static_assert.hpp> + +#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED +#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME allocate +#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace container_detail { +#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}} +#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 2 +#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 2 +#include <boost/intrusive/detail/has_member_function_callable_with.hpp> + +#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME destroy +#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace container_detail { +#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}} +#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 1 +#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 1 +#include <boost/intrusive/detail/has_member_function_callable_with.hpp> + +#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME construct +#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace container_detail { +#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}} +#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 1 +#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 9 +#include <boost/intrusive/detail/has_member_function_callable_with.hpp> +#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED namespace boost { namespace container { + +#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED + namespace allocator_traits_detail { -} +BOOST_INTRUSIVE_HAS_STATIC_MEMBER_FUNC_SIGNATURE(has_max_size, max_size) +BOOST_INTRUSIVE_HAS_STATIC_MEMBER_FUNC_SIGNATURE(has_select_on_container_copy_construction, select_on_container_copy_construction) -#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED +} //namespace allocator_traits_detail { namespace container_detail { //workaround needed for C++03 compilers with no construct() //supporting rvalue references -template<class A> +template<class Allocator> struct is_std_allocator { static const bool value = false; }; @@ -57,56 +96,77 @@ template<class T> struct is_std_allocator< std::allocator<T> > { static const bool value = true; }; +BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(pointer) +BOOST_INTRUSIVE_INSTANTIATE_EVAL_DEFAULT_TYPE_TMPLT(const_pointer) +BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(reference) +BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(const_reference) +BOOST_INTRUSIVE_INSTANTIATE_EVAL_DEFAULT_TYPE_TMPLT(void_pointer) +BOOST_INTRUSIVE_INSTANTIATE_EVAL_DEFAULT_TYPE_TMPLT(const_void_pointer) +BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(size_type) +BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(propagate_on_container_copy_assignment) +BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(propagate_on_container_move_assignment) +BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(propagate_on_container_swap) +BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(is_always_equal) +BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(difference_type) +BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(is_partially_propagable) + } //namespace container_detail { #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED //! The class template allocator_traits supplies a uniform interface to all allocator types. //! This class is a C++03-compatible implementation of std::allocator_traits -template <typename Alloc> +template <typename Allocator> struct allocator_traits { //allocator_type - typedef Alloc allocator_type; + typedef Allocator allocator_type; //value_type - typedef typename Alloc::value_type value_type; + typedef typename allocator_type::value_type value_type; #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) - //! Alloc::pointer if such a type exists; otherwise, value_type* + //! Allocator::pointer if such a type exists; otherwise, value_type* //! typedef unspecified pointer; - //! Alloc::const_pointer if such a type exists ; otherwise, pointer_traits<pointer>::rebind<const + //! Allocator::const_pointer if such a type exists ; otherwise, pointer_traits<pointer>::rebind<const //! typedef see_documentation const_pointer; //! Non-standard extension - //! Alloc::reference if such a type exists; otherwise, value_type& + //! Allocator::reference if such a type exists; otherwise, value_type& typedef see_documentation reference; //! Non-standard extension - //! Alloc::const_reference if such a type exists ; otherwise, const value_type& + //! Allocator::const_reference if such a type exists ; otherwise, const value_type& typedef see_documentation const_reference; - //! Alloc::void_pointer if such a type exists ; otherwise, pointer_traits<pointer>::rebind<void>. + //! Allocator::void_pointer if such a type exists ; otherwise, pointer_traits<pointer>::rebind<void>. //! typedef see_documentation void_pointer; - //! Alloc::const_void_pointer if such a type exists ; otherwis e, pointer_traits<pointer>::rebind<const + //! Allocator::const_void_pointer if such a type exists ; otherwis e, pointer_traits<pointer>::rebind<const //! typedef see_documentation const_void_pointer; - //! Alloc::difference_type if such a type exists ; otherwise, pointer_traits<pointer>::difference_type. + //! Allocator::difference_type if such a type exists ; otherwise, pointer_traits<pointer>::difference_type. //! typedef see_documentation difference_type; - //! Alloc::size_type if such a type exists ; otherwise, make_unsigned<difference_type>::type + //! Allocator::size_type if such a type exists ; otherwise, make_unsigned<difference_type>::type //! typedef see_documentation size_type; - //! Alloc::propagate_on_container_copy_assignment if such a type exists, otherwise an integral_constant - //! type with internal constant static member <code>value</code> == false. + //! Allocator::propagate_on_container_copy_assignment if such a type exists, otherwise a type + //! with an internal constant static boolean member <code>value</code> == false. typedef see_documentation propagate_on_container_copy_assignment; - //! Alloc::propagate_on_container_move_assignment if such a type exists, otherwise an integral_constant - //! type with internal constant static member <code>value</code> == false. + //! Allocator::propagate_on_container_move_assignment if such a type exists, otherwise a type + //! with an internal constant static boolean member <code>value</code> == false. typedef see_documentation propagate_on_container_move_assignment; - //! Alloc::propagate_on_container_swap if such a type exists, otherwise an integral_constant - //! type with internal constant static member <code>value</code> == false. + //! Allocator::propagate_on_container_swap if such a type exists, otherwise a type + //! with an internal constant static boolean member <code>value</code> == false. typedef see_documentation propagate_on_container_swap; - //! Defines an allocator: Alloc::rebind<T>::other if such a type exists; otherwise, Alloc<T, Args> - //! if Alloc is a class template instantiation of the form Alloc<U, Args>, where Args is zero or + //! Allocator::is_always_equal if such a type exists, otherwise a type + //! with an internal constant static boolean member <code>value</code> == is_empty<Allocator>::value + typedef see_documentation is_always_equal; + //! Allocator::is_partially_propagable if such a type exists, otherwise a type + //! with an internal constant static boolean member <code>value</code> == false + //! <b>Note</b>: Non-standard extension used to implement `small_vector_allocator`. + typedef see_documentation is_partially_propagable; + //! Defines an allocator: Allocator::rebind<T>::other if such a type exists; otherwise, Allocator<T, Args> + //! if Allocator is a class template instantiation of the form Allocator<U, Args>, where Args is zero or //! more type arguments ; otherwise, the instantiation of rebind_alloc is ill-formed. //! //! In C++03 compilers <code>rebind_alloc</code> is a struct derived from an allocator @@ -119,114 +179,121 @@ struct allocator_traits template <class T> using rebind_traits = allocator_traits<rebind_alloc<T> >; //! Non-standard extension: Portable allocator rebind for C++03 and C++11 compilers. - //! <code>type</code> is an allocator related to Alloc deduced deduced by rules explained in <code>rebind_alloc</code>. + //! <code>type</code> is an allocator related to Allocator deduced deduced by rules explained in <code>rebind_alloc</code>. template <class T> struct portable_rebind_alloc { typedef see_documentation type; }; #else //pointer - typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc, + typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Allocator, pointer, value_type*) pointer; //const_pointer - typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_EVAL_DEFAULT(boost::container::container_detail::, Alloc, + typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_EVAL_DEFAULT(boost::container::container_detail::, Allocator, const_pointer, typename boost::intrusive::pointer_traits<pointer>::template rebind_pointer<const value_type>) const_pointer; //reference - typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc, + typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Allocator, reference, typename container_detail::unvoid<value_type>::type&) reference; //const_reference - typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc, + typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Allocator, const_reference, const typename container_detail::unvoid<value_type>::type&) const_reference; //void_pointer - typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_EVAL_DEFAULT(boost::container::container_detail::, Alloc, + typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_EVAL_DEFAULT(boost::container::container_detail::, Allocator, void_pointer, typename boost::intrusive::pointer_traits<pointer>::template rebind_pointer<void>) void_pointer; //const_void_pointer - typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_EVAL_DEFAULT(boost::container::container_detail::, Alloc, + typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_EVAL_DEFAULT(boost::container::container_detail::, Allocator, const_void_pointer, typename boost::intrusive::pointer_traits<pointer>::template rebind_pointer<const void>) const_void_pointer; //difference_type - typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc, + typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Allocator, difference_type, std::ptrdiff_t) difference_type; //size_type - typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc, + typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Allocator, size_type, std::size_t) size_type; //propagate_on_container_copy_assignment - typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc, + typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Allocator, propagate_on_container_copy_assignment, container_detail::false_type) propagate_on_container_copy_assignment; //propagate_on_container_move_assignment - typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc, + typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Allocator, propagate_on_container_move_assignment, container_detail::false_type) propagate_on_container_move_assignment; //propagate_on_container_swap - typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc, + typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Allocator, propagate_on_container_swap, container_detail::false_type) propagate_on_container_swap; - + //is_always_equal + typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Allocator, + is_always_equal, container_detail::is_empty<Allocator>) + is_always_equal; + //is_partially_propagable + typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Allocator, + is_partially_propagable, container_detail::false_type) + is_partially_propagable; + + //rebind_alloc & rebind_traits #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) //C++11 - template <typename T> using rebind_alloc = typename boost::intrusive::pointer_rebind<Alloc, T>::type; + template <typename T> using rebind_alloc = typename boost::intrusive::pointer_rebind<Allocator, T>::type; template <typename T> using rebind_traits = allocator_traits< rebind_alloc<T> >; #else // #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) //Some workaround for C++03 or C++11 compilers with no template aliases template <typename T> - struct rebind_alloc : boost::intrusive::pointer_rebind<Alloc,T>::type + struct rebind_alloc : boost::intrusive::pointer_rebind<Allocator,T>::type { - typedef typename boost::intrusive::pointer_rebind<Alloc,T>::type Base; + typedef typename boost::intrusive::pointer_rebind<Allocator,T>::type Base; #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - template <typename... Args> - rebind_alloc(BOOST_FWD_REF(Args)... args) - : Base(boost::forward<Args>(args)...) - {} + template <typename... Args> + rebind_alloc(BOOST_FWD_REF(Args)... args) : Base(boost::forward<Args>(args)...) {} #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - #define BOOST_PP_LOCAL_MACRO(n) \ - BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ - rebind_alloc(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ - : Base(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)) \ - {} \ - // - #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) - #include BOOST_PP_LOCAL_ITERATE() + #define BOOST_CONTAINER_ALLOCATOR_TRAITS_REBIND_ALLOC(N) \ + BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N\ + explicit rebind_alloc(BOOST_MOVE_UREF##N) : Base(BOOST_MOVE_FWD##N){}\ + // + BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_ALLOCATOR_TRAITS_REBIND_ALLOC) + #undef BOOST_CONTAINER_ALLOCATOR_TRAITS_REBIND_ALLOC #endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) }; template <typename T> struct rebind_traits - : allocator_traits<typename boost::intrusive::pointer_rebind<Alloc, T>::type> + : allocator_traits<typename boost::intrusive::pointer_rebind<Allocator, T>::type> {}; #endif // #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + + //portable_rebind_alloc template <class T> struct portable_rebind_alloc - { typedef typename boost::intrusive::pointer_rebind<Alloc, T>::type type; }; + { typedef typename boost::intrusive::pointer_rebind<Allocator, T>::type type; }; #endif //BOOST_CONTAINER_DOXYGEN_INVOKED //! <b>Returns</b>: <code>a.allocate(n)</code> //! - static pointer allocate(Alloc &a, size_type n) + static pointer allocate(Allocator &a, size_type n) { return a.allocate(n); } //! <b>Returns</b>: <code>a.deallocate(p, n)</code> //! //! <b>Throws</b>: Nothing - static void deallocate(Alloc &a, pointer p, size_type n) + static void deallocate(Allocator &a, pointer p, size_type n) { a.deallocate(p, n); } //! <b>Effects</b>: calls <code>a.allocate(n, p)</code> if that call is well-formed; //! otherwise, invokes <code>a.allocate(n)</code> - static pointer allocate(Alloc &a, size_type n, const_void_pointer p) + static pointer allocate(Allocator &a, size_type n, const_void_pointer p) { const bool value = boost::container::container_detail:: has_member_function_callable_with_allocate - <Alloc, const size_type, const const_void_pointer>::value; + <Allocator, const size_type, const const_void_pointer>::value; container_detail::bool_<value> flag; return allocator_traits::priv_allocate(flag, a, n, p); } @@ -234,46 +301,35 @@ struct allocator_traits //! <b>Effects</b>: calls <code>a.destroy(p)</code> if that call is well-formed; //! otherwise, invokes <code>p->~T()</code>. template<class T> - static void destroy(Alloc &a, T*p) BOOST_CONTAINER_NOEXCEPT + static void destroy(Allocator &a, T*p) BOOST_NOEXCEPT_OR_NOTHROW { typedef T* destroy_pointer; const bool value = boost::container::container_detail:: has_member_function_callable_with_destroy - <Alloc, const destroy_pointer>::value; + <Allocator, const destroy_pointer>::value; container_detail::bool_<value> flag; allocator_traits::priv_destroy(flag, a, p); } //! <b>Returns</b>: <code>a.max_size()</code> if that expression is well-formed; otherwise, //! <code>numeric_limits<size_type>::max()</code>. - static size_type max_size(const Alloc &a) BOOST_CONTAINER_NOEXCEPT + static size_type max_size(const Allocator &a) BOOST_NOEXCEPT_OR_NOTHROW { - const bool value = boost::container::container_detail:: - has_member_function_callable_with_max_size - <const Alloc>::value; + const bool value = allocator_traits_detail::has_max_size<Allocator, size_type (Allocator::*)() const>::value; container_detail::bool_<value> flag; return allocator_traits::priv_max_size(flag, a); } //! <b>Returns</b>: <code>a.select_on_container_copy_construction()</code> if that expression is well-formed; //! otherwise, a. - static - #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) - typename container_detail::if_c - < boost::container::container_detail:: - has_member_function_callable_with_select_on_container_copy_construction - <const Alloc>::value - , Alloc - , const Alloc & - >::type - #else - Alloc - #endif - select_on_container_copy_construction(const Alloc &a) + static BOOST_CONTAINER_DOC1ST(Allocator, + typename container_detail::if_c + < allocator_traits_detail::has_select_on_container_copy_construction<Allocator BOOST_MOVE_I Allocator (Allocator::*)() const>::value + BOOST_MOVE_I Allocator BOOST_MOVE_I const Allocator & >::type) + select_on_container_copy_construction(const Allocator &a) { - const bool value = boost::container::container_detail:: - has_member_function_callable_with_select_on_container_copy_construction - <const Alloc>::value; + const bool value = allocator_traits_detail::has_select_on_container_copy_construction + <Allocator, Allocator (Allocator::*)() const>::value; container_detail::bool_<value> flag; return allocator_traits::priv_select_on_container_copy_construction(flag, a); } @@ -282,123 +338,149 @@ struct allocator_traits //! <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> template <class T, class ...Args> - static void construct(Alloc & a, T* p, BOOST_FWD_REF(Args)... args) + static void construct(Allocator & a, T* p, BOOST_FWD_REF(Args)... args) { - container_detail::bool_<container_detail::is_std_allocator<Alloc>::value> flag; + container_detail::bool_<container_detail::is_std_allocator<Allocator>::value> flag; allocator_traits::priv_construct(flag, a, p, ::boost::forward<Args>(args)...); } #endif - #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED + + //! <b>Returns</b>: <code>a.storage_is_unpropagable(p)</code> if is_partially_propagable::value is true; otherwise, + //! <code>false</code>. + static bool storage_is_unpropagable(const Allocator &a, pointer p) BOOST_NOEXCEPT_OR_NOTHROW + { + container_detail::bool_<is_partially_propagable::value> flag; + return allocator_traits::priv_storage_is_unpropagable(flag, a, p); + } + + //! <b>Returns</b>: <code>true</code> if <code>is_always_equal::value == true</code>, otherwise, + //! <code>a == b</code>. + static bool equal(const Allocator &a, const Allocator &b) BOOST_NOEXCEPT_OR_NOTHROW + { + container_detail::bool_<is_always_equal::value> flag; + return allocator_traits::priv_equal(flag, a, b); + } + #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) - private: - static pointer priv_allocate(container_detail::true_type, Alloc &a, size_type n, const_void_pointer p) - { return a.allocate(n, p); } + private: + static pointer priv_allocate(container_detail::true_type, Allocator &a, size_type n, const_void_pointer p) + { return a.allocate(n, p); } - static pointer priv_allocate(container_detail::false_type, Alloc &a, size_type n, const_void_pointer) - { return allocator_traits::allocate(a, n); } + static pointer priv_allocate(container_detail::false_type, Allocator &a, size_type n, const_void_pointer) + { return a.allocate(n); } - template<class T> - static void priv_destroy(container_detail::true_type, Alloc &a, T* p) BOOST_CONTAINER_NOEXCEPT - { a.destroy(p); } + template<class T> + static void priv_destroy(container_detail::true_type, Allocator &a, T* p) BOOST_NOEXCEPT_OR_NOTHROW + { a.destroy(p); } - template<class T> - static void priv_destroy(container_detail::false_type, Alloc &, T* p) BOOST_CONTAINER_NOEXCEPT - { p->~T(); (void)p; } + template<class T> + static void priv_destroy(container_detail::false_type, Allocator &, T* p) BOOST_NOEXCEPT_OR_NOTHROW + { p->~T(); (void)p; } - static size_type priv_max_size(container_detail::true_type, const Alloc &a) BOOST_CONTAINER_NOEXCEPT - { return a.max_size(); } + static size_type priv_max_size(container_detail::true_type, const Allocator &a) BOOST_NOEXCEPT_OR_NOTHROW + { return a.max_size(); } - static size_type priv_max_size(container_detail::false_type, const Alloc &) BOOST_CONTAINER_NOEXCEPT - { return size_type(-1); } + static size_type priv_max_size(container_detail::false_type, const Allocator &) BOOST_NOEXCEPT_OR_NOTHROW + { return size_type(-1)/sizeof(value_type); } - static Alloc priv_select_on_container_copy_construction(container_detail::true_type, const Alloc &a) - { return a.select_on_container_copy_construction(); } + static Allocator priv_select_on_container_copy_construction(container_detail::true_type, const Allocator &a) + { return a.select_on_container_copy_construction(); } - static const Alloc &priv_select_on_container_copy_construction(container_detail::false_type, const Alloc &a) BOOST_CONTAINER_NOEXCEPT - { return a; } + static const Allocator &priv_select_on_container_copy_construction(container_detail::false_type, const Allocator &a) BOOST_NOEXCEPT_OR_NOTHROW + { return a; } - #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - template<class T, class ...Args> - static void priv_construct(container_detail::false_type, Alloc &a, T *p, BOOST_FWD_REF(Args) ...args) - { - const bool value = boost::container::container_detail:: - has_member_function_callable_with_construct - < Alloc, T*, Args... >::value; - container_detail::bool_<value> flag; - priv_construct_dispatch2(flag, a, p, ::boost::forward<Args>(args)...); - } - - template<class T, class ...Args> - static void priv_construct(container_detail::true_type, Alloc &a, T *p, BOOST_FWD_REF(Args) ...args) - { - priv_construct_dispatch2(container_detail::false_type(), a, p, ::boost::forward<Args>(args)...); - } - - template<class T, class ...Args> - static void priv_construct_dispatch2(container_detail::true_type, Alloc &a, T *p, BOOST_FWD_REF(Args) ...args) - { a.construct( p, ::boost::forward<Args>(args)...); } - - template<class T, class ...Args> - static void priv_construct_dispatch2(container_detail::false_type, Alloc &, T *p, BOOST_FWD_REF(Args) ...args) - { ::new((void*)p, boost_container_new_t()) T(::boost::forward<Args>(args)...); } - #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - public: - #define BOOST_PP_LOCAL_MACRO(n) \ - template<class T BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) > \ - static void construct(Alloc &a, T *p \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ - { \ - container_detail::bool_ \ - <container_detail::is_std_allocator<Alloc>::value> flag; \ - allocator_traits::priv_construct(flag, a, p \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \ - } \ - // - #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) - #include BOOST_PP_LOCAL_ITERATE() - - private: - #define BOOST_PP_LOCAL_MACRO(n) \ - template<class T BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) > \ - static void priv_construct(container_detail::false_type, Alloc &a, T *p \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST,_)) \ - { \ - const bool value = \ - boost::container::container_detail::has_member_function_callable_with_construct \ - < Alloc, T* BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_FWD_TYPE, _) >::value; \ - container_detail::bool_<value> flag; \ - priv_construct_dispatch2(flag, a, p \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \ - } \ - \ - template<class T BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) > \ - static void priv_construct(container_detail::true_type, Alloc &a, T *p \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST,_)) \ - { \ - priv_construct_dispatch2(container_detail::false_type(), a, p \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \ - } \ - \ - template<class T BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) > \ - static void priv_construct_dispatch2(container_detail::true_type, Alloc &a, T *p \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST,_)) \ - { a.construct( p BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); } \ - \ - template<class T BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) > \ - static void priv_construct_dispatch2(container_detail::false_type, Alloc &, T *p \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _) ) \ - { ::new((void*)p, boost_container_new_t()) T(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); }\ - // - #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) - #include BOOST_PP_LOCAL_ITERATE() - #endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - - template<class T> - static void priv_construct_dispatch2(container_detail::false_type, Alloc &, T *p, ::boost::container::default_init_t) - { ::new((void*)p) T; } - #endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template<class T, class ...Args> + static void priv_construct(container_detail::false_type, Allocator &a, T *p, BOOST_FWD_REF(Args) ...args) + { + const bool value = boost::container::container_detail:: + has_member_function_callable_with_construct + < Allocator, T*, Args... >::value; + container_detail::bool_<value> flag; + (priv_construct_dispatch_next)(flag, a, p, ::boost::forward<Args>(args)...); + } + + template<class T, class ...Args> + static void priv_construct(container_detail::true_type, Allocator &a, T *p, BOOST_FWD_REF(Args) ...args) + { (priv_construct_dispatch_next)(container_detail::false_type(), a, p, ::boost::forward<Args>(args)...); } + + template<class T, class ...Args> + static void priv_construct_dispatch_next(container_detail::true_type, Allocator &a, T *p, BOOST_FWD_REF(Args) ...args) + { a.construct( p, ::boost::forward<Args>(args)...); } + + template<class T, class ...Args> + static void priv_construct_dispatch_next(container_detail::false_type, Allocator &, T *p, BOOST_FWD_REF(Args) ...args) + { ::new((void*)p, boost_container_new_t()) T(::boost::forward<Args>(args)...); } + #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + public: + + #define BOOST_CONTAINER_ALLOCATOR_TRAITS_CONSTRUCT_IMPL(N) \ + template<class T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\ + static void construct(Allocator &a, T *p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ + {\ + container_detail::bool_<container_detail::is_std_allocator<Allocator>::value> flag;\ + (priv_construct)(flag, a, p BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\ + }\ + // + BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_ALLOCATOR_TRAITS_CONSTRUCT_IMPL) + #undef BOOST_CONTAINER_ALLOCATOR_TRAITS_CONSTRUCT_IMPL + + private: + + ////////////////// + // priv_construct + ////////////////// + #define BOOST_CONTAINER_ALLOCATOR_TRAITS_PRIV_CONSTRUCT_IMPL(N) \ + template<class T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\ + static void priv_construct(container_detail::false_type, Allocator &a, T *p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ + {\ + const bool value = boost::container::container_detail::has_member_function_callable_with_construct\ + < Allocator, T* BOOST_MOVE_I##N BOOST_MOVE_FWD_T##N>::value;\ + container_detail::bool_<value> flag;\ + (priv_construct_dispatch_next)(flag, a, p BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\ + }\ + \ + template<class T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\ + static void priv_construct(container_detail::true_type, Allocator &a, T *p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ + { (priv_construct_dispatch_next)(container_detail::false_type(), a, p BOOST_MOVE_I##N BOOST_MOVE_FWD##N); }\ + // + BOOST_MOVE_ITERATE_0TO8(BOOST_CONTAINER_ALLOCATOR_TRAITS_PRIV_CONSTRUCT_IMPL) + #undef BOOST_CONTAINER_ALLOCATOR_TRAITS_PRIV_CONSTRUCT_IMPL + + ///////////////////////////////// + // priv_construct_dispatch_next + ///////////////////////////////// + #define BOOST_CONTAINER_ALLOCATOR_TRAITS_PRIV_CONSTRUCT_DISPATCH_NEXT_IMPL(N) \ + template<class T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\ + static void priv_construct_dispatch_next(container_detail::true_type, Allocator &a, T *p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ + { a.construct( p BOOST_MOVE_I##N BOOST_MOVE_FWD##N ); }\ + \ + template<class T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\ + static void priv_construct_dispatch_next(container_detail::false_type, Allocator &, T *p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ + { ::new((void*)p, boost_container_new_t()) T(BOOST_MOVE_FWD##N); }\ + // + BOOST_MOVE_ITERATE_0TO8(BOOST_CONTAINER_ALLOCATOR_TRAITS_PRIV_CONSTRUCT_DISPATCH_NEXT_IMPL) + #undef BOOST_CONTAINER_ALLOCATOR_TRAITS_PRIV_CONSTRUCT_DISPATCH_NEXT_IMPL + + #endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + + template<class T> + static void priv_construct_dispatch_next(container_detail::false_type, Allocator &, T *p, const ::boost::container::default_init_t&) + { ::new((void*)p) T; } + + static bool priv_storage_is_unpropagable(container_detail::true_type, const Allocator &a, pointer p) + { return a.storage_is_unpropagable(p); } + + static bool priv_storage_is_unpropagable(container_detail::false_type, const Allocator &, pointer) + { return false; } - #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED + static bool priv_equal(container_detail::true_type, const Allocator &, const Allocator &) + { return true; } + + static bool priv_equal(container_detail::false_type, const Allocator &a, const Allocator &b) + { return a == b; } + + #endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) }; } //namespace container { diff --git a/boost/container/container_fwd.hpp b/boost/container/container_fwd.hpp index 20ac77861d..a9b421c2b2 100644 --- a/boost/container/container_fwd.hpp +++ b/boost/container/container_fwd.hpp @@ -11,7 +11,11 @@ #ifndef BOOST_CONTAINER_CONTAINER_FWD_HPP #define BOOST_CONTAINER_CONTAINER_FWD_HPP -#if defined(_MSC_VER) +#ifndef BOOST_CONFIG_HPP +# include <boost/config.hpp> +#endif + +#if defined(BOOST_HAS_PRAGMA_ONCE) # pragma once #endif @@ -80,27 +84,34 @@ enum tree_type_enum #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED +template<class T> +class new_allocator; + template <class T - ,class Allocator = std::allocator<T> > + ,class Allocator = new_allocator<T> > class vector; template <class T - ,class Allocator = std::allocator<T> > + ,class Allocator = new_allocator<T> > class stable_vector; template <class T, std::size_t Capacity> class static_vector; +template < class T, std::size_t N + , class Allocator= new_allocator<T> > +class small_vector; + template <class T - ,class Allocator = std::allocator<T> > + ,class Allocator = new_allocator<T> > class deque; template <class T - ,class Allocator = std::allocator<T> > + ,class Allocator = new_allocator<T> > class list; template <class T - ,class Allocator = std::allocator<T> > + ,class Allocator = new_allocator<T> > class slist; template<tree_type_enum TreeType, bool OptimizeSize> @@ -110,67 +121,67 @@ typedef tree_opt<red_black_tree, true> tree_assoc_defaults; template <class Key ,class Compare = std::less<Key> - ,class Allocator = std::allocator<Key> + ,class Allocator = new_allocator<Key> ,class Options = tree_assoc_defaults > class set; template <class Key ,class Compare = std::less<Key> - ,class Allocator = std::allocator<Key> + ,class Allocator = new_allocator<Key> ,class Options = tree_assoc_defaults > class multiset; template <class Key ,class T ,class Compare = std::less<Key> - ,class Allocator = std::allocator<std::pair<const Key, T> > + ,class Allocator = new_allocator<std::pair<const Key, T> > ,class Options = tree_assoc_defaults > class map; template <class Key ,class T ,class Compare = std::less<Key> - ,class Allocator = std::allocator<std::pair<const Key, T> > + ,class Allocator = new_allocator<std::pair<const Key, T> > ,class Options = tree_assoc_defaults > class multimap; template <class Key ,class Compare = std::less<Key> - ,class Allocator = std::allocator<Key> > + ,class Allocator = new_allocator<Key> > class flat_set; template <class Key ,class Compare = std::less<Key> - ,class Allocator = std::allocator<Key> > + ,class Allocator = new_allocator<Key> > class flat_multiset; template <class Key ,class T ,class Compare = std::less<Key> - ,class Allocator = std::allocator<std::pair<Key, T> > > + ,class Allocator = new_allocator<std::pair<Key, T> > > class flat_map; template <class Key ,class T ,class Compare = std::less<Key> - ,class Allocator = std::allocator<std::pair<Key, T> > > + ,class Allocator = new_allocator<std::pair<Key, T> > > class flat_multimap; template <class CharT ,class Traits = std::char_traits<CharT> - ,class Allocator = std::allocator<CharT> > + ,class Allocator = new_allocator<CharT> > class basic_string; typedef basic_string <char ,std::char_traits<char> - ,std::allocator<char> > + ,new_allocator<char> > string; typedef basic_string <wchar_t ,std::char_traits<wchar_t> - ,std::allocator<wchar_t> > + ,new_allocator<wchar_t> > wstring; static const std::size_t ADP_nodes_per_block = 256u; diff --git a/boost/container/deque.hpp b/boost/container/deque.hpp index d8a546c86f..eb372a430a 100644 --- a/boost/container/deque.hpp +++ b/boost/container/deque.hpp @@ -7,42 +7,51 @@ // See http://www.boost.org/libs/container for documentation. // ////////////////////////////////////////////////////////////////////////////// - #ifndef BOOST_CONTAINER_DEQUE_HPP #define BOOST_CONTAINER_DEQUE_HPP -#if defined(_MSC_VER) +#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> - -#include <boost/container/detail/utilities.hpp> -#include <boost/container/detail/iterators.hpp> -#include <boost/container/detail/algorithms.hpp> -#include <boost/container/detail/mpl.hpp> +// container #include <boost/container/allocator_traits.hpp> #include <boost/container/container_fwd.hpp> +#include <boost/container/new_allocator.hpp> //new_allocator #include <boost/container/throw_exception.hpp> -#include <cstddef> -#include <iterator> -#include <boost/assert.hpp> -#include <memory> -#include <algorithm> -#include <boost/core/no_exceptions_support.hpp> -#include <boost/type_traits/has_trivial_destructor.hpp> -#include <boost/type_traits/has_trivial_copy.hpp> -#include <boost/type_traits/has_trivial_assign.hpp> -#include <boost/type_traits/has_nothrow_copy.hpp> -#include <boost/type_traits/has_nothrow_assign.hpp> -#include <boost/move/utility_core.hpp> +// container/detail +#include <boost/container/detail/advanced_insert_int.hpp> +#include <boost/container/detail/algorithm.hpp> //algo_equal(), algo_lexicographical_compare +#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/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/container/detail/type_traits.hpp> +// move +#include <boost/move/adl_move_swap.hpp> #include <boost/move/iterator.hpp> -#include <boost/move/algorithm.hpp> -#include <boost/move/detail/move_helpers.hpp> #include <boost/move/traits.hpp> -#include <boost/container/detail/advanced_insert_int.hpp> +#include <boost/move/utility_core.hpp> +// move/detail +#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +#include <boost/move/detail/fwd_macros.hpp> +#endif +#include <boost/move/detail/move_helpers.hpp> +// other +#include <boost/assert.hpp> #include <boost/core/no_exceptions_support.hpp> +// std +#include <cstddef> #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) #include <initializer_list> @@ -59,13 +68,8 @@ template <class T> struct deque_value_traits { typedef T value_type; - static const bool trivial_dctr = boost::has_trivial_destructor<value_type>::value; + static const bool trivial_dctr = container_detail::is_trivially_destructible<value_type>::value; static const bool trivial_dctr_after_move = ::boost::has_trivial_destructor_after_move<value_type>::value; - static const bool trivial_copy = has_trivial_copy<value_type>::value; - static const bool nothrow_copy = has_nothrow_copy<value_type>::value; - static const bool trivial_assign = has_trivial_assign<value_type>::value; - //static const bool nothrow_assign = has_nothrow_assign<value_type>::value; - static const bool nothrow_assign = false; }; // Note: this function is simply a kludge to work around several compilers' @@ -102,7 +106,7 @@ namespace container_detail { // [map, map + map_size) is a valid, non-empty range. // [start.node, finish.node] is a valid range contained within // [map, map + map_size). -// Allocator pointer in the range [map, map + map_size) points to an allocated node +// A pointer in the range [map, map + map_size) points to an allocated node // if and only if the pointer is in the range [start.node, finish.node]. template<class Pointer, bool IsConst> class deque_iterator @@ -142,34 +146,34 @@ class deque_iterator Pointer get_last() const { return m_last; } index_pointer get_node() const { return m_node; } - deque_iterator(val_alloc_ptr x, index_pointer y) BOOST_CONTAINER_NOEXCEPT + deque_iterator(val_alloc_ptr x, index_pointer y) BOOST_NOEXCEPT_OR_NOTHROW : m_cur(x), m_first(*y), m_last(*y + s_buffer_size()), m_node(y) {} - deque_iterator() BOOST_CONTAINER_NOEXCEPT + deque_iterator() BOOST_NOEXCEPT_OR_NOTHROW : m_cur(), m_first(), m_last(), m_node() //Value initialization to achieve "null iterators" (N3644) {} - deque_iterator(deque_iterator<Pointer, false> const& x) BOOST_CONTAINER_NOEXCEPT + deque_iterator(deque_iterator<Pointer, false> const& x) BOOST_NOEXCEPT_OR_NOTHROW : m_cur(x.get_cur()), m_first(x.get_first()), m_last(x.get_last()), m_node(x.get_node()) {} - deque_iterator(Pointer cur, Pointer first, Pointer last, index_pointer node) BOOST_CONTAINER_NOEXCEPT + deque_iterator(Pointer cur, Pointer first, Pointer last, index_pointer node) BOOST_NOEXCEPT_OR_NOTHROW : m_cur(cur), m_first(first), m_last(last), m_node(node) {} - deque_iterator<Pointer, false> unconst() const BOOST_CONTAINER_NOEXCEPT + deque_iterator<Pointer, false> unconst() const BOOST_NOEXCEPT_OR_NOTHROW { return deque_iterator<Pointer, false>(this->get_cur(), this->get_first(), this->get_last(), this->get_node()); } - reference operator*() const BOOST_CONTAINER_NOEXCEPT + reference operator*() const BOOST_NOEXCEPT_OR_NOTHROW { return *this->m_cur; } - pointer operator->() const BOOST_CONTAINER_NOEXCEPT + pointer operator->() const BOOST_NOEXCEPT_OR_NOTHROW { return this->m_cur; } - difference_type operator-(const deque_iterator& x) const BOOST_CONTAINER_NOEXCEPT + difference_type operator-(const deque_iterator& x) const BOOST_NOEXCEPT_OR_NOTHROW { if(!this->m_cur && !x.m_cur){ return 0; @@ -178,7 +182,7 @@ class deque_iterator (this->m_cur - this->m_first) + (x.m_last - x.m_cur); } - deque_iterator& operator++() BOOST_CONTAINER_NOEXCEPT + deque_iterator& operator++() BOOST_NOEXCEPT_OR_NOTHROW { ++this->m_cur; if (this->m_cur == this->m_last) { @@ -188,14 +192,14 @@ class deque_iterator return *this; } - deque_iterator operator++(int) BOOST_CONTAINER_NOEXCEPT + deque_iterator operator++(int) BOOST_NOEXCEPT_OR_NOTHROW { deque_iterator tmp(*this); ++*this; return tmp; } - deque_iterator& operator--() BOOST_CONTAINER_NOEXCEPT + deque_iterator& operator--() BOOST_NOEXCEPT_OR_NOTHROW { if (this->m_cur == this->m_first) { this->priv_set_node(this->m_node - 1); @@ -205,14 +209,14 @@ class deque_iterator return *this; } - deque_iterator operator--(int) BOOST_CONTAINER_NOEXCEPT + deque_iterator operator--(int) BOOST_NOEXCEPT_OR_NOTHROW { deque_iterator tmp(*this); --*this; return tmp; } - deque_iterator& operator+=(difference_type n) BOOST_CONTAINER_NOEXCEPT + deque_iterator& operator+=(difference_type n) BOOST_NOEXCEPT_OR_NOTHROW { difference_type offset = n + (this->m_cur - this->m_first); if (offset >= 0 && offset < difference_type(this->s_buffer_size())) @@ -228,44 +232,44 @@ class deque_iterator return *this; } - deque_iterator operator+(difference_type n) const BOOST_CONTAINER_NOEXCEPT + deque_iterator operator+(difference_type n) const BOOST_NOEXCEPT_OR_NOTHROW { deque_iterator tmp(*this); return tmp += n; } - deque_iterator& operator-=(difference_type n) BOOST_CONTAINER_NOEXCEPT + deque_iterator& operator-=(difference_type n) BOOST_NOEXCEPT_OR_NOTHROW { return *this += -n; } - deque_iterator operator-(difference_type n) const BOOST_CONTAINER_NOEXCEPT + deque_iterator operator-(difference_type n) const BOOST_NOEXCEPT_OR_NOTHROW { deque_iterator tmp(*this); return tmp -= n; } - reference operator[](difference_type n) const BOOST_CONTAINER_NOEXCEPT + reference operator[](difference_type n) const BOOST_NOEXCEPT_OR_NOTHROW { return *(*this + n); } - friend bool operator==(const deque_iterator& l, const deque_iterator& r) BOOST_CONTAINER_NOEXCEPT + friend bool operator==(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW { return l.m_cur == r.m_cur; } - friend bool operator!=(const deque_iterator& l, const deque_iterator& r) BOOST_CONTAINER_NOEXCEPT + friend bool operator!=(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW { return l.m_cur != r.m_cur; } - friend bool operator<(const deque_iterator& l, const deque_iterator& r) BOOST_CONTAINER_NOEXCEPT + friend bool operator<(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW { return (l.m_node == r.m_node) ? (l.m_cur < r.m_cur) : (l.m_node < r.m_node); } - friend bool operator>(const deque_iterator& l, const deque_iterator& r) BOOST_CONTAINER_NOEXCEPT + friend bool operator>(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW { return r < l; } - friend bool operator<=(const deque_iterator& l, const deque_iterator& r) BOOST_CONTAINER_NOEXCEPT + friend bool operator<=(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW { return !(r < l); } - friend bool operator>=(const deque_iterator& l, const deque_iterator& r) BOOST_CONTAINER_NOEXCEPT + friend bool operator>=(const deque_iterator& l, const deque_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW { return !(l < r); } - void priv_set_node(index_pointer new_node) BOOST_CONTAINER_NOEXCEPT + void priv_set_node(index_pointer new_node) BOOST_NOEXCEPT_OR_NOTHROW { this->m_node = new_node; this->m_first = *new_node; this->m_last = this->m_first + this->s_buffer_size(); } - friend deque_iterator operator+(difference_type n, deque_iterator x) BOOST_CONTAINER_NOEXCEPT + friend deque_iterator operator+(difference_type n, deque_iterator x) BOOST_NOEXCEPT_OR_NOTHROW { return x += n; } }; @@ -304,19 +308,19 @@ class deque_base typedef deque_value_traits<val_alloc_val> traits_t; typedef ptr_alloc_t map_allocator_type; - static size_type s_buffer_size() BOOST_CONTAINER_NOEXCEPT + static size_type s_buffer_size() BOOST_NOEXCEPT_OR_NOTHROW { return deque_buf_size<val_alloc_val>::value; } val_alloc_ptr priv_allocate_node() { return this->alloc().allocate(s_buffer_size()); } - void priv_deallocate_node(val_alloc_ptr p) BOOST_CONTAINER_NOEXCEPT + void priv_deallocate_node(val_alloc_ptr p) BOOST_NOEXCEPT_OR_NOTHROW { this->alloc().deallocate(p, s_buffer_size()); } ptr_alloc_ptr priv_allocate_map(size_type n) { return this->ptr_alloc().allocate(n); } - void priv_deallocate_map(ptr_alloc_ptr p, size_type n) BOOST_CONTAINER_NOEXCEPT + void priv_deallocate_map(ptr_alloc_ptr p, size_type n) BOOST_NOEXCEPT_OR_NOTHROW { this->ptr_alloc().deallocate(p, n); } typedef container_detail::deque_iterator<val_alloc_ptr, false> iterator; @@ -352,12 +356,12 @@ class deque_base protected: - void swap_members(deque_base &x) BOOST_CONTAINER_NOEXCEPT + void swap_members(deque_base &x) BOOST_NOEXCEPT_OR_NOTHROW { - std::swap(this->members_.m_start, x.members_.m_start); - std::swap(this->members_.m_finish, x.members_.m_finish); - std::swap(this->members_.m_map, x.members_.m_map); - std::swap(this->members_.m_map_size, x.members_.m_map_size); + ::boost::adl_move_swap(this->members_.m_start, x.members_.m_start); + ::boost::adl_move_swap(this->members_.m_finish, x.members_.m_finish); + ::boost::adl_move_swap(this->members_.m_map, x.members_.m_map); + ::boost::adl_move_swap(this->members_.m_map_size, x.members_.m_map_size); } void priv_initialize_map(size_type num_elements) @@ -392,9 +396,9 @@ class deque_base void priv_create_nodes(ptr_alloc_ptr nstart, ptr_alloc_ptr nfinish) { - ptr_alloc_ptr cur; + ptr_alloc_ptr cur = nstart; BOOST_TRY { - for (cur = nstart; cur < nfinish; ++cur) + for (; cur < nfinish; ++cur) *cur = this->priv_allocate_node(); } BOOST_CATCH(...){ @@ -404,13 +408,13 @@ class deque_base BOOST_CATCH_END } - void priv_destroy_nodes(ptr_alloc_ptr nstart, ptr_alloc_ptr nfinish) BOOST_CONTAINER_NOEXCEPT + void priv_destroy_nodes(ptr_alloc_ptr nstart, ptr_alloc_ptr nfinish) BOOST_NOEXCEPT_OR_NOTHROW { for (ptr_alloc_ptr n = nstart; n < nfinish; ++n) this->priv_deallocate_node(*n); } - void priv_clear_map() BOOST_CONTAINER_NOEXCEPT + void priv_clear_map() BOOST_NOEXCEPT_OR_NOTHROW { if (this->members_.m_map) { this->priv_destroy_nodes(this->members_.m_start.m_node, this->members_.m_finish.m_node + 1); @@ -455,16 +459,16 @@ class deque_base iterator m_finish; } members_; - ptr_alloc_t &ptr_alloc() BOOST_CONTAINER_NOEXCEPT + ptr_alloc_t &ptr_alloc() BOOST_NOEXCEPT_OR_NOTHROW { return members_; } - const ptr_alloc_t &ptr_alloc() const BOOST_CONTAINER_NOEXCEPT + const ptr_alloc_t &ptr_alloc() const BOOST_NOEXCEPT_OR_NOTHROW { return members_; } - allocator_type &alloc() BOOST_CONTAINER_NOEXCEPT + allocator_type &alloc() BOOST_NOEXCEPT_OR_NOTHROW { return members_; } - const allocator_type &alloc() const BOOST_CONTAINER_NOEXCEPT + const allocator_type &alloc() const BOOST_NOEXCEPT_OR_NOTHROW { return members_; } }; #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED @@ -475,7 +479,7 @@ class deque_base //! //! \tparam T The type of object that is stored in the deque //! \tparam Allocator The allocator used for all internal memory management -template <class T, class Allocator = std::allocator<T> > +template <class T, class Allocator = new_allocator<T> > #else template <class T, class Allocator> #endif @@ -505,8 +509,8 @@ class deque : protected deque_base<Allocator> typedef BOOST_CONTAINER_IMPDEF(allocator_type) stored_allocator_type; typedef BOOST_CONTAINER_IMPDEF(typename Base::iterator) iterator; typedef BOOST_CONTAINER_IMPDEF(typename Base::const_iterator) const_iterator; - typedef BOOST_CONTAINER_IMPDEF(container_detail::reverse_iterator<iterator>) reverse_iterator; - typedef BOOST_CONTAINER_IMPDEF(container_detail::reverse_iterator<const_iterator>) const_reverse_iterator; + typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<iterator>) reverse_iterator; + typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<const_iterator>) const_reverse_iterator; #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED @@ -540,11 +544,11 @@ class deque : protected deque_base<Allocator> //! <b>Throws</b>: Nothing //! //! <b>Complexity</b>: Constant. - explicit deque(const allocator_type& a) BOOST_CONTAINER_NOEXCEPT + explicit deque(const allocator_type& a) BOOST_NOEXCEPT_OR_NOTHROW : Base(a) {} - //! <b>Effects</b>: Constructs a deque that will use a copy of allocator a + //! <b>Effects</b>: Constructs a deque //! and inserts n value initialized values. //! //! <b>Throws</b>: If allocator_type's default constructor @@ -559,7 +563,7 @@ class deque : protected deque_base<Allocator> //deque_base will deallocate in case of exception... } - //! <b>Effects</b>: Constructs a deque that will use a copy of allocator a + //! <b>Effects</b>: Constructs a deque //! and inserts n default initialized values. //! //! <b>Throws</b>: If allocator_type's default constructor @@ -577,6 +581,38 @@ class deque : protected deque_base<Allocator> } //! <b>Effects</b>: Constructs a deque that will use a copy of allocator a + //! and inserts n value initialized values. + //! + //! <b>Throws</b>: If allocator_type's default constructor + //! throws or T's value initialization throws. + //! + //! <b>Complexity</b>: Linear to n. + explicit deque(size_type n, const allocator_type &a) + : Base(n, a) + { + container_detail::insert_value_initialized_n_proxy<Allocator, iterator> proxy; + proxy.uninitialized_copy_n_and_update(this->alloc(), this->begin(), n); + //deque_base will deallocate in case of exception... + } + + //! <b>Effects</b>: Constructs a deque that will use a copy of allocator a + //! and inserts n default initialized values. + //! + //! <b>Throws</b>: If allocator_type's default constructor + //! throws or T's default initialization or copy constructor throws. + //! + //! <b>Complexity</b>: Linear to n. + //! + //! <b>Note</b>: Non-standard extension + deque(size_type n, default_init_t, const allocator_type &a) + : Base(n, a) + { + container_detail::insert_default_initialized_n_proxy<Allocator, iterator> proxy; + proxy.uninitialized_copy_n_and_update(this->alloc(), this->begin(), n); + //deque_base will deallocate in case of exception... + } + + //! <b>Effects</b>: Constructs a deque that will use a copy of allocator a //! and inserts n copies of value. //! //! <b>Throws</b>: If allocator_type's default constructor @@ -605,8 +641,7 @@ class deque : protected deque_base<Allocator> ) : Base(a) { - typedef typename std::iterator_traits<InIt>::iterator_category ItCat; - this->priv_range_initialize(first, last, ItCat()); + this->priv_range_initialize(first, last); } #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) @@ -620,7 +655,7 @@ class deque : protected deque_base<Allocator> deque(std::initializer_list<value_type> il, const allocator_type& a = allocator_type()) : Base(a) { - this->priv_range_initialize(il.begin(), il.end(), std::input_iterator_tag()); + this->priv_range_initialize(il.begin(), il.end()); } #endif @@ -639,13 +674,13 @@ class deque : protected deque_base<Allocator> } } - //! <b>Effects</b>: Move constructor. Moves mx's resources to *this. + //! <b>Effects</b>: Move constructor. Moves x's resources to *this. //! //! <b>Throws</b>: If allocator_type's copy constructor throws. //! //! <b>Complexity</b>: Constant. deque(BOOST_RV_REF(deque) x) - : Base(boost::move(static_cast<Base&>(x))) + : Base(BOOST_MOVE_BASE(Base, x)) { this->swap_members(x); } //! <b>Effects</b>: Copy constructs a vector using the specified allocator. @@ -667,23 +702,24 @@ class deque : protected deque_base<Allocator> } //! <b>Effects</b>: Move constructor using the specified allocator. - //! Moves mx's resources to *this if a == allocator_type(). + //! Moves x's resources to *this if a == allocator_type(). //! Otherwise copies values from x to *this. //! //! <b>Throws</b>: If allocation or T's copy constructor throws. //! - //! <b>Complexity</b>: Constant if a == mx.get_allocator(), linear otherwise. - deque(BOOST_RV_REF(deque) mx, const allocator_type &a) + //! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise. + deque(BOOST_RV_REF(deque) x, const allocator_type &a) : Base(a) { - if(mx.alloc() == a){ - this->swap_members(mx); + if(x.alloc() == a){ + this->swap_members(x); } else{ - if(mx.size()){ - this->priv_initialize_map(mx.size()); + if(x.size()){ + this->priv_initialize_map(x.size()); boost::container::uninitialized_copy_alloc - (this->alloc(), mx.begin(), mx.end(), this->members_.m_start); + ( this->alloc(), boost::make_move_iterator(x.begin()) + , boost::make_move_iterator(x.end()), this->members_.m_start); } } } @@ -694,7 +730,7 @@ class deque : protected deque_base<Allocator> //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Linear to the number of elements. - ~deque() BOOST_CONTAINER_NOEXCEPT + ~deque() BOOST_NOEXCEPT_OR_NOTHROW { this->priv_destroy_range(this->members_.m_start, this->members_.m_finish); } @@ -734,7 +770,8 @@ class deque : protected deque_base<Allocator> //! propagate_on_container_move_assignment is true or //! this->get>allocator() == x.get_allocator(). Linear otherwise. deque& operator= (BOOST_RV_REF(deque) x) - BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value) + BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value + || allocator_traits_type::is_always_equal::value) { BOOST_ASSERT(this != &x); allocator_type &this_alloc = this->alloc(); @@ -826,10 +863,10 @@ class deque : protected deque_base<Allocator> >::type * = 0 ) { - const size_type len = std::distance(first, last); + const size_type len = boost::container::iterator_distance(first, last); if (len > size()) { FwdIt mid = first; - std::advance(mid, this->size()); + boost::container::iterator_advance(mid, this->size()); boost::container::copy(first, mid, begin()); this->insert(this->cend(), mid, last); } @@ -855,7 +892,7 @@ class deque : protected deque_base<Allocator> //! <b>Throws</b>: If allocator's copy constructor throws. //! //! <b>Complexity</b>: Constant. - allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT + allocator_type get_allocator() const BOOST_NOEXCEPT_OR_NOTHROW { return Base::alloc(); } //! <b>Effects</b>: Returns a reference to the internal allocator. @@ -865,7 +902,7 @@ class deque : protected deque_base<Allocator> //! <b>Complexity</b>: Constant. //! //! <b>Note</b>: Non-standard extension. - const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT + const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW { return Base::alloc(); } ////////////////////////////////////////////// @@ -881,7 +918,7 @@ class deque : protected deque_base<Allocator> //! <b>Complexity</b>: Constant. //! //! <b>Note</b>: Non-standard extension. - stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT + stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW { return Base::alloc(); } //! <b>Effects</b>: Returns an iterator to the first element contained in the deque. @@ -889,7 +926,7 @@ class deque : protected deque_base<Allocator> //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - iterator begin() BOOST_CONTAINER_NOEXCEPT + iterator begin() BOOST_NOEXCEPT_OR_NOTHROW { return this->members_.m_start; } //! <b>Effects</b>: Returns a const_iterator to the first element contained in the deque. @@ -897,7 +934,7 @@ class deque : protected deque_base<Allocator> //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator begin() const BOOST_CONTAINER_NOEXCEPT + const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW { return this->members_.m_start; } //! <b>Effects</b>: Returns an iterator to the end of the deque. @@ -905,7 +942,7 @@ class deque : protected deque_base<Allocator> //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - iterator end() BOOST_CONTAINER_NOEXCEPT + iterator end() BOOST_NOEXCEPT_OR_NOTHROW { return this->members_.m_finish; } //! <b>Effects</b>: Returns a const_iterator to the end of the deque. @@ -913,7 +950,7 @@ class deque : protected deque_base<Allocator> //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator end() const BOOST_CONTAINER_NOEXCEPT + const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW { return this->members_.m_finish; } //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning @@ -922,7 +959,7 @@ class deque : protected deque_base<Allocator> //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT + reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW { return reverse_iterator(this->members_.m_finish); } //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning @@ -931,7 +968,7 @@ class deque : protected deque_base<Allocator> //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT + const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW { return const_reverse_iterator(this->members_.m_finish); } //! <b>Effects</b>: Returns a reverse_iterator pointing to the end @@ -940,7 +977,7 @@ class deque : protected deque_base<Allocator> //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT + reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW { return reverse_iterator(this->members_.m_start); } //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end @@ -949,7 +986,7 @@ class deque : protected deque_base<Allocator> //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT + const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW { return const_reverse_iterator(this->members_.m_start); } //! <b>Effects</b>: Returns a const_iterator to the first element contained in the deque. @@ -957,7 +994,7 @@ class deque : protected deque_base<Allocator> //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT + const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW { return this->members_.m_start; } //! <b>Effects</b>: Returns a const_iterator to the end of the deque. @@ -965,7 +1002,7 @@ class deque : protected deque_base<Allocator> //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator cend() const BOOST_CONTAINER_NOEXCEPT + const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW { return this->members_.m_finish; } //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning @@ -974,7 +1011,7 @@ class deque : protected deque_base<Allocator> //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT + const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW { return const_reverse_iterator(this->members_.m_finish); } //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end @@ -983,7 +1020,7 @@ class deque : protected deque_base<Allocator> //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT + const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW { return const_reverse_iterator(this->members_.m_start); } ////////////////////////////////////////////// @@ -997,7 +1034,7 @@ class deque : protected deque_base<Allocator> //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - bool empty() const BOOST_CONTAINER_NOEXCEPT + bool empty() const BOOST_NOEXCEPT_OR_NOTHROW { return this->members_.m_finish == this->members_.m_start; } //! <b>Effects</b>: Returns the number of the elements contained in the deque. @@ -1005,7 +1042,7 @@ class deque : protected deque_base<Allocator> //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - size_type size() const BOOST_CONTAINER_NOEXCEPT + size_type size() const BOOST_NOEXCEPT_OR_NOTHROW { return this->members_.m_finish - this->members_.m_start; } //! <b>Effects</b>: Returns the largest possible size of the deque. @@ -1013,7 +1050,7 @@ class deque : protected deque_base<Allocator> //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - size_type max_size() const BOOST_CONTAINER_NOEXCEPT + size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW { return allocator_traits_type::max_size(this->alloc()); } //! <b>Effects</b>: Inserts or erases elements at the end such that @@ -1100,7 +1137,7 @@ class deque : protected deque_base<Allocator> //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - reference front() BOOST_CONTAINER_NOEXCEPT + reference front() BOOST_NOEXCEPT_OR_NOTHROW { return *this->members_.m_start; } //! <b>Requires</b>: !empty() @@ -1111,7 +1148,7 @@ class deque : protected deque_base<Allocator> //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reference front() const BOOST_CONTAINER_NOEXCEPT + const_reference front() const BOOST_NOEXCEPT_OR_NOTHROW { return *this->members_.m_start; } //! <b>Requires</b>: !empty() @@ -1122,7 +1159,7 @@ class deque : protected deque_base<Allocator> //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - reference back() BOOST_CONTAINER_NOEXCEPT + reference back() BOOST_NOEXCEPT_OR_NOTHROW { return *(end()-1); } //! <b>Requires</b>: !empty() @@ -1133,7 +1170,7 @@ class deque : protected deque_base<Allocator> //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reference back() const BOOST_CONTAINER_NOEXCEPT + const_reference back() const BOOST_NOEXCEPT_OR_NOTHROW { return *(cend()-1); } //! <b>Requires</b>: size() > n. @@ -1144,7 +1181,7 @@ class deque : protected deque_base<Allocator> //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - reference operator[](size_type n) BOOST_CONTAINER_NOEXCEPT + reference operator[](size_type n) BOOST_NOEXCEPT_OR_NOTHROW { return this->members_.m_start[difference_type(n)]; } //! <b>Requires</b>: size() > n. @@ -1155,9 +1192,70 @@ class deque : protected deque_base<Allocator> //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reference operator[](size_type n) const BOOST_CONTAINER_NOEXCEPT + const_reference operator[](size_type n) const BOOST_NOEXCEPT_OR_NOTHROW { return this->members_.m_start[difference_type(n)]; } + //! <b>Requires</b>: size() >= n. + //! + //! <b>Effects</b>: Returns an iterator to the nth element + //! from the beginning of the container. Returns end() + //! if n == size(). + //! + //! <b>Throws</b>: Nothing. + //! + //! <b>Complexity</b>: Constant. + //! + //! <b>Note</b>: Non-standard extension + iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW + { + BOOST_ASSERT(this->size() >= n); + return iterator(this->begin()+n); + } + + //! <b>Requires</b>: size() >= n. + //! + //! <b>Effects</b>: Returns a const_iterator to the nth element + //! from the beginning of the container. Returns end() + //! if n == size(). + //! + //! <b>Throws</b>: Nothing. + //! + //! <b>Complexity</b>: Constant. + //! + //! <b>Note</b>: Non-standard extension + const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW + { + BOOST_ASSERT(this->size() >= n); + return const_iterator(this->cbegin()+n); + } + + //! <b>Requires</b>: size() >= n. + //! + //! <b>Effects</b>: Returns an iterator to the nth element + //! from the beginning of the container. Returns end() + //! if n == size(). + //! + //! <b>Throws</b>: Nothing. + //! + //! <b>Complexity</b>: Constant. + //! + //! <b>Note</b>: Non-standard extension + size_type index_of(iterator p) BOOST_NOEXCEPT_OR_NOTHROW + { return this->priv_index_of(p); } + + //! <b>Requires</b>: begin() <= p <= end(). + //! + //! <b>Effects</b>: Returns the index of the element pointed by p + //! and size() if p == end(). + //! + //! <b>Throws</b>: Nothing. + //! + //! <b>Complexity</b>: Constant. + //! + //! <b>Note</b>: Non-standard extension + size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW + { return this->priv_index_of(p); } + //! <b>Requires</b>: size() > n. //! //! <b>Effects</b>: Returns a reference to the nth element @@ -1186,7 +1284,7 @@ class deque : protected deque_base<Allocator> // ////////////////////////////////////////////// - #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) //! <b>Effects</b>: Inserts an object of type T constructed with //! std::forward<Args>(args)... in the beginning of the deque. @@ -1195,7 +1293,7 @@ class deque : protected deque_base<Allocator> //! //! <b>Complexity</b>: Amortized constant time template <class... Args> - void emplace_front(Args&&... args) + void emplace_front(BOOST_FWD_REF(Args)... args) { if(this->priv_push_front_simple_available()){ allocator_traits_type::construct @@ -1205,7 +1303,7 @@ class deque : protected deque_base<Allocator> this->priv_push_front_simple_commit(); } else{ - typedef container_detail::insert_non_movable_emplace_proxy<Allocator, iterator, Args...> type; + typedef container_detail::insert_nonmovable_emplace_proxy<Allocator, iterator, Args...> type; this->priv_insert_front_aux_impl(1, type(boost::forward<Args>(args)...)); } } @@ -1217,7 +1315,7 @@ class deque : protected deque_base<Allocator> //! //! <b>Complexity</b>: Amortized constant time template <class... Args> - void emplace_back(Args&&... args) + void emplace_back(BOOST_FWD_REF(Args)... args) { if(this->priv_push_back_simple_available()){ allocator_traits_type::construct @@ -1227,7 +1325,7 @@ class deque : protected deque_base<Allocator> this->priv_push_back_simple_commit(); } else{ - typedef container_detail::insert_non_movable_emplace_proxy<Allocator, iterator, Args...> type; + typedef container_detail::insert_nonmovable_emplace_proxy<Allocator, iterator, Args...> type; this->priv_insert_back_aux_impl(1, type(boost::forward<Args>(args)...)); } } @@ -1242,7 +1340,7 @@ class deque : protected deque_base<Allocator> //! <b>Complexity</b>: If p is end(), amortized constant time //! Linear time otherwise. template <class... Args> - iterator emplace(const_iterator p, Args&&... args) + iterator emplace(const_iterator p, BOOST_FWD_REF(Args)... args) { if(p == this->cbegin()){ this->emplace_front(boost::forward<Args>(args)...); @@ -1258,70 +1356,61 @@ class deque : protected deque_base<Allocator> } } - #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING - - //advanced_insert_int.hpp includes all necessary preprocessor machinery... - #define BOOST_PP_LOCAL_MACRO(n) \ - BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, > ) \ - void emplace_front(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ - { \ - if(priv_push_front_simple_available()){ \ - allocator_traits_type::construct \ - ( this->alloc() \ - , this->priv_push_front_simple_pos() \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \ - priv_push_front_simple_commit(); \ - } \ - else{ \ - typedef container_detail::BOOST_PP_CAT(insert_non_movable_emplace_proxy_arg, n) \ - <Allocator, iterator BOOST_PP_ENUM_TRAILING_PARAMS(n, P)> type; \ - priv_insert_front_aux_impl \ - (1, type(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \ - } \ - } \ - \ - BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ - void emplace_back(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ - { \ - if(priv_push_back_simple_available()){ \ - allocator_traits_type::construct \ - ( this->alloc() \ - , this->priv_push_back_simple_pos() \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \ - priv_push_back_simple_commit(); \ - } \ - else{ \ - typedef container_detail::BOOST_PP_CAT(insert_non_movable_emplace_proxy_arg, n) \ - <Allocator, iterator BOOST_PP_ENUM_TRAILING_PARAMS(n, P)> type; \ - priv_insert_back_aux_impl \ - (1, type(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \ - } \ - } \ - \ - BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ - iterator emplace(const_iterator p \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ - { \ - if(p == this->cbegin()){ \ - this->emplace_front(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \ - return this->begin(); \ - } \ - else if(p == cend()){ \ - this->emplace_back(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \ - return (this->end()-1); \ - } \ - else{ \ - typedef container_detail::BOOST_PP_CAT(insert_emplace_proxy_arg, n) \ - <Allocator, iterator BOOST_PP_ENUM_TRAILING_PARAMS(n, P)> type; \ - return this->priv_insert_aux_impl \ - (p, 1, type(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \ - } \ - } \ - //! - #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) - #include BOOST_PP_LOCAL_ITERATE() - - #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING + #else //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + + #define BOOST_CONTAINER_DEQUE_EMPLACE_CODE(N) \ + BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N\ + void emplace_front(BOOST_MOVE_UREF##N)\ + {\ + if(priv_push_front_simple_available()){\ + allocator_traits_type::construct\ + ( this->alloc(), this->priv_push_front_simple_pos() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\ + priv_push_front_simple_commit();\ + }\ + else{\ + typedef container_detail::insert_nonmovable_emplace_proxy##N\ + <Allocator, iterator BOOST_MOVE_I##N BOOST_MOVE_TARG##N> type;\ + priv_insert_front_aux_impl(1, type(BOOST_MOVE_FWD##N));\ + }\ + }\ + \ + BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N\ + void emplace_back(BOOST_MOVE_UREF##N)\ + {\ + if(priv_push_back_simple_available()){\ + allocator_traits_type::construct\ + ( this->alloc(), this->priv_push_back_simple_pos() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\ + priv_push_back_simple_commit();\ + }\ + else{\ + typedef container_detail::insert_nonmovable_emplace_proxy##N\ + <Allocator, iterator BOOST_MOVE_I##N BOOST_MOVE_TARG##N> type;\ + priv_insert_back_aux_impl(1, type(BOOST_MOVE_FWD##N));\ + }\ + }\ + \ + BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N\ + iterator emplace(const_iterator p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ + {\ + if(p == this->cbegin()){\ + this->emplace_front(BOOST_MOVE_FWD##N);\ + return this->begin();\ + }\ + else if(p == cend()){\ + this->emplace_back(BOOST_MOVE_FWD##N);\ + return (--this->end());\ + }\ + else{\ + typedef container_detail::insert_emplace_proxy_arg##N\ + <Allocator, iterator BOOST_MOVE_I##N BOOST_MOVE_TARG##N> type;\ + return this->priv_insert_aux_impl(p, 1, type(BOOST_MOVE_FWD##N));\ + }\ + } + // + BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_DEQUE_EMPLACE_CODE) + #undef BOOST_CONTAINER_DEQUE_EMPLACE_CODE + + #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) //! <b>Effects</b>: Inserts a copy of x at the front of the deque. @@ -1333,7 +1422,7 @@ class deque : protected deque_base<Allocator> void push_front(const T &x); //! <b>Effects</b>: Constructs a new element in the front of the deque - //! and moves the resources of mx to this new element. + //! and moves the resources of x to this new element. //! //! <b>Throws</b>: If memory allocation throws. //! @@ -1353,7 +1442,7 @@ class deque : protected deque_base<Allocator> void push_back(const T &x); //! <b>Effects</b>: Constructs a new element in the end of the deque - //! and moves the resources of mx to this new element. + //! and moves the resources of x to this new element. //! //! <b>Throws</b>: If memory allocation throws. //! @@ -1379,7 +1468,7 @@ class deque : protected deque_base<Allocator> //! <b>Requires</b>: p must be a valid iterator of *this. //! - //! <b>Effects</b>: Insert a new element before p with mx's resources. + //! <b>Effects</b>: Insert a new element before p with x's resources. //! //! <b>Returns</b>: an iterator to the inserted element. //! @@ -1416,7 +1505,7 @@ class deque : protected deque_base<Allocator> //! <b>Throws</b>: If memory allocation throws, T's constructor from a //! dereferenced InIt throws or T's copy constructor throws. //! - //! <b>Complexity</b>: Linear to std::distance [first, last). + //! <b>Complexity</b>: Linear to distance [first, last). template <class InIt> iterator insert(const_iterator pos, InIt first, InIt last #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) @@ -1447,7 +1536,7 @@ class deque : protected deque_base<Allocator> //! <b>Throws</b>: If memory allocation throws, T's constructor from a //! dereferenced std::initializer_list throws or T's copy constructor throws. //! - //! <b>Complexity</b>: Linear to std::distance [il.begin(), il.end()). + //! <b>Complexity</b>: Linear to distance [il.begin(), il.end()). iterator insert(const_iterator pos, std::initializer_list<value_type> il) { return insert(pos, il.begin(), il.end()); } #endif @@ -1464,7 +1553,7 @@ class deque : protected deque_base<Allocator> ) { container_detail::insert_range_proxy<Allocator, FwdIt, iterator> proxy(first); - return priv_insert_aux_impl(p, (size_type)std::distance(first, last), proxy); + return priv_insert_aux_impl(p, boost::container::iterator_distance(first, last), proxy); } #endif @@ -1473,7 +1562,7 @@ class deque : protected deque_base<Allocator> //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant time. - void pop_front() BOOST_CONTAINER_NOEXCEPT + void pop_front() BOOST_NOEXCEPT_OR_NOTHROW { if (this->members_.m_start.m_cur != this->members_.m_start.m_last - 1) { allocator_traits_type::destroy @@ -1491,7 +1580,7 @@ class deque : protected deque_base<Allocator> //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant time. - void pop_back() BOOST_CONTAINER_NOEXCEPT + void pop_back() BOOST_NOEXCEPT_OR_NOTHROW { if (this->members_.m_finish.m_cur != this->members_.m_finish.m_first) { --this->members_.m_finish.m_cur; @@ -1512,17 +1601,17 @@ class deque : protected deque_base<Allocator> //! last element (if pos is near the end) or the first element //! if(pos is near the beginning). //! Constant if pos is the first or the last element. - iterator erase(const_iterator pos) BOOST_CONTAINER_NOEXCEPT + iterator erase(const_iterator pos) BOOST_NOEXCEPT_OR_NOTHROW { iterator next = pos.unconst(); ++next; size_type index = pos - this->members_.m_start; if (index < (this->size()/2)) { - boost::move_backward(this->begin(), pos.unconst(), next); + boost::container::move_backward(this->begin(), pos.unconst(), next); pop_front(); } else { - boost::move(next, this->end(), pos.unconst()); + boost::container::move(next, this->end(), pos.unconst()); pop_back(); } return this->members_.m_start + index; @@ -1536,7 +1625,7 @@ class deque : protected deque_base<Allocator> //! last plus the elements between pos and the //! last element (if pos is near the end) or the first element //! if(pos is near the beginning). - iterator erase(const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT + iterator erase(const_iterator first, const_iterator last) BOOST_NOEXCEPT_OR_NOTHROW { if (first == this->members_.m_start && last == this->members_.m_finish) { this->clear(); @@ -1546,7 +1635,7 @@ class deque : protected deque_base<Allocator> const size_type n = static_cast<size_type>(last - first); const size_type elems_before = static_cast<size_type>(first - this->members_.m_start); if (elems_before < (this->size() - n) - elems_before) { - boost::move_backward(begin(), first.unconst(), last.unconst()); + boost::container::move_backward(begin(), first.unconst(), last.unconst()); iterator new_start = this->members_.m_start + n; if(!Base::traits_t::trivial_dctr_after_move) this->priv_destroy_range(this->members_.m_start, new_start); @@ -1554,7 +1643,7 @@ class deque : protected deque_base<Allocator> this->members_.m_start = new_start; } else { - boost::move(last.unconst(), end(), first.unconst()); + boost::container::move(last.unconst(), end(), first.unconst()); iterator new_finish = this->members_.m_finish - n; if(!Base::traits_t::trivial_dctr_after_move) this->priv_destroy_range(new_finish, this->members_.m_finish); @@ -1571,6 +1660,8 @@ class deque : protected deque_base<Allocator> //! //! <b>Complexity</b>: Constant. void swap(deque &x) + BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_swap::value + || allocator_traits_type::is_always_equal::value) { this->swap_members(x); container_detail::bool_<allocator_traits_type::propagate_on_container_swap::value> flag; @@ -1583,7 +1674,7 @@ class deque : protected deque_base<Allocator> //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Linear to the number of elements in the deque. - void clear() BOOST_CONTAINER_NOEXCEPT + void clear() BOOST_NOEXCEPT_OR_NOTHROW { for (index_pointer node = this->members_.m_start.m_node + 1; node < this->members_.m_finish.m_node; @@ -1607,7 +1698,7 @@ class deque : protected deque_base<Allocator> //! //! <b>Complexity</b>: Linear to the number of elements in the container. friend bool operator==(const deque& x, const deque& y) - { return x.size() == y.size() && std::equal(x.begin(), x.end(), y.begin()); } + { 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 //! @@ -1619,7 +1710,7 @@ class deque : protected deque_base<Allocator> //! //! <b>Complexity</b>: Linear to the number of elements in the container. friend bool operator<(const deque& x, const deque& y) - { return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } + { 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 //! @@ -1648,6 +1739,13 @@ class deque : protected deque_base<Allocator> #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED private: + size_type priv_index_of(const_iterator p) const + { + BOOST_ASSERT(this->cbegin() <= p); + BOOST_ASSERT(p <= this->cend()); + return static_cast<size_type>(p - this->cbegin()); + } + void priv_erase_last_n(size_type n) { if(n == this->size()) { @@ -1743,21 +1841,19 @@ class deque : protected deque_base<Allocator> void priv_destroy_range(iterator p, iterator p2) { - for(;p != p2; ++p){ - allocator_traits_type::destroy - ( this->alloc() - , container_detail::to_raw_pointer(container_detail::iterator_to_pointer(p)) - ); + if(!Base::traits_t::trivial_dctr){ + for(;p != p2; ++p){ + allocator_traits_type::destroy(this->alloc(), container_detail::iterator_to_raw_pointer(p)); + } } } void priv_destroy_range(pointer p, pointer p2) { - for(;p != p2; ++p){ - allocator_traits_type::destroy - ( this->alloc() - , container_detail::to_raw_pointer(container_detail::iterator_to_pointer(p)) - ); + if(!Base::traits_t::trivial_dctr){ + for(;p != p2; ++p){ + allocator_traits_type::destroy(this->alloc(), container_detail::iterator_to_raw_pointer(p)); + } } } @@ -1787,7 +1883,7 @@ class deque : protected deque_base<Allocator> ::boost::container::uninitialized_move_alloc (this->alloc(), this->members_.m_start, start_n, new_start); this->members_.m_start = new_start; - boost::move(start_n, pos, old_start); + boost::container::move(start_n, pos, old_start); proxy.copy_n_and_update(this->alloc(), pos - n, n); } else { @@ -1817,7 +1913,7 @@ class deque : protected deque_base<Allocator> ::boost::container::uninitialized_move_alloc (this->alloc(), finish_n, old_finish, old_finish); this->members_.m_finish = new_finish; - boost::move_backward(pos, finish_n, old_finish); + boost::container::move_backward(pos, finish_n, old_finish); proxy.copy_n_and_update(this->alloc(), pos, n); } else { @@ -1877,9 +1973,9 @@ class deque : protected deque_base<Allocator> // but none of the deque's elements have yet been constructed. void priv_fill_initialize(const value_type& value) { - index_pointer cur; + index_pointer cur = this->members_.m_start.m_node; BOOST_TRY { - for (cur = this->members_.m_start.m_node; cur < this->members_.m_finish.m_node; ++cur){ + for ( ; cur < this->members_.m_finish.m_node; ++cur){ boost::container::uninitialized_fill_alloc (this->alloc(), *cur, *cur + this->s_buffer_size(), value); } @@ -1894,7 +1990,8 @@ class deque : protected deque_base<Allocator> } template <class InIt> - void priv_range_initialize(InIt first, InIt last, std::input_iterator_tag) + typename iterator_enable_if_tag<InIt, std::input_iterator_tag>::type + priv_range_initialize(InIt first, InIt last) { this->priv_initialize_map(0); BOOST_TRY { @@ -1909,19 +2006,18 @@ class deque : protected deque_base<Allocator> } template <class FwdIt> - void priv_range_initialize(FwdIt first, FwdIt last, std::forward_iterator_tag) + typename iterator_disable_if_tag<FwdIt, std::input_iterator_tag>::type + priv_range_initialize(FwdIt first, FwdIt last) { size_type n = 0; - n = std::distance(first, last); + n = boost::container::iterator_distance(first, last); this->priv_initialize_map(n); - index_pointer cur_node; + index_pointer cur_node = this->members_.m_start.m_node; BOOST_TRY { - for (cur_node = this->members_.m_start.m_node; - cur_node < this->members_.m_finish.m_node; - ++cur_node) { + for (; cur_node < this->members_.m_finish.m_node; ++cur_node) { FwdIt mid = first; - std::advance(mid, this->s_buffer_size()); + boost::container::iterator_advance(mid, this->s_buffer_size()); ::boost::container::uninitialized_copy_alloc(this->alloc(), first, mid, *cur_node); first = mid; } @@ -1935,7 +2031,7 @@ class deque : protected deque_base<Allocator> } // Called only if this->members_.m_finish.m_cur == this->members_.m_finish.m_first. - void priv_pop_back_aux() BOOST_CONTAINER_NOEXCEPT + void priv_pop_back_aux() BOOST_NOEXCEPT_OR_NOTHROW { this->priv_deallocate_node(this->members_.m_finish.m_first); this->members_.m_finish.priv_set_node(this->members_.m_finish.m_node - 1); @@ -1950,7 +2046,7 @@ class deque : protected deque_base<Allocator> // if the deque has at least one element (a precondition for this member // function), and if this->members_.m_start.m_cur == this->members_.m_start.m_last, then the deque // must have at least two nodes. - void priv_pop_front_aux() BOOST_CONTAINER_NOEXCEPT + void priv_pop_front_aux() BOOST_NOEXCEPT_OR_NOTHROW { allocator_traits_type::destroy ( this->alloc() @@ -1997,9 +2093,9 @@ class deque : protected deque_base<Allocator> if (new_nodes + 1 > s){ this->priv_reallocate_map(new_nodes, false); } - size_type i; + size_type i = 1; BOOST_TRY { - for (i = 1; i <= new_nodes; ++i) + for (; i <= new_nodes; ++i) *(this->members_.m_finish.m_node + i) = this->priv_allocate_node(); } BOOST_CATCH(...) { @@ -2022,9 +2118,9 @@ class deque : protected deque_base<Allocator> new_nstart = this->members_.m_map + (this->members_.m_map_size - new_num_nodes) / 2 + (add_at_front ? nodes_to_add : 0); if (new_nstart < this->members_.m_start.m_node) - boost::move(this->members_.m_start.m_node, this->members_.m_finish.m_node + 1, new_nstart); + boost::container::move(this->members_.m_start.m_node, this->members_.m_finish.m_node + 1, new_nstart); else - boost::move_backward + boost::container::move_backward (this->members_.m_start.m_node, this->members_.m_finish.m_node + 1, new_nstart + old_num_nodes); } else { @@ -2034,7 +2130,7 @@ class deque : protected deque_base<Allocator> index_pointer new_map = this->priv_allocate_map(new_map_size); new_nstart = new_map + (new_map_size - new_num_nodes) / 2 + (add_at_front ? nodes_to_add : 0); - boost::move(this->members_.m_start.m_node, this->members_.m_finish.m_node + 1, new_nstart); + boost::container::move(this->members_.m_start.m_node, this->members_.m_finish.m_node + 1, new_nstart); this->priv_deallocate_map(this->members_.m_map, this->members_.m_map_size); this->members_.m_map = new_map; @@ -2057,8 +2153,11 @@ namespace boost { //!specialization for optimizations template <class T, class Allocator> struct has_trivial_destructor_after_move<boost::container::deque<T, Allocator> > - : public ::boost::has_trivial_destructor_after_move<Allocator> -{}; +{ + typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer; + static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value && + ::boost::has_trivial_destructor_after_move<pointer>::value; +}; } diff --git a/boost/container/detail/adaptive_node_pool.hpp b/boost/container/detail/adaptive_node_pool.hpp index 4e7375412b..4a1f07c4a8 100644 --- a/boost/container/detail/adaptive_node_pool.hpp +++ b/boost/container/detail/adaptive_node_pool.hpp @@ -11,7 +11,11 @@ #ifndef BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_HPP #define BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_HPP -#if defined(_MSC_VER) && (_MSC_VER >= 1200) +#ifndef BOOST_CONFIG_HPP +# include <boost/config.hpp> +#endif + +#if defined(BOOST_HAS_PRAGMA_ONCE) # pragma once #endif @@ -19,13 +23,14 @@ #include <boost/container/detail/workaround.hpp> #include <boost/intrusive/set.hpp> -#include <boost/aligned_storage.hpp> #include <boost/container/detail/alloc_lib_auto_link.hpp> #include <boost/container/detail/multiallocation_chain.hpp> #include <boost/container/detail/pool_common_alloc.hpp> #include <boost/container/detail/mutex.hpp> #include <boost/container/detail/adaptive_node_pool_impl.hpp> #include <boost/container/detail/multiallocation_chain.hpp> +#include <boost/container/detail/type_traits.hpp> + #include <cstddef> #include <cmath> #include <cassert> diff --git a/boost/container/detail/adaptive_node_pool_impl.hpp b/boost/container/detail/adaptive_node_pool_impl.hpp index dc1a7f102e..24c81dda3b 100644 --- a/boost/container/detail/adaptive_node_pool_impl.hpp +++ b/boost/container/detail/adaptive_node_pool_impl.hpp @@ -11,24 +11,34 @@ #ifndef BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_IMPL_HPP #define BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_IMPL_HPP -#if defined(_MSC_VER) +#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> +// container #include <boost/container/container_fwd.hpp> -#include <boost/container/detail/utilities.hpp> +#include <boost/container/throw_exception.hpp> +// 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/container/detail/math_functions.hpp> +#include <boost/container/detail/mpl.hpp> +#include <boost/container/detail/to_raw_pointer.hpp> +#include <boost/container/detail/type_traits.hpp> +// intrusive #include <boost/intrusive/pointer_traits.hpp> #include <boost/intrusive/set.hpp> #include <boost/intrusive/list.hpp> #include <boost/intrusive/slist.hpp> -#include <boost/container/detail/type_traits.hpp> -#include <boost/container/detail/math_functions.hpp> -#include <boost/container/detail/mpl.hpp> -#include <boost/container/detail/pool_common.hpp> -#include <boost/container/throw_exception.hpp> +// other #include <boost/assert.hpp> #include <boost/core/no_exceptions_support.hpp> #include <cstddef> @@ -482,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_pointer(itf)); + void *pElem = container_detail::to_raw_pointer(container_detail::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; diff --git a/boost/container/detail/addressof.hpp b/boost/container/detail/addressof.hpp new file mode 100644 index 0000000000..cc582c439d --- /dev/null +++ b/boost/container/detail/addressof.hpp @@ -0,0 +1,41 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_ADDRESSOF_HPP +#define BOOST_CONTAINER_DETAIL_ADDRESSOF_HPP + +#ifndef BOOST_CONFIG_HPP +# include <boost/config.hpp> +#endif + +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include <cstddef> + +namespace boost { +namespace container { +namespace container_detail { + +template <typename T> +inline T* addressof(T& obj) +{ + return static_cast<T*>( + static_cast<void*>( + const_cast<char*>( + &reinterpret_cast<const char&>(obj) + ))); +} + +} //namespace container_detail { +} //namespace container { +} //namespace boost { + +#endif //#ifndef BOOST_CONTAINER_DETAIL_ADDRESSOF_HPP diff --git a/boost/container/detail/advanced_insert_int.hpp b/boost/container/detail/advanced_insert_int.hpp index a35279dcf7..56df588706 100644 --- a/boost/container/detail/advanced_insert_int.hpp +++ b/boost/container/detail/advanced_insert_int.hpp @@ -11,44 +11,55 @@ #ifndef BOOST_CONTAINER_ADVANCED_INSERT_INT_HPP #define BOOST_CONTAINER_ADVANCED_INSERT_INT_HPP -#if defined(_MSC_VER) +#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> +// container #include <boost/container/allocator_traits.hpp> +// container/detail +#include <boost/container/detail/copy_move_algo.hpp> #include <boost/container/detail/destroyers.hpp> -#include <boost/aligned_storage.hpp> -#include <boost/move/utility_core.hpp> #include <boost/container/detail/mpl.hpp> -#include <boost/container/detail/utilities.hpp> #include <boost/container/detail/type_traits.hpp> +#include <boost/container/detail/iterator.hpp> #include <boost/container/detail/iterators.hpp> -#include <iterator> //std::iterator_traits +#include <boost/container/detail/iterator_to_raw_pointer.hpp> +#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +#include <boost/move/detail/fwd_macros.hpp> +#endif +// move +#include <boost/move/utility_core.hpp> +// other #include <boost/assert.hpp> #include <boost/core/no_exceptions_support.hpp> namespace boost { namespace container { namespace container_detail { -template<class A, class FwdIt, class Iterator> +template<class Allocator, class FwdIt, class Iterator> struct move_insert_range_proxy { - typedef typename allocator_traits<A>::size_type size_type; - typedef typename allocator_traits<A>::value_type value_type; + typedef typename allocator_traits<Allocator>::size_type size_type; + typedef typename allocator_traits<Allocator>::value_type value_type; explicit move_insert_range_proxy(FwdIt first) : first_(first) {} - void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n) + void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) { this->first_ = ::boost::container::uninitialized_move_alloc_n_source (a, this->first_, n, p); } - void copy_n_and_update(A &, Iterator p, size_type n) + void copy_n_and_update(Allocator &, Iterator p, size_type n) { this->first_ = ::boost::container::move_n_source(this->first_, n, p); } @@ -57,22 +68,22 @@ struct move_insert_range_proxy }; -template<class A, class FwdIt, class Iterator> +template<class Allocator, class FwdIt, class Iterator> struct insert_range_proxy { - typedef typename allocator_traits<A>::size_type size_type; - typedef typename allocator_traits<A>::value_type value_type; + typedef typename allocator_traits<Allocator>::size_type size_type; + typedef typename allocator_traits<Allocator>::value_type value_type; explicit insert_range_proxy(FwdIt first) : first_(first) {} - void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n) + void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) { this->first_ = ::boost::container::uninitialized_copy_alloc_n_source(a, this->first_, n, p); } - void copy_n_and_update(A &, Iterator p, size_type n) + void copy_n_and_update(Allocator &, Iterator p, size_type n) { this->first_ = ::boost::container::copy_n_source(this->first_, n, p); } @@ -81,20 +92,20 @@ struct insert_range_proxy }; -template<class A, class Iterator> +template<class Allocator, class Iterator> struct insert_n_copies_proxy { - typedef typename allocator_traits<A>::size_type size_type; - typedef typename allocator_traits<A>::value_type value_type; + typedef typename allocator_traits<Allocator>::size_type size_type; + typedef typename allocator_traits<Allocator>::value_type value_type; explicit insert_n_copies_proxy(const value_type &v) : v_(v) {} - void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n) const + void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const { boost::container::uninitialized_fill_alloc_n(a, v_, n, p); } - void copy_n_and_update(A &, Iterator p, size_type n) const + void copy_n_and_update(Allocator &, Iterator p, size_type n) const { for (; 0 < n; --n, ++p){ *p = v_; @@ -104,38 +115,38 @@ struct insert_n_copies_proxy const value_type &v_; }; -template<class A, class Iterator> +template<class Allocator, class Iterator> struct insert_value_initialized_n_proxy { - typedef ::boost::container::allocator_traits<A> alloc_traits; - typedef typename allocator_traits<A>::size_type size_type; - typedef typename allocator_traits<A>::value_type value_type; + typedef ::boost::container::allocator_traits<Allocator> alloc_traits; + typedef typename allocator_traits<Allocator>::size_type size_type; + typedef typename allocator_traits<Allocator>::value_type value_type; - void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n) const + void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const { boost::container::uninitialized_value_init_alloc_n(a, n, p); } - void copy_n_and_update(A &, Iterator, size_type) const + void copy_n_and_update(Allocator &, Iterator, size_type) const { BOOST_ASSERT(false); } }; -template<class A, class Iterator> +template<class Allocator, class Iterator> struct insert_default_initialized_n_proxy { - typedef ::boost::container::allocator_traits<A> alloc_traits; - typedef typename allocator_traits<A>::size_type size_type; - typedef typename allocator_traits<A>::value_type value_type; + typedef ::boost::container::allocator_traits<Allocator> alloc_traits; + typedef typename allocator_traits<Allocator>::size_type size_type; + typedef typename allocator_traits<Allocator>::value_type value_type; - void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n) const + void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const { boost::container::uninitialized_default_init_alloc_n(a, n, p); } - void copy_n_and_update(A &, Iterator, size_type) const + void copy_n_and_update(Allocator &, Iterator, size_type) const { BOOST_ASSERT(false); } }; -template<class A, class Iterator> +template<class Allocator, class Iterator> struct insert_copy_proxy { - typedef boost::container::allocator_traits<A> alloc_traits; + typedef boost::container::allocator_traits<Allocator> alloc_traits; typedef typename alloc_traits::size_type size_type; typedef typename alloc_traits::value_type value_type; @@ -143,13 +154,13 @@ struct insert_copy_proxy : v_(v) {} - void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n) const + 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_); } - void copy_n_and_update(A &, Iterator p, size_type n) const + void copy_n_and_update(Allocator &, Iterator p, size_type n) const { BOOST_ASSERT(n == 1); (void)n; *p =v_; @@ -159,10 +170,10 @@ struct insert_copy_proxy }; -template<class A, class Iterator> +template<class Allocator, class Iterator> struct insert_move_proxy { - typedef boost::container::allocator_traits<A> alloc_traits; + typedef boost::container::allocator_traits<Allocator> alloc_traits; typedef typename alloc_traits::size_type size_type; typedef typename alloc_traits::value_type value_type; @@ -170,13 +181,13 @@ struct insert_move_proxy : v_(v) {} - void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n) const + 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_) ); } - void copy_n_and_update(A &, Iterator p, size_type n) const + void copy_n_and_update(Allocator &, Iterator p, size_type n) const { BOOST_ASSERT(n == 1); (void)n; *p = ::boost::move(v_); @@ -185,50 +196,48 @@ struct insert_move_proxy value_type &v_; }; -template<class It, class A> -insert_move_proxy<A, It> get_insert_value_proxy(BOOST_RV_REF(typename std::iterator_traits<It>::value_type) v) +template<class It, class Allocator> +insert_move_proxy<Allocator, It> get_insert_value_proxy(BOOST_RV_REF(typename boost::container::iterator_traits<It>::value_type) v) { - return insert_move_proxy<A, It>(v); + return insert_move_proxy<Allocator, It>(v); } -template<class It, class A> -insert_copy_proxy<A, It> get_insert_value_proxy(const typename std::iterator_traits<It>::value_type &v) +template<class It, class Allocator> +insert_copy_proxy<Allocator, It> get_insert_value_proxy(const typename boost::container::iterator_traits<It>::value_type &v) { - return insert_copy_proxy<A, It>(v); + return insert_copy_proxy<Allocator, It>(v); } }}} //namespace boost { namespace container { namespace container_detail { -#ifdef BOOST_CONTAINER_PERFECT_FORWARDING +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) #include <boost/container/detail/variadic_templates_tools.hpp> #include <boost/move/utility_core.hpp> -#include <typeinfo> -//#include <iostream> //For debugging purposes namespace boost { namespace container { namespace container_detail { -template<class A, class Iterator, class ...Args> -struct insert_non_movable_emplace_proxy +template<class Allocator, class Iterator, class ...Args> +struct insert_nonmovable_emplace_proxy { - typedef boost::container::allocator_traits<A> alloc_traits; + typedef boost::container::allocator_traits<Allocator> alloc_traits; typedef typename alloc_traits::size_type size_type; typedef typename alloc_traits::value_type value_type; typedef typename build_number_seq<sizeof...(Args)>::type index_tuple_t; - explicit insert_non_movable_emplace_proxy(Args&&... args) + explicit insert_nonmovable_emplace_proxy(BOOST_FWD_REF(Args)... args) : args_(args...) {} - void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n) + void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) { this->priv_uninitialized_copy_some_and_update(a, index_tuple_t(), p, n); } private: template<int ...IdxPack> - void priv_uninitialized_copy_some_and_update(A &a, const index_tuple<IdxPack...>&, Iterator p, size_type n) + 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_))... ); @@ -238,30 +247,30 @@ struct insert_non_movable_emplace_proxy tuple<Args&...> args_; }; -template<class A, class Iterator, class ...Args> +template<class Allocator, class Iterator, class ...Args> struct insert_emplace_proxy - : public insert_non_movable_emplace_proxy<A, Iterator, Args...> + : public insert_nonmovable_emplace_proxy<Allocator, Iterator, Args...> { - typedef insert_non_movable_emplace_proxy<A, Iterator, Args...> base_t; - typedef boost::container::allocator_traits<A> alloc_traits; + typedef insert_nonmovable_emplace_proxy<Allocator, Iterator, Args...> base_t; + typedef boost::container::allocator_traits<Allocator> alloc_traits; typedef typename base_t::value_type value_type; typedef typename base_t::size_type size_type; typedef typename base_t::index_tuple_t index_tuple_t; - explicit insert_emplace_proxy(Args&&... args) + explicit insert_emplace_proxy(BOOST_FWD_REF(Args)... args) : base_t(::boost::forward<Args>(args)...) {} - void copy_n_and_update(A &a, Iterator p, size_type n) + void copy_n_and_update(Allocator &a, Iterator p, size_type n) { this->priv_copy_some_and_update(a, index_tuple_t(), p, n); } private: template<int ...IdxPack> - void priv_copy_some_and_update(A &a, const index_tuple<IdxPack...>&, Iterator p, size_type n) + void priv_copy_some_and_update(Allocator &a, const index_tuple<IdxPack...>&, Iterator p, size_type n) { BOOST_ASSERT(n ==1); (void)n; - aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v; + typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v; value_type *vp = static_cast<value_type *>(static_cast<void *>(&v)); alloc_traits::construct(a, vp, ::boost::forward<Args>(get<IdxPack>(this->args_))...); @@ -278,191 +287,182 @@ struct insert_emplace_proxy }; //Specializations to avoid an unneeded temporary when emplacing from a single argument o type value_type -template<class A, class Iterator> -struct insert_emplace_proxy<A, Iterator, typename boost::container::allocator_traits<A>::value_type> - : public insert_move_proxy<A, Iterator> +template<class Allocator, class Iterator> +struct insert_emplace_proxy<Allocator, Iterator, typename boost::container::allocator_traits<Allocator>::value_type> + : public insert_move_proxy<Allocator, Iterator> { - explicit insert_emplace_proxy(typename boost::container::allocator_traits<A>::value_type &&v) - : insert_move_proxy<A, Iterator>(v) + explicit insert_emplace_proxy(typename boost::container::allocator_traits<Allocator>::value_type &&v) + : insert_move_proxy<Allocator, Iterator>(v) {} }; //We use "add_const" here as adding "const" only confuses MSVC12(and maybe later) provoking -//compiler error C2752 (“more than one partial specialization matches”). +//compiler error C2752 ("more than one partial specialization matches"). //Any problem is solvable with an extra layer of indirection? ;-) -template<class A, class Iterator> -struct insert_emplace_proxy<A, Iterator - , typename boost::container::container_detail::add_const<typename boost::container::allocator_traits<A>::value_type>::type +template<class Allocator, class Iterator> +struct insert_emplace_proxy<Allocator, Iterator + , typename boost::container::container_detail::add_const<typename boost::container::allocator_traits<Allocator>::value_type>::type > - : public insert_copy_proxy<A, Iterator> + : public insert_copy_proxy<Allocator, Iterator> { - explicit insert_emplace_proxy(const typename boost::container::allocator_traits<A>::value_type &v) - : insert_copy_proxy<A, Iterator>(v) + explicit insert_emplace_proxy(const typename boost::container::allocator_traits<Allocator>::value_type &v) + : insert_copy_proxy<Allocator, Iterator>(v) {} }; -template<class A, class Iterator> -struct insert_emplace_proxy<A, Iterator, typename boost::container::allocator_traits<A>::value_type &> - : public insert_copy_proxy<A, Iterator> +template<class Allocator, class Iterator> +struct insert_emplace_proxy<Allocator, Iterator, typename boost::container::allocator_traits<Allocator>::value_type &> + : public insert_copy_proxy<Allocator, Iterator> { - explicit insert_emplace_proxy(const typename boost::container::allocator_traits<A>::value_type &v) - : insert_copy_proxy<A, Iterator>(v) + explicit insert_emplace_proxy(const typename boost::container::allocator_traits<Allocator>::value_type &v) + : insert_copy_proxy<Allocator, Iterator>(v) {} }; -template<class A, class Iterator> -struct insert_emplace_proxy<A, Iterator - , typename boost::container::container_detail::add_const<typename boost::container::allocator_traits<A>::value_type>::type & +template<class Allocator, class Iterator> +struct insert_emplace_proxy<Allocator, Iterator + , typename boost::container::container_detail::add_const<typename boost::container::allocator_traits<Allocator>::value_type>::type & > - : public insert_copy_proxy<A, Iterator> + : public insert_copy_proxy<Allocator, Iterator> { - explicit insert_emplace_proxy(const typename boost::container::allocator_traits<A>::value_type &v) - : insert_copy_proxy<A, Iterator>(v) + explicit insert_emplace_proxy(const typename boost::container::allocator_traits<Allocator>::value_type &v) + : insert_copy_proxy<Allocator, Iterator>(v) {} }; }}} //namespace boost { namespace container { namespace container_detail { -#else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING +#else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) -#include <boost/container/detail/preprocessor.hpp> #include <boost/container/detail/value_init.hpp> namespace boost { namespace container { namespace container_detail { -#define BOOST_PP_LOCAL_MACRO(N) \ -template<class A, class Iterator BOOST_PP_ENUM_TRAILING_PARAMS(N, class P) > \ -struct BOOST_PP_CAT(insert_non_movable_emplace_proxy_arg, N) \ -{ \ - typedef boost::container::allocator_traits<A> alloc_traits; \ - typedef typename alloc_traits::size_type size_type; \ - typedef typename alloc_traits::value_type value_type; \ - \ - explicit BOOST_PP_CAT(insert_non_movable_emplace_proxy_arg, N) \ - ( BOOST_PP_ENUM(N, BOOST_CONTAINER_PP_PARAM_LIST, _) ) \ - BOOST_PP_EXPR_IF(N, :) BOOST_PP_ENUM(N, BOOST_CONTAINER_PP_PARAM_INIT, _) \ - {} \ - \ - void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n) \ - { \ - BOOST_ASSERT(n == 1); (void)n; \ - alloc_traits::construct \ - ( a, iterator_to_raw_pointer(p) \ - BOOST_PP_ENUM_TRAILING(N, BOOST_CONTAINER_PP_MEMBER_FORWARD, _) \ - ); \ - } \ - \ - void copy_n_and_update(A &, Iterator, size_type) \ - { BOOST_ASSERT(false); } \ - \ - protected: \ - BOOST_PP_REPEAT(N, BOOST_CONTAINER_PP_PARAM_DEFINE, _) \ -}; \ - \ -template<class A, class Iterator BOOST_PP_ENUM_TRAILING_PARAMS(N, class P) > \ -struct BOOST_PP_CAT(insert_emplace_proxy_arg, N) \ - : BOOST_PP_CAT(insert_non_movable_emplace_proxy_arg, N) \ - < A, Iterator BOOST_PP_ENUM_TRAILING_PARAMS(N, P) > \ -{ \ - typedef BOOST_PP_CAT(insert_non_movable_emplace_proxy_arg, N) \ - <A, Iterator BOOST_PP_ENUM_TRAILING_PARAMS(N, P) > base_t; \ - typedef typename base_t::value_type value_type; \ - typedef typename base_t::size_type size_type; \ - typedef boost::container::allocator_traits<A> alloc_traits; \ - \ - explicit BOOST_PP_CAT(insert_emplace_proxy_arg, N) \ - ( BOOST_PP_ENUM(N, BOOST_CONTAINER_PP_PARAM_LIST, _) ) \ - : base_t(BOOST_PP_ENUM(N, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ) \ - {} \ - \ - void copy_n_and_update(A &a, Iterator p, size_type n) \ - { \ - BOOST_ASSERT(n == 1); (void)n; \ - aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v; \ - value_type *vp = static_cast<value_type *>(static_cast<void *>(&v)); \ - alloc_traits::construct(a, vp \ - BOOST_PP_ENUM_TRAILING(N, BOOST_CONTAINER_PP_MEMBER_FORWARD, _)); \ - BOOST_TRY{ \ - *p = ::boost::move(*vp); \ - } \ - BOOST_CATCH(...){ \ - alloc_traits::destroy(a, vp); \ - BOOST_RETHROW \ - } \ - BOOST_CATCH_END \ - alloc_traits::destroy(a, vp); \ - } \ -}; \ -//! -#define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) -#include BOOST_PP_LOCAL_ITERATE() +#define BOOST_CONTAINER_ADVANCED_INSERT_INT_CODE(N) \ +template< class Allocator, class Iterator BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\ +struct insert_nonmovable_emplace_proxy##N\ +{\ + typedef boost::container::allocator_traits<Allocator> alloc_traits;\ + typedef typename alloc_traits::size_type size_type;\ + typedef typename alloc_traits::value_type value_type;\ + \ + explicit insert_nonmovable_emplace_proxy##N(BOOST_MOVE_UREF##N)\ + BOOST_MOVE_COLON##N BOOST_MOVE_FWD_INIT##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);\ + }\ + \ + void copy_n_and_update(Allocator &, Iterator, size_type)\ + { BOOST_ASSERT(false); }\ + \ + protected:\ + BOOST_MOVE_MREF##N\ +};\ +\ +template< class Allocator, class Iterator BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\ +struct insert_emplace_proxy_arg##N\ + : insert_nonmovable_emplace_proxy##N< Allocator, Iterator BOOST_MOVE_I##N BOOST_MOVE_TARG##N >\ +{\ + typedef insert_nonmovable_emplace_proxy##N\ + < Allocator, Iterator BOOST_MOVE_I##N BOOST_MOVE_TARG##N > base_t;\ + typedef typename base_t::value_type value_type;\ + typedef typename base_t::size_type size_type;\ + typedef boost::container::allocator_traits<Allocator> alloc_traits;\ + \ + explicit insert_emplace_proxy_arg##N(BOOST_MOVE_UREF##N)\ + : base_t(BOOST_MOVE_FWD##N){}\ + \ + void copy_n_and_update(Allocator &a, Iterator p, size_type n)\ + {\ + BOOST_ASSERT(n == 1); (void)n;\ + typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v;\ + BOOST_ASSERT((((size_type)(&v)) % alignment_of<value_type>::value) == 0);\ + value_type *vp = static_cast<value_type *>(static_cast<void *>(&v));\ + alloc_traits::construct(a, vp BOOST_MOVE_I##N BOOST_MOVE_MFWD##N);\ + BOOST_TRY{\ + *p = ::boost::move(*vp);\ + }\ + BOOST_CATCH(...){\ + alloc_traits::destroy(a, vp);\ + BOOST_RETHROW\ + }\ + BOOST_CATCH_END\ + alloc_traits::destroy(a, vp);\ + }\ +};\ +// +BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_ADVANCED_INSERT_INT_CODE) +#undef BOOST_CONTAINER_ADVANCED_INSERT_INT_CODE #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) //Specializations to avoid an unneeded temporary when emplacing from a single argument o type value_type -template<class A, class Iterator> -struct insert_emplace_proxy_arg1<A, Iterator, ::boost::rv<typename boost::container::allocator_traits<A>::value_type> > - : public insert_move_proxy<A, Iterator> +template<class Allocator, class Iterator> +struct insert_emplace_proxy_arg1<Allocator, Iterator, ::boost::rv<typename boost::container::allocator_traits<Allocator>::value_type> > + : public insert_move_proxy<Allocator, Iterator> { - explicit insert_emplace_proxy_arg1(typename boost::container::allocator_traits<A>::value_type &v) - : insert_move_proxy<A, Iterator>(v) + explicit insert_emplace_proxy_arg1(typename boost::container::allocator_traits<Allocator>::value_type &v) + : insert_move_proxy<Allocator, Iterator>(v) {} }; -template<class A, class Iterator> -struct insert_emplace_proxy_arg1<A, Iterator, typename boost::container::allocator_traits<A>::value_type> - : public insert_copy_proxy<A, Iterator> +template<class Allocator, class Iterator> +struct insert_emplace_proxy_arg1<Allocator, Iterator, typename boost::container::allocator_traits<Allocator>::value_type> + : public insert_copy_proxy<Allocator, Iterator> { - explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<A>::value_type &v) - : insert_copy_proxy<A, Iterator>(v) + explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<Allocator>::value_type &v) + : insert_copy_proxy<Allocator, Iterator>(v) {} }; #else //e.g. MSVC10 & MSVC11 //Specializations to avoid an unneeded temporary when emplacing from a single argument o type value_type -template<class A, class Iterator> -struct insert_emplace_proxy_arg1<A, Iterator, typename boost::container::allocator_traits<A>::value_type> - : public insert_move_proxy<A, Iterator> +template<class Allocator, class Iterator> +struct insert_emplace_proxy_arg1<Allocator, Iterator, typename boost::container::allocator_traits<Allocator>::value_type> + : public insert_move_proxy<Allocator, Iterator> { - explicit insert_emplace_proxy_arg1(typename boost::container::allocator_traits<A>::value_type &&v) - : insert_move_proxy<A, Iterator>(v) + explicit insert_emplace_proxy_arg1(typename boost::container::allocator_traits<Allocator>::value_type &&v) + : insert_move_proxy<Allocator, Iterator>(v) {} }; //We use "add_const" here as adding "const" only confuses MSVC10&11 provoking -//compiler error C2752 (“more than one partial specialization matches”). +//compiler error C2752 ("more than one partial specialization matches"). //Any problem is solvable with an extra layer of indirection? ;-) -template<class A, class Iterator> -struct insert_emplace_proxy_arg1<A, Iterator - , typename boost::container::container_detail::add_const<typename boost::container::allocator_traits<A>::value_type>::type +template<class Allocator, class Iterator> +struct insert_emplace_proxy_arg1<Allocator, Iterator + , typename boost::container::container_detail::add_const<typename boost::container::allocator_traits<Allocator>::value_type>::type > - : public insert_copy_proxy<A, Iterator> + : public insert_copy_proxy<Allocator, Iterator> { - explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<A>::value_type &v) - : insert_copy_proxy<A, Iterator>(v) + explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<Allocator>::value_type &v) + : insert_copy_proxy<Allocator, Iterator>(v) {} }; -template<class A, class Iterator> -struct insert_emplace_proxy_arg1<A, Iterator, typename boost::container::allocator_traits<A>::value_type &> - : public insert_copy_proxy<A, Iterator> +template<class Allocator, class Iterator> +struct insert_emplace_proxy_arg1<Allocator, Iterator, typename boost::container::allocator_traits<Allocator>::value_type &> + : public insert_copy_proxy<Allocator, Iterator> { - explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<A>::value_type &v) - : insert_copy_proxy<A, Iterator>(v) + explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<Allocator>::value_type &v) + : insert_copy_proxy<Allocator, Iterator>(v) {} }; -template<class A, class Iterator> -struct insert_emplace_proxy_arg1<A, Iterator - , typename boost::container::container_detail::add_const<typename boost::container::allocator_traits<A>::value_type>::type & +template<class Allocator, class Iterator> +struct insert_emplace_proxy_arg1<Allocator, Iterator + , typename boost::container::container_detail::add_const<typename boost::container::allocator_traits<Allocator>::value_type>::type & > - : public insert_copy_proxy<A, Iterator> + : public insert_copy_proxy<Allocator, Iterator> { - explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<A>::value_type &v) - : insert_copy_proxy<A, Iterator>(v) + explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<Allocator>::value_type &v) + : insert_copy_proxy<Allocator, Iterator>(v) {} }; @@ -470,7 +470,7 @@ struct insert_emplace_proxy_arg1<A, Iterator }}} //namespace boost { namespace container { namespace container_detail { -#endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING +#endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) #include <boost/container/detail/config_end.hpp> diff --git a/boost/container/detail/algorithm.hpp b/boost/container/detail/algorithm.hpp new file mode 100644 index 0000000000..67e7876345 --- /dev/null +++ b/boost/container/detail/algorithm.hpp @@ -0,0 +1,35 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2014-2014. +// +// 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_ALGORITHM_HPP +#define BOOST_CONTAINER_DETAIL_ALGORITHM_HPP + +#ifndef BOOST_CONFIG_HPP +# include <boost/config.hpp> +#endif + +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include <boost/intrusive/detail/algorithm.hpp> + +namespace boost { +namespace container { + +using boost::intrusive::algo_equal; +using boost::intrusive::algo_lexicographical_compare; + +} //namespace container { +} //namespace boost { + +#endif //#ifndef BOOST_CONTAINER_DETAIL_ALGORITHM_HPP diff --git a/boost/container/detail/algorithms.hpp b/boost/container/detail/algorithms.hpp deleted file mode 100644 index af15f65737..0000000000 --- a/boost/container/detail/algorithms.hpp +++ /dev/null @@ -1,62 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (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_DETAIL_ALGORITHMS_HPP -#define BOOST_CONTAINER_DETAIL_ALGORITHMS_HPP - -#if defined(_MSC_VER) -# pragma once -#endif - -#include <boost/container/detail/config_begin.hpp> -#include <boost/container/detail/workaround.hpp> -#include <boost/container/allocator_traits.hpp> -#include <boost/container/detail/iterators.hpp> - -namespace boost { -namespace container { - -template<class A, class T, class InpIt> -inline void construct_in_place(A &a, T* dest, InpIt source) -{ boost::container::allocator_traits<A>::construct(a, dest, *source); } - -template<class A, class T, class U, class D> -inline void construct_in_place(A &a, T *dest, value_init_construct_iterator<U, D>) -{ - boost::container::allocator_traits<A>::construct(a, dest); -} - -template <class T, class Difference> -class default_init_construct_iterator; - -template<class A, class T, class U, class D> -inline void construct_in_place(A &a, T *dest, default_init_construct_iterator<U, D>) -{ - boost::container::allocator_traits<A>::construct(a, dest, default_init); -} - -template <class T, class EmplaceFunctor, class Difference> -class emplace_iterator; - -template<class A, class T, class U, class EF, class D> -inline void construct_in_place(A &a, T *dest, emplace_iterator<U, EF, D> ei) -{ - ei.construct_in_place(a, dest); -} - -} //namespace container { -} //namespace boost { - -#include <boost/container/detail/config_end.hpp> - -#endif //#ifndef BOOST_CONTAINER_DETAIL_ALGORITHMS_HPP - diff --git a/boost/container/detail/alloc_helpers.hpp b/boost/container/detail/alloc_helpers.hpp new file mode 100644 index 0000000000..656e0c2a5e --- /dev/null +++ b/boost/container/detail/alloc_helpers.hpp @@ -0,0 +1,60 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_ALLOC_TRAITS_HPP +#define BOOST_CONTAINER_DETAIL_ALLOC_TRAITS_HPP + +#ifndef BOOST_CONFIG_HPP +# include <boost/config.hpp> +#endif + +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +// move +#include <boost/move/adl_move_swap.hpp> +#include <boost/move/utility_core.hpp> + +namespace boost { +namespace container { +namespace container_detail { + +template<class AllocatorType> +inline void swap_alloc(AllocatorType &, AllocatorType &, container_detail::false_type) + BOOST_NOEXCEPT_OR_NOTHROW +{} + +template<class AllocatorType> +inline void swap_alloc(AllocatorType &l, AllocatorType &r, container_detail::true_type) +{ boost::adl_move_swap(l, r); } + +template<class AllocatorType> +inline void assign_alloc(AllocatorType &, const AllocatorType &, container_detail::false_type) + BOOST_NOEXCEPT_OR_NOTHROW +{} + +template<class AllocatorType> +inline void assign_alloc(AllocatorType &l, const AllocatorType &r, container_detail::true_type) +{ l = r; } + +template<class AllocatorType> +inline void move_alloc(AllocatorType &, AllocatorType &, container_detail::false_type) + BOOST_NOEXCEPT_OR_NOTHROW +{} + +template<class AllocatorType> +inline void move_alloc(AllocatorType &l, AllocatorType &r, container_detail::true_type) +{ l = ::boost::move(r); } + +} //namespace container_detail { +} //namespace container { +} //namespace boost { + +#endif //#ifndef BOOST_CONTAINER_DETAIL_ALLOC_TRAITS_HPP diff --git a/boost/container/detail/alloc_lib_auto_link.hpp b/boost/container/detail/alloc_lib_auto_link.hpp index e0a01b6086..aea99a65c3 100644 --- a/boost/container/detail/alloc_lib_auto_link.hpp +++ b/boost/container/detail/alloc_lib_auto_link.hpp @@ -10,7 +10,11 @@ #ifndef BOOST_CONTAINER_DETAIL_BOOST_CONT_EXT_AUTO_LINK_HPP #define BOOST_CONTAINER_DETAIL_BOOST_CONT_EXT_AUTO_LINK_HPP -#if defined(_MSC_VER) +#ifndef BOOST_CONFIG_HPP +# include <boost/config.hpp> +#endif + +#if defined(BOOST_HAS_PRAGMA_ONCE) # pragma once #endif diff --git a/boost/container/detail/allocation_type.hpp b/boost/container/detail/allocation_type.hpp index 65d543ad50..1e8aa67310 100644 --- a/boost/container/detail/allocation_type.hpp +++ b/boost/container/detail/allocation_type.hpp @@ -11,7 +11,11 @@ #ifndef BOOST_CONTAINER_ALLOCATION_TYPE_HPP #define BOOST_CONTAINER_ALLOCATION_TYPE_HPP -#if defined(_MSC_VER) +#ifndef BOOST_CONFIG_HPP +# include <boost/config.hpp> +#endif + +#if defined(BOOST_HAS_PRAGMA_ONCE) # pragma once #endif @@ -36,7 +40,7 @@ enum allocation_type_v try_shrink_in_place_v = 0x40 }; -typedef int allocation_type; +typedef unsigned int allocation_type; #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED static const allocation_type allocate_new = (allocation_type)allocate_new_v; static const allocation_type expand_fwd = (allocation_type)expand_fwd_v; diff --git a/boost/container/detail/allocator_version_traits.hpp b/boost/container/detail/allocator_version_traits.hpp index 18bb2ac613..62492da091 100644 --- a/boost/container/detail/allocator_version_traits.hpp +++ b/boost/container/detail/allocator_version_traits.hpp @@ -11,7 +11,11 @@ #ifndef BOOST_CONTAINER_DETAIL_ALLOCATOR_VERSION_TRAITS_HPP #define BOOST_CONTAINER_DETAIL_ALLOCATOR_VERSION_TRAITS_HPP -#if defined(_MSC_VER) +#ifndef BOOST_CONFIG_HPP +# include <boost/config.hpp> +#endif + +#if defined(BOOST_HAS_PRAGMA_ONCE) # pragma once #endif @@ -25,7 +29,6 @@ #include <boost/container/detail/allocation_type.hpp> //allocation_type #include <boost/container/detail/mpl.hpp> //integral_constant #include <boost/intrusive/pointer_traits.hpp> //pointer_traits -#include <utility> //pair #include <boost/core/no_exceptions_support.hpp> //BOOST_TRY namespace boost { @@ -56,14 +59,9 @@ struct allocator_version_traits static void deallocate_individual(Allocator &a, multiallocation_chain &holder) { a.deallocate_individual(holder); } - static std::pair<pointer, bool> - allocation_command(Allocator &a, allocation_type command, - size_type limit_size, size_type preferred_size, - size_type &received_size, const pointer &reuse) - { - return a.allocation_command - (command, limit_size, preferred_size, received_size, reuse); - } + static pointer allocation_command(Allocator &a, allocation_type command, + size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse) + { return a.allocation_command(command, limit_size, prefer_in_recvd_out_size, reuse); } }; template<class Allocator> @@ -132,21 +130,16 @@ struct allocator_version_traits<Allocator, 1> rollback.release(); } - static std::pair<pointer, bool> - allocation_command(Allocator &a, allocation_type command, - size_type, size_type preferred_size, - size_type &received_size, const pointer &) + static pointer allocation_command(Allocator &a, allocation_type command, + size_type, size_type &prefer_in_recvd_out_size, pointer &reuse) { - std::pair<pointer, bool> ret(pointer(), false); - if(!(command & allocate_new)){ - if(!(command & nothrow_allocation)){ - throw_logic_error("version 1 allocator without allocate_new flag"); - } + pointer ret = pointer(); + if(BOOST_UNLIKELY(!(command & allocate_new) && !(command & nothrow_allocation))){ + throw_logic_error("version 1 allocator without allocate_new flag"); } else{ - received_size = preferred_size; BOOST_TRY{ - ret.first = a.allocate(received_size); + ret = a.allocate(prefer_in_recvd_out_size); } BOOST_CATCH(...){ if(!(command & nothrow_allocation)){ @@ -154,6 +147,7 @@ struct allocator_version_traits<Allocator, 1> } } BOOST_CATCH_END + reuse = pointer(); } return ret; } diff --git a/boost/container/detail/auto_link.hpp b/boost/container/detail/auto_link.hpp index 2e4733363d..da078e8342 100644 --- a/boost/container/detail/auto_link.hpp +++ b/boost/container/detail/auto_link.hpp @@ -10,7 +10,11 @@ #ifndef BOOST_CONTAINER_DETAIL_AUTO_LINK_HPP_INCLUDED #define BOOST_CONTAINER_DETAIL_AUTO_LINK_HPP_INCLUDED -#if defined(_MSC_VER) +#ifndef BOOST_CONFIG_HPP +# include <boost/config.hpp> +#endif + +#if defined(BOOST_HAS_PRAGMA_ONCE) # pragma once #endif diff --git a/boost/container/detail/compare_functors.hpp b/boost/container/detail/compare_functors.hpp new file mode 100644 index 0000000000..4220d50996 --- /dev/null +++ b/boost/container/detail/compare_functors.hpp @@ -0,0 +1,74 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2014-2014. 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_COMPARE_FUNCTORS_HPP +#define BOOST_CONTAINER_DETAIL_COMPARE_FUNCTORS_HPP + +#ifndef BOOST_CONFIG_HPP +# include <boost/config.hpp> +#endif + +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +namespace boost { +namespace container { + +template<class Allocator> +class equal_to_value +{ + typedef typename Allocator::value_type value_type; + const value_type &t_; + + public: + explicit equal_to_value(const value_type &t) + : t_(t) + {} + + bool operator()(const value_type &t)const + { return t_ == t; } +}; + +template<class Node, class Pred> +struct value_to_node_compare + : Pred +{ + typedef Pred predicate_type; + typedef Node node_type; + + value_to_node_compare() + : Pred() + {} + + explicit value_to_node_compare(Pred pred) + : Pred(pred) + {} + + bool operator()(const Node &a, const Node &b) const + { return static_cast<const Pred&>(*this)(a.m_data, b.m_data); } + + bool operator()(const Node &a) const + { return static_cast<const Pred&>(*this)(a.m_data); } + + bool operator()(const Node &a, const Node &b) + { return static_cast<Pred&>(*this)(a.m_data, b.m_data); } + + bool operator()(const Node &a) + { return static_cast<Pred&>(*this)(a.m_data); } + + predicate_type & predicate() { return static_cast<predicate_type&>(*this); } + const predicate_type & predicate() const { return static_cast<predicate_type&>(*this); } +}; + +} //namespace container { +} //namespace boost { + +#endif //BOOST_CONTAINER_DETAIL_COMPARE_FUNCTORS_HPP diff --git a/boost/container/detail/config_begin.hpp b/boost/container/detail/config_begin.hpp index ca9dd59682..3f509e320b 100644 --- a/boost/container/detail/config_begin.hpp +++ b/boost/container/detail/config_begin.hpp @@ -17,32 +17,34 @@ #ifdef BOOST_MSVC #pragma warning (push) - #pragma warning (disable : 4702) // unreachable code - #pragma warning (disable : 4706) // assignment within conditional expression #pragma warning (disable : 4127) // conditional expression is constant #pragma warning (disable : 4146) // unary minus operator applied to unsigned type, result still unsigned - #pragma warning (disable : 4284) // odd return type for operator-> + #pragma warning (disable : 4197) // top-level volatile in cast is ignored #pragma warning (disable : 4244) // possible loss of data #pragma warning (disable : 4251) // "identifier" : class "type" needs to have dll-interface to be used by clients of class "type2" #pragma warning (disable : 4267) // conversion from "X" to "Y", possible loss of data #pragma warning (disable : 4275) // non DLL-interface classkey "identifier" used as base for DLL-interface classkey "identifier" + #pragma warning (disable : 4284) // odd return type for operator-> + #pragma warning (disable : 4324) // structure was padded due to __declspec(align( + #pragma warning (disable : 4345) // behavior change: an object of POD type constructed with an initializer of the form () will be default-initialized #pragma warning (disable : 4355) // "this" : used in base member initializer list #pragma warning (disable : 4503) // "identifier" : decorated name length exceeded, name was truncated + #pragma warning (disable : 4510) // default constructor could not be generated #pragma warning (disable : 4511) // copy constructor could not be generated #pragma warning (disable : 4512) // assignment operator could not be generated #pragma warning (disable : 4514) // unreferenced inline removed #pragma warning (disable : 4521) // Disable "multiple copy constructors specified" #pragma warning (disable : 4522) // "class" : multiple assignment operators specified + #pragma warning (disable : 4541) // 'typeid' used on polymorphic type '' with /GR-; unpredictable behavior may result + #pragma warning (disable : 4584) // X is already a base-class of Y + #pragma warning (disable : 4610) // struct can never be instantiated - user defined constructor required + #pragma warning (disable : 4671) // the copy constructor is inaccessible + #pragma warning (disable : 4673) // throwing '' the following types will not be considered at the catch site #pragma warning (disable : 4675) // "method" should be declared "static" and have exactly one parameter + #pragma warning (disable : 4702) // unreachable code + #pragma warning (disable : 4706) // assignment within conditional expression #pragma warning (disable : 4710) // function not inlined #pragma warning (disable : 4711) // function selected for automatic inline expansion #pragma warning (disable : 4786) // identifier truncated in debug info #pragma warning (disable : 4996) // "function": was declared deprecated - #pragma warning (disable : 4197) // top-level volatile in cast is ignored - #pragma warning (disable : 4541) // 'typeid' used on polymorphic type 'boost::exception' - // with /GR-; unpredictable behavior may result - #pragma warning (disable : 4673) // throwing '' the following types will not be considered at the catch site - #pragma warning (disable : 4671) // the copy constructor is inaccessible - #pragma warning (disable : 4584) // X is already a base-class of Y - #pragma warning (disable : 4510) // default constructor could not be generated #endif //BOOST_MSVC diff --git a/boost/container/detail/construct_in_place.hpp b/boost/container/detail/construct_in_place.hpp new file mode 100644 index 0000000000..6cb339519c --- /dev/null +++ b/boost/container/detail/construct_in_place.hpp @@ -0,0 +1,62 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2014-2014. +// +// 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_CONSTRUCT_IN_PLACE_HPP +#define BOOST_CONTAINER_DETAIL_CONSTRUCT_IN_PLACE_HPP + +#ifndef BOOST_CONFIG_HPP +# include <boost/config.hpp> +#endif + +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include <boost/container/allocator_traits.hpp> +#include <boost/container/detail/iterators.hpp> + +namespace boost { +namespace container { + +template<class Allocator, class T, class InpIt> +inline void construct_in_place(Allocator &a, T* dest, InpIt source) +{ boost::container::allocator_traits<Allocator>::construct(a, dest, *source); } + +template<class Allocator, class T, class U, class D> +inline void construct_in_place(Allocator &a, T *dest, value_init_construct_iterator<U, D>) +{ + boost::container::allocator_traits<Allocator>::construct(a, dest); +} + +template <class T, class Difference> +class default_init_construct_iterator; + +template<class Allocator, class T, class U, class D> +inline void construct_in_place(Allocator &a, T *dest, default_init_construct_iterator<U, D>) +{ + boost::container::allocator_traits<Allocator>::construct(a, dest, default_init); +} + +template <class T, class EmplaceFunctor, class Difference> +class emplace_iterator; + +template<class Allocator, class T, class U, class EF, class D> +inline void construct_in_place(Allocator &a, T *dest, emplace_iterator<U, EF, D> ei) +{ + ei.construct_in_place(a, dest); +} + +} //namespace container { +} //namespace boost { + +#endif //#ifndef BOOST_CONTAINER_DETAIL_CONSTRUCT_IN_PLACE_HPP + diff --git a/boost/container/detail/utilities.hpp b/boost/container/detail/copy_move_algo.hpp index 25f035df50..79cbde80a9 100644 --- a/boost/container/detail/utilities.hpp +++ b/boost/container/detail/copy_move_algo.hpp @@ -7,225 +7,37 @@ // See http://www.boost.org/libs/container for documentation. // ////////////////////////////////////////////////////////////////////////////// - #ifndef BOOST_CONTAINER_DETAIL_UTILITIES_HPP #define BOOST_CONTAINER_DETAIL_UTILITIES_HPP -#if defined(_MSC_VER) +#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> - -#include <cstdio> -#include <cstring> //for ::memmove / ::memcpy -#include <boost/type_traits/is_pointer.hpp> -#include <boost/type_traits/is_enum.hpp> -#include <boost/type_traits/is_class.hpp> -#include <boost/type_traits/is_integral.hpp> -#include <boost/type_traits/is_floating_point.hpp> -#include <boost/type_traits/is_copy_constructible.hpp> -#include <boost/type_traits/has_trivial_destructor.hpp> -#include <boost/type_traits/has_trivial_copy.hpp> -#include <boost/type_traits/has_trivial_assign.hpp> -#include <boost/type_traits/is_pod.hpp> -#include <boost/move/core.hpp> -#include <boost/move/utility_core.hpp> -#include <boost/move/iterator.hpp> -#include <boost/assert.hpp> -#include <boost/container/throw_exception.hpp> +// container +#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/container/detail/mpl.hpp> #include <boost/container/detail/type_traits.hpp> -#include <boost/container/allocator_traits.hpp> +// move +#include <boost/move/adl_move_swap.hpp> +#include <boost/move/iterator.hpp> +#include <boost/move/utility_core.hpp> +// other #include <boost/core/no_exceptions_support.hpp> -#include <boost/container/detail/memory_util.hpp> -#include <boost/intrusive/pointer_traits.hpp> -#include <boost/aligned_storage.hpp> -#include <iterator> -#include <utility> //std::distance +// std +#include <cstring> //for emmove/memcpy namespace boost { namespace container { - -////////////////////////////////////////////////////////////////////////////// -// -// swap -// -////////////////////////////////////////////////////////////////////////////// - -namespace container_swap { - -template<class T, bool IsClass = boost::is_class<T>::value > -struct has_member_swap -{ - static const bool value = boost::container::container_detail:: - has_member_function_callable_with_swap<T, T &>::value; -}; - -template<class T> -struct has_member_swap<T, false> -{ - static const bool value = false; -}; - -} //namespace container_swap { - -template<class T> inline -typename container_detail::enable_if_c - <container_swap::has_member_swap<T>::value, void>::type -swap_dispatch(T &left, T &right) //swap using member swap -{ - left.swap(right); // may throw -} - -template<class T> inline -typename container_detail::enable_if_c - <!container_swap::has_member_swap<T>::value/* && boost::has_move_emulation_enabled<T>::value*/, void>::type - swap_dispatch(T &left, T &right) -{ - T temp(boost::move(left)); // may throw - left = boost::move(right); // may throw - right = boost::move(temp); // may throw -} -/* -template<class T> inline -typename container_detail::enable_if_c - <!container_swap::has_member_swap<T>::value && !boost::has_move_emulation_enabled<T>::value, void>::type - swap_dispatch(T &left, T &right) -{ - using std::swap; - swap(left, right); // may throw -} -*/ namespace container_detail { -template <typename T> -inline T* addressof(T& obj) -{ - return static_cast<T*>( - static_cast<void*>( - const_cast<char*>( - &reinterpret_cast<const char&>(obj) - ))); -} - -template<class T> -const T &max_value(const T &a, const T &b) -{ return a > b ? a : b; } - -template<class T> -const T &min_value(const T &a, const T &b) -{ return a < b ? a : b; } - -enum NextCapacityOption { NextCapacityDouble, NextCapacity60Percent }; - -template<class SizeType, NextCapacityOption Option> -struct next_capacity_calculator; - -template<class SizeType> -struct next_capacity_calculator<SizeType, NextCapacityDouble> -{ - static SizeType get(const SizeType max_size - ,const SizeType capacity - ,const SizeType n) - { - const SizeType remaining = max_size - capacity; - if ( remaining < n ) - boost::container::throw_length_error("get_next_capacity, allocator's max_size reached"); - const SizeType additional = max_value(n, capacity); - return ( remaining < additional ) ? max_size : ( capacity + additional ); - } -}; - - -template<class SizeType> -struct next_capacity_calculator<SizeType, NextCapacity60Percent> -{ - static SizeType get(const SizeType max_size - ,const SizeType capacity - ,const SizeType n) - { - const SizeType remaining = max_size - capacity; - if ( remaining < n ) - boost::container::throw_length_error("get_next_capacity, allocator's max_size reached"); - const SizeType m3 = max_size/3; - - if (capacity < m3) - return capacity + max_value(3*(capacity+1)/5, n); - - if (capacity < m3*2) - return capacity + max_value((capacity+1)/2, n); - return max_size; - } -}; - -template <class T> -inline T* to_raw_pointer(T* p) -{ return p; } - -template <class Pointer> -inline typename boost::intrusive::pointer_traits<Pointer>::element_type* - to_raw_pointer(const Pointer &p) -{ return boost::container::container_detail::to_raw_pointer(p.operator->()); } - -template <class T> -inline T* iterator_to_pointer(T* i) -{ return i; } - -template <class Iterator> -inline typename std::iterator_traits<Iterator>::pointer - iterator_to_pointer(const Iterator &i) -{ return i.operator->(); } - -template <class Iterator> -inline - typename boost::intrusive::pointer_traits - <typename std::iterator_traits<Iterator>::pointer>::element_type* - iterator_to_raw_pointer(const Iterator &i) -{ return (to_raw_pointer)((iterator_to_pointer)(i)); } - - -template<class AllocatorType> -inline void swap_alloc(AllocatorType &, AllocatorType &, container_detail::false_type) - BOOST_CONTAINER_NOEXCEPT -{} - -template<class AllocatorType> -inline void swap_alloc(AllocatorType &l, AllocatorType &r, container_detail::true_type) -{ boost::container::swap_dispatch(l, r); } - -template<class AllocatorType> -inline void assign_alloc(AllocatorType &, const AllocatorType &, container_detail::false_type) - BOOST_CONTAINER_NOEXCEPT -{} - -template<class AllocatorType> -inline void assign_alloc(AllocatorType &l, const AllocatorType &r, container_detail::true_type) -{ l = r; } - -template<class AllocatorType> -inline void move_alloc(AllocatorType &, AllocatorType &, container_detail::false_type) - BOOST_CONTAINER_NOEXCEPT -{} - -template<class AllocatorType> -inline void move_alloc(AllocatorType &l, AllocatorType &r, container_detail::true_type) -{ l = ::boost::move(r); } - -//Rounds "orig_size" by excess to round_to bytes -template<class SizeType> -inline SizeType get_rounded_size(SizeType orig_size, SizeType round_to) -{ - return ((orig_size-1)/round_to+1)*round_to; -} - -template <std::size_t OrigSize, std::size_t RoundTo> -struct ct_rounded_size -{ - enum { value = ((OrigSize-1)/RoundTo+1)*RoundTo }; -}; - template<class I> struct are_elements_contiguous { @@ -243,6 +55,15 @@ struct are_elements_contiguous<T*> }; ///////////////////////// +// move iterators +///////////////////////// + +template<class It> +struct are_elements_contiguous< ::boost::move_iterator<It> > + : are_elements_contiguous<It> +{}; + +///////////////////////// // predeclarations ///////////////////////// @@ -304,8 +125,8 @@ template <typename I, typename O> struct are_contiguous_and_same { static const bool is_same_io = - is_same< typename remove_const< typename ::std::iterator_traits<I>::value_type >::type - , typename ::std::iterator_traits<O>::value_type + is_same< typename remove_const< typename ::boost::container::iterator_traits<I>::value_type >::type + , typename ::boost::container::iterator_traits<O>::value_type >::value; static const bool value = is_same_io && are_elements_contiguous<I>::value && @@ -316,112 +137,125 @@ template <typename I, typename O> struct is_memtransfer_copy_assignable { static const bool value = are_contiguous_and_same<I, O>::value && - boost::has_trivial_assign< typename ::std::iterator_traits<I>::value_type >::value; + container_detail::is_trivially_copy_assignable< typename ::boost::container::iterator_traits<I>::value_type >::value; }; template <typename I, typename O> struct is_memtransfer_copy_constructible { static const bool value = are_contiguous_and_same<I, O>::value && - boost::has_trivial_copy< typename ::std::iterator_traits<I>::value_type >::value; + container_detail::is_trivially_copy_constructible< typename ::boost::container::iterator_traits<I>::value_type >::value; }; template <typename I, typename O, typename R> struct enable_if_memtransfer_copy_constructible - : public enable_if_c<container_detail::is_memtransfer_copy_constructible<I, O>::value, R> + : enable_if_c<container_detail::is_memtransfer_copy_constructible<I, O>::value, R> {}; template <typename I, typename O, typename R> struct disable_if_memtransfer_copy_constructible - : public enable_if_c<!container_detail::is_memtransfer_copy_constructible<I, O>::value, R> + : enable_if_c<!container_detail::is_memtransfer_copy_constructible<I, O>::value, R> {}; template <typename I, typename O, typename R> struct enable_if_memtransfer_copy_assignable - : public enable_if_c<container_detail::is_memtransfer_copy_assignable<I, O>::value, R> + : enable_if_c<container_detail::is_memtransfer_copy_assignable<I, O>::value, R> {}; template <typename I, typename O, typename R> struct disable_if_memtransfer_copy_assignable - : public enable_if_c<!container_detail::is_memtransfer_copy_assignable<I, O>::value, R> + : enable_if_c<!container_detail::is_memtransfer_copy_assignable<I, O>::value, R> {}; template <typename I, // I models InputIterator typename F> // F models ForwardIterator -inline F memmove(I f, I l, F r) BOOST_CONTAINER_NOEXCEPT +inline F memmove(I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW { - typedef typename std::iterator_traits<I>::value_type value_type; - typename std::iterator_traits<I>::difference_type n = std::distance(f, l); - ::memmove((iterator_to_raw_pointer)(r), (iterator_to_raw_pointer)(f), sizeof(value_type)*n); - std::advance(r, n); + 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); + std::memmove((iterator_to_raw_pointer)(r), (iterator_to_raw_pointer)(f), sizeof(value_type)*n); + boost::container::iterator_advance(r, n); return r; } template <typename I, // I models InputIterator typename F> // F models ForwardIterator -F memmove_n(I f, typename std::iterator_traits<I>::difference_type n, F r) BOOST_CONTAINER_NOEXCEPT +F memmove_n(I f, typename boost::container::iterator_traits<I>::difference_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW { - typedef typename std::iterator_traits<I>::value_type value_type; - ::memmove((iterator_to_raw_pointer)(r), (iterator_to_raw_pointer)(f), sizeof(value_type)*n); - std::advance(r, 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); + boost::container::iterator_advance(r, n); return r; } template <typename I, // I models InputIterator typename F> // F models ForwardIterator -I memmove_n_source(I f, typename std::iterator_traits<I>::difference_type n, F r) BOOST_CONTAINER_NOEXCEPT +I memmove_n_source(I f, typename boost::container::iterator_traits<I>::difference_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW { - typedef typename std::iterator_traits<I>::value_type value_type; - ::memmove((iterator_to_raw_pointer)(r), (iterator_to_raw_pointer)(f), sizeof(value_type)*n); - std::advance(f, 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); + boost::container::iterator_advance(f, n); return f; } template <typename I, // I models InputIterator typename F> // F models ForwardIterator -I memmove_n_source_dest(I f, typename std::iterator_traits<I>::difference_type n, F &r) BOOST_CONTAINER_NOEXCEPT +I memmove_n_source_dest(I f, typename boost::container::iterator_traits<I>::difference_type n, F &r) BOOST_NOEXCEPT_OR_NOTHROW { - typedef typename std::iterator_traits<I>::value_type value_type; - ::memmove((iterator_to_raw_pointer)(r), (iterator_to_raw_pointer)(f), sizeof(value_type)*n); - std::advance(f, n); - std::advance(r, 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); + boost::container::iterator_advance(f, n); + boost::container::iterator_advance(r, n); return f; } template <typename O> struct is_memzero_initializable { - typedef typename ::std::iterator_traits<O>::value_type value_type; + typedef typename ::boost::container::iterator_traits<O>::value_type value_type; static const bool value = are_elements_contiguous<O>::value && - ( ::boost::is_integral<value_type>::value || ::boost::is_enum<value_type>::value + ( container_detail::is_integral<value_type>::value || container_detail::is_enum<value_type>::value #if defined(BOOST_CONTAINER_MEMZEROED_POINTER_IS_NULL) - || ::boost::is_pointer<value_type>::value + || container_detail::is_pointer<value_type>::value #endif #if defined(BOOST_CONTAINER_MEMZEROED_FLOATING_POINT_IS_ZERO) - || ::boost::is_floating_point<value_type>::value + || container_detail::is_floating_point<value_type>::value #endif #if defined(BOOST_CONTAINER_MEMZEROED_FLOATING_POINT_IS_ZERO) && defined(BOOST_CONTAINER_MEMZEROED_POINTER_IS_NULL) - || ::boost::is_pod<value_type>::value + || container_detail::is_pod<value_type>::value #endif ); }; template <typename O, typename R> struct enable_if_memzero_initializable - : public enable_if_c<container_detail::is_memzero_initializable<O>::value, R> + : enable_if_c<container_detail::is_memzero_initializable<O>::value, R> {}; template <typename O, typename R> struct disable_if_memzero_initializable - : public enable_if_c<!container_detail::is_memzero_initializable<O>::value, R> + : enable_if_c<!container_detail::is_memzero_initializable<O>::value, R> {}; -} //namespace container_detail { +template <typename I, typename R> +struct enable_if_trivially_destructible + : enable_if_c < false/*container_detail::is_trivially_destructible + <typename boost::container::iterator_traits<I>::value_type>::value*/ + , R> +{}; +template <typename I, typename R> +struct disable_if_trivially_destructible + : enable_if_c <true/*!container_detail::is_trivially_destructible + <typename boost::container::iterator_traits<I>::value_type>::value*/ + , R> +{}; + +} //namespace container_detail { ////////////////////////////////////////////////////////////////////////////// // @@ -438,22 +272,22 @@ struct disable_if_memzero_initializable //! //! <b>Returns</b>: r template - <typename A, + <typename Allocator, typename I, // I models InputIterator typename F> // F models ForwardIterator inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F, F>::type - uninitialized_move_alloc(A &a, I f, I l, F r) + uninitialized_move_alloc(Allocator &a, I f, I l, F r) { F back = r; BOOST_TRY{ while (f != l) { - allocator_traits<A>::construct(a, container_detail::iterator_to_raw_pointer(r), boost::move(*f)); + allocator_traits<Allocator>::construct(a, container_detail::iterator_to_raw_pointer(r), boost::move(*f)); ++f; ++r; } } BOOST_CATCH(...){ for (; back != r; ++back){ - allocator_traits<A>::destroy(a, container_detail::iterator_to_raw_pointer(back)); + allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(back)); } BOOST_RETHROW; } @@ -462,11 +296,11 @@ inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F } template - <typename A, + <typename Allocator, typename I, // I models InputIterator typename F> // F models ForwardIterator inline typename container_detail::enable_if_memtransfer_copy_constructible<I, F, F>::type - uninitialized_move_alloc(A &, I f, I l, F r) BOOST_CONTAINER_NOEXCEPT + uninitialized_move_alloc(Allocator &, I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::memmove(f, l, r); } ////////////////////////////////////////////////////////////////////////////// @@ -483,22 +317,22 @@ inline typename container_detail::enable_if_memtransfer_copy_constructible<I, F, //! //! <b>Returns</b>: r template - <typename A, + <typename Allocator, typename I, // I models InputIterator typename F> // F models ForwardIterator inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F, F>::type - uninitialized_move_alloc_n(A &a, I f, typename std::iterator_traits<I>::difference_type n, F r) + uninitialized_move_alloc_n(Allocator &a, I f, typename boost::container::iterator_traits<I>::difference_type n, F r) { F back = r; BOOST_TRY{ while (n--) { - allocator_traits<A>::construct(a, container_detail::iterator_to_raw_pointer(r), boost::move(*f)); + allocator_traits<Allocator>::construct(a, container_detail::iterator_to_raw_pointer(r), boost::move(*f)); ++f; ++r; } } BOOST_CATCH(...){ for (; back != r; ++back){ - allocator_traits<A>::destroy(a, container_detail::iterator_to_raw_pointer(back)); + allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(back)); } BOOST_RETHROW; } @@ -507,11 +341,11 @@ inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F } template - <typename A, + <typename Allocator, typename I, // I models InputIterator typename F> // F models ForwardIterator inline typename container_detail::enable_if_memtransfer_copy_constructible<I, F, F>::type - uninitialized_move_alloc_n(A &, I f, typename std::iterator_traits<I>::difference_type n, F r) BOOST_CONTAINER_NOEXCEPT + uninitialized_move_alloc_n(Allocator &, I f, typename boost::container::iterator_traits<I>::difference_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::memmove_n(f, n, r); } ////////////////////////////////////////////////////////////////////////////// @@ -528,22 +362,22 @@ inline typename container_detail::enable_if_memtransfer_copy_constructible<I, F, //! //! <b>Returns</b>: f (after incremented) template - <typename A, + <typename Allocator, typename I, // I models InputIterator typename F> // F models ForwardIterator inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F, I>::type - uninitialized_move_alloc_n_source(A &a, I f, typename std::iterator_traits<I>::difference_type n, F r) + uninitialized_move_alloc_n_source(Allocator &a, I f, typename boost::container::iterator_traits<I>::difference_type n, F r) { F back = r; BOOST_TRY{ while (n--) { - allocator_traits<A>::construct(a, container_detail::iterator_to_raw_pointer(r), boost::move(*f)); + allocator_traits<Allocator>::construct(a, container_detail::iterator_to_raw_pointer(r), boost::move(*f)); ++f; ++r; } } BOOST_CATCH(...){ for (; back != r; ++back){ - allocator_traits<A>::destroy(a, container_detail::iterator_to_raw_pointer(back)); + allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(back)); } BOOST_RETHROW; } @@ -552,11 +386,11 @@ inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F } template - <typename A, + <typename Allocator, typename I, // I models InputIterator typename F> // F models ForwardIterator inline typename container_detail::enable_if_memtransfer_copy_constructible<I, F, I>::type - uninitialized_move_alloc_n_source(A &, I f, typename std::iterator_traits<I>::difference_type n, F r) BOOST_CONTAINER_NOEXCEPT + uninitialized_move_alloc_n_source(Allocator &, I f, typename boost::container::iterator_traits<I>::difference_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::memmove_n_source(f, n, r); } ////////////////////////////////////////////////////////////////////////////// @@ -573,22 +407,22 @@ inline typename container_detail::enable_if_memtransfer_copy_constructible<I, F, //! //! <b>Returns</b>: r template - <typename A, + <typename Allocator, typename I, // I models InputIterator typename F> // F models ForwardIterator inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F, F>::type - uninitialized_copy_alloc(A &a, I f, I l, F r) + uninitialized_copy_alloc(Allocator &a, I f, I l, F r) { F back = r; BOOST_TRY{ while (f != l) { - allocator_traits<A>::construct(a, container_detail::iterator_to_raw_pointer(r), *f); + allocator_traits<Allocator>::construct(a, container_detail::iterator_to_raw_pointer(r), *f); ++f; ++r; } } BOOST_CATCH(...){ for (; back != r; ++back){ - allocator_traits<A>::destroy(a, container_detail::iterator_to_raw_pointer(back)); + allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(back)); } BOOST_RETHROW; } @@ -597,11 +431,11 @@ inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F } template - <typename A, + <typename Allocator, typename I, // I models InputIterator typename F> // F models ForwardIterator inline typename container_detail::enable_if_memtransfer_copy_constructible<I, F, F>::type - uninitialized_copy_alloc(A &, I f, I l, F r) BOOST_CONTAINER_NOEXCEPT + uninitialized_copy_alloc(Allocator &, I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::memmove(f, l, r); } ////////////////////////////////////////////////////////////////////////////// @@ -618,22 +452,22 @@ inline typename container_detail::enable_if_memtransfer_copy_constructible<I, F, //! //! <b>Returns</b>: r template - <typename A, + <typename Allocator, typename I, // I models InputIterator typename F> // F models ForwardIterator inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F, F>::type - uninitialized_copy_alloc_n(A &a, I f, typename std::iterator_traits<I>::difference_type n, F r) + uninitialized_copy_alloc_n(Allocator &a, I f, typename boost::container::iterator_traits<I>::difference_type n, F r) { F back = r; BOOST_TRY{ while (n--) { - allocator_traits<A>::construct(a, container_detail::iterator_to_raw_pointer(r), *f); + allocator_traits<Allocator>::construct(a, container_detail::iterator_to_raw_pointer(r), *f); ++f; ++r; } } BOOST_CATCH(...){ for (; back != r; ++back){ - allocator_traits<A>::destroy(a, container_detail::iterator_to_raw_pointer(back)); + allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(back)); } BOOST_RETHROW; } @@ -642,11 +476,11 @@ inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F } template - <typename A, + <typename Allocator, typename I, // I models InputIterator typename F> // F models ForwardIterator inline typename container_detail::enable_if_memtransfer_copy_constructible<I, F, F>::type - uninitialized_copy_alloc_n(A &, I f, typename std::iterator_traits<I>::difference_type n, F r) BOOST_CONTAINER_NOEXCEPT + uninitialized_copy_alloc_n(Allocator &, I f, typename boost::container::iterator_traits<I>::difference_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::memmove_n(f, n, r); } ////////////////////////////////////////////////////////////////////////////// @@ -663,22 +497,22 @@ inline typename container_detail::enable_if_memtransfer_copy_constructible<I, F, //! //! <b>Returns</b>: f (after incremented) template - <typename A, + <typename Allocator, typename I, // I models InputIterator typename F> // F models ForwardIterator inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F, I>::type - uninitialized_copy_alloc_n_source(A &a, I f, typename std::iterator_traits<I>::difference_type n, F r) + uninitialized_copy_alloc_n_source(Allocator &a, I f, typename boost::container::iterator_traits<I>::difference_type n, F r) { F back = r; BOOST_TRY{ while (n--) { - allocator_traits<A>::construct(a, container_detail::iterator_to_raw_pointer(r), *f); + allocator_traits<Allocator>::construct(a, container_detail::iterator_to_raw_pointer(r), *f); ++f; ++r; } } BOOST_CATCH(...){ for (; back != r; ++back){ - allocator_traits<A>::destroy(a, container_detail::iterator_to_raw_pointer(back)); + allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(back)); } BOOST_RETHROW; } @@ -687,11 +521,11 @@ inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F } template - <typename A, + <typename Allocator, typename I, // I models InputIterator typename F> // F models ForwardIterator inline typename container_detail::enable_if_memtransfer_copy_constructible<I, F, I>::type - uninitialized_copy_alloc_n_source(A &, I f, typename std::iterator_traits<I>::difference_type n, F r) BOOST_CONTAINER_NOEXCEPT + uninitialized_copy_alloc_n_source(Allocator &, I f, typename boost::container::iterator_traits<I>::difference_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::memmove_n_source(f, n, r); } ////////////////////////////////////////////////////////////////////////////// @@ -708,21 +542,21 @@ inline typename container_detail::enable_if_memtransfer_copy_constructible<I, F, //! //! <b>Returns</b>: r template - <typename A, + <typename Allocator, typename F> // F models ForwardIterator inline typename container_detail::disable_if_memzero_initializable<F, F>::type - uninitialized_value_init_alloc_n(A &a, typename allocator_traits<A>::difference_type n, F r) + uninitialized_value_init_alloc_n(Allocator &a, typename allocator_traits<Allocator>::difference_type n, F r) { F back = r; BOOST_TRY{ while (n--) { - allocator_traits<A>::construct(a, container_detail::iterator_to_raw_pointer(r)); + allocator_traits<Allocator>::construct(a, container_detail::iterator_to_raw_pointer(r)); ++r; } } BOOST_CATCH(...){ for (; back != r; ++back){ - allocator_traits<A>::destroy(a, container_detail::iterator_to_raw_pointer(back)); + allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(back)); } BOOST_RETHROW; } @@ -731,14 +565,14 @@ inline typename container_detail::disable_if_memzero_initializable<F, F>::type } template - <typename A, + <typename Allocator, typename F> // F models ForwardIterator inline typename container_detail::enable_if_memzero_initializable<F, F>::type - uninitialized_value_init_alloc_n(A &, typename allocator_traits<A>::difference_type n, F r) + uninitialized_value_init_alloc_n(Allocator &, typename allocator_traits<Allocator>::difference_type n, F r) { - typedef typename std::iterator_traits<F>::value_type value_type; - ::memset((void*)container_detail::iterator_to_raw_pointer(r), 0, sizeof(value_type)*n); - std::advance(r, n); + 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); + boost::container::iterator_advance(r, n); return r; } @@ -756,20 +590,20 @@ inline typename container_detail::enable_if_memzero_initializable<F, F>::type //! //! <b>Returns</b>: r template - <typename A, + <typename Allocator, typename F> // F models ForwardIterator -inline F uninitialized_default_init_alloc_n(A &a, typename allocator_traits<A>::difference_type n, F r) +inline F uninitialized_default_init_alloc_n(Allocator &a, typename allocator_traits<Allocator>::difference_type n, F r) { F back = r; BOOST_TRY{ while (n--) { - allocator_traits<A>::construct(a, container_detail::iterator_to_raw_pointer(r), default_init); + allocator_traits<Allocator>::construct(a, container_detail::iterator_to_raw_pointer(r), default_init); ++r; } } BOOST_CATCH(...){ for (; back != r; ++back){ - allocator_traits<A>::destroy(a, container_detail::iterator_to_raw_pointer(back)); + allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(back)); } BOOST_RETHROW; } @@ -791,21 +625,21 @@ inline F uninitialized_default_init_alloc_n(A &a, typename allocator_traits<A>:: //! //! <b>Returns</b>: r template - <typename A, + <typename Allocator, typename F, // F models ForwardIterator typename T> -inline void uninitialized_fill_alloc(A &a, F f, F l, const T &t) +inline void uninitialized_fill_alloc(Allocator &a, F f, F l, const T &t) { F back = f; BOOST_TRY{ while (f != l) { - allocator_traits<A>::construct(a, container_detail::iterator_to_raw_pointer(f), t); + allocator_traits<Allocator>::construct(a, container_detail::iterator_to_raw_pointer(f), t); ++f; } } BOOST_CATCH(...){ for (; back != l; ++back){ - allocator_traits<A>::destroy(a, container_detail::iterator_to_raw_pointer(back)); + allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(back)); } BOOST_RETHROW; } @@ -827,21 +661,21 @@ inline void uninitialized_fill_alloc(A &a, F f, F l, const T &t) //! //! <b>Returns</b>: r template - <typename A, + <typename Allocator, typename T, typename F> // F models ForwardIterator -inline F uninitialized_fill_alloc_n(A &a, const T &v, typename allocator_traits<A>::difference_type n, F r) +inline F uninitialized_fill_alloc_n(Allocator &a, const T &v, typename allocator_traits<Allocator>::difference_type n, F r) { F back = r; BOOST_TRY{ while (n--) { - allocator_traits<A>::construct(a, container_detail::iterator_to_raw_pointer(r), v); + allocator_traits<Allocator>::construct(a, container_detail::iterator_to_raw_pointer(r), v); ++r; } } BOOST_CATCH(...){ for (; back != r; ++back){ - allocator_traits<A>::destroy(a, container_detail::iterator_to_raw_pointer(back)); + allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(back)); } BOOST_RETHROW; } @@ -872,7 +706,7 @@ template <typename I, // I models InputIterator typename F> // F models ForwardIterator inline typename container_detail::enable_if_memtransfer_copy_assignable<I, F, F>::type - copy(I f, I l, F r) BOOST_CONTAINER_NOEXCEPT + copy(I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::memmove(f, l, r); } ////////////////////////////////////////////////////////////////////////////// @@ -885,7 +719,7 @@ template <typename I, // I models InputIterator typename F> // F models ForwardIterator inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, F>::type - copy_n(I f, typename std::iterator_traits<I>::difference_type n, F r) + copy_n(I f, typename boost::container::iterator_traits<I>::difference_type n, F r) { while (n--) { *r = *f; @@ -898,7 +732,7 @@ template <typename I, // I models InputIterator typename F> // F models ForwardIterator inline typename container_detail::enable_if_memtransfer_copy_assignable<I, F, F>::type - copy_n(I f, typename std::iterator_traits<I>::difference_type n, F r) BOOST_CONTAINER_NOEXCEPT + copy_n(I f, typename boost::container::iterator_traits<I>::difference_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::memmove_n(f, n, r); } ////////////////////////////////////////////////////////////////////////////// @@ -911,7 +745,7 @@ template <typename I, // I models InputIterator typename F> // F models ForwardIterator inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, I>::type - copy_n_source(I f, typename std::iterator_traits<I>::difference_type n, F r) + copy_n_source(I f, typename boost::container::iterator_traits<I>::difference_type n, F r) { while (n--) { *r = *f; @@ -924,7 +758,7 @@ template <typename I, // I models InputIterator typename F> // F models ForwardIterator inline typename container_detail::enable_if_memtransfer_copy_assignable<I, F, I>::type - copy_n_source(I f, typename std::iterator_traits<I>::difference_type n, F r) BOOST_CONTAINER_NOEXCEPT + copy_n_source(I f, typename boost::container::iterator_traits<I>::difference_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::memmove_n_source(f, n, r); } ////////////////////////////////////////////////////////////////////////////// @@ -937,7 +771,7 @@ template <typename I, // I models InputIterator typename F> // F models ForwardIterator inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, I>::type - copy_n_source_dest(I f, typename std::iterator_traits<I>::difference_type n, F &r) + copy_n_source_dest(I f, typename boost::container::iterator_traits<I>::difference_type n, F &r) { while (n--) { *r = *f; @@ -950,7 +784,7 @@ template <typename I, // I models InputIterator typename F> // F models ForwardIterator inline typename container_detail::enable_if_memtransfer_copy_assignable<I, F, I>::type - copy_n_source_dest(I f, typename std::iterator_traits<I>::difference_type n, F &r) BOOST_CONTAINER_NOEXCEPT + copy_n_source_dest(I f, typename boost::container::iterator_traits<I>::difference_type n, F &r) BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::memmove_n_source_dest(f, n, r); } ////////////////////////////////////////////////////////////////////////////// @@ -976,7 +810,7 @@ template <typename I, // I models InputIterator typename F> // F models ForwardIterator inline typename container_detail::enable_if_memtransfer_copy_assignable<I, F, F>::type - move(I f, I l, F r) BOOST_CONTAINER_NOEXCEPT + move(I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::memmove(f, l, r); } ////////////////////////////////////////////////////////////////////////////// @@ -989,7 +823,7 @@ template <typename I, // I models InputIterator typename F> // F models ForwardIterator inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, F>::type - move_n(I f, typename std::iterator_traits<I>::difference_type n, F r) + move_n(I f, typename boost::container::iterator_traits<I>::difference_type n, F r) { while (n--) { *r = ::boost::move(*f); @@ -1002,12 +836,45 @@ template <typename I, // I models InputIterator typename F> // F models ForwardIterator inline typename container_detail::enable_if_memtransfer_copy_assignable<I, F, F>::type - move_n(I f, typename std::iterator_traits<I>::difference_type n, F r) BOOST_CONTAINER_NOEXCEPT + move_n(I f, typename boost::container::iterator_traits<I>::difference_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::memmove_n(f, n, r); } + ////////////////////////////////////////////////////////////////////////////// // -// move_n_source +// move_backward +// +////////////////////////////////////////////////////////////////////////////// + +template +<typename I, // I models BidirectionalIterator +typename F> // F models ForwardIterator +inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, F>::type + move_backward(I f, I l, F r) +{ + while (f != l) { + --l; --r; + *r = ::boost::move(*l); + } + return r; +} + +template +<typename I, // I models InputIterator +typename F> // F models ForwardIterator +inline typename container_detail::enable_if_memtransfer_copy_assignable<I, F, F>::type + move_backward(I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW +{ + 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); + return r; +} + +////////////////////////////////////////////////////////////////////////////// +// +// move_n_source_dest // ////////////////////////////////////////////////////////////////////////////// @@ -1015,7 +882,7 @@ template <typename I // I models InputIterator ,typename F> // F models ForwardIterator inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, I>::type - move_n_source(I f, typename std::iterator_traits<I>::difference_type n, F r) + move_n_source_dest(I f, typename boost::container::iterator_traits<I>::difference_type n, F &r) { while (n--) { *r = ::boost::move(*f); @@ -1028,12 +895,12 @@ template <typename I // I models InputIterator ,typename F> // F models ForwardIterator inline typename container_detail::enable_if_memtransfer_copy_assignable<I, F, I>::type - move_n_source(I f, typename std::iterator_traits<I>::difference_type n, F r) BOOST_CONTAINER_NOEXCEPT -{ return container_detail::memmove_n_source(f, n, r); } + move_n_source_dest(I f, typename boost::container::iterator_traits<I>::difference_type n, F &r) BOOST_NOEXCEPT_OR_NOTHROW +{ return container_detail::memmove_n_source_dest(f, n, r); } ////////////////////////////////////////////////////////////////////////////// // -// move_n_source_dest +// move_n_source // ////////////////////////////////////////////////////////////////////////////// @@ -1041,7 +908,7 @@ template <typename I // I models InputIterator ,typename F> // F models ForwardIterator inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, I>::type - move_n_source_dest(I f, typename std::iterator_traits<I>::difference_type n, F &r) + move_n_source(I f, typename boost::container::iterator_traits<I>::difference_type n, F r) { while (n--) { *r = ::boost::move(*f); @@ -1054,33 +921,34 @@ template <typename I // I models InputIterator ,typename F> // F models ForwardIterator inline typename container_detail::enable_if_memtransfer_copy_assignable<I, F, I>::type - move_n_source_dest(I f, typename std::iterator_traits<I>::difference_type n, F &r) BOOST_CONTAINER_NOEXCEPT -{ return container_detail::memmove_n_source_dest(f, n, r); } + move_n_source(I f, typename boost::container::iterator_traits<I>::difference_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW +{ return container_detail::memmove_n_source(f, n, r); } ////////////////////////////////////////////////////////////////////////////// // -// destroy_n +// destroy_alloc_n // ////////////////////////////////////////////////////////////////////////////// template - <typename A - ,typename I> // I models InputIterator -inline void destroy_alloc_n(A &a, I f, typename std::iterator_traits<I>::difference_type n - ,typename boost::container::container_detail::enable_if_c - < !boost::has_trivial_destructor<typename std::iterator_traits<I>::value_type>::value >::type* = 0) + <typename Allocator + ,typename I // I models InputIterator + ,typename U> // U models unsigned integral constant +inline typename container_detail::disable_if_trivially_destructible<I, void>::type + destroy_alloc_n(Allocator &a, I f, U n) { while(n--){ - allocator_traits<A>::destroy(a, container_detail::iterator_to_raw_pointer(f++)); + allocator_traits<Allocator>::destroy(a, container_detail::iterator_to_raw_pointer(f)); + ++f; } } template - <typename A - ,typename I> // I models InputIterator -inline void destroy_alloc_n(A &, I, typename std::iterator_traits<I>::difference_type - ,typename boost::container::container_detail::enable_if_c - < boost::has_trivial_destructor<typename std::iterator_traits<I>::value_type>::value >::type* = 0) + <typename Allocator + ,typename I // I models InputIterator + ,typename U> // U models unsigned integral constant +inline typename container_detail::enable_if_trivially_destructible<I, void>::type + destroy_alloc_n(Allocator &, I, U) {} ////////////////////////////////////////////////////////////////////////////// @@ -1091,17 +959,17 @@ inline void destroy_alloc_n(A &, I, typename std::iterator_traits<I>::difference template <std::size_t MaxTmpBytes - ,typename A + ,typename Allocator ,typename F // F models ForwardIterator ,typename G // G models ForwardIterator > inline typename container_detail::disable_if_memtransfer_copy_assignable<F, G, void>::type - deep_swap_alloc_n( A &a, F short_range_f, typename allocator_traits<A>::size_type n_i - , G large_range_f, typename allocator_traits<A>::size_type n_j) + deep_swap_alloc_n( Allocator &a, F short_range_f, typename allocator_traits<Allocator>::size_type n_i + , G large_range_f, typename allocator_traits<Allocator>::size_type n_j) { - typename allocator_traits<A>::size_type n = 0; + typename allocator_traits<Allocator>::size_type n = 0; for (; n != n_i ; ++short_range_f, ++large_range_f, ++n){ - boost::container::swap_dispatch(*short_range_f, *large_range_f); + boost::adl_move_swap(*short_range_f, *large_range_f); } boost::container::uninitialized_move_alloc_n(a, large_range_f, n_j - n_i, short_range_f); // may throw boost::container::destroy_alloc_n(a, large_range_f, n_j - n_i); @@ -1111,18 +979,18 @@ static const std::size_t DeepSwapAllocNMaxStorage = std::size_t(1) << std::size_ template <std::size_t MaxTmpBytes - ,typename A + ,typename Allocator ,typename F // F models ForwardIterator ,typename G // G models ForwardIterator > inline typename container_detail::enable_if_c < container_detail::is_memtransfer_copy_assignable<F, G>::value && (MaxTmpBytes <= DeepSwapAllocNMaxStorage) && false , void>::type - deep_swap_alloc_n( A &a, F short_range_f, typename allocator_traits<A>::size_type n_i - , G large_range_f, typename allocator_traits<A>::size_type n_j) + deep_swap_alloc_n( Allocator &a, F short_range_f, typename allocator_traits<Allocator>::size_type n_i + , G large_range_f, typename allocator_traits<Allocator>::size_type n_j) { - typedef typename allocator_traits<A>::value_type value_type; - typedef typename boost::aligned_storage + typedef typename allocator_traits<Allocator>::value_type value_type; + typedef typename container_detail::aligned_storage <MaxTmpBytes, container_detail::alignment_of<value_type>::value>::type storage_type; storage_type storage; @@ -1130,29 +998,29 @@ inline typename container_detail::enable_if_c 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)); - ::memcpy(stora_ptr, large_ptr, n_i_bytes); - ::memcpy(large_ptr, short_ptr, n_i_bytes); - ::memcpy(short_ptr, stora_ptr, n_i_bytes); - std::advance(large_range_f, n_i); - std::advance(short_range_f, n_i); + 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); + boost::container::iterator_advance(large_range_f, n_i); + boost::container::iterator_advance(short_range_f, n_i); boost::container::uninitialized_move_alloc_n(a, large_range_f, n_j - n_i, short_range_f); // may throw boost::container::destroy_alloc_n(a, large_range_f, n_j - n_i); } template <std::size_t MaxTmpBytes - ,typename A + ,typename Allocator ,typename F // F models ForwardIterator ,typename G // G models ForwardIterator > inline typename container_detail::enable_if_c < container_detail::is_memtransfer_copy_assignable<F, G>::value && true//(MaxTmpBytes > DeepSwapAllocNMaxStorage) , void>::type - deep_swap_alloc_n( A &a, F short_range_f, typename allocator_traits<A>::size_type n_i - , G large_range_f, typename allocator_traits<A>::size_type n_j) + deep_swap_alloc_n( Allocator &a, F short_range_f, typename allocator_traits<Allocator>::size_type n_i + , G large_range_f, typename allocator_traits<Allocator>::size_type n_j) { - typedef typename allocator_traits<A>::value_type value_type; - typedef typename boost::aligned_storage + typedef typename allocator_traits<Allocator>::value_type value_type; + typedef typename container_detail::aligned_storage <DeepSwapAllocNMaxStorage, container_detail::alignment_of<value_type>::value>::type storage_type; storage_type storage; const std::size_t sizeof_storage = sizeof(storage); @@ -1173,39 +1041,39 @@ inline typename container_detail::enable_if_c case 4: break; case 0: do{ - ::memcpy(stora_ptr, large_ptr, sizeof_storage); - ::memcpy(large_ptr, short_ptr, sizeof_storage); - ::memcpy(short_ptr, stora_ptr, sizeof_storage); + std::memcpy(stora_ptr, large_ptr, sizeof_storage); + std::memcpy(large_ptr, short_ptr, sizeof_storage); + std::memcpy(short_ptr, stora_ptr, sizeof_storage); large_ptr += sizeof_storage; short_ptr += sizeof_storage; BOOST_CONTAINER_FALLTHOUGH case 3: - ::memcpy(stora_ptr, large_ptr, sizeof_storage); - ::memcpy(large_ptr, short_ptr, sizeof_storage); - ::memcpy(short_ptr, stora_ptr, sizeof_storage); + std::memcpy(stora_ptr, large_ptr, sizeof_storage); + std::memcpy(large_ptr, short_ptr, sizeof_storage); + std::memcpy(short_ptr, stora_ptr, sizeof_storage); large_ptr += sizeof_storage; short_ptr += sizeof_storage; BOOST_CONTAINER_FALLTHOUGH case 2: - ::memcpy(stora_ptr, large_ptr, sizeof_storage); - ::memcpy(large_ptr, short_ptr, sizeof_storage); - ::memcpy(short_ptr, stora_ptr, sizeof_storage); + std::memcpy(stora_ptr, large_ptr, sizeof_storage); + std::memcpy(large_ptr, short_ptr, sizeof_storage); + std::memcpy(short_ptr, stora_ptr, sizeof_storage); large_ptr += sizeof_storage; short_ptr += sizeof_storage; BOOST_CONTAINER_FALLTHOUGH case 1: - ::memcpy(stora_ptr, large_ptr, sizeof_storage); - ::memcpy(large_ptr, short_ptr, sizeof_storage); - ::memcpy(short_ptr, stora_ptr, sizeof_storage); + std::memcpy(stora_ptr, large_ptr, sizeof_storage); + std::memcpy(large_ptr, short_ptr, sizeof_storage); + std::memcpy(short_ptr, stora_ptr, sizeof_storage); large_ptr += sizeof_storage; short_ptr += sizeof_storage; } while(--n); } - ::memcpy(stora_ptr, large_ptr, szt_rem); - ::memcpy(large_ptr, short_ptr, szt_rem); - ::memcpy(short_ptr, stora_ptr, szt_rem); - std::advance(large_range_f, n_i); - std::advance(short_range_f, n_i); + std::memcpy(stora_ptr, large_ptr, szt_rem); + std::memcpy(large_ptr, short_ptr, szt_rem); + std::memcpy(short_ptr, stora_ptr, szt_rem); + boost::container::iterator_advance(large_range_f, n_i); + boost::container::iterator_advance(short_range_f, n_i); boost::container::uninitialized_move_alloc_n(a, large_range_f, n_j - n_i, short_range_f); // may throw boost::container::destroy_alloc_n(a, large_range_f, n_j - n_i); } @@ -1218,12 +1086,12 @@ inline typename container_detail::enable_if_c ////////////////////////////////////////////////////////////////////////////// template - <typename A + <typename Allocator ,typename I // F models InputIterator ,typename O // G models OutputIterator > -void copy_assign_range_alloc_n( A &a, I inp_start, typename allocator_traits<A>::size_type n_i - , O out_start, typename allocator_traits<A>::size_type n_o ) +void copy_assign_range_alloc_n( Allocator &a, I inp_start, typename allocator_traits<Allocator>::size_type n_i + , O out_start, typename allocator_traits<Allocator>::size_type n_o ) { if (n_o < n_i){ inp_start = boost::container::copy_n_source_dest(inp_start, n_o, out_start); // may throw @@ -1242,12 +1110,12 @@ void copy_assign_range_alloc_n( A &a, I inp_start, typename allocator_traits<A>: ////////////////////////////////////////////////////////////////////////////// template - <typename A + <typename Allocator ,typename I // F models InputIterator ,typename O // G models OutputIterator > -void move_assign_range_alloc_n( A &a, I inp_start, typename allocator_traits<A>::size_type n_i - , O out_start, typename allocator_traits<A>::size_type n_o ) +void move_assign_range_alloc_n( Allocator &a, I inp_start, typename allocator_traits<Allocator>::size_type n_i + , O out_start, typename allocator_traits<Allocator>::size_type n_o ) { if (n_o < n_i){ inp_start = boost::container::move_n_source_dest(inp_start, n_o, out_start); // may throw @@ -1262,6 +1130,4 @@ void move_assign_range_alloc_n( A &a, I inp_start, typename allocator_traits<A>: } //namespace container { } //namespace boost { -#include <boost/container/detail/config_end.hpp> - #endif //#ifndef BOOST_CONTAINER_DETAIL_UTILITIES_HPP diff --git a/boost/container/detail/destroyers.hpp b/boost/container/detail/destroyers.hpp index ea9b617437..52b44c0363 100644 --- a/boost/container/detail/destroyers.hpp +++ b/boost/container/detail/destroyers.hpp @@ -13,16 +13,20 @@ #ifndef BOOST_CONTAINER_DESTROYERS_HPP #define BOOST_CONTAINER_DESTROYERS_HPP -#if defined(_MSC_VER) +#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> -#include <boost/container/detail/version_type.hpp> -#include <boost/container/detail/utilities.hpp> #include <boost/container/allocator_traits.hpp> +#include <boost/container/detail/to_raw_pointer.hpp> +#include <boost/container/detail/version_type.hpp> namespace boost { namespace container { @@ -30,22 +34,20 @@ namespace container_detail { //!A deleter for scoped_ptr that deallocates the memory //!allocated for an object using a STL allocator. -template <class A> +template <class Allocator> struct scoped_deallocator { - typedef allocator_traits<A> allocator_traits_type; + typedef allocator_traits<Allocator> allocator_traits_type; typedef typename allocator_traits_type::pointer pointer; typedef container_detail::integral_constant<unsigned, boost::container::container_detail:: - version<A>::value> alloc_version; - typedef container_detail::integral_constant<unsigned, 1> allocator_v1; - typedef container_detail::integral_constant<unsigned, 2> allocator_v2; + version<Allocator>::value> alloc_version; private: - void priv_deallocate(allocator_v1) + void priv_deallocate(version_1) { m_alloc.deallocate(m_ptr, 1); } - void priv_deallocate(allocator_v2) + void priv_deallocate(version_2) { m_alloc.deallocate_one(m_ptr); } BOOST_MOVABLE_BUT_NOT_COPYABLE(scoped_deallocator) @@ -53,9 +55,9 @@ struct scoped_deallocator public: pointer m_ptr; - A& m_alloc; + Allocator& m_alloc; - scoped_deallocator(pointer p, A& a) + scoped_deallocator(pointer p, Allocator& a) : m_ptr(p), m_alloc(a) {} @@ -143,8 +145,6 @@ struct scoped_destroy_deallocator typedef container_detail::integral_constant<unsigned, boost::container::container_detail:: version<Allocator>::value> alloc_version; - typedef container_detail::integral_constant<unsigned, 1> allocator_v1; - typedef container_detail::integral_constant<unsigned, 2> allocator_v2; scoped_destroy_deallocator(pointer p, Allocator& a) : m_ptr(p), m_alloc(a) {} @@ -162,10 +162,10 @@ struct scoped_destroy_deallocator private: - void priv_deallocate(const pointer &p, allocator_v1) + void priv_deallocate(const pointer &p, version_1) { AllocTraits::deallocate(m_alloc, p, 1); } - void priv_deallocate(const pointer &p, allocator_v2) + void priv_deallocate(const pointer &p, version_2) { m_alloc.deallocate_one(p); } pointer m_ptr; @@ -239,13 +239,13 @@ struct null_scoped_destructor_n {} }; -template<class A> +template<class Allocator> class scoped_destructor { - typedef boost::container::allocator_traits<A> AllocTraits; + typedef boost::container::allocator_traits<Allocator> AllocTraits; public: - typedef typename A::value_type value_type; - scoped_destructor(A &a, value_type *pv) + typedef typename Allocator::value_type value_type; + scoped_destructor(Allocator &a, value_type *pv) : pv_(pv), a_(a) {} @@ -266,17 +266,17 @@ class scoped_destructor private: value_type *pv_; - A &a_; + Allocator &a_; }; -template<class A> +template<class Allocator> class value_destructor { - typedef boost::container::allocator_traits<A> AllocTraits; + typedef boost::container::allocator_traits<Allocator> AllocTraits; public: - typedef typename A::value_type value_type; - value_destructor(A &a, value_type &rv) + typedef typename Allocator::value_type value_type; + value_destructor(Allocator &a, value_type &rv) : rv_(rv), a_(a) {} @@ -287,7 +287,7 @@ class value_destructor private: value_type &rv_; - A &a_; + Allocator &a_; }; template <class Allocator> @@ -299,21 +299,19 @@ class allocator_destroyer typedef container_detail::integral_constant<unsigned, boost::container::container_detail:: version<Allocator>::value> alloc_version; - typedef container_detail::integral_constant<unsigned, 1> allocator_v1; - typedef container_detail::integral_constant<unsigned, 2> allocator_v2; private: Allocator & a_; private: - void priv_deallocate(const pointer &p, allocator_v1) + void priv_deallocate(const pointer &p, version_1) { AllocTraits::deallocate(a_,p, 1); } - void priv_deallocate(const pointer &p, allocator_v2) + void priv_deallocate(const pointer &p, version_2) { a_.deallocate_one(p); } public: - allocator_destroyer(Allocator &a) + explicit allocator_destroyer(Allocator &a) : a_(a) {} @@ -324,41 +322,41 @@ class allocator_destroyer } }; -template <class A> +template <class Allocator> class allocator_destroyer_and_chain_builder { - typedef allocator_traits<A> allocator_traits_type; + typedef allocator_traits<Allocator> allocator_traits_type; typedef typename allocator_traits_type::value_type value_type; - typedef typename A::multiallocation_chain multiallocation_chain; + typedef typename Allocator::multiallocation_chain multiallocation_chain; - A & a_; + Allocator & a_; multiallocation_chain &c_; public: - allocator_destroyer_and_chain_builder(A &a, multiallocation_chain &c) + allocator_destroyer_and_chain_builder(Allocator &a, multiallocation_chain &c) : a_(a), c_(c) {} - void operator()(const typename A::pointer &p) + void operator()(const typename Allocator::pointer &p) { - allocator_traits<A>::destroy(a_, container_detail::to_raw_pointer(p)); + allocator_traits<Allocator>::destroy(a_, container_detail::to_raw_pointer(p)); c_.push_back(p); } }; -template <class A> +template <class Allocator> class allocator_multialloc_chain_node_deallocator { - typedef allocator_traits<A> allocator_traits_type; + typedef allocator_traits<Allocator> allocator_traits_type; typedef typename allocator_traits_type::value_type value_type; - typedef typename A::multiallocation_chain multiallocation_chain; - typedef allocator_destroyer_and_chain_builder<A> chain_builder; + typedef typename Allocator::multiallocation_chain multiallocation_chain; + typedef allocator_destroyer_and_chain_builder<Allocator> chain_builder; - A & a_; + Allocator & a_; multiallocation_chain c_; public: - allocator_multialloc_chain_node_deallocator(A &a) + allocator_multialloc_chain_node_deallocator(Allocator &a) : a_(a), c_() {} diff --git a/boost/container/detail/flat_tree.hpp b/boost/container/detail/flat_tree.hpp index a6f7568b43..a94043c6bd 100644 --- a/boost/container/detail/flat_tree.hpp +++ b/boost/container/detail/flat_tree.hpp @@ -11,7 +11,11 @@ #ifndef BOOST_CONTAINER_FLAT_TREE_HPP #define BOOST_CONTAINER_FLAT_TREE_HPP -#if defined(_MSC_VER) +#ifndef BOOST_CONFIG_HPP +# include <boost/config.hpp> +#endif + +#if defined(BOOST_HAS_PRAGMA_ONCE) # pragma once #endif @@ -20,29 +24,29 @@ #include <boost/container/container_fwd.hpp> -#include <algorithm> -#include <functional> -#include <utility> - -#include <boost/type_traits/has_trivial_destructor.hpp> #include <boost/move/utility_core.hpp> -#include <boost/container/detail/utilities.hpp> #include <boost/container/detail/pair.hpp> #include <boost/container/vector.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/allocator_traits.hpp> #ifdef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER #include <boost/intrusive/pointer_traits.hpp> #endif -#include <boost/aligned_storage.hpp> +#include <boost/container/detail/type_traits.hpp> #include <boost/move/make_unique.hpp> +#include <boost/move/adl_move_swap.hpp> +#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +#include <boost/move/detail/fwd_macros.hpp> +#endif -namespace boost { +#include <boost/intrusive/detail/minimal_pair_header.hpp> //pair +namespace boost { namespace container { - namespace container_detail { template<class Compare, class Value, class KeyOfValue> @@ -78,30 +82,29 @@ template<class Pointer> struct get_flat_tree_iterators { #ifdef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER - typedef Pointer iterator; + typedef Pointer iterator; typedef typename boost::intrusive:: - pointer_traits<Pointer>::element_type iterator_element_type; + pointer_traits<Pointer>::element_type iterator_element_type; typedef typename boost::intrusive:: pointer_traits<Pointer>:: template - rebind_pointer<const iterator_element_type>::type const_iterator; + rebind_pointer<const iterator_element_type>::type const_iterator; #else //BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER typedef typename boost::container::container_detail:: - vec_iterator<Pointer, false> iterator; + vec_iterator<Pointer, false> iterator; typedef typename boost::container::container_detail:: - vec_iterator<Pointer, true > const_iterator; + vec_iterator<Pointer, true > const_iterator; #endif //BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER - typedef boost::container::container_detail:: - reverse_iterator<iterator> reverse_iterator; - typedef boost::container::container_detail:: - reverse_iterator<const_iterator> const_reverse_iterator; + typedef boost::container::reverse_iterator<iterator> reverse_iterator; + typedef boost::container::reverse_iterator<const_iterator> const_reverse_iterator; }; template <class Key, class Value, class KeyOfValue, - class Compare, class A> + class Compare, class Allocator> class flat_tree { - typedef boost::container::vector<Value, A> vector_t; - typedef A allocator_t; + typedef boost::container::vector<Value, Allocator> vector_t; + typedef Allocator allocator_t; + typedef allocator_traits<Allocator> allocator_traits_type; public: typedef flat_tree_value_compare<Compare, Value, KeyOfValue> value_compare; @@ -126,11 +129,11 @@ class flat_tree : value_compare(boost::move(static_cast<value_compare&>(d))), m_vect(boost::move(d.m_vect)) {} - Data(const Data &d, const A &a) + Data(const Data &d, const Allocator &a) : value_compare(static_cast<const value_compare&>(d)), m_vect(d.m_vect, a) {} - Data(BOOST_RV_REF(Data) d, const A &a) + 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) {} @@ -163,7 +166,7 @@ class flat_tree void swap(Data &d) { value_compare& mycomp = *this, & othercomp = d; - boost::container::swap_dispatch(mycomp, othercomp); + boost::adl_move_swap(mycomp, othercomp); this->m_vect.swap(d.m_vect); } @@ -265,8 +268,10 @@ class flat_tree flat_tree& operator=(BOOST_COPY_ASSIGN_REF(flat_tree) x) { m_data = x.m_data; return *this; } - flat_tree& operator=(BOOST_RV_REF(flat_tree) mx) - { m_data = boost::move(mx.m_data); return *this; } + flat_tree& operator=(BOOST_RV_REF(flat_tree) x) + BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value + && boost::container::container_detail::is_nothrow_move_assignable<Compare>::value ) + { m_data = boost::move(x.m_data); return *this; } public: // accessors: @@ -331,6 +336,8 @@ class flat_tree { return this->m_data.m_vect.max_size(); } void swap(flat_tree& other) + BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value + && boost::container::container_detail::is_nothrow_swappable<Compare>::value ) { this->m_data.swap(other.m_data); } public: @@ -428,7 +435,7 @@ class flat_tree #endif ) { - const size_type len = static_cast<size_type>(std::distance(first, last)); + const size_type len = static_cast<size_type>(boost::container::iterator_distance(first, last)); this->reserve(this->size()+len); this->priv_insert_equal_loop(first, last); } @@ -455,7 +462,7 @@ class flat_tree #endif ) { - const size_type len = static_cast<size_type>(std::distance(first, last)); + const size_type len = static_cast<size_type>(boost::container::iterator_distance(first, last)); this->reserve(this->size()+len); this->priv_insert_equal_loop_ordered(first, last); } @@ -499,12 +506,12 @@ class flat_tree ) { this->priv_insert_ordered_range(true, first, last); } - #ifdef BOOST_CONTAINER_PERFECT_FORWARDING + #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) template <class... Args> - std::pair<iterator, bool> emplace_unique(Args&&... args) + std::pair<iterator, bool> emplace_unique(BOOST_FWD_REF(Args)... args) { - aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v; + typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v; value_type &val = *static_cast<value_type *>(static_cast<void *>(&v)); stored_allocator_type &a = this->get_stored_allocator(); stored_allocator_traits::construct(a, &val, ::boost::forward<Args>(args)... ); @@ -513,9 +520,9 @@ class flat_tree } template <class... Args> - iterator emplace_hint_unique(const_iterator hint, Args&&... args) + iterator emplace_hint_unique(const_iterator hint, BOOST_FWD_REF(Args)... args) { - aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v; + typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v; value_type &val = *static_cast<value_type *>(static_cast<void *>(&v)); stored_allocator_type &a = this->get_stored_allocator(); stored_allocator_traits::construct(a, &val, ::boost::forward<Args>(args)... ); @@ -524,9 +531,9 @@ class flat_tree } template <class... Args> - iterator emplace_equal(Args&&... args) + iterator emplace_equal(BOOST_FWD_REF(Args)... args) { - aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v; + typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v; value_type &val = *static_cast<value_type *>(static_cast<void *>(&v)); stored_allocator_type &a = this->get_stored_allocator(); stored_allocator_traits::construct(a, &val, ::boost::forward<Args>(args)... ); @@ -535,9 +542,9 @@ class flat_tree } template <class... Args> - iterator emplace_hint_equal(const_iterator hint, Args&&... args) + iterator emplace_hint_equal(const_iterator hint, BOOST_FWD_REF(Args)... args) { - aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v; + typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v; value_type &val = *static_cast<value_type *>(static_cast<void *>(&v)); stored_allocator_type &a = this->get_stored_allocator(); stored_allocator_traits::construct(a, &val, ::boost::forward<Args>(args)... ); @@ -545,64 +552,57 @@ class flat_tree return this->insert_equal(hint, ::boost::move(val)); } - #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING - - #define BOOST_PP_LOCAL_MACRO(n) \ - BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ - std::pair<iterator, bool> \ - emplace_unique(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ - { \ - aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v; \ - value_type &val = *static_cast<value_type *>(static_cast<void *>(&v)); \ - stored_allocator_type &a = this->get_stored_allocator(); \ - stored_allocator_traits::construct(a, &val \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \ - value_destructor<stored_allocator_type> d(a, val); \ - return this->insert_unique(::boost::move(val)); \ - } \ - \ - BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ - iterator emplace_hint_unique(const_iterator hint \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ - { \ - aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v; \ - value_type &val = *static_cast<value_type *>(static_cast<void *>(&v)); \ - stored_allocator_type &a = this->get_stored_allocator(); \ - stored_allocator_traits::construct(a, &val \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \ - value_destructor<stored_allocator_type> d(a, val); \ - return this->insert_unique(hint, ::boost::move(val)); \ - } \ - \ - BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ - iterator emplace_equal(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ - { \ - aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v; \ - value_type &val = *static_cast<value_type *>(static_cast<void *>(&v)); \ - stored_allocator_type &a = this->get_stored_allocator(); \ - stored_allocator_traits::construct(a, &val \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \ - value_destructor<stored_allocator_type> d(a, val); \ - return this->insert_equal(::boost::move(val)); \ - } \ - \ - BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ - iterator emplace_hint_equal(const_iterator hint \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ - { \ - aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v; \ - value_type &val = *static_cast<value_type *>(static_cast<void *>(&v)); \ - stored_allocator_type &a = this->get_stored_allocator(); \ - stored_allocator_traits::construct(a, &val \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \ - value_destructor<stored_allocator_type> d(a, val); \ - return this->insert_equal(hint, ::boost::move(val)); \ - } \ - //! - #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) - #include BOOST_PP_LOCAL_ITERATE() - - #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING + #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + + #define BOOST_CONTAINER_FLAT_TREE_EMPLACE_CODE(N) \ + BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ + std::pair<iterator, bool> emplace_unique(BOOST_MOVE_UREF##N)\ + {\ + typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v;\ + value_type &val = *static_cast<value_type *>(static_cast<void *>(&v));\ + stored_allocator_type &a = this->get_stored_allocator();\ + stored_allocator_traits::construct(a, &val BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\ + value_destructor<stored_allocator_type> d(a, val);\ + return this->insert_unique(::boost::move(val));\ + }\ + \ + BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ + iterator emplace_hint_unique(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ + {\ + typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v;\ + value_type &val = *static_cast<value_type *>(static_cast<void *>(&v));\ + stored_allocator_type &a = this->get_stored_allocator();\ + stored_allocator_traits::construct(a, &val BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\ + value_destructor<stored_allocator_type> d(a, val);\ + return this->insert_unique(hint, ::boost::move(val));\ + }\ + \ + BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ + iterator emplace_equal(BOOST_MOVE_UREF##N)\ + {\ + typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v;\ + value_type &val = *static_cast<value_type *>(static_cast<void *>(&v));\ + stored_allocator_type &a = this->get_stored_allocator();\ + stored_allocator_traits::construct(a, &val BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\ + value_destructor<stored_allocator_type> d(a, val);\ + return this->insert_equal(::boost::move(val));\ + }\ + \ + BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ + iterator emplace_hint_equal(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ + {\ + typename aligned_storage <sizeof(value_type), alignment_of<value_type>::value>::type v;\ + value_type &val = *static_cast<value_type *>(static_cast<void *>(&v));\ + stored_allocator_type &a = this->get_stored_allocator();\ + stored_allocator_traits::construct(a, &val BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\ + value_destructor<stored_allocator_type> d(a, val);\ + return this->insert_equal(hint, ::boost::move(val));\ + }\ + // + BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_FLAT_TREE_EMPLACE_CODE) + #undef BOOST_CONTAINER_FLAT_TREE_EMPLACE_CODE + + #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) iterator erase(const_iterator position) { return this->m_data.m_vect.erase(position); } @@ -632,6 +632,18 @@ class flat_tree void shrink_to_fit() { this->m_data.m_vect.shrink_to_fit(); } + iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW + { return this->m_data.m_vect.nth(n); } + + const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW + { return this->m_data.m_vect.nth(n); } + + size_type index_of(iterator p) BOOST_NOEXCEPT_OR_NOTHROW + { return this->m_data.m_vect.index_of(p); } + + size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW + { return this->m_data.m_vect.index_of(p); } + // set operations: iterator find(const key_type& k) { @@ -694,13 +706,12 @@ class flat_tree friend bool operator==(const flat_tree& x, const flat_tree& y) { - return x.size() == y.size() && std::equal(x.begin(), x.end(), y.begin()); + return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin()); } friend bool operator<(const flat_tree& x, const flat_tree& y) { - return std::lexicographical_compare(x.begin(), x.end(), - y.begin(), y.end()); + return ::boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } friend bool operator!=(const flat_tree& x, const flat_tree& y) @@ -936,7 +947,7 @@ class flat_tree template <class BidirIt> void priv_insert_ordered_range(const bool unique_values, BidirIt first, BidirIt last) { - size_type len = static_cast<size_type>(std::distance(first, last)); + size_type len = static_cast<size_type>(boost::container::iterator_distance(first, last)); //Prereserve all memory so that iterators are not invalidated this->reserve(this->size()+len); //Auxiliary data for insertion positions. @@ -955,10 +966,10 @@ class flat_tree size_type unique_burst = 0u; size_type checked = 0; for(; checked != burst; ++checked){ - //Get the insertion position for each key, use std::iterator_traits<BidirIt>::value_type + //Get the insertion position for each key, use iterator_traits<BidirIt>::value_type //because it can be different from container::value_type - //(e.g. conversion between std::pair<A, B> -> boost::container::pair<A, B> - const typename std::iterator_traits<BidirIt>::value_type & val = *first; + //(e.g. conversion between std::pair<T1, T2> -> boost::container::pair<T1, T2> + const typename boost::container::iterator_traits<BidirIt>::value_type & val = *first; pos = const_cast<const flat_tree&>(*this).priv_lower_bound(pos, ce, KeyOfValue()(val)); //Check if already present if (pos != ce){ @@ -984,7 +995,11 @@ class flat_tree while(len--){ BidirIt next(first); ++next; - if(next == last || val_cmp(*first, *next)){ + //Use iterator_traits<BidirIt>::value_type + //because it can be different from container::value_type + //(e.g. conversion between std::pair<T1, T2> -> boost::container::pair<T1, T2> + const typename boost::container::iterator_traits<BidirIt>::value_type & val = *first; + if (next == last || val_cmp(val, *next)){ const bool room = this->m_data.m_vect.stable_emplace_back(*first); (void)room; BOOST_ASSERT(room); @@ -994,7 +1009,7 @@ class flat_tree BOOST_ASSERT(first == last); } else{ - BOOST_ASSERT(size_type(std::distance(first, last)) == len); + BOOST_ASSERT(size_type(boost::container::iterator_distance(first, last)) == len); if(len) this->m_data.m_vect.insert(this->m_data.m_vect.cend(), len, first, last); } @@ -1004,16 +1019,18 @@ class flat_tree } //namespace container_detail { } //namespace container { -/* + //!has_trivial_destructor_after_move<> == true_type //!specialization for optimizations -template <class K, class V, class KOV, -class C, class A> -struct has_trivial_destructor_after_move<boost::container::container_detail::flat_tree<K, V, KOV, C, A> > +template <class Key, class T, class KeyOfValue, +class Compare, class Allocator> +struct has_trivial_destructor_after_move<boost::container::container_detail::flat_tree<Key, T, KeyOfValue, Compare, Allocator> > { - static const bool value = has_trivial_destructor_after_move<A>::value && has_trivial_destructor_after_move<C>::value; + typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer; + static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value && + ::boost::has_trivial_destructor_after_move<pointer>::value; }; -*/ + } //namespace boost { #include <boost/container/detail/config_end.hpp> diff --git a/boost/container/detail/function_detector.hpp b/boost/container/detail/function_detector.hpp index 242eb41352..00caced5ba 100644 --- a/boost/container/detail/function_detector.hpp +++ b/boost/container/detail/function_detector.hpp @@ -22,7 +22,11 @@ #ifndef BOOST_CONTAINER_DETAIL_FUNCTION_DETECTOR_HPP #define BOOST_CONTAINER_DETAIL_FUNCTION_DETECTOR_HPP -#if defined(_MSC_VER) +#ifndef BOOST_CONFIG_HPP +# include <boost/config.hpp> +#endif + +#if defined(BOOST_HAS_PRAGMA_ONCE) # pragma once #endif diff --git a/boost/container/detail/hash_table.hpp b/boost/container/detail/hash_table.hpp index da7bb536e4..4bc5c901de 100644 --- a/boost/container/detail/hash_table.hpp +++ b/boost/container/detail/hash_table.hpp @@ -1,6 +1,6 @@ /* template <class Value, unsigned int Options = 0, class Hash = hash<Value>, class Pred = equal_to<Value>, - class Alloc = allocator<Value> > + class Allocator = allocator<Value> > class hash_set { public: @@ -9,7 +9,7 @@ public: typedef key_type value_type; typedef Hash hasher; typedef Pred key_equal; - typedef Alloc allocator_type; + typedef Allocator allocator_type; typedef value_type& reference; typedef const value_type& const_reference; typedef typename allocator_traits<allocator_type>::pointer pointer; @@ -71,9 +71,9 @@ public: const_iterator cend() const noexcept; template <class... Args> - pair<iterator, bool> emplace(Args&&... args); + pair<iterator, bool> emplace(BOOST_FWD_REF(Args)... args); template <class... Args> - iterator emplace_hint(const_iterator position, Args&&... args); + iterator emplace_hint(const_iterator position, BOOST_FWD_REF(Args)... args); pair<iterator, bool> insert(const value_type& obj); pair<iterator, bool> insert(value_type&& obj); iterator insert(const_iterator hint, const value_type& obj); @@ -124,7 +124,7 @@ public: }; template <class Key, class T, unsigned int Options = 0, class Hash = hash<Key>, class Pred = equal_to<Key>, - class Alloc = allocator<pair<const Key, T> > > + class Allocator = allocator<pair<const Key, T> > > class hash_map { public: @@ -133,7 +133,7 @@ public: typedef T mapped_type; typedef Hash hasher; typedef Pred key_equal; - typedef Alloc allocator_type; + typedef Allocator allocator_type; typedef pair<const key_type, mapped_type> value_type; typedef value_type& reference; typedef const value_type& const_reference; @@ -196,9 +196,9 @@ public: const_iterator cend() const noexcept; template <class... Args> - pair<iterator, bool> emplace(Args&&... args); + pair<iterator, bool> emplace(BOOST_FWD_REF(Args)... args); template <class... Args> - iterator emplace_hint(const_iterator position, Args&&... args); + iterator emplace_hint(const_iterator position, BOOST_FWD_REF(Args)... args); pair<iterator, bool> insert(const value_type& obj); template <class P> pair<iterator, bool> insert(P&& obj); @@ -259,7 +259,7 @@ public: */ template <class Key, class Value, class KeyOfValue, unsigned int Options = 0, class Hash = hash<Key>, class Pred = equal_to<Key>, - class Alloc = allocator<Value> > + class Allocator = allocator<Value> > class hash_table { public: @@ -268,7 +268,7 @@ public: typedef key_type value_type; typedef Hash hasher; typedef Pred key_equal; - typedef Alloc allocator_type; + typedef Allocator allocator_type; typedef value_type& reference; typedef const value_type& const_reference; typedef typename allocator_traits<allocator_type>::pointer pointer; @@ -330,9 +330,9 @@ public: const_iterator cend() const noexcept; template <class... Args> - pair<iterator, bool> emplace(Args&&... args); + pair<iterator, bool> emplace(BOOST_FWD_REF(Args)... args); template <class... Args> - iterator emplace_hint(const_iterator position, Args&&... args); + iterator emplace_hint(const_iterator position, BOOST_FWD_REF(Args)... args); pair<iterator, bool> insert(const value_type& obj); pair<iterator, bool> insert(value_type&& obj); iterator insert(const_iterator hint, const value_type& obj); diff --git a/boost/container/detail/iterator.hpp b/boost/container/detail/iterator.hpp new file mode 100644 index 0000000000..ceb224f3ad --- /dev/null +++ b/boost/container/detail/iterator.hpp @@ -0,0 +1,39 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2014-2014. +// +// 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_ITERATOR_HPP +#define BOOST_CONTAINER_DETAIL_ITERATOR_HPP + +#ifndef BOOST_CONFIG_HPP +# include <boost/config.hpp> +#endif + +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include <boost/intrusive/detail/iterator.hpp> + +namespace boost { +namespace container { + +using ::boost::intrusive::iterator_traits; +using ::boost::intrusive::iterator_distance; +using ::boost::intrusive::iterator_advance; +using ::boost::intrusive::iterator; +using ::boost::intrusive::iterator_enable_if_tag; +using ::boost::intrusive::iterator_disable_if_tag; + +} //namespace container { +} //namespace boost { + +#endif //#ifndef BOOST_CONTAINER_DETAIL_ITERATORS_HPP diff --git a/boost/container/detail/iterator_to_raw_pointer.hpp b/boost/container/detail/iterator_to_raw_pointer.hpp new file mode 100644 index 0000000000..83736d8bb1 --- /dev/null +++ b/boost/container/detail/iterator_to_raw_pointer.hpp @@ -0,0 +1,58 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_ITERATOR_TO_RAW_POINTER_HPP +#define BOOST_CONTAINER_DETAIL_ITERATOR_TO_RAW_POINTER_HPP + +#ifndef BOOST_CONFIG_HPP +# include <boost/config.hpp> +#endif + +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include <boost/container/detail/iterator.hpp> +#include <boost/container/detail/to_raw_pointer.hpp> +#include <boost/intrusive/pointer_traits.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) ); +} + +} //namespace container_detail { +} //namespace container { +} //namespace boost { + +#endif //#ifndef BOOST_CONTAINER_DETAIL_ITERATOR_TO_RAW_POINTER_HPP diff --git a/boost/container/detail/iterators.hpp b/boost/container/detail/iterators.hpp index 0dabd3c73e..1f80d3e122 100644 --- a/boost/container/detail/iterators.hpp +++ b/boost/container/detail/iterators.hpp @@ -14,7 +14,11 @@ #ifndef BOOST_CONTAINER_DETAIL_ITERATORS_HPP #define BOOST_CONTAINER_DETAIL_ITERATORS_HPP -#if defined(_MSC_VER) +#ifndef BOOST_CONFIG_HPP +# include <boost/config.hpp> +#endif + +#if defined(BOOST_HAS_PRAGMA_ONCE) # pragma once #endif @@ -26,20 +30,19 @@ #include <boost/move/utility_core.hpp> #include <boost/intrusive/detail/reverse_iterator.hpp> -#ifdef BOOST_CONTAINER_PERFECT_FORWARDING -#include <boost/container/detail/variadic_templates_tools.hpp> +#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +#include <boost/move/detail/fwd_macros.hpp> #else -#include <boost/container/detail/preprocessor.hpp> +#include <boost/container/detail/variadic_templates_tools.hpp> #endif - -#include <iterator> +#include <boost/container/detail/iterator.hpp> namespace boost { namespace container { template <class T, class Difference = std::ptrdiff_t> class constant_iterator - : public std::iterator + : public ::boost::container::iterator <std::random_access_iterator_tag, T, Difference, const T*, const T &> { typedef constant_iterator<T, Difference> this_type; @@ -150,7 +153,7 @@ class constant_iterator template <class T, class Difference> class value_init_construct_iterator - : public std::iterator + : public ::boost::container::iterator <std::random_access_iterator_tag, T, Difference, const T*, const T &> { typedef value_init_construct_iterator<T, Difference> this_type; @@ -261,7 +264,7 @@ class value_init_construct_iterator template <class T, class Difference> class default_init_construct_iterator - : public std::iterator + : public ::boost::container::iterator <std::random_access_iterator_tag, T, Difference, const T*, const T &> { typedef default_init_construct_iterator<T, Difference> this_type; @@ -373,7 +376,7 @@ class default_init_construct_iterator template <class T, class Difference = std::ptrdiff_t> class repeat_iterator - : public std::iterator + : public ::boost::container::iterator <std::random_access_iterator_tag, T, Difference> { typedef repeat_iterator<T, Difference> this_type; @@ -483,7 +486,7 @@ class repeat_iterator template <class T, class EmplaceFunctor, class Difference /*= std::ptrdiff_t*/> class emplace_iterator - : public std::iterator + : public ::boost::container::iterator <std::random_access_iterator_tag, T, Difference, const T*, const T &> { typedef emplace_iterator this_type; @@ -564,8 +567,8 @@ class emplace_iterator //const T& operator[](difference_type) const; //const T* operator->() const; - template<class A> - void construct_in_place(A &a, T* ptr) + template<class Allocator> + void construct_in_place(Allocator &a, T* ptr) { (*m_pe)(a, ptr); } private: @@ -597,54 +600,49 @@ class emplace_iterator { return difference_type(m_num - other.m_num); } }; -#ifdef BOOST_CONTAINER_PERFECT_FORWARDING +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) template<class ...Args> struct emplace_functor { typedef typename container_detail::build_number_seq<sizeof...(Args)>::type index_tuple_t; - emplace_functor(Args&&... args) + emplace_functor(BOOST_FWD_REF(Args)... args) : args_(args...) {} - template<class A, class T> - void operator()(A &a, T *ptr) + template<class Allocator, class T> + void operator()(Allocator &a, T *ptr) { emplace_functor::inplace_impl(a, ptr, index_tuple_t()); } - template<class A, class T, int ...IdxPack> - void inplace_impl(A &a, T* ptr, const container_detail::index_tuple<IdxPack...>&) + template<class Allocator, class T, int ...IdxPack> + void inplace_impl(Allocator &a, T* ptr, const container_detail::index_tuple<IdxPack...>&) { - allocator_traits<A>::construct + allocator_traits<Allocator>::construct (a, ptr, ::boost::forward<Args>(container_detail::get<IdxPack>(args_))...); } container_detail::tuple<Args&...> args_; }; -#else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING - -#define BOOST_PP_LOCAL_MACRO(n) \ - BOOST_PP_EXPR_IF(n, template <) \ - BOOST_PP_ENUM_PARAMS(n, class P) \ - BOOST_PP_EXPR_IF(n, >) \ - struct BOOST_PP_CAT(BOOST_PP_CAT(emplace_functor, n), arg) \ - { \ - BOOST_PP_CAT(BOOST_PP_CAT(emplace_functor, n), arg) \ - ( BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _) ) \ - BOOST_PP_EXPR_IF(n, :) BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_INIT, _){} \ - \ - template<class A, class T> \ - void operator()(A &a, T *ptr) \ - { \ - allocator_traits<A>::construct \ - (a, ptr BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_MEMBER_FORWARD, _) ); \ - } \ - BOOST_PP_REPEAT(n, BOOST_CONTAINER_PP_PARAM_DEFINE, _) \ - }; \ - //! -#define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) -#include BOOST_PP_LOCAL_ITERATE() +#else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + +#define BOOST_MOVE_ITERATOR_EMPLACE_FUNCTOR_CODE(N) \ +BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ +struct emplace_functor##N\ +{\ + explicit emplace_functor##N( BOOST_MOVE_UREF##N )\ + BOOST_MOVE_COLON##N BOOST_MOVE_FWD_INIT##N{}\ + \ + template<class Allocator, class T>\ + void operator()(Allocator &a, T *ptr)\ + { allocator_traits<Allocator>::construct(a, ptr BOOST_MOVE_I##N BOOST_MOVE_MFWD##N); }\ + \ + BOOST_MOVE_MREF##N\ +};\ +// +BOOST_MOVE_ITERATE_0TO9(BOOST_MOVE_ITERATOR_EMPLACE_FUNCTOR_CODE) +#undef BOOST_MOVE_ITERATOR_EMPLACE_FUNCTOR_CODE #endif @@ -709,8 +707,8 @@ struct iiterator_types { typedef typename IIterator::value_type it_value_type; typedef typename iiterator_node_value_type<it_value_type>::type value_type; - typedef typename std::iterator_traits<IIterator>::pointer it_pointer; - typedef typename std::iterator_traits<IIterator>::difference_type difference_type; + typedef typename boost::container::iterator_traits<IIterator>::pointer it_pointer; + typedef typename boost::container::iterator_traits<IIterator>::difference_type difference_type; typedef typename ::boost::intrusive::pointer_traits<it_pointer>:: template rebind_pointer<value_type>::type pointer; typedef typename ::boost::intrusive::pointer_traits<it_pointer>:: @@ -723,9 +721,9 @@ struct iiterator_types }; template<class IIterator, bool IsConst> -struct std_iterator +struct iterator_types { - typedef typename std::iterator + typedef typename ::boost::container::iterator < typename iiterator_types<IIterator>::iterator_category , typename iiterator_types<IIterator>::value_type , typename iiterator_types<IIterator>::difference_type @@ -734,9 +732,9 @@ struct std_iterator }; template<class IIterator> -struct std_iterator<IIterator, false> +struct iterator_types<IIterator, false> { - typedef typename std::iterator + typedef typename ::boost::container::iterator < typename iiterator_types<IIterator>::iterator_category , typename iiterator_types<IIterator>::value_type , typename iiterator_types<IIterator>::difference_type @@ -745,9 +743,9 @@ struct std_iterator<IIterator, false> }; template<class IIterator, bool IsConst> -class iterator +class iterator_from_iiterator { - typedef typename std_iterator<IIterator, IsConst>::type types_t; + typedef typename iterator_types<IIterator, IsConst>::type types_t; public: typedef typename types_t::pointer pointer; @@ -756,63 +754,64 @@ class iterator typedef typename types_t::iterator_category iterator_category; typedef typename types_t::value_type value_type; - iterator() + iterator_from_iiterator() {} - explicit iterator(IIterator iit) BOOST_CONTAINER_NOEXCEPT + explicit iterator_from_iiterator(IIterator iit) BOOST_NOEXCEPT_OR_NOTHROW : m_iit(iit) {} - iterator(iterator<IIterator, false> const& other) BOOST_CONTAINER_NOEXCEPT + iterator_from_iiterator(iterator_from_iiterator<IIterator, false> const& other) BOOST_NOEXCEPT_OR_NOTHROW : m_iit(other.get()) {} - iterator& operator++() BOOST_CONTAINER_NOEXCEPT + iterator_from_iiterator& operator++() BOOST_NOEXCEPT_OR_NOTHROW { ++this->m_iit; return *this; } - iterator operator++(int) BOOST_CONTAINER_NOEXCEPT + iterator_from_iiterator operator++(int) BOOST_NOEXCEPT_OR_NOTHROW { - iterator result (*this); + iterator_from_iiterator result (*this); ++this->m_iit; return result; } - iterator& operator--() BOOST_CONTAINER_NOEXCEPT + iterator_from_iiterator& operator--() BOOST_NOEXCEPT_OR_NOTHROW { - //If the iterator is not a bidirectional iterator, operator-- should not exist - BOOST_STATIC_ASSERT((is_bidirectional_iterator<iterator>::value)); + //If the iterator_from_iiterator is not a bidirectional iterator, operator-- should not exist + BOOST_STATIC_ASSERT((is_bidirectional_iterator<iterator_from_iiterator>::value)); --this->m_iit; return *this; } - iterator operator--(int) BOOST_CONTAINER_NOEXCEPT + iterator_from_iiterator operator--(int) BOOST_NOEXCEPT_OR_NOTHROW { - iterator result (*this); + iterator_from_iiterator result (*this); --this->m_iit; return result; } - friend bool operator== (const iterator& l, const iterator& r) BOOST_CONTAINER_NOEXCEPT + friend bool operator== (const iterator_from_iiterator& l, const iterator_from_iiterator& r) BOOST_NOEXCEPT_OR_NOTHROW { return l.m_iit == r.m_iit; } - friend bool operator!= (const iterator& l, const iterator& r) BOOST_CONTAINER_NOEXCEPT + friend bool operator!= (const iterator_from_iiterator& l, const iterator_from_iiterator& r) BOOST_NOEXCEPT_OR_NOTHROW { return !(l == r); } - reference operator*() const BOOST_CONTAINER_NOEXCEPT + reference operator*() const BOOST_NOEXCEPT_OR_NOTHROW { return (*this->m_iit).get_data(); } - pointer operator->() const BOOST_CONTAINER_NOEXCEPT + pointer operator->() const BOOST_NOEXCEPT_OR_NOTHROW { return ::boost::intrusive::pointer_traits<pointer>::pointer_to(this->operator*()); } - const IIterator &get() const BOOST_CONTAINER_NOEXCEPT + const IIterator &get() const BOOST_NOEXCEPT_OR_NOTHROW { return this->m_iit; } private: IIterator m_iit; }; -using ::boost::intrusive::detail::reverse_iterator; - } //namespace container_detail { + +using ::boost::intrusive::reverse_iterator; + } //namespace container { } //namespace boost { diff --git a/boost/container/detail/math_functions.hpp b/boost/container/detail/math_functions.hpp index 6853b9c59f..e499f633ec 100644 --- a/boost/container/detail/math_functions.hpp +++ b/boost/container/detail/math_functions.hpp @@ -16,7 +16,11 @@ #ifndef BOOST_CONTAINER_DETAIL_MATH_FUNCTIONS_HPP #define BOOST_CONTAINER_DETAIL_MATH_FUNCTIONS_HPP -#if defined(_MSC_VER) +#ifndef BOOST_CONFIG_HPP +# include <boost/config.hpp> +#endif + +#if defined(BOOST_HAS_PRAGMA_ONCE) # pragma once #endif diff --git a/boost/container/detail/memory_util.hpp b/boost/container/detail/memory_util.hpp deleted file mode 100644 index 7f055cb55b..0000000000 --- a/boost/container/detail/memory_util.hpp +++ /dev/null @@ -1,90 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2011-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_ALLOCATOR_MEMORY_UTIL_HPP -#define BOOST_CONTAINER_ALLOCATOR_MEMORY_UTIL_HPP - -#if defined(_MSC_VER) -# pragma once -#endif - -#include <boost/container/detail/config_begin.hpp> -#include <boost/container/detail/workaround.hpp> - -#include <boost/container/detail/preprocessor.hpp> -#include <boost/intrusive/detail/mpl.hpp> -#include <boost/intrusive/detail/has_member_function_callable_with.hpp> - - -#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME allocate -#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace container { namespace container_detail { -#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}} -#define BOOST_PP_ITERATION_PARAMS_1 (3, (2, 2, <boost/intrusive/detail/has_member_function_callable_with.hpp>)) -#include BOOST_PP_ITERATE() - -#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME destroy -#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace container { namespace container_detail { -#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}} -#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 1, <boost/intrusive/detail/has_member_function_callable_with.hpp>)) -#include BOOST_PP_ITERATE() - -#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME max_size -#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace container { namespace container_detail { -#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}} -#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, 0, <boost/intrusive/detail/has_member_function_callable_with.hpp>)) -#include BOOST_PP_ITERATE() - -#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME select_on_container_copy_construction -#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace container { namespace container_detail { -#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}} -#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, 0, <boost/intrusive/detail/has_member_function_callable_with.hpp>)) -#include BOOST_PP_ITERATE() - -#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME construct -#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace container { namespace container_detail { -#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}} -#ifdef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_SINGLE_ITERATION -# define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 1, <boost/intrusive/detail/has_member_function_callable_with.hpp>)) -#else -# define BOOST_PP_ITERATION_PARAMS_1 (3, (1, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS+1, <boost/intrusive/detail/has_member_function_callable_with.hpp>)) -#endif -#include BOOST_PP_ITERATE() - -#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME swap -#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace container { namespace container_detail { -#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}} -#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 1, <boost/intrusive/detail/has_member_function_callable_with.hpp>)) -#include BOOST_PP_ITERATE() - -namespace boost { -namespace container { -namespace container_detail { - -BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(pointer) -BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(const_pointer) -BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(reference) -BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(const_reference) -BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(void_pointer) -BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(const_void_pointer) -BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(size_type) -BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(propagate_on_container_copy_assignment) -BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(propagate_on_container_move_assignment) -BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(propagate_on_container_swap) -BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(difference_type) -BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(value_compare) -BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(wrapped_value_compare) - -} //namespace container_detail { -} //namespace container { -} //namespace boost { - -#include <boost/container/detail/config_end.hpp> - -#endif // ! defined(BOOST_CONTAINER_ALLOCATOR_MEMORY_UTIL_HPP) diff --git a/boost/container/detail/min_max.hpp b/boost/container/detail/min_max.hpp new file mode 100644 index 0000000000..7486db7d05 --- /dev/null +++ b/boost/container/detail/min_max.hpp @@ -0,0 +1,37 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_DETAIL_MIN_MAX_HPP +#define BOOST_CONTAINER_DETAIL_MIN_MAX_HPP + +#ifndef BOOST_CONFIG_HPP +# include <boost/config.hpp> +#endif + +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +namespace boost { +namespace container { +namespace container_detail { + +template<class T> +const T &max_value(const T &a, const T &b) +{ return a > b ? a : b; } + +template<class T> +const T &min_value(const T &a, const T &b) +{ return a < b ? a : b; } + +} //namespace container_detail { +} //namespace container { +} //namespace boost { + +#endif //#ifndef BOOST_CONTAINER_DETAIL_MIN_MAX_HPP diff --git a/boost/container/detail/minimal_char_traits_header.hpp b/boost/container/detail/minimal_char_traits_header.hpp new file mode 100644 index 0000000000..a92a31a2b4 --- /dev/null +++ b/boost/container/detail/minimal_char_traits_header.hpp @@ -0,0 +1,32 @@ +///////////////////////////////////////////////////////////////////////////// +// +// (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_MINIMAL_CHAR_TRAITS_HEADER_HPP +#define BOOST_CONTAINER_DETAIL_MINIMAL_CHAR_TRAITS_HEADER_HPP +# +#ifndef BOOST_CONFIG_HPP +# include <boost/config.hpp> +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif +# +#//Try to avoid including <string>, as it's quite big +#if defined(_MSC_VER) && defined(BOOST_DINKUMWARE_STDLIB) + #include <iosfwd> //Dinkum libraries for MSVC define std::char_traits there +#elif defined(BOOST_GNU_STDLIB) + #include <bits/char_traits.h> +#else + #include <string> //Fallback +#endif + +#endif //BOOST_CONTAINER_DETAIL_MINIMAL_CHAR_TRAITS_HEADER_HPP diff --git a/boost/container/detail/mpl.hpp b/boost/container/detail/mpl.hpp index ceac52a371..74b618f8c6 100644 --- a/boost/container/detail/mpl.hpp +++ b/boost/container/detail/mpl.hpp @@ -13,7 +13,11 @@ #ifndef BOOST_CONTAINER_CONTAINER_DETAIL_MPL_HPP #define BOOST_CONTAINER_CONTAINER_DETAIL_MPL_HPP -#if defined(_MSC_VER) +#ifndef BOOST_CONFIG_HPP +# include <boost/config.hpp> +#endif + +#if defined(BOOST_HAS_PRAGMA_ONCE) # pragma once #endif @@ -40,6 +44,13 @@ struct bool_ : integral_constant<bool, C_> operator bool() const { return bool_::value; } }; +template< unsigned V_ > +struct unsigned_ : integral_constant<unsigned, V_> +{ + static const unsigned value = V_; + operator unsigned() const { return unsigned_::value; } +}; + typedef bool_<true> true_; typedef bool_<false> false_; @@ -169,6 +180,12 @@ struct ls_zeros<1> static const std::size_t value = 0; }; +template <std::size_t OrigSize, std::size_t RoundTo> +struct ct_rounded_size +{ + static const std::size_t value = ((OrigSize-1)/RoundTo+1)*RoundTo; +}; + template <typename T> struct unvoid { typedef T type; }; template <> struct unvoid<void> { struct type { }; }; template <> struct unvoid<const void> { struct type { }; }; diff --git a/boost/container/detail/multiallocation_chain.hpp b/boost/container/detail/multiallocation_chain.hpp index 96f6202671..32f87c8ae9 100644 --- a/boost/container/detail/multiallocation_chain.hpp +++ b/boost/container/detail/multiallocation_chain.hpp @@ -11,20 +11,26 @@ #ifndef BOOST_CONTAINER_DETAIL_MULTIALLOCATION_CHAIN_HPP #define BOOST_CONTAINER_DETAIL_MULTIALLOCATION_CHAIN_HPP -#if defined(_MSC_VER) +#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> - +// container #include <boost/container/container_fwd.hpp> -#include <boost/container/detail/utilities.hpp> -#include <boost/container/detail/type_traits.hpp> +// container/detail +#include <boost/container/detail/to_raw_pointer.hpp> #include <boost/container/detail/transform_iterator.hpp> +#include <boost/container/detail/type_traits.hpp> +// intrusive #include <boost/intrusive/slist.hpp> #include <boost/intrusive/pointer_traits.hpp> -#include <boost/type_traits/make_unsigned.hpp> +// move #include <boost/move/utility_core.hpp> namespace boost { @@ -47,7 +53,7 @@ class basic_multiallocation_chain typedef bi::slist< node , bi::linear<true> , bi::cache_last<true> - , bi::size_type<typename boost::make_unsigned<difference_type>::type> + , bi::size_type<typename boost::container::container_detail::make_unsigned<difference_type>::type> > slist_impl_t; slist_impl_t slist_impl_; diff --git a/boost/container/detail/mutex.hpp b/boost/container/detail/mutex.hpp index c53afa1f42..f8efa7fe6b 100644 --- a/boost/container/detail/mutex.hpp +++ b/boost/container/detail/mutex.hpp @@ -19,7 +19,11 @@ #ifndef BOOST_CONTAINER_MUTEX_HPP #define BOOST_CONTAINER_MUTEX_HPP -#if defined(_MSC_VER) +#ifndef BOOST_CONFIG_HPP +# include <boost/config.hpp> +#endif + +#if defined(BOOST_HAS_PRAGMA_ONCE) # pragma once #endif @@ -162,7 +166,7 @@ #define BOOST_CONTAINER_TRY_LOCK(sl) !BOOST_CONTAINER_CAS_LOCK(sl) #define BOOST_CONTAINER_RELEASE_LOCK(sl) BOOST_CONTAINER_CLEAR_LOCK(sl) #define BOOST_CONTAINER_ACQUIRE_LOCK(sl) (BOOST_CONTAINER_CAS_LOCK(sl)? boost_interprocess_spin_acquire_lock(sl) : 0) - #define BOOST_CONTAINER_INITIAL_LOCK(sl) (*sl = 0) + #define BOOST_MOVE_INITIAL_LOCK(sl) (*sl = 0) #define BOOST_CONTAINER_DESTROY_LOCK(sl) (0) #elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_WIN32 // @@ -199,7 +203,7 @@ namespace container_detail { void operator=(const spin_mutex &); public: - spin_mutex() { BOOST_CONTAINER_INITIAL_LOCK(&sl); } + spin_mutex() { BOOST_MOVE_INITIAL_LOCK(&sl); } void lock() { BOOST_CONTAINER_ACQUIRE_LOCK(&sl); } void unlock() { BOOST_CONTAINER_RELEASE_LOCK(&sl); } diff --git a/boost/container/detail/next_capacity.hpp b/boost/container/detail/next_capacity.hpp new file mode 100644 index 0000000000..3bc98a3c91 --- /dev/null +++ b/boost/container/detail/next_capacity.hpp @@ -0,0 +1,75 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_NEXT_CAPACITY_HPP +#define BOOST_CONTAINER_DETAIL_NEXT_CAPACITY_HPP + +#ifndef BOOST_CONFIG_HPP +# include <boost/config.hpp> +#endif + +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +// container +#include <boost/container/throw_exception.hpp> +// container/detail +#include <boost/container/detail/min_max.hpp> + +namespace boost { +namespace container { +namespace container_detail { + +enum NextCapacityOption { NextCapacityDouble, NextCapacity60Percent }; + +template<class SizeType, NextCapacityOption Option> +struct next_capacity_calculator; + +template<class SizeType> +struct next_capacity_calculator<SizeType, NextCapacityDouble> +{ + static SizeType get(const SizeType max_size + ,const SizeType capacity + ,const SizeType n) + { + const SizeType remaining = max_size - capacity; + if ( remaining < n ) + boost::container::throw_length_error("get_next_capacity, allocator's max_size reached"); + const SizeType additional = max_value(n, capacity); + return ( remaining < additional ) ? max_size : ( capacity + additional ); + } +}; + +template<class SizeType> +struct next_capacity_calculator<SizeType, NextCapacity60Percent> +{ + static SizeType get(const SizeType max_size + ,const SizeType capacity + ,const SizeType n) + { + const SizeType remaining = max_size - capacity; + if ( remaining < n ) + boost::container::throw_length_error("get_next_capacity, allocator's max_size reached"); + const SizeType m3 = max_size/3; + + if (capacity < m3) + return capacity + max_value(3*(capacity+1)/5, n); + + if (capacity < m3*2) + return capacity + max_value((capacity+1)/2, n); + return max_size; + } +}; + +} //namespace container_detail { +} //namespace container { +} //namespace boost { + +#endif //#ifndef BOOST_CONTAINER_DETAIL_NEXT_CAPACITY_HPP diff --git a/boost/container/detail/node_alloc_holder.hpp b/boost/container/detail/node_alloc_holder.hpp index 250c559765..98c8e62baa 100644 --- a/boost/container/detail/node_alloc_holder.hpp +++ b/boost/container/detail/node_alloc_holder.hpp @@ -11,82 +11,63 @@ #ifndef BOOST_CONTAINER_DETAIL_NODE_ALLOC_HPP_ #define BOOST_CONTAINER_DETAIL_NODE_ALLOC_HPP_ -#if defined(_MSC_VER) +#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> -#include <utility> -#include <functional> - -#include <boost/move/utility_core.hpp> -#include <boost/intrusive/options.hpp> - -#include <boost/container/detail/version_type.hpp> -#include <boost/container/detail/type_traits.hpp> -#include <boost/container/detail/utilities.hpp> +// container #include <boost/container/allocator_traits.hpp> +// container/detail +#include <boost/container/detail/addressof.hpp> +#include <boost/container/detail/alloc_helpers.hpp> #include <boost/container/detail/allocator_version_traits.hpp> -#include <boost/container/detail/mpl.hpp> +#include <boost/container/detail/construct_in_place.hpp> #include <boost/container/detail/destroyers.hpp> -#include <boost/container/detail/memory_util.hpp> +#include <boost/container/detail/iterator_to_raw_pointer.hpp> +#include <boost/container/detail/mpl.hpp> #include <boost/container/detail/placement_new.hpp> -#include <boost/core/no_exceptions_support.hpp> - -#ifndef BOOST_CONTAINER_PERFECT_FORWARDING -#include <boost/container/detail/preprocessor.hpp> +#include <boost/container/detail/to_raw_pointer.hpp> +#include <boost/container/detail/type_traits.hpp> +#include <boost/container/detail/version_type.hpp> +// intrusive +#include <boost/intrusive/detail/mpl.hpp> +#include <boost/intrusive/options.hpp> +// move +#include <boost/move/utility_core.hpp> +#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +#include <boost/move/detail/fwd_macros.hpp> #endif - -#include <boost/container/detail/algorithms.hpp> - +// other +#include <boost/core/no_exceptions_support.hpp> namespace boost { namespace container { namespace container_detail { -template<class ValueCompare, class Node> -struct node_compare - : private ValueCompare -{ - typedef ValueCompare wrapped_value_compare; - typedef typename wrapped_value_compare::key_type key_type; - typedef typename wrapped_value_compare::value_type value_type; - typedef typename wrapped_value_compare::key_of_value key_of_value; - - explicit node_compare(const wrapped_value_compare &pred) - : wrapped_value_compare(pred) - {} - - node_compare() - : wrapped_value_compare() - {} - - wrapped_value_compare &value_comp() - { return static_cast<wrapped_value_compare &>(*this); } +BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(value_compare) +BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(predicate_type) - wrapped_value_compare &value_comp() const - { return static_cast<const wrapped_value_compare &>(*this); } - - bool operator()(const Node &a, const Node &b) const - { return wrapped_value_compare::operator()(a.get_data(), b.get_data()); } -}; - -template<class A, class ICont> +template<class Allocator, class ICont> struct node_alloc_holder { //If the intrusive container is an associative container, obtain the predicate, which will //be of type node_compare<>. If not an associative container value_compare will be a "nat" type. typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, ICont, value_compare, container_detail::nat) intrusive_value_compare; - //In that case obtain the value predicate from the node predicate via wrapped_value_compare + //In that case obtain the value predicate from the node predicate via predicate_type //if intrusive_value_compare is node_compare<>, nat otherwise - typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, ICont, - wrapped_value_compare, container_detail::nat) value_compare; + typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, intrusive_value_compare, + predicate_type, container_detail::nat) value_compare; - typedef allocator_traits<A> allocator_traits_type; + typedef allocator_traits<Allocator> allocator_traits_type; typedef typename allocator_traits_type::value_type value_type; typedef ICont intrusive_container; typedef typename ICont::value_type Node; @@ -94,13 +75,11 @@ struct node_alloc_holder portable_rebind_alloc<Node>::type NodeAlloc; typedef allocator_traits<NodeAlloc> node_allocator_traits_type; typedef container_detail::allocator_version_traits<NodeAlloc> node_allocator_version_traits_type; - typedef A ValAlloc; + typedef Allocator ValAlloc; typedef typename node_allocator_traits_type::pointer NodePtr; typedef container_detail::scoped_deallocator<NodeAlloc> Deallocator; typedef typename node_allocator_traits_type::size_type size_type; typedef typename node_allocator_traits_type::difference_type difference_type; - typedef container_detail::integral_constant<unsigned, 1> allocator_v1; - typedef container_detail::integral_constant<unsigned, 2> allocator_v2; typedef container_detail::integral_constant<unsigned, boost::container::container_detail:: version<NodeAlloc>::value> alloc_version; @@ -133,11 +112,11 @@ struct node_alloc_holder { this->icont().swap(x.icont()); } //Constructors for associative containers - explicit node_alloc_holder(const ValAlloc &a, const value_compare &c) + explicit node_alloc_holder(const value_compare &c, const ValAlloc &a) : members_(a, c) {} - explicit node_alloc_holder(const node_alloc_holder &x, const value_compare &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) {} @@ -176,7 +155,7 @@ struct node_alloc_holder void deallocate_one(const NodePtr &p) { AllocVersionTraits::deallocate_one(this->node_alloc(), p); } - #ifdef BOOST_CONTAINER_PERFECT_FORWARDING + #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) template<class ...Args> NodePtr create_node(Args &&...args) @@ -193,28 +172,90 @@ struct node_alloc_holder return (p); } - #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING - - #define BOOST_PP_LOCAL_MACRO(n) \ - \ - BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ - NodePtr create_node(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ - { \ - NodePtr p = this->allocate_one(); \ - Deallocator node_deallocator(p, this->node_alloc()); \ - allocator_traits<NodeAlloc>::construct \ - (this->node_alloc(), container_detail::addressof(p->m_data) \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \ - 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; \ - return (p); \ - } \ - //! - #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) - #include BOOST_PP_LOCAL_ITERATE() - - #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING + #else //defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + NodePtr create_node() + { + NodePtr p = this->allocate_one(); + Deallocator node_deallocator(p, this->node_alloc()); + allocator_traits<NodeAlloc>::construct + (this->node_alloc(), container_detail::addressof(p->m_data)); + 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; + return (p); + } + + template<BOOST_MOVE_CLASS1> + NodePtr create_node(BOOST_MOVE_UREF1) + { + NodePtr p = this->allocate_one(); + Deallocator node_deallocator(p, this->node_alloc()); + allocator_traits<NodeAlloc>::construct + (this->node_alloc(), container_detail::addressof(p->m_data) + , BOOST_MOVE_FWD1); + 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; + return (p); + } + + template<BOOST_MOVE_CLASS2> + NodePtr create_node(BOOST_MOVE_UREF2) + { + NodePtr p = this->allocate_one(); + Deallocator node_deallocator(p, this->node_alloc()); + allocator_traits<NodeAlloc>::construct + (this->node_alloc(), container_detail::addressof(p->m_data) + , BOOST_MOVE_FWD2); + 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; + return (p); + } + + template<BOOST_MOVE_CLASS3> + NodePtr create_node(BOOST_MOVE_UREF3) + { + NodePtr p = this->allocate_one(); + Deallocator node_deallocator(p, this->node_alloc()); + allocator_traits<NodeAlloc>::construct + (this->node_alloc(), container_detail::addressof(p->m_data) + , BOOST_MOVE_FWD3); + 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; + return (p); + } + + template<BOOST_MOVE_CLASS4> + NodePtr create_node(BOOST_MOVE_UREF4) + { + NodePtr p = this->allocate_one(); + Deallocator node_deallocator(p, this->node_alloc()); + allocator_traits<NodeAlloc>::construct + (this->node_alloc(), container_detail::addressof(p->m_data) + , BOOST_MOVE_FWD4); + 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; + return (p); + } + + template<BOOST_MOVE_CLASS5> + NodePtr create_node(BOOST_MOVE_UREF5) + { + NodePtr p = this->allocate_one(); + Deallocator node_deallocator(p, this->node_alloc()); + allocator_traits<NodeAlloc>::construct + (this->node_alloc(), container_detail::addressof(p->m_data) + , BOOST_MOVE_FWD5); + 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; + return (p); + } + + #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) template<class It> NodePtr create_node_from_it(const It &it) @@ -261,7 +302,7 @@ struct node_alloc_holder Deallocator node_deallocator(NodePtr(), nalloc); container_detail::scoped_destructor<NodeAlloc> sdestructor(nalloc, 0); while(n--){ - p = container_detail::to_raw_pointer(iterator_to_pointer(itbeg)); + p = container_detail::iterator_to_raw_pointer(itbeg); node_deallocator.set(p); ++itbeg; //This can throw @@ -288,10 +329,10 @@ struct node_alloc_holder } } - void clear(allocator_v1) + void clear(version_1) { this->icont().clear_and_dispose(Destroyer(this->node_alloc())); } - void clear(allocator_v2) + void clear(version_2) { typename NodeAlloc::multiallocation_chain chain; allocator_destroyer_and_chain_builder<NodeAlloc> builder(this->node_alloc(), chain); @@ -301,10 +342,10 @@ struct node_alloc_holder this->node_alloc().deallocate_individual(chain); } - icont_iterator erase_range(const icont_iterator &first, const icont_iterator &last, allocator_v1) + icont_iterator erase_range(const icont_iterator &first, const icont_iterator &last, version_1) { return this->icont().erase_and_dispose(first, last, Destroyer(this->node_alloc())); } - icont_iterator erase_range(const icont_iterator &first, const icont_iterator &last, allocator_v2) + icont_iterator erase_range(const icont_iterator &first, const icont_iterator &last, version_2) { typedef typename NodeAlloc::multiallocation_chain multiallocation_chain; NodeAlloc & nalloc = this->node_alloc(); @@ -316,11 +357,11 @@ struct node_alloc_holder } template<class Key, class Comparator> - size_type erase_key(const Key& k, const Comparator &comp, allocator_v1) + size_type erase_key(const Key& k, const Comparator &comp, version_1) { return this->icont().erase_and_dispose(k, comp, Destroyer(this->node_alloc())); } template<class Key, class Comparator> - size_type erase_key(const Key& k, const Comparator &comp, allocator_v2) + size_type erase_key(const Key& k, const Comparator &comp, version_2) { allocator_multialloc_chain_node_deallocator<NodeAlloc> chain_holder(this->node_alloc()); return this->icont().erase_and_dispose(k, comp, chain_holder.get_chain_builder()); @@ -329,7 +370,7 @@ struct node_alloc_holder protected: struct cloner { - cloner(node_alloc_holder &holder) + explicit cloner(node_alloc_holder &holder) : m_holder(holder) {} @@ -339,6 +380,18 @@ struct node_alloc_holder node_alloc_holder &m_holder; }; + struct move_cloner + { + move_cloner(node_alloc_holder &holder) + : m_holder(holder) + {} + + NodePtr operator()(Node &other) + { return m_holder.create_node(::boost::move(other.get_data())); } + + node_alloc_holder &m_holder; + }; + struct members_holder : public NodeAlloc { diff --git a/boost/container/detail/node_pool.hpp b/boost/container/detail/node_pool.hpp index 60d826675a..00e35dfa8d 100644 --- a/boost/container/detail/node_pool.hpp +++ b/boost/container/detail/node_pool.hpp @@ -11,7 +11,11 @@ #ifndef BOOST_CONTAINER_DETAIL_NODE_POOL_HPP #define BOOST_CONTAINER_DETAIL_NODE_POOL_HPP -#if defined(_MSC_VER) && (_MSC_VER >= 1200) +#ifndef BOOST_CONFIG_HPP +# include <boost/config.hpp> +#endif + +#if defined(BOOST_HAS_PRAGMA_ONCE) # pragma once #endif @@ -22,11 +26,8 @@ #include <boost/container/detail/pool_common_alloc.hpp> #include <boost/container/detail/node_pool_impl.hpp> #include <boost/container/detail/mutex.hpp> -#include <boost/intrusive/slist.hpp> #include <boost/move/utility_core.hpp> #include <cstddef> -#include <functional> //std::unary_function -#include <algorithm> //std::swap #include <cassert> namespace boost { diff --git a/boost/container/detail/node_pool_impl.hpp b/boost/container/detail/node_pool_impl.hpp index 2450e5103e..4febf19e90 100644 --- a/boost/container/detail/node_pool_impl.hpp +++ b/boost/container/detail/node_pool_impl.hpp @@ -7,26 +7,31 @@ // See http://www.boost.org/libs/container for documentation. // ////////////////////////////////////////////////////////////////////////////// - #ifndef BOOST_CONTAINER_DETAIL_NODE_POOL_IMPL_HPP #define BOOST_CONTAINER_DETAIL_NODE_POOL_IMPL_HPP -#if defined(_MSC_VER) +#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> - #include <boost/container/container_fwd.hpp> -#include <boost/container/detail/utilities.hpp> -#include <boost/intrusive/pointer_traits.hpp> -#include <boost/intrusive/set.hpp> -#include <boost/intrusive/slist.hpp> -#include <boost/container/detail/type_traits.hpp> + #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/container/detail/type_traits.hpp> + +#include <boost/intrusive/pointer_traits.hpp> +#include <boost/intrusive/set.hpp> +#include <boost/intrusive/slist.hpp> + #include <boost/core/no_exceptions_support.hpp> #include <boost/assert.hpp> #include <cstddef> @@ -57,6 +62,10 @@ class private_node_pool_impl < node_t, bi::base_hook<slist_hook_t> , bi::linear<true> , bi::constant_time_size<false> >::type blockslist_t; + + static size_type get_rounded_size(size_type orig_size, size_type round_to) + { return ((orig_size-1)/round_to+1)*round_to; } + public: //!Segment manager typedef @@ -145,7 +154,7 @@ class private_node_pool_impl nodelist_iterator backup_list_last = backup_list.before_begin(); //Execute the algorithm and get an iterator to the last value - size_type blocksize = get_rounded_size + size_type blocksize = (get_rounded_size) (m_real_node_size*m_nodes_per_block, (size_type) alignment_of<node_t>::value); while(it != itend){ @@ -205,7 +214,7 @@ class private_node_pool_impl { //check for memory leaks BOOST_ASSERT(m_allocated==0); - size_type blocksize = get_rounded_size + size_type blocksize = (get_rounded_size) (m_real_node_size*m_nodes_per_block, (size_type)alignment_of<node_t>::value); //We iterate though the NodeBlock list to free the memory @@ -298,7 +307,7 @@ class private_node_pool_impl { BOOST_ASSERT(num_blocks > 0); size_type blocksize = - get_rounded_size(m_real_node_size*m_nodes_per_block, (size_type)alignment_of<node_t>::value); + (get_rounded_size)(m_real_node_size*m_nodes_per_block, (size_type)alignment_of<node_t>::value); BOOST_TRY{ for(size_type i = 0; i != num_blocks; ++i){ diff --git a/boost/container/detail/pair.hpp b/boost/container/detail/pair.hpp index b7ad84c80e..6d31d3b796 100644 --- a/boost/container/detail/pair.hpp +++ b/boost/container/detail/pair.hpp @@ -13,7 +13,11 @@ #ifndef BOOST_CONTAINER_CONTAINER_DETAIL_PAIR_HPP #define BOOST_CONTAINER_CONTAINER_DETAIL_PAIR_HPP -#if defined(_MSC_VER) +#ifndef BOOST_CONFIG_HPP +# include <boost/config.hpp> +#endif + +#if defined(BOOST_HAS_PRAGMA_ONCE) # pragma once #endif @@ -24,17 +28,11 @@ #include <boost/container/detail/type_traits.hpp> #include <boost/container/detail/mpl.hpp> #include <boost/container/detail/type_traits.hpp> +#include <boost/move/adl_move_swap.hpp> //swap -#include <utility> //std::pair -#include <algorithm> //std::swap - +#include <boost/intrusive/detail/minimal_pair_header.hpp> //pair #include <boost/move/utility_core.hpp> - -#ifndef BOOST_CONTAINER_PERFECT_FORWARDING -#include <boost/container/detail/preprocessor.hpp> -#endif - namespace boost { namespace container { namespace container_detail { @@ -166,37 +164,7 @@ struct pair //template <class... Args1, class... Args2> // pair(piecewise_construct_t, tuple<Args1...> first_args, // tuple<Args2...> second_args); -/* - //Variadic versions - template<class U> - pair(BOOST_CONTAINER_PP_PARAM(U, u), typename container_detail::disable_if - < container_detail::is_pair< typename container_detail::remove_ref_const<U>::type >, pair_nat>::type* = 0) - : first(::boost::forward<U>(u)) - , second() - {} - - #ifdef BOOST_CONTAINER_PERFECT_FORWARDING - template<class U, class V, class ...Args> - pair(U &&u, V &&v) - : first(::boost::forward<U>(u)) - , second(::boost::forward<V>(v), ::boost::forward<Args>(args)...) - {} - - #else - - #define BOOST_PP_LOCAL_MACRO(n) \ - template<class U, BOOST_PP_ENUM_PARAMS(n, class P)> \ - pair(BOOST_CONTAINER_PP_PARAM(U, u) \ - ,BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ - : first(::boost::forward<U>(u)) \ - , second(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)) \ - {} \ - //! - #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) - #include BOOST_PP_LOCAL_ITERATE() - #endif -*/ //pair copy assignment pair& operator=(BOOST_COPY_ASSIGN_REF(pair) p) { @@ -272,9 +240,8 @@ struct pair //swap void swap(pair& p) { - using std::swap; - swap(this->first, p.first); - swap(this->second, p.second); + ::boost::adl_move_swap(this->first, p.first); + ::boost::adl_move_swap(this->second, p.second); } }; @@ -309,10 +276,7 @@ inline pair<T1, T2> make_pair(T1 x, T2 y) template <class T1, class T2> inline void swap(pair<T1, T2>& x, pair<T1, T2>& y) -{ - swap(x.first, y.first); - swap(x.second, y.second); -} +{ x.swap(y); } } //namespace container_detail { } //namespace container { diff --git a/boost/container/detail/placement_new.hpp b/boost/container/detail/placement_new.hpp index 2489d8a45e..c50981f685 100644 --- a/boost/container/detail/placement_new.hpp +++ b/boost/container/detail/placement_new.hpp @@ -1,6 +1,8 @@ +#ifndef BOOST_CONTAINER_DETAIL_PLACEMENT_NEW_HPP +#define BOOST_CONTAINER_DETAIL_PLACEMENT_NEW_HPP /////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2014-2014. Distributed under the Boost +// (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) // @@ -8,10 +10,11 @@ // /////////////////////////////////////////////////////////////////////////////// -#ifndef BOOST_CONTAINER_DETAIL_PLACEMENT_NEW_HPP -#define BOOST_CONTAINER_DETAIL_PLACEMENT_NEW_HPP +#ifndef BOOST_CONFIG_HPP +# include <boost/config.hpp> +#endif -#if defined(_MSC_VER) +#if defined(BOOST_HAS_PRAGMA_ONCE) # pragma once #endif diff --git a/boost/container/detail/pool_common.hpp b/boost/container/detail/pool_common.hpp index 11fb6c2e50..61d0612ed1 100644 --- a/boost/container/detail/pool_common.hpp +++ b/boost/container/detail/pool_common.hpp @@ -11,7 +11,11 @@ #ifndef BOOST_CONTAINER_DETAIL_POOL_COMMON_HPP #define BOOST_CONTAINER_DETAIL_POOL_COMMON_HPP -#if defined(_MSC_VER) +#ifndef BOOST_CONFIG_HPP +# include <boost/config.hpp> +#endif + +#if defined(BOOST_HAS_PRAGMA_ONCE) # pragma once #endif diff --git a/boost/container/detail/pool_common_alloc.hpp b/boost/container/detail/pool_common_alloc.hpp index dfae7efd13..72e9c8d278 100644 --- a/boost/container/detail/pool_common_alloc.hpp +++ b/boost/container/detail/pool_common_alloc.hpp @@ -11,7 +11,11 @@ #ifndef BOOST_CONTAINER_DETAIL_POOL_COMMON_ALLOC_HPP #define BOOST_CONTAINER_DETAIL_POOL_COMMON_ALLOC_HPP -#if defined(_MSC_VER) +#ifndef BOOST_CONFIG_HPP +# include <boost/config.hpp> +#endif + +#if defined(BOOST_HAS_PRAGMA_ONCE) # pragma once #endif diff --git a/boost/container/detail/preprocessor.hpp b/boost/container/detail/preprocessor.hpp deleted file mode 100644 index 838eff2ca1..0000000000 --- a/boost/container/detail/preprocessor.hpp +++ /dev/null @@ -1,228 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2008-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_DETAIL_PREPROCESSOR_HPP -#define BOOST_CONTAINER_DETAIL_PREPROCESSOR_HPP - -#if defined(_MSC_VER) -# pragma once -#endif - -#include <boost/container/detail/config_begin.hpp> -#include <boost/container/detail/workaround.hpp> -#include <boost/move/utility_core.hpp> - -#ifdef BOOST_CONTAINER_PERFECT_FORWARDING -//#error "This file is not needed when perfect forwarding is available" -#endif //BOOST_CONTAINER_PERFECT_FORWARDING - -#include <boost/preprocessor/iteration/local.hpp> -#include <boost/preprocessor/punctuation/paren_if.hpp> -#include <boost/preprocessor/punctuation/comma_if.hpp> -#include <boost/preprocessor/control/expr_if.hpp> -#include <boost/preprocessor/cat.hpp> -#include <boost/preprocessor/repetition/enum.hpp> -#include <boost/preprocessor/repetition/enum_params.hpp> -#include <boost/preprocessor/repetition/enum_trailing_params.hpp> -#include <boost/preprocessor/repetition/enum_trailing.hpp> -#include <boost/preprocessor/repetition/repeat.hpp> -#include <boost/preprocessor/arithmetic/sub.hpp> -#include <boost/preprocessor/arithmetic/add.hpp> -#include <boost/preprocessor/iteration/iterate.hpp> - -#define BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS 10 - -//Note: -//We define template parameters as const references to -//be able to bind temporaries. After that we will un-const them. -//This cast is ugly but it is necessary until "perfect forwarding" -//is achieved in C++0x. Meanwhile, if we want to be able to -//bind rvalues with non-const references, we have to be ugly -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - #define BOOST_CONTAINER_PP_PARAM_LIST(z, n, data) \ - BOOST_PP_CAT(P, n) && BOOST_PP_CAT(p, n) \ - //! -#else - #define BOOST_CONTAINER_PP_PARAM_LIST(z, n, data) \ - const BOOST_PP_CAT(P, n) & BOOST_PP_CAT(p, n) \ - //! -#endif //#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - -#define BOOST_CONTAINER_PP_CONST_REF_PARAM_LIST_Q(z, n, Data) \ -const BOOST_PP_CAT(Q, n) & BOOST_PP_CAT(q, n) \ -//! - -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - #define BOOST_CONTAINER_PP_PARAM(U, u) \ - U && u \ - //! -#else - #define BOOST_CONTAINER_PP_PARAM(U, u) \ - const U & u \ - //! -#endif //#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - - #define BOOST_CONTAINER_PP_PARAM_INIT(z, n, data) \ - BOOST_PP_CAT(m_p, n) (::boost::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(p, n) )) \ - //! - -#else //BOOST_NO_CXX11_RVALUE_REFERENCES - - #define BOOST_CONTAINER_PP_PARAM_INIT(z, n, data) \ - BOOST_PP_CAT(m_p, n) (const_cast<BOOST_PP_CAT(P, n) &>(BOOST_PP_CAT(p, n))) \ - //! -#endif //#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - - #if defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG) - - namespace boost { - namespace container { - namespace container_detail { - template<class T> - struct ref_holder; - - template<class T> - struct ref_holder<T &> - { - explicit ref_holder(T &t) - : t_(t) - {} - T &t_; - T & get() { return t_; } - }; - - template<class T> - struct ref_holder<const T> - { - explicit ref_holder(const T &t) - : t_(t) - {} - const T &t_; - const T & get() { return t_; } - }; - - template<class T> - struct ref_holder<const T &&> - { - explicit ref_holder(const T &t) - : t_(t) - {} - const T &t_; - const T & get() { return t_; } - }; - - template<class T> - struct ref_holder - { - explicit ref_holder(T &&t) - : t_(t) - {} - T &t_; - T && get() { return ::boost::move(t_); } - }; - - template<class T> - struct ref_holder<T &&> - { - explicit ref_holder(T &&t) - : t_(t) - {} - T &t_; - T && get() { return ::boost::move(t_); } - }; - - } //namespace container_detail { - } //namespace container { - } //namespace boost { - - #define BOOST_CONTAINER_PP_PARAM_DEFINE(z, n, data) \ - ::boost::container::container_detail::ref_holder<BOOST_PP_CAT(P, n)> BOOST_PP_CAT(m_p, n); \ - //! - - #else //BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG - - #define BOOST_CONTAINER_PP_PARAM_DEFINE(z, n, data) \ - BOOST_PP_CAT(P, n) && BOOST_PP_CAT(m_p, n); \ - //! - - #endif //defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG) - -#else //BOOST_NO_CXX11_RVALUE_REFERENCES - - #define BOOST_CONTAINER_PP_PARAM_DEFINE(z, n, data) \ - BOOST_PP_CAT(P, n) & BOOST_PP_CAT(m_p, n); \ - //! -#endif //#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - -#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG) - - #define BOOST_CONTAINER_PP_MEMBER_FORWARD(z, n, data) BOOST_PP_CAT(this->m_p, n).get() \ - //! - -#else //!defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG) - - #define BOOST_CONTAINER_PP_MEMBER_FORWARD(z, n, data) \ - ::boost::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(this->m_p, n) ) \ - //! - -#endif //!defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG) - -#define BOOST_CONTAINER_PP_PARAM_INC(z, n, data) \ - BOOST_PP_CAT(++this->m_p, n) \ -//! - -#define BOOST_CONTAINER_PP_IDENTITY(z, n, data) data - - -#define BOOST_CONTAINER_PP_PARAM_FORWARD(z, n, data) \ -::boost::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(p, n) ) \ -//! - -#define BOOST_CONTAINER_PP_DECLVAL(z, n, data) \ -::boost::move_detail::declval< BOOST_PP_CAT(P, n) >() \ -//! - -#define BOOST_CONTAINER_PP_MEMBER_IT_FORWARD(z, n, data) \ -BOOST_PP_CAT(*this->m_p, n) \ -//! - -#define BOOST_CONTAINER_PP_TEMPLATE_PARAM_VOID_DEFAULT(z, n, data) \ - BOOST_PP_CAT(class P, n) = void \ -//! - -#define BOOST_CONTAINER_PP_TEMPLATE_PARAM_WITH_DEFAULT(z, n, default_type) \ - BOOST_PP_CAT(class P, n) = default_type \ -//! - -#define BOOST_CONTAINER_PP_STATIC_PARAM_REF_DECLARE(z, n, data) \ - static BOOST_PP_CAT(P, n) & BOOST_PP_CAT(p, n); \ -//! - -#define BOOST_CONTAINER_PP_PARAM_PASS(z, n, data) \ - BOOST_PP_CAT(p, n) \ -//! - -#define BOOST_CONTAINER_PP_FWD_TYPE(z, n, data) \ - typename ::boost::move_detail::forward_type< BOOST_PP_CAT(P, n) >::type \ -//! - -#include <boost/container/detail/config_end.hpp> - -//#else - -//#ifdef BOOST_CONTAINER_PERFECT_FORWARDING -//#error "This file is not needed when perfect forwarding is available" -//#endif //BOOST_CONTAINER_PERFECT_FORWARDING - -#endif //#ifndef BOOST_CONTAINER_DETAIL_PREPROCESSOR_HPP diff --git a/boost/container/detail/singleton.hpp b/boost/container/detail/singleton.hpp index a2372c3a96..6fd6a54f30 100644 --- a/boost/container/detail/singleton.hpp +++ b/boost/container/detail/singleton.hpp @@ -22,7 +22,11 @@ #ifndef BOOST_CONTAINER_DETAIL_SINGLETON_DETAIL_HPP #define BOOST_CONTAINER_DETAIL_SINGLETON_DETAIL_HPP -#if defined(_MSC_VER) +#ifndef BOOST_CONFIG_HPP +# include <boost/config.hpp> +#endif + +#if defined(BOOST_HAS_PRAGMA_ONCE) # pragma once #endif diff --git a/boost/container/detail/std_fwd.hpp b/boost/container/detail/std_fwd.hpp index a2edeccff1..a2931c134b 100644 --- a/boost/container/detail/std_fwd.hpp +++ b/boost/container/detail/std_fwd.hpp @@ -11,7 +11,11 @@ #ifndef BOOST_CONTAINER_DETAIL_STD_FWD_HPP #define BOOST_CONTAINER_DETAIL_STD_FWD_HPP -#if defined(_MSC_VER) +#ifndef BOOST_CONFIG_HPP +# include <boost/config.hpp> +#endif + +#if defined(BOOST_HAS_PRAGMA_ONCE) # pragma once #endif @@ -25,6 +29,12 @@ #pragma GCC diagnostic ignored "-Wc++11-extensions" #define BOOST_CONTAINER_STD_NS_BEG _LIBCPP_BEGIN_NAMESPACE_STD #define BOOST_CONTAINER_STD_NS_END _LIBCPP_END_NAMESPACE_STD +#elif defined(BOOST_GNU_STDLIB) && defined(_GLIBCXX_BEGIN_NAMESPACE_VERSION) //GCC >= 4.6 + #define BOOST_CONTAINER_STD_NS_BEG namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION + #define BOOST_CONTAINER_STD_NS_END _GLIBCXX_END_NAMESPACE_VERSION } // namespace +#elif defined(BOOST_GNU_STDLIB) && defined(_GLIBCXX_BEGIN_NAMESPACE) //GCC >= 4.2 + #define BOOST_CONTAINER_STD_NS_BEG _GLIBCXX_BEGIN_NAMESPACE(std) + #define BOOST_CONTAINER_STD_NS_END _GLIBCXX_END_NAMESPACE #else #define BOOST_CONTAINER_STD_NS_BEG namespace std{ #define BOOST_CONTAINER_STD_NS_END } @@ -49,6 +59,11 @@ struct forward_iterator_tag; struct bidirectional_iterator_tag; struct random_access_iterator_tag; +template<class Container> +class insert_iterator; + +struct allocator_arg_t; + BOOST_CONTAINER_STD_NS_END #ifdef BOOST_CONTAINER_CLANG_INLINE_STD_NS diff --git a/boost/container/detail/to_raw_pointer.hpp b/boost/container/detail/to_raw_pointer.hpp new file mode 100644 index 0000000000..0b4445a942 --- /dev/null +++ b/boost/container/detail/to_raw_pointer.hpp @@ -0,0 +1,33 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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/transform_iterator.hpp b/boost/container/detail/transform_iterator.hpp index c4e746c389..ba64c7de79 100644 --- a/boost/container/detail/transform_iterator.hpp +++ b/boost/container/detail/transform_iterator.hpp @@ -14,15 +14,18 @@ #ifndef BOOST_CONTAINER_DETAIL_TRANSFORM_ITERATORS_HPP #define BOOST_CONTAINER_DETAIL_TRANSFORM_ITERATORS_HPP -#if defined(_MSC_VER) +#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> - #include <boost/container/detail/type_traits.hpp> -#include <iterator> +#include <boost/container/detail/iterator.hpp> namespace boost { namespace container { @@ -58,7 +61,7 @@ struct operator_arrow_proxy<T&> template <class Iterator, class UnaryFunction> class transform_iterator : public UnaryFunction - , public std::iterator + , public boost::container::iterator < typename Iterator::iterator_category , typename container_detail::remove_reference<typename UnaryFunction::result_type>::type , typename Iterator::difference_type @@ -156,10 +159,10 @@ class transform_iterator { return UnaryFunction::operator()(*m_it); } void advance(typename Iterator::difference_type n) - { std::advance(m_it, n); } + { boost::container::iterator_advance(m_it, n); } typename Iterator::difference_type distance_to(const transform_iterator &other)const - { return std::distance(other.m_it, m_it); } + { return boost::container::iterator_distance(other.m_it, m_it); } }; template <class Iterator, class UnaryFunc> diff --git a/boost/container/detail/tree.hpp b/boost/container/detail/tree.hpp index e59bca0887..0f90b5a4e2 100644 --- a/boost/container/detail/tree.hpp +++ b/boost/container/detail/tree.hpp @@ -11,62 +11,66 @@ #ifndef BOOST_CONTAINER_TREE_HPP #define BOOST_CONTAINER_TREE_HPP -#if defined(_MSC_VER) +#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> +// container +#include <boost/container/allocator_traits.hpp> #include <boost/container/container_fwd.hpp> +#include <boost/container/options.hpp> -#include <boost/container/detail/utilities.hpp> +// container/detail +#include <boost/container/detail/algorithm.hpp> //algo_equal(), algo_lexicographical_compare +#include <boost/container/detail/compare_functors.hpp> +#include <boost/container/detail/destroyers.hpp> +#include <boost/container/detail/iterator.hpp> #include <boost/container/detail/iterators.hpp> -#include <boost/container/detail/algorithms.hpp> #include <boost/container/detail/node_alloc_holder.hpp> -#include <boost/container/detail/destroyers.hpp> #include <boost/container/detail/pair.hpp> #include <boost/container/detail/type_traits.hpp> -#include <boost/container/allocator_traits.hpp> -#include <boost/container/options.hpp> - -// +// intrusive #include <boost/intrusive/pointer_traits.hpp> #include <boost/intrusive/rbtree.hpp> #include <boost/intrusive/avltree.hpp> #include <boost/intrusive/splaytree.hpp> #include <boost/intrusive/sgtree.hpp> -// +// intrusive/detail +#include <boost/intrusive/detail/minimal_pair_header.hpp> //pair +// move #include <boost/move/utility_core.hpp> -#include <boost/type_traits/has_trivial_destructor.hpp> -#include <boost/core/no_exceptions_support.hpp> -// -#ifndef BOOST_CONTAINER_PERFECT_FORWARDING -#include <boost/container/detail/preprocessor.hpp> +// move/detail +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +#include <boost/move/detail/fwd_macros.hpp> #endif - -#include <utility> //std::pair -#include <iterator> -#include <algorithm> +// other +#include <boost/core/no_exceptions_support.hpp> namespace boost { namespace container { namespace container_detail { -template<class Key, class Value, class KeyCompare, class KeyOfValue> +template<class Key, class T, class Compare, class KeyOfValue> struct tree_value_compare - : public KeyCompare + : public Compare { - typedef Value value_type; - typedef KeyCompare key_compare; + typedef T value_type; + typedef Compare key_compare; typedef KeyOfValue key_of_value; typedef Key key_type; explicit tree_value_compare(const key_compare &kcomp) - : KeyCompare(kcomp) + : Compare(kcomp) {} tree_value_compare() - : KeyCompare() + : Compare() {} const key_compare &key_comp() const @@ -75,25 +79,29 @@ struct tree_value_compare key_compare &key_comp() { return static_cast<key_compare &>(*this); } - template<class T> + template<class U> struct is_key { - static const bool value = is_same<const T, const key_type>::value; + static const bool value = is_same<const U, const key_type>::value; }; - template<class T> - typename enable_if_c<is_key<T>::value, const key_type &>::type - key_forward(const T &key) const + template<class U> + typename enable_if_c<is_key<U>::value, const key_type &>::type + key_forward(const U &key) const { return key; } - template<class T> - typename enable_if_c<!is_key<T>::value, const key_type &>::type - key_forward(const T &key) const + template<class U> + typename enable_if_c<!is_key<U>::value, const key_type &>::type + key_forward(const U &key) const { return KeyOfValue()(key); } template<class KeyType, class KeyType2> bool operator()(const KeyType &key1, const KeyType2 &key2) const { return key_compare::operator()(this->key_forward(key1), this->key_forward(key2)); } + + template<class KeyType, class KeyType2> + bool operator()(const KeyType &key1, const KeyType2 &key2) + { return key_compare::operator()(this->key_forward(key1), this->key_forward(key2)); } }; template<class VoidPointer, boost::container::tree_type_enum tree_type_value, bool OptimizeSize> @@ -183,17 +191,17 @@ struct tree_node internal_type m_data; - template<class A, class B> - void do_assign(const std::pair<const A, B> &p) + template<class T1, class T2> + void do_assign(const std::pair<const T1, T2> &p) { - const_cast<A&>(m_data.first) = p.first; + const_cast<T1&>(m_data.first) = p.first; m_data.second = p.second; } - template<class A, class B> - void do_assign(const pair<const A, B> &p) + template<class T1, class T2> + void do_assign(const pair<const T1, T2> &p) { - const_cast<A&>(m_data.first) = p.first; + const_cast<T1&>(m_data.first) = p.first; m_data.second = p.second; } @@ -201,17 +209,17 @@ struct tree_node void do_assign(const V &v) { m_data = v; } - template<class A, class B> - void do_move_assign(std::pair<const A, B> &p) + template<class T1, class T2> + void do_move_assign(std::pair<const T1, T2> &p) { - const_cast<A&>(m_data.first) = ::boost::move(p.first); + const_cast<T1&>(m_data.first) = ::boost::move(p.first); m_data.second = ::boost::move(p.second); } - template<class A, class B> - void do_move_assign(pair<const A, B> &p) + template<class T1, class T2> + void do_move_assign(pair<const T1, T2> &p) { - const_cast<A&>(m_data.first) = ::boost::move(p.first); + const_cast<T1&>(m_data.first) = ::boost::move(p.first); m_data.second = ::boost::move(p.second); } @@ -314,20 +322,21 @@ struct intrusive_tree_dispatch >::type type; }; -template<class A, class ValueCompare, boost::container::tree_type_enum tree_type_value, bool OptimizeSize> +template<class Allocator, class ValueCompare, boost::container::tree_type_enum tree_type_value, bool OptimizeSize> struct intrusive_tree_type { private: typedef typename boost::container:: - allocator_traits<A>::value_type value_type; + allocator_traits<Allocator>::value_type value_type; typedef typename boost::container:: - allocator_traits<A>::void_pointer void_pointer; + allocator_traits<Allocator>::void_pointer void_pointer; typedef typename boost::container:: - allocator_traits<A>::size_type size_type; + allocator_traits<Allocator>::size_type size_type; typedef typename container_detail::tree_node < value_type, void_pointer , tree_type_value, OptimizeSize> node_type; - typedef node_compare<ValueCompare, node_type> node_compare_type; + typedef value_to_node_compare + <node_type, ValueCompare> node_compare_type; //Deducing the hook type from node_type (e.g. node_type::hook_type) would //provoke an early instantiation of node_type that could ruin recursive //tree definitions, so retype the complete type to avoid any problem. @@ -391,10 +400,10 @@ class RecyclingCloner {} static void do_assign(node_ptr_type &p, const node_type &other, bool_<true>) - { p->do_assign(other.m_data); } + { p->do_move_assign(const_cast<node_type &>(other).m_data); } static void do_assign(node_ptr_type &p, const node_type &other, bool_<false>) - { p->do_move_assign(const_cast<node_type &>(other).m_data); } + { p->do_assign(other.m_data); } node_ptr_type operator()(const node_type &other) const { @@ -425,7 +434,7 @@ class RecyclingCloner }; template<class KeyValueCompare, class Node> -//where KeyValueCompare is tree_value_compare<Key, Value, KeyCompare, KeyOfValue> +//where KeyValueCompare is tree_value_compare<Key, T, Compare, KeyOfValue> struct key_node_compare : private KeyValueCompare { @@ -454,35 +463,35 @@ struct key_node_compare { return KeyValueCompare::operator()(this->key_forward(key1), this->key_forward(key2)); } }; -template <class Key, class Value, class KeyOfValue, - class KeyCompare, class A, +template <class Key, class T, class KeyOfValue, + class Compare, class Allocator, class Options = tree_assoc_defaults> class tree : protected container_detail::node_alloc_holder - < A + < Allocator , typename container_detail::intrusive_tree_type - < A, tree_value_compare<Key, Value, KeyCompare, KeyOfValue> //ValComp + < Allocator, tree_value_compare<Key, T, Compare, KeyOfValue> //ValComp , Options::tree_type, Options::optimize_size>::type > { typedef tree_value_compare - <Key, Value, KeyCompare, KeyOfValue> ValComp; + <Key, T, Compare, KeyOfValue> ValComp; typedef typename container_detail::intrusive_tree_type - < A, ValComp, Options::tree_type + < Allocator, ValComp, Options::tree_type , Options::optimize_size>::type Icont; typedef container_detail::node_alloc_holder - <A, Icont> AllocHolder; + <Allocator, Icont> AllocHolder; typedef typename AllocHolder::NodePtr NodePtr; - typedef tree < Key, Value, KeyOfValue - , KeyCompare, A, Options> ThisType; + typedef tree < Key, T, KeyOfValue + , Compare, Allocator, Options> ThisType; typedef typename AllocHolder::NodeAlloc NodeAlloc; + typedef boost::container:: + allocator_traits<NodeAlloc> allocator_traits_type; typedef typename AllocHolder::ValAlloc ValAlloc; typedef typename AllocHolder::Node Node; typedef typename Icont::iterator iiterator; typedef typename Icont::const_iterator iconst_iterator; typedef container_detail::allocator_destroyer<NodeAlloc> Destroyer; - typedef typename AllocHolder::allocator_v1 allocator_v1; - typedef typename AllocHolder::allocator_v2 allocator_v2; typedef typename AllocHolder::alloc_version alloc_version; typedef intrusive_tree_proxy<Options::tree_type> intrusive_tree_proxy_t; @@ -491,22 +500,22 @@ class tree public: typedef Key key_type; - typedef Value value_type; - typedef A allocator_type; - typedef KeyCompare key_compare; + typedef T value_type; + typedef Allocator allocator_type; + typedef Compare key_compare; typedef ValComp value_compare; typedef typename boost::container:: - allocator_traits<A>::pointer pointer; + allocator_traits<Allocator>::pointer pointer; typedef typename boost::container:: - allocator_traits<A>::const_pointer const_pointer; + allocator_traits<Allocator>::const_pointer const_pointer; typedef typename boost::container:: - allocator_traits<A>::reference reference; + allocator_traits<Allocator>::reference reference; typedef typename boost::container:: - allocator_traits<A>::const_reference const_reference; + allocator_traits<Allocator>::const_reference const_reference; typedef typename boost::container:: - allocator_traits<A>::size_type size_type; + allocator_traits<Allocator>::size_type size_type; typedef typename boost::container:: - allocator_traits<A>::difference_type difference_type; + allocator_traits<Allocator>::difference_type difference_type; typedef difference_type tree_difference_type; typedef pointer tree_pointer; typedef const_pointer tree_const_pointer; @@ -519,17 +528,17 @@ class tree typedef key_node_compare<value_compare, Node> KeyNodeCompare; public: - typedef container_detail::iterator<iiterator, false> iterator; - typedef container_detail::iterator<iiterator, true > const_iterator; - typedef container_detail::reverse_iterator<iterator> reverse_iterator; - typedef container_detail::reverse_iterator<const_iterator> const_reverse_iterator; + typedef container_detail::iterator_from_iiterator<iiterator, false> iterator; + typedef container_detail::iterator_from_iiterator<iiterator, true > const_iterator; + typedef boost::container::reverse_iterator<iterator> reverse_iterator; + typedef boost::container::reverse_iterator<const_iterator> const_reverse_iterator; tree() - : AllocHolder(ValComp(key_compare())) + : AllocHolder() {} explicit tree(const key_compare& comp, const allocator_type& a = allocator_type()) - : AllocHolder(a, ValComp(comp)) + : AllocHolder(ValComp(comp), a) {} explicit tree(const allocator_type& a) @@ -542,11 +551,11 @@ class tree #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) , typename container_detail::enable_if_c < container_detail::is_input_iterator<InputIterator>::value - || container_detail::is_same<alloc_version, allocator_v1>::value + || container_detail::is_same<alloc_version, version_1>::value >::type * = 0 #endif ) - : AllocHolder(a, value_compare(comp)) + : AllocHolder(value_compare(comp), a) { //Use cend() as hint to achieve linear time for //ordered ranges as required by the standard @@ -570,11 +579,11 @@ class tree #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) , typename container_detail::enable_if_c < !(container_detail::is_input_iterator<InputIterator>::value - || container_detail::is_same<alloc_version, allocator_v1>::value) + || container_detail::is_same<alloc_version, version_1>::value) >::type * = 0 #endif ) - : AllocHolder(a, value_compare(comp)) + : AllocHolder(value_compare(comp), a) { if(unique_insertion){ //Use cend() as hint to achieve linear time for @@ -588,7 +597,7 @@ class tree else{ //Optimized allocation and construction this->allocate_many_and_construct - ( first, std::distance(first, last) + ( first, boost::container::iterator_distance(first, last) , insert_equal_end_hint_functor<Node, Icont>(this->icont())); } } @@ -599,11 +608,11 @@ class tree #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) , typename container_detail::enable_if_c < container_detail::is_input_iterator<InputIterator>::value - || container_detail::is_same<alloc_version, allocator_v1>::value + || container_detail::is_same<alloc_version, version_1>::value >::type * = 0 #endif ) - : AllocHolder(a, value_compare(comp)) + : AllocHolder(value_compare(comp), a) { for ( ; first != last; ++first){ this->push_back_impl(*first); @@ -616,45 +625,45 @@ class tree #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) , typename container_detail::enable_if_c < !(container_detail::is_input_iterator<InputIterator>::value - || container_detail::is_same<alloc_version, allocator_v1>::value) + || container_detail::is_same<alloc_version, version_1>::value) >::type * = 0 #endif ) - : AllocHolder(a, value_compare(comp)) + : AllocHolder(value_compare(comp), a) { //Optimized allocation and construction this->allocate_many_and_construct - ( first, std::distance(first, last) + ( first, boost::container::iterator_distance(first, last) , container_detail::push_back_functor<Node, Icont>(this->icont())); } tree(const tree& x) - : AllocHolder(x, x.value_comp()) + : AllocHolder(x.value_comp(), x) { this->icont().clone_from (x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc())); } tree(BOOST_RV_REF(tree) x) - : AllocHolder(::boost::move(static_cast<AllocHolder&>(x)), x.value_comp()) + : AllocHolder(BOOST_MOVE_BASE(AllocHolder, x), x.value_comp()) {} tree(const tree& x, const allocator_type &a) - : AllocHolder(a, x.value_comp()) + : AllocHolder(x.value_comp(), a) { this->icont().clone_from (x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc())); } tree(BOOST_RV_REF(tree) x, const allocator_type &a) - : AllocHolder(a, x.value_comp()) + : AllocHolder(x.value_comp(), a) { if(this->node_alloc() == x.node_alloc()){ this->icont().swap(x.icont()); } else{ this->icont().clone_from - (x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc())); + (x.icont(), typename AllocHolder::move_cloner(*this), Destroyer(this->node_alloc())); } } @@ -693,6 +702,8 @@ class tree } tree& operator=(BOOST_RV_REF(tree) x) + BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value + && boost::container::container_detail::is_nothrow_move_assignable<Compare>::value ) { BOOST_ASSERT(this != &x); NodeAlloc &this_alloc = this->node_alloc(); @@ -735,10 +746,10 @@ class tree public: // accessors: value_compare value_comp() const - { return this->icont().value_comp().value_comp(); } + { return this->icont().value_comp().predicate(); } key_compare key_comp() const - { return this->icont().value_comp().value_comp().key_comp(); } + { return this->icont().value_comp().predicate().key_comp(); } allocator_type get_allocator() const { return allocator_type(this->node_alloc()); } @@ -817,6 +828,8 @@ class tree { return AllocHolder::max_size(); } void swap(ThisType& x) + BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value + && boost::container::container_detail::is_nothrow_swappable<Compare>::value ) { AllocHolder::swap(x); } public: @@ -851,9 +864,9 @@ class tree template<class MovableConvertible> iterator insert_unique_commit - (BOOST_FWD_REF(MovableConvertible) mv, insert_commit_data &data) + (BOOST_FWD_REF(MovableConvertible) v, insert_commit_data &data) { - NodePtr tmp = AllocHolder::create_node(boost::forward<MovableConvertible>(mv)); + NodePtr tmp = AllocHolder::create_node(boost::forward<MovableConvertible>(v)); scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc()); iterator ret(this->icont().insert_unique_commit(*tmp, data)); destroy_deallocator.release(); @@ -872,13 +885,13 @@ class tree } template<class MovableConvertible> - std::pair<iterator,bool> insert_unique(BOOST_FWD_REF(MovableConvertible) mv) + std::pair<iterator,bool> insert_unique(BOOST_FWD_REF(MovableConvertible) v) { insert_commit_data data; std::pair<iterator,bool> ret = - this->insert_unique_check(KeyOfValue()(mv), data); + this->insert_unique_check(KeyOfValue()(v), data); if(ret.second){ - ret.first = this->insert_unique_commit(boost::forward<MovableConvertible>(mv), data); + ret.first = this->insert_unique_commit(boost::forward<MovableConvertible>(v), data); } return ret; } @@ -886,9 +899,9 @@ class tree private: template<class MovableConvertible> - void push_back_impl(BOOST_FWD_REF(MovableConvertible) mv) + void push_back_impl(BOOST_FWD_REF(MovableConvertible) v) { - NodePtr tmp(AllocHolder::create_node(boost::forward<MovableConvertible>(mv))); + NodePtr tmp(AllocHolder::create_node(boost::forward<MovableConvertible>(v))); //push_back has no-throw guarantee so avoid any deallocator/destroyer this->icont().push_back(*tmp); } @@ -925,18 +938,18 @@ class tree public: - #ifdef BOOST_CONTAINER_PERFECT_FORWARDING + #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) template <class... Args> - std::pair<iterator, bool> emplace_unique(Args&&... args) + std::pair<iterator, bool> emplace_unique(BOOST_FWD_REF(Args)... args) { return this->emplace_unique_impl(AllocHolder::create_node(boost::forward<Args>(args)...)); } template <class... Args> - iterator emplace_hint_unique(const_iterator hint, Args&&... args) + iterator emplace_hint_unique(const_iterator hint, BOOST_FWD_REF(Args)... args) { return this->emplace_unique_hint_impl(hint, AllocHolder::create_node(boost::forward<Args>(args)...)); } template <class... Args> - iterator emplace_equal(Args&&... args) + iterator emplace_equal(BOOST_FWD_REF(Args)... args) { NodePtr tmp(AllocHolder::create_node(boost::forward<Args>(args)...)); scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc()); @@ -946,7 +959,7 @@ class tree } template <class... Args> - iterator emplace_hint_equal(const_iterator hint, Args&&... args) + iterator emplace_hint_equal(const_iterator hint, BOOST_FWD_REF(Args)... args) { NodePtr tmp(AllocHolder::create_node(boost::forward<Args>(args)...)); scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc()); @@ -955,49 +968,41 @@ class tree return ret; } - #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING - - #define BOOST_PP_LOCAL_MACRO(n) \ - BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ - std::pair<iterator, bool> emplace_unique(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ - { \ - return this->emplace_unique_impl \ - (AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \ - } \ - \ - BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ - iterator emplace_hint_unique(const_iterator hint \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ - { \ - return this->emplace_unique_hint_impl \ - (hint, AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \ - } \ - \ - BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ - iterator emplace_equal(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ - { \ - NodePtr tmp(AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \ - scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc()); \ - iterator ret(this->icont().insert_equal(this->icont().end(), *tmp)); \ - destroy_deallocator.release(); \ - return ret; \ - } \ - \ - BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ - iterator emplace_hint_equal(const_iterator hint \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ - { \ - NodePtr tmp(AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \ - scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc()); \ - iterator ret(this->icont().insert_equal(hint.get(), *tmp)); \ - destroy_deallocator.release(); \ - return ret; \ - } \ - //! - #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) - #include BOOST_PP_LOCAL_ITERATE() - - #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING + #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + + #define BOOST_CONTAINER_TREE_EMPLACE_CODE(N) \ + BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ + std::pair<iterator, bool> emplace_unique(BOOST_MOVE_UREF##N)\ + { return this->emplace_unique_impl(AllocHolder::create_node(BOOST_MOVE_FWD##N)); }\ + \ + BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ + iterator emplace_hint_unique(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ + { return this->emplace_unique_hint_impl(hint, AllocHolder::create_node(BOOST_MOVE_FWD##N)); }\ + \ + BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ + iterator emplace_equal(BOOST_MOVE_UREF##N)\ + {\ + NodePtr tmp(AllocHolder::create_node(BOOST_MOVE_FWD##N));\ + scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());\ + iterator ret(this->icont().insert_equal(this->icont().end(), *tmp));\ + destroy_deallocator.release();\ + return ret;\ + }\ + \ + BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ + iterator emplace_hint_equal(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ + {\ + NodePtr tmp(AllocHolder::create_node(BOOST_MOVE_FWD##N));\ + scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());\ + iterator ret(this->icont().insert_equal(hint.get(), *tmp));\ + destroy_deallocator.release();\ + return ret;\ + }\ + // + BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_TREE_EMPLACE_CODE) + #undef BOOST_CONTAINER_TREE_EMPLACE_CODE + + #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) iterator insert_unique(const_iterator hint, const value_type& v) { @@ -1010,14 +1015,14 @@ class tree } template<class MovableConvertible> - iterator insert_unique(const_iterator hint, BOOST_FWD_REF(MovableConvertible) mv) + iterator insert_unique(const_iterator hint, BOOST_FWD_REF(MovableConvertible) v) { insert_commit_data data; std::pair<iterator,bool> ret = - this->insert_unique_check(hint, KeyOfValue()(mv), data); + this->insert_unique_check(hint, KeyOfValue()(v), data); if(!ret.second) return ret.first; - return this->insert_unique_commit(boost::forward<MovableConvertible>(mv), data); + return this->insert_unique_commit(boost::forward<MovableConvertible>(v), data); } template <class InputIterator> @@ -1037,9 +1042,9 @@ class tree } template<class MovableConvertible> - iterator insert_equal(BOOST_FWD_REF(MovableConvertible) mv) + iterator insert_equal(BOOST_FWD_REF(MovableConvertible) v) { - NodePtr tmp(AllocHolder::create_node(boost::forward<MovableConvertible>(mv))); + NodePtr tmp(AllocHolder::create_node(boost::forward<MovableConvertible>(v))); scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc()); iterator ret(this->icont().insert_equal(this->icont().end(), *tmp)); destroy_deallocator.release(); @@ -1056,9 +1061,9 @@ class tree } template<class MovableConvertible> - iterator insert_equal(const_iterator hint, BOOST_FWD_REF(MovableConvertible) mv) + iterator insert_equal(const_iterator hint, BOOST_FWD_REF(MovableConvertible) v) { - NodePtr tmp(AllocHolder::create_node(boost::forward<MovableConvertible>(mv))); + NodePtr tmp(AllocHolder::create_node(boost::forward<MovableConvertible>(v))); scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc()); iterator ret(this->icont().insert_equal(hint.get(), *tmp)); destroy_deallocator.release(); @@ -1141,10 +1146,10 @@ class tree { intrusive_tree_proxy_t::rebalance(this->icont()); } friend bool operator==(const tree& x, const tree& y) - { return x.size() == y.size() && std::equal(x.begin(), x.end(), y.begin()); } + { return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin()); } friend bool operator<(const tree& x, const tree& y) - { return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } + { return ::boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } friend bool operator!=(const tree& x, const tree& y) { return !(x == y); } @@ -1164,17 +1169,25 @@ class tree } //namespace container_detail { } //namespace container { -/* + +template <class T> +struct has_trivial_destructor_after_move; + //!has_trivial_destructor_after_move<> == true_type //!specialization for optimizations -template <class K, class V, class KOV, -class C, class A> +template <class Key, class T, class KeyOfValue, class Compare, class Allocator, class Options> struct has_trivial_destructor_after_move - <boost::container::container_detail::tree<K, V, KOV, C, A> > + < + ::boost::container::container_detail::tree + <Key, T, KeyOfValue, Compare, Allocator, Options> + > { - static const bool value = has_trivial_destructor_after_move<A>::value && has_trivial_destructor_after_move<C>::value; + typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer; + static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value && + ::boost::has_trivial_destructor_after_move<pointer>::value && + ::boost::has_trivial_destructor_after_move<Compare>::value; }; -*/ + } //namespace boost { #include <boost/container/detail/config_end.hpp> diff --git a/boost/container/detail/type_traits.hpp b/boost/container/detail/type_traits.hpp index 9ff361454a..1ae2426863 100644 --- a/boost/container/detail/type_traits.hpp +++ b/boost/container/detail/type_traits.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // (C) Copyright John Maddock 2000. -// (C) Copyright Ion Gaztanaga 2005-2013. +// (C) Copyright Ion Gaztanaga 2005-2015. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -8,230 +8,60 @@ // // See http://www.boost.org/libs/container for documentation. // -// The alignment_of implementation comes from John Maddock's boost::alignment_of code +// The alignment and Type traits implementation comes from +// John Maddock's TypeTraits library. // +// Some other tricks come from Howard Hinnant's papers and StackOverflow replies ////////////////////////////////////////////////////////////////////////////// - #ifndef BOOST_CONTAINER_CONTAINER_DETAIL_TYPE_TRAITS_HPP #define BOOST_CONTAINER_CONTAINER_DETAIL_TYPE_TRAITS_HPP -#if defined(_MSC_VER) +#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> +#include <boost/move/detail/type_traits.hpp> namespace boost { namespace container { namespace container_detail { -struct nat{}; - -template <typename U> -struct LowPriorityConversion -{ - // Convertible from T with user-defined-conversion rank. - LowPriorityConversion(const U&) { } -}; - -//boost::alignment_of yields to 10K lines of preprocessed code, so we -//need an alternative -template <typename T> struct alignment_of; - -template <typename T> -struct alignment_of_hack -{ - char c; - T t; - alignment_of_hack(); -}; - -template <unsigned A, unsigned S> -struct alignment_logic -{ - enum{ value = A < S ? A : S }; -}; - -template< typename T > -struct alignment_of -{ - enum{ value = alignment_logic - < sizeof(alignment_of_hack<T>) - sizeof(T) - , sizeof(T)>::value }; -}; - -//This is not standard, but should work with all compilers -union max_align -{ - char char_; - short short_; - int int_; - long long_; - #ifdef BOOST_HAS_LONG_LONG - long long long_long_; - #endif - float float_; - double double_; - long double long_double_; - void * void_ptr_; -}; - -template<class T> -struct remove_reference -{ - typedef T type; -}; - -template<class T> -struct remove_reference<T&> -{ - typedef T type; -}; - -#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES - -template<class T> -struct remove_reference<T&&> -{ - typedef T type; -}; - -#else - -} // namespace container_detail { -} //namespace container { - -template<class T> -class rv; - -namespace container { -namespace container_detail { - -template<class T> -struct remove_reference< ::boost::rv<T> > -{ - typedef T type; -}; - -#endif - -template<class T> -struct is_reference -{ - enum { value = false }; -}; - -template<class T> -struct is_reference<T&> -{ - enum { value = true }; -}; - -template<class T> -struct is_pointer -{ - enum { value = false }; -}; - -template<class T> -struct is_pointer<T*> -{ - enum { value = true }; -}; - -template <typename T> -struct add_reference -{ - typedef T& type; -}; - -template<class T> -struct add_reference<T&> -{ - typedef T& type; -}; - -template<> -struct add_reference<void> -{ - typedef nat &type; -}; - -template<> -struct add_reference<const void> -{ - typedef const nat &type; -}; - -template <class T> -struct add_const_reference -{ typedef const T &type; }; - -template <class T> -struct add_const_reference<T&> -{ typedef T& type; }; - -template <class T> -struct add_const -{ typedef const T type; }; - -template <typename T, typename U> -struct is_same -{ - typedef char yes_type; - struct no_type - { - char padding[8]; - }; - - template <typename V> - static yes_type is_same_tester(V*, V*); - static no_type is_same_tester(...); - - static T *t; - static U *u; - - static const bool value = sizeof(yes_type) == sizeof(is_same_tester(t,u)); -}; - -template<class T> -struct remove_const -{ - typedef T type; -}; - -template<class T> -struct remove_const< const T> -{ - typedef T type; -}; - -template<class T> -struct remove_ref_const -{ - typedef typename remove_const< typename remove_reference<T>::type >::type type; -}; - -template <class T> -struct make_unsigned -{ - typedef T type; -}; - -template <> struct make_unsigned<bool> {}; -template <> struct make_unsigned<signed char> {typedef unsigned char type;}; -template <> struct make_unsigned<signed short> {typedef unsigned short type;}; -template <> struct make_unsigned<signed int> {typedef unsigned int type;}; -template <> struct make_unsigned<signed long> {typedef unsigned long type;}; -#ifdef BOOST_HAS_LONG_LONG -template <> struct make_unsigned<signed long long> {typedef unsigned long long type;}; -#endif - -} // namespace container_detail +using ::boost::move_detail::is_same; +using ::boost::move_detail::is_pointer; +using ::boost::move_detail::add_reference; +using ::boost::move_detail::add_const; +using ::boost::move_detail::add_const_reference; +using ::boost::move_detail::remove_const; +using ::boost::move_detail::remove_reference; +using ::boost::move_detail::make_unsigned; +using ::boost::move_detail::is_floating_point; +using ::boost::move_detail::is_integral; +using ::boost::move_detail::is_enum; +using ::boost::move_detail::is_pod; +using ::boost::move_detail::is_empty; +using ::boost::move_detail::is_trivially_destructible; +using ::boost::move_detail::is_trivially_default_constructible; +using ::boost::move_detail::is_trivially_copy_constructible; +using ::boost::move_detail::is_trivially_move_constructible; +using ::boost::move_detail::is_trivially_copy_assignable; +using ::boost::move_detail::is_trivially_move_assignable; +using ::boost::move_detail::is_nothrow_default_constructible; +using ::boost::move_detail::is_nothrow_copy_constructible; +using ::boost::move_detail::is_nothrow_move_constructible; +using ::boost::move_detail::is_nothrow_copy_assignable; +using ::boost::move_detail::is_nothrow_move_assignable; +using ::boost::move_detail::is_nothrow_swappable; +using ::boost::move_detail::alignment_of; +using ::boost::move_detail::aligned_storage; +using ::boost::move_detail::nat; +using ::boost::move_detail::max_align_t; + +} //namespace container_detail { } //namespace container { } //namespace boost { -#include <boost/container/detail/config_end.hpp> - #endif //#ifndef BOOST_CONTAINER_CONTAINER_DETAIL_TYPE_TRAITS_HPP diff --git a/boost/container/detail/value_init.hpp b/boost/container/detail/value_init.hpp index 68f9678358..eb4c976d92 100644 --- a/boost/container/detail/value_init.hpp +++ b/boost/container/detail/value_init.hpp @@ -13,7 +13,11 @@ #ifndef BOOST_CONTAINER_DETAIL_VALUE_INIT_HPP #define BOOST_CONTAINER_DETAIL_VALUE_INIT_HPP -#if defined(_MSC_VER) +#ifndef BOOST_CONFIG_HPP +# include <boost/config.hpp> +#endif + +#if defined(BOOST_HAS_PRAGMA_ONCE) # pragma once #endif diff --git a/boost/container/detail/variadic_templates_tools.hpp b/boost/container/detail/variadic_templates_tools.hpp index b07fe3050e..ec8b8ceef0 100644 --- a/boost/container/detail/variadic_templates_tools.hpp +++ b/boost/container/detail/variadic_templates_tools.hpp @@ -11,7 +11,11 @@ #ifndef BOOST_CONTAINER_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP #define BOOST_CONTAINER_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP -#if defined(_MSC_VER) +#ifndef BOOST_CONFIG_HPP +# include <boost/config.hpp> +#endif + +#if defined(BOOST_HAS_PRAGMA_ONCE) # pragma once #endif diff --git a/boost/container/detail/version_type.hpp b/boost/container/detail/version_type.hpp index 2eabc62483..a20b3eedaa 100644 --- a/boost/container/detail/version_type.hpp +++ b/boost/container/detail/version_type.hpp @@ -16,7 +16,11 @@ #ifndef BOOST_CONTAINER_DETAIL_VERSION_TYPE_HPP #define BOOST_CONTAINER_DETAIL_VERSION_TYPE_HPP -#if defined(_MSC_VER) +#ifndef BOOST_CONFIG_HPP +# include <boost/config.hpp> +#endif + +#if defined(BOOST_HAS_PRAGMA_ONCE) # pragma once #endif @@ -30,8 +34,6 @@ namespace boost{ namespace container { namespace container_detail { -//using namespace boost; - template <class T, unsigned V> struct version_type : public container_detail::integral_constant<unsigned, V> @@ -95,6 +97,11 @@ struct is_version }; } //namespace container_detail { + +typedef container_detail::integral_constant<unsigned, 0> version_0; +typedef container_detail::integral_constant<unsigned, 1> version_1; +typedef container_detail::integral_constant<unsigned, 2> version_2; + } //namespace container { } //namespace boost{ diff --git a/boost/container/detail/workaround.hpp b/boost/container/detail/workaround.hpp index 55ebe339ce..026e65d6bb 100644 --- a/boost/container/detail/workaround.hpp +++ b/boost/container/detail/workaround.hpp @@ -11,7 +11,11 @@ #ifndef BOOST_CONTAINER_DETAIL_WORKAROUND_HPP #define BOOST_CONTAINER_DETAIL_WORKAROUND_HPP -#if defined(_MSC_VER) +#ifndef BOOST_CONFIG_HPP +# include <boost/config.hpp> +#endif + +#if defined(BOOST_HAS_PRAGMA_ONCE) # pragma once #endif @@ -22,18 +26,6 @@ #define BOOST_CONTAINER_PERFECT_FORWARDING #endif -#if defined(BOOST_NO_CXX11_NOEXCEPT) - #if defined(BOOST_MSVC) - #define BOOST_CONTAINER_NOEXCEPT throw() - #else - #define BOOST_CONTAINER_NOEXCEPT - #endif - #define BOOST_CONTAINER_NOEXCEPT_IF(x) -#else - #define BOOST_CONTAINER_NOEXCEPT noexcept - #define BOOST_CONTAINER_NOEXCEPT_IF(x) noexcept(x) -#endif - #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && defined(__GXX_EXPERIMENTAL_CXX0X__)\ && (__GNUC__*10000 + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__ < 40700) #define BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST diff --git a/boost/container/flat_map.hpp b/boost/container/flat_map.hpp index e7ff31a30b..ef0e1cb252 100644 --- a/boost/container/flat_map.hpp +++ b/boost/container/flat_map.hpp @@ -7,29 +7,41 @@ // See http://www.boost.org/libs/container for documentation. // ////////////////////////////////////////////////////////////////////////////// - #ifndef BOOST_CONTAINER_FLAT_MAP_HPP #define BOOST_CONTAINER_FLAT_MAP_HPP -#if defined(_MSC_VER) +#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> - +// container +#include <boost/container/allocator_traits.hpp> #include <boost/container/container_fwd.hpp> -#include <utility> -#include <functional> -#include <memory> +#include <boost/container/new_allocator.hpp> //new_allocator +#include <boost/container/throw_exception.hpp> +// container/detail #include <boost/container/detail/flat_tree.hpp> -#include <boost/type_traits/has_trivial_destructor.hpp> +#include <boost/container/detail/type_traits.hpp> #include <boost/container/detail/mpl.hpp> -#include <boost/container/allocator_traits.hpp> -#include <boost/container/throw_exception.hpp> +#include <boost/container/detail/algorithm.hpp> //equal() +// move #include <boost/move/utility_core.hpp> -#include <boost/move/detail/move_helpers.hpp> #include <boost/move/traits.hpp> +// move/detail +#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +#include <boost/move/detail/fwd_macros.hpp> +#endif +#include <boost/move/detail/move_helpers.hpp> +// intrusive +#include <boost/intrusive/detail/minimal_pair_header.hpp> //pair +#include <boost/intrusive/detail/minimal_less_equal_header.hpp>//less, equal +//others #include <boost/core/no_exceptions_support.hpp> #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) @@ -88,7 +100,7 @@ static D force_copy(S s) //! \tparam Allocator is the allocator to allocate the <code>value_type</code>s //! (e.g. <i>allocator< std::pair<Key, T> > </i>). #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED -template <class Key, class T, class Compare = std::less<Key>, class Allocator = std::allocator< std::pair< Key, T> > > +template <class Key, class T, class Compare = std::less<Key>, class Allocator = new_allocator< std::pair< Key, T> > > #else template <class Key, class T, class Compare, class Allocator> #endif @@ -115,6 +127,7 @@ class flat_map typedef typename impl_tree_t::value_type impl_value_type; typedef typename impl_tree_t::const_iterator impl_const_iterator; + typedef typename impl_tree_t::iterator impl_iterator; typedef typename impl_tree_t::allocator_type impl_allocator_type; typedef container_detail::flat_tree_value_compare < Compare @@ -128,6 +141,9 @@ 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; + private: #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED public: @@ -170,7 +186,7 @@ class flat_map flat_map() : m_flat_tree() { - //Allocator type must be std::pair<Key, T> + //A type must be std::pair<Key, T> BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); } @@ -181,7 +197,7 @@ class flat_map explicit flat_map(const Compare& comp, const allocator_type& a = allocator_type()) : m_flat_tree(comp, container_detail::force<impl_allocator_type>(a)) { - //Allocator type must be std::pair<Key, T> + //A type must be std::pair<Key, T> BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); } @@ -191,7 +207,7 @@ class flat_map explicit flat_map(const allocator_type& a) : m_flat_tree(container_detail::force<impl_allocator_type>(a)) { - //Allocator type must be std::pair<Key, T> + //A type must be std::pair<Key, T> BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); } @@ -205,7 +221,20 @@ class flat_map const allocator_type& a = allocator_type()) : m_flat_tree(true, first, last, comp, container_detail::force<impl_allocator_type>(a)) { - //Allocator type must be std::pair<Key, T> + //A 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, 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_map(InputIterator first, InputIterator last, const allocator_type& a) + : m_flat_tree(true, first, last, Compare(), container_detail::force<impl_allocator_type>(a)) + { + //A type must be std::pair<Key, T> BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); } @@ -224,7 +253,7 @@ class flat_map , const Compare& comp = Compare(), const allocator_type& a = allocator_type()) : m_flat_tree(ordered_range, first, last, comp, a) { - //Allocator type must be std::pair<Key, T> + //A type must be std::pair<Key, T> BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); } @@ -238,7 +267,19 @@ class flat_map const allocator_type& a = allocator_type()) : m_flat_tree(true, il.begin(), il.end(), comp, container_detail::force<impl_allocator_type>(a)) { - //Allocator type must be std::pair<Key, T> + //A 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, 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)) + { + //A type must be std::pair<Key, T> BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); } @@ -256,7 +297,7 @@ class flat_map const allocator_type& a = allocator_type()) : m_flat_tree(ordered_range, il.begin(), il.end(), comp, a) { - //Allocator type must be std::pair<Key, T> + //A type must be std::pair<Key, T> BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); } #endif @@ -267,7 +308,7 @@ class flat_map flat_map(const flat_map& x) : m_flat_tree(x.m_flat_tree) { - //Allocator type must be std::pair<Key, T> + //A type must be std::pair<Key, T> BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); } @@ -280,7 +321,7 @@ class flat_map flat_map(BOOST_RV_REF(flat_map) x) : m_flat_tree(boost::move(x.m_flat_tree)) { - //Allocator type must be std::pair<Key, T> + //A type must be std::pair<Key, T> BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); } @@ -290,7 +331,7 @@ class flat_map flat_map(const flat_map& x, const allocator_type &a) : m_flat_tree(x.m_flat_tree, a) { - //Allocator type must be std::pair<Key, T> + //A type must be std::pair<Key, T> BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); } @@ -301,7 +342,7 @@ class flat_map flat_map(BOOST_RV_REF(flat_map) x, const allocator_type &a) : m_flat_tree(boost::move(x.m_flat_tree), a) { - //Allocator type must be std::pair<Key, T> + //A type must be std::pair<Key, T> BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); } @@ -321,7 +362,8 @@ class flat_map //! 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_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value) + BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value + && boost::container::container_detail::is_nothrow_move_assignable<Compare>::value ) { m_flat_tree = boost::move(x.m_flat_tree); return *this; } #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) @@ -334,11 +376,11 @@ class flat_map } #endif - //! <b>Effects</b>: Returns a copy of the Allocator that + //! <b>Effects</b>: Returns a copy of the allocator that //! was passed to the object's constructor. //! //! <b>Complexity</b>: Constant. - allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT + 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. @@ -348,7 +390,7 @@ class flat_map //! <b>Complexity</b>: Constant. //! //! <b>Note</b>: Non-standard extension. - stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT + 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. @@ -358,7 +400,7 @@ class flat_map //! <b>Complexity</b>: Constant. //! //! <b>Note</b>: Non-standard extension. - const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT + 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()); } ////////////////////////////////////////////// @@ -372,7 +414,7 @@ class flat_map //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - iterator begin() BOOST_CONTAINER_NOEXCEPT + 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. @@ -380,7 +422,7 @@ class flat_map //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator begin() const BOOST_CONTAINER_NOEXCEPT + 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. @@ -388,7 +430,7 @@ class flat_map //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - iterator end() BOOST_CONTAINER_NOEXCEPT + 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. @@ -396,7 +438,7 @@ class flat_map //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator end() const BOOST_CONTAINER_NOEXCEPT + 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 @@ -405,7 +447,7 @@ class flat_map //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT + 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 @@ -414,7 +456,7 @@ class flat_map //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT + 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 @@ -423,7 +465,7 @@ class flat_map //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT + 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 @@ -432,7 +474,7 @@ class flat_map //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT + 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. @@ -440,7 +482,7 @@ class flat_map //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT + 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. @@ -448,7 +490,7 @@ class flat_map //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator cend() const BOOST_CONTAINER_NOEXCEPT + 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 @@ -457,7 +499,7 @@ class flat_map //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT + 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 @@ -466,7 +508,7 @@ class flat_map //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT + const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::force_copy<const_reverse_iterator>(m_flat_tree.crend()); } ////////////////////////////////////////////// @@ -480,7 +522,7 @@ class flat_map //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - bool empty() const BOOST_CONTAINER_NOEXCEPT + 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. @@ -488,7 +530,7 @@ class flat_map //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - size_type size() const BOOST_CONTAINER_NOEXCEPT + size_type size() const BOOST_NOEXCEPT_OR_NOTHROW { return m_flat_tree.size(); } //! <b>Effects</b>: Returns the largest possible size of the container. @@ -496,7 +538,7 @@ class flat_map //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - size_type max_size() const BOOST_CONTAINER_NOEXCEPT + 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. @@ -505,7 +547,7 @@ class flat_map //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - size_type capacity() const BOOST_CONTAINER_NOEXCEPT + 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 @@ -539,7 +581,7 @@ class flat_map //! Effects: If there is no key equivalent to x in the flat_map, inserts //! value_type(x, T()) into the flat_map. //! - //! Returns: Allocator reference to the mapped_type corresponding to x in *this. + //! Returns: A reference to the mapped_type corresponding to x in *this. //! //! Complexity: Logarithmic. mapped_type &operator[](const key_type& k); @@ -547,7 +589,7 @@ class flat_map //! Effects: If there is no key equivalent to x in the flat_map, inserts //! value_type(move(x), T()) into the flat_map (the key is move-constructed) //! - //! Returns: Allocator reference to the mapped_type corresponding to x in *this. + //! Returns: A reference to the mapped_type corresponding to x in *this. //! //! Complexity: Logarithmic. mapped_type &operator[](key_type &&k) ; @@ -556,7 +598,23 @@ class flat_map BOOST_MOVE_CONVERSION_AWARE_CATCH( operator[] , key_type, mapped_type&, this->priv_subscript) #endif - //! Returns: Allocator reference to the element whose key is equivalent to x. + //! @copydoc ::boost::container::flat_set::nth(size_type) + 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 + { 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 + { 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 + { 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. //! //! Throws: An exception object of type out_of_range if no such element is present. //! @@ -570,7 +628,7 @@ class flat_map return i->second; } - //! Returns: Allocator reference to the element whose key is equivalent to x. + //! Returns: A reference to the element whose key is equivalent to x. //! //! Throws: An exception object of type out_of_range if no such element is present. //! @@ -590,7 +648,7 @@ class flat_map // ////////////////////////////////////////////// - #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) //! <b>Effects</b>: Inserts an object x of type T constructed with //! std::forward<Args>(args)... if and only if there is no element in the container @@ -605,7 +663,7 @@ class flat_map //! //! <b>Note</b>: If an element is inserted it might invalidate elements. template <class... Args> - std::pair<iterator,bool> emplace(Args&&... args) + 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 @@ -621,32 +679,34 @@ class flat_map //! //! <b>Note</b>: If an element is inserted it might invalidate elements. template <class... Args> - iterator emplace_hint(const_iterator hint, Args&&... args) + 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) , boost::forward<Args>(args)...)); } - #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING - - #define BOOST_PP_LOCAL_MACRO(n) \ - BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ - std::pair<iterator,bool> emplace(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ - { return container_detail::force_copy< std::pair<iterator, bool> > \ - (m_flat_tree.emplace_unique(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); } \ - \ - BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ - iterator emplace_hint(const_iterator hint \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ - { return container_detail::force_copy<iterator>(m_flat_tree.emplace_hint_unique \ - (container_detail::force_copy<impl_const_iterator>(hint) \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); } \ - //! - #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) - #include BOOST_PP_LOCAL_ITERATE() + #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + + #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)\ + {\ + 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)\ + {\ + 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));\ + }\ + // + BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_FLAT_MAP_EMPLACE_CODE) + #undef BOOST_CONTAINER_FLAT_MAP_EMPLACE_CODE - #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING + #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) //! <b>Effects</b>: Inserts x if and only if there is no element in the container //! with key equivalent to the key of x. @@ -660,7 +720,7 @@ class flat_map //! //! <b>Note</b>: If an element is inserted it might invalidate elements. std::pair<iterator,bool> insert(const value_type& x) - { return container_detail::force_copy<std::pair<iterator,bool> >( + { return container_detail::force_copy<std::pair<iterator,bool> >( m_flat_tree.insert_unique(container_detail::force<impl_value_type>(x))); } //! <b>Effects</b>: Inserts a new value_type move constructed from the pair if and @@ -850,6 +910,8 @@ class flat_map //! //! <b>Complexity</b>: Constant. 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); } //! <b>Effects</b>: erase(a.begin(),a.end()). @@ -857,7 +919,7 @@ class flat_map //! <b>Postcondition</b>: size() == 0. //! //! <b>Complexity</b>: linear in size(). - void clear() BOOST_CONTAINER_NOEXCEPT + void clear() BOOST_NOEXCEPT_OR_NOTHROW { m_flat_tree.clear(); } ////////////////////////////////////////////// @@ -893,7 +955,7 @@ class flat_map iterator find(const key_type& x) { return container_detail::force_copy<iterator>(m_flat_tree.find(x)); } - //! <b>Returns</b>: Allocator const_iterator pointing to an element with the key + //! <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.s @@ -913,7 +975,7 @@ class flat_map iterator lower_bound(const key_type& x) { return container_detail::force_copy<iterator>(m_flat_tree.lower_bound(x)); } - //! <b>Returns</b>: Allocator const iterator pointing to the first element with key not + //! <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 @@ -927,7 +989,7 @@ class flat_map iterator upper_bound(const key_type& x) { return container_detail::force_copy<iterator>(m_flat_tree.upper_bound(x)); } - //! <b>Returns</b>: Allocator const iterator pointing to the first element with key not + //! <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 @@ -950,7 +1012,7 @@ class flat_map //! //! <b>Complexity</b>: Linear to the number of elements in the container. friend bool operator==(const flat_map& x, const flat_map& y) - { return x.size() == y.size() && std::equal(x.begin(), x.end(), y.begin()); } + { 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 //! @@ -962,7 +1024,7 @@ class flat_map //! //! <b>Complexity</b>: Linear to the number of elements in the container. friend bool operator<(const flat_map& x, const flat_map& y) - { return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } + { 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 //! @@ -1020,10 +1082,13 @@ class flat_map //!has_trivial_destructor_after_move<> == true_type //!specialization for optimizations -template <class K, class T, class C, class Allocator> -struct has_trivial_destructor_after_move<boost::container::flat_map<K, T, C, Allocator> > +template <class Key, class T, class Compare, class Allocator> +struct has_trivial_destructor_after_move<boost::container::flat_map<Key, T, Compare, Allocator> > { - static const bool value = has_trivial_destructor_after_move<Allocator>::value && has_trivial_destructor_after_move<C>::value; + typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer; + static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value && + ::boost::has_trivial_destructor_after_move<pointer>::value && + ::boost::has_trivial_destructor_after_move<Compare>::value; }; namespace container { @@ -1060,7 +1125,7 @@ namespace container { //! \tparam Allocator is the allocator to allocate the <code>value_type</code>s //! (e.g. <i>allocator< std::pair<Key, T> > </i>). #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED -template <class Key, class T, class Compare = std::less<Key>, class Allocator = std::allocator< std::pair< Key, T> > > +template <class Key, class T, class Compare = std::less<Key>, class Allocator = new_allocator< std::pair< Key, T> > > #else template <class Key, class T, class Compare, class Allocator> #endif @@ -1085,6 +1150,7 @@ class flat_multimap typedef typename impl_tree_t::value_type impl_value_type; typedef typename impl_tree_t::const_iterator impl_const_iterator; + typedef typename impl_tree_t::iterator impl_iterator; typedef typename impl_tree_t::allocator_type impl_allocator_type; typedef container_detail::flat_tree_value_compare < Compare @@ -1098,6 +1164,9 @@ class flat_multimap <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; + private: #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED public: @@ -1139,7 +1208,7 @@ class flat_multimap flat_multimap() : m_flat_tree() { - //Allocator type must be std::pair<Key, T> + //A type must be std::pair<Key, T> BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); } @@ -1151,7 +1220,7 @@ class flat_multimap const allocator_type& a = allocator_type()) : m_flat_tree(comp, container_detail::force<impl_allocator_type>(a)) { - //Allocator type must be std::pair<Key, T> + //A type must be std::pair<Key, T> BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); } @@ -1161,7 +1230,7 @@ class flat_multimap explicit flat_multimap(const allocator_type& a) : m_flat_tree(container_detail::force<impl_allocator_type>(a)) { - //Allocator type must be std::pair<Key, T> + //A type must be std::pair<Key, T> BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); } @@ -1176,7 +1245,20 @@ class flat_multimap const allocator_type& a = allocator_type()) : m_flat_tree(false, first, last, comp, container_detail::force<impl_allocator_type>(a)) { - //Allocator type must be std::pair<Key, T> + //A 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, 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_multimap(InputIterator first, InputIterator last, const allocator_type& a) + : m_flat_tree(false, first, last, Compare(), container_detail::force<impl_allocator_type>(a)) + { + //A type must be std::pair<Key, T> BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); } @@ -1195,7 +1277,7 @@ class flat_multimap const allocator_type& a = allocator_type()) : m_flat_tree(ordered_range, first, last, comp, a) { - //Allocator type must be std::pair<Key, T> + //A type must be std::pair<Key, T> BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); } @@ -1208,7 +1290,19 @@ class flat_multimap 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)) { - //Allocator type must be std::pair<Key, T> + //A 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, 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 allocator_type& a) + : m_flat_tree(false, il.begin(), il.end(), Compare(), container_detail::force<impl_allocator_type>(a)) + { + //A type must be std::pair<Key, T> BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); } @@ -1225,7 +1319,7 @@ class flat_multimap const allocator_type& a = allocator_type()) : m_flat_tree(ordered_range, il.begin(), il.end(), comp, a) { - //Allocator type must be std::pair<Key, T> + //A type must be std::pair<Key, T> BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); } #endif @@ -1236,7 +1330,7 @@ class flat_multimap flat_multimap(const flat_multimap& x) : m_flat_tree(x.m_flat_tree) { - //Allocator type must be std::pair<Key, T> + //A type must be std::pair<Key, T> BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); } @@ -1248,7 +1342,7 @@ class flat_multimap flat_multimap(BOOST_RV_REF(flat_multimap) x) : m_flat_tree(boost::move(x.m_flat_tree)) { - //Allocator type must be std::pair<Key, T> + //A type must be std::pair<Key, T> BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); } @@ -1258,7 +1352,7 @@ class flat_multimap flat_multimap(const flat_multimap& x, const allocator_type &a) : m_flat_tree(x.m_flat_tree, a) { - //Allocator type must be std::pair<Key, T> + //A type must be std::pair<Key, T> BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); } @@ -1269,7 +1363,7 @@ class flat_multimap flat_multimap(BOOST_RV_REF(flat_multimap) x, const allocator_type &a) : m_flat_tree(boost::move(x.m_flat_tree), a) { - //Allocator type must be std::pair<Key, T> + //A type must be std::pair<Key, T> BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value)); } @@ -1283,7 +1377,8 @@ class flat_multimap //! //! <b>Complexity</b>: Constant. flat_multimap& operator=(BOOST_RV_REF(flat_multimap) x) - BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value) + BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value + && boost::container::container_detail::is_nothrow_move_assignable<Compare>::value ) { m_flat_tree = boost::move(x.m_flat_tree); return *this; } #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) @@ -1298,11 +1393,11 @@ class flat_multimap } #endif - //! <b>Effects</b>: Returns a copy of the Allocator that + //! <b>Effects</b>: Returns a copy of the allocator that //! was passed to the object's constructor. //! //! <b>Complexity</b>: Constant. - allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT + 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. @@ -1312,7 +1407,7 @@ class flat_multimap //! <b>Complexity</b>: Constant. //! //! <b>Note</b>: Non-standard extension. - stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT + 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. @@ -1322,7 +1417,7 @@ class flat_multimap //! <b>Complexity</b>: Constant. //! //! <b>Note</b>: Non-standard extension. - const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT + 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()); } ////////////////////////////////////////////// @@ -1336,7 +1431,7 @@ class flat_multimap //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - iterator begin() BOOST_CONTAINER_NOEXCEPT + 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. @@ -1344,7 +1439,7 @@ class flat_multimap //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator begin() const BOOST_CONTAINER_NOEXCEPT + 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. @@ -1352,7 +1447,7 @@ class flat_multimap //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - iterator end() BOOST_CONTAINER_NOEXCEPT + 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. @@ -1360,7 +1455,7 @@ class flat_multimap //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator end() const BOOST_CONTAINER_NOEXCEPT + 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 @@ -1369,7 +1464,7 @@ class flat_multimap //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT + 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 @@ -1378,7 +1473,7 @@ class flat_multimap //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT + 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 @@ -1387,7 +1482,7 @@ class flat_multimap //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT + 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 @@ -1396,7 +1491,7 @@ class flat_multimap //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT + 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. @@ -1404,7 +1499,7 @@ class flat_multimap //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT + 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. @@ -1412,7 +1507,7 @@ class flat_multimap //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator cend() const BOOST_CONTAINER_NOEXCEPT + 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 @@ -1421,7 +1516,7 @@ class flat_multimap //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT + 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 @@ -1430,7 +1525,7 @@ class flat_multimap //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT + const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::force_copy<const_reverse_iterator>(m_flat_tree.crend()); } ////////////////////////////////////////////// @@ -1444,7 +1539,7 @@ class flat_multimap //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - bool empty() const BOOST_CONTAINER_NOEXCEPT + 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. @@ -1452,7 +1547,7 @@ class flat_multimap //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - size_type size() const BOOST_CONTAINER_NOEXCEPT + size_type size() const BOOST_NOEXCEPT_OR_NOTHROW { return m_flat_tree.size(); } //! <b>Effects</b>: Returns the largest possible size of the container. @@ -1460,7 +1555,7 @@ class flat_multimap //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - size_type max_size() const BOOST_CONTAINER_NOEXCEPT + 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. @@ -1469,7 +1564,7 @@ class flat_multimap //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - size_type capacity() const BOOST_CONTAINER_NOEXCEPT + 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 @@ -1493,13 +1588,23 @@ class flat_multimap void shrink_to_fit() { m_flat_tree.shrink_to_fit(); } - ////////////////////////////////////////////// - // - // modifiers - // - ////////////////////////////////////////////// + //! @copydoc ::boost::container::flat_set::nth(size_type) + 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 + { 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 + { 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 + { return m_flat_tree.index_of(container_detail::force_copy<impl_const_iterator>(p)); } - #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) //! <b>Effects</b>: Inserts an object of type T constructed with //! std::forward<Args>(args)... and returns the iterator pointing to the @@ -1510,7 +1615,7 @@ class flat_multimap //! //! <b>Note</b>: If an element is inserted it might invalidate elements. template <class... Args> - iterator emplace(Args&&... args) + iterator emplace(BOOST_FWD_REF(Args)... args) { return container_detail::force_copy<iterator>(m_flat_tree.emplace_equal(boost::forward<Args>(args)...)); } //! <b>Effects</b>: Inserts an object of type T constructed with @@ -1526,31 +1631,30 @@ class flat_multimap //! //! <b>Note</b>: If an element is inserted it might invalidate elements. template <class... Args> - iterator emplace_hint(const_iterator hint, Args&&... args) + iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args) { return container_detail::force_copy<iterator>(m_flat_tree.emplace_hint_equal (container_detail::force_copy<impl_const_iterator>(hint), boost::forward<Args>(args)...)); } - #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING - - #define BOOST_PP_LOCAL_MACRO(n) \ - BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ - iterator emplace(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ - { return container_detail::force_copy<iterator>(m_flat_tree.emplace_equal \ - (BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); } \ - \ - BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ - iterator emplace_hint(const_iterator hint \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ - { return container_detail::force_copy<iterator>(m_flat_tree.emplace_hint_equal \ - (container_detail::force_copy<impl_const_iterator>(hint) \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); } \ - //! - #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) - #include BOOST_PP_LOCAL_ITERATE() + #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + + #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)\ + { 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)\ + {\ + 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));\ + }\ + // + BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_FLAT_MULTIMAP_EMPLACE_CODE) + #undef BOOST_CONTAINER_FLAT_MULTIMAP_EMPLACE_CODE - #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING + #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) //! <b>Effects</b>: Inserts x and returns the iterator pointing to the //! newly inserted element. @@ -1740,6 +1844,8 @@ class flat_multimap //! //! <b>Complexity</b>: Constant. 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); } //! <b>Effects</b>: erase(a.begin(),a.end()). @@ -1747,7 +1853,7 @@ class flat_multimap //! <b>Postcondition</b>: size() == 0. //! //! <b>Complexity</b>: linear in size(). - void clear() BOOST_CONTAINER_NOEXCEPT + void clear() BOOST_NOEXCEPT_OR_NOTHROW { m_flat_tree.clear(); } ////////////////////////////////////////////// @@ -1803,7 +1909,7 @@ class flat_multimap iterator lower_bound(const key_type& x) { return container_detail::force_copy<iterator>(m_flat_tree.lower_bound(x)); } - //! <b>Returns</b>: Allocator const iterator pointing to the first element with key + //! <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 @@ -1817,7 +1923,7 @@ class flat_multimap iterator upper_bound(const key_type& x) {return container_detail::force_copy<iterator>(m_flat_tree.upper_bound(x)); } - //! <b>Returns</b>: Allocator const iterator pointing to the first element with key + //! <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 @@ -1840,7 +1946,7 @@ class flat_multimap //! //! <b>Complexity</b>: Linear to the number of elements in the container. friend bool operator==(const flat_multimap& x, const flat_multimap& y) - { return x.size() == y.size() && std::equal(x.begin(), x.end(), y.begin()); } + { 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 //! @@ -1852,7 +1958,7 @@ class flat_multimap //! //! <b>Complexity</b>: Linear to the number of elements in the container. friend bool operator<(const flat_multimap& x, const flat_multimap& y) - { return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } + { 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 //! @@ -1887,10 +1993,13 @@ namespace boost { //!has_trivial_destructor_after_move<> == true_type //!specialization for optimizations -template <class K, class T, class C, class Allocator> -struct has_trivial_destructor_after_move< boost::container::flat_multimap<K, T, C, Allocator> > +template <class Key, class T, class Compare, class Allocator> +struct has_trivial_destructor_after_move< boost::container::flat_multimap<Key, T, Compare, Allocator> > { - static const bool value = has_trivial_destructor_after_move<Allocator>::value && has_trivial_destructor_after_move<C>::value; + typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer; + static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value && + ::boost::has_trivial_destructor_after_move<pointer>::value && + ::boost::has_trivial_destructor_after_move<Compare>::value; }; } //namespace boost { @@ -1899,4 +2008,4 @@ struct has_trivial_destructor_after_move< boost::container::flat_multimap<K, T, #include <boost/container/detail/config_end.hpp> -#endif /* BOOST_CONTAINER_FLAT_MAP_HPP */ +#endif // BOOST_CONTAINER_FLAT_MAP_HPP diff --git a/boost/container/flat_set.hpp b/boost/container/flat_set.hpp index 1307f3492f..8f592798d2 100644 --- a/boost/container/flat_set.hpp +++ b/boost/container/flat_set.hpp @@ -7,31 +7,43 @@ // See http://www.boost.org/libs/container for documentation. // ////////////////////////////////////////////////////////////////////////////// - #ifndef BOOST_CONTAINER_FLAT_SET_HPP #define BOOST_CONTAINER_FLAT_SET_HPP -#if defined(_MSC_VER) +#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> +// container +#include <boost/container/allocator_traits.hpp> #include <boost/container/container_fwd.hpp> -#include <utility> -#include <functional> -#include <memory> +#include <boost/container/new_allocator.hpp> //new_allocator +// container/detail #include <boost/container/detail/flat_tree.hpp> #include <boost/container/detail/mpl.hpp> -#include <boost/container/allocator_traits.hpp> +// move +#include <boost/move/traits.hpp> #include <boost/move/utility_core.hpp> +// move/detail +#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +#include <boost/move/detail/fwd_macros.hpp> +#endif #include <boost/move/detail/move_helpers.hpp> -#include <boost/move/traits.hpp> - +// intrusive/detail +#include <boost/intrusive/detail/minimal_pair_header.hpp> //pair +#include <boost/intrusive/detail/minimal_less_equal_header.hpp>//less, equal +// std #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) #include <initializer_list> #endif + namespace boost { namespace container { @@ -51,7 +63,7 @@ namespace container { //! \tparam Compare is the comparison functor used to order keys //! \tparam Allocator is the allocator to be used to allocate memory for this container #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED -template <class Key, class Compare = std::less<Key>, class Allocator = std::allocator<Key> > +template <class Key, class Compare = std::less<Key>, class Allocator = new_allocator<Key> > #else template <class Key, class Compare, class Allocator> #endif @@ -132,6 +144,16 @@ class flat_set : base_t(true, first, last, comp, a) {} + //! <b>Effects</b>: Constructs an empty container 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. + template <class InputIterator> + flat_set(InputIterator first, InputIterator last, const allocator_type& a) + : base_t(true, first, last, Compare(), a) + {} + //! <b>Effects</b>: Constructs an empty container using the specified comparison object and //! allocator, and inserts elements from the ordered unique range [first ,last). This function //! is more efficient than the normal range creation for ordered ranges. @@ -158,9 +180,16 @@ class flat_set 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) - { + {} - } + //! <b>Effects</b>: Constructs an empty container 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(). + flat_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 container using the specified comparison object and //! allocator, and inserts elements from the ordered unique range [il.begin(), il.end()). This function @@ -175,9 +204,7 @@ class flat_set flat_set(ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp = Compare(), const allocator_type& a = allocator_type()) : base_t(ordered_range, il.begin(), il.end(), comp, a) - { - - } + {} #endif //! <b>Effects</b>: Copy constructs the container. @@ -187,13 +214,13 @@ class flat_set : base_t(static_cast<const base_t&>(x)) {} - //! <b>Effects</b>: Move constructs thecontainer. Constructs *this using mx's resources. + //! <b>Effects</b>: Move constructs thecontainer. Constructs *this using x's resources. //! //! <b>Complexity</b>: Constant. //! - //! <b>Postcondition</b>: mx is emptied. - flat_set(BOOST_RV_REF(flat_set) mx) - : base_t(boost::move(static_cast<base_t&>(mx))) + //! <b>Postcondition</b>: x is emptied. + flat_set(BOOST_RV_REF(flat_set) x) + : base_t(BOOST_MOVE_BASE(base_t, x)) {} //! <b>Effects</b>: Copy constructs a container using the specified allocator. @@ -204,11 +231,11 @@ class flat_set {} //! <b>Effects</b>: Move constructs a container using the specified allocator. - //! Constructs *this using mx's resources. + //! Constructs *this using x's resources. //! - //! <b>Complexity</b>: Constant if a == mx.get_allocator(), linear otherwise - flat_set(BOOST_RV_REF(flat_set) mx, const allocator_type &a) - : base_t(boost::move(static_cast<base_t&>(mx)), a) + //! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise + 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. @@ -224,8 +251,9 @@ class flat_set //! 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_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value) - { return static_cast<flat_set&>(this->base_t::operator=(boost::move(static_cast<base_t&>(x)))); } + BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value + && boost::container::container_detail::is_nothrow_move_assignable<Compare>::value ) + { return static_cast<flat_set&>(this->base_t::operator=(BOOST_MOVE_BASE(base_t, x))); } #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) //! <b>Effects</b>: Copy all elements from il to *this. @@ -240,11 +268,11 @@ class flat_set #endif #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED - //! <b>Effects</b>: Returns a copy of the Allocator that + //! <b>Effects</b>: Returns a copy of the allocator that //! was passed to the object's constructor. //! //! <b>Complexity</b>: Constant. - allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT; + allocator_type get_allocator() const BOOST_NOEXCEPT_OR_NOTHROW; //! <b>Effects</b>: Returns a reference to the internal allocator. //! @@ -253,7 +281,7 @@ class flat_set //! <b>Complexity</b>: Constant. //! //! <b>Note</b>: Non-standard extension. - stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT; + stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW; //! <b>Effects</b>: Returns a reference to the internal allocator. //! @@ -262,35 +290,35 @@ class flat_set //! <b>Complexity</b>: Constant. //! //! <b>Note</b>: Non-standard extension. - const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT; + const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW; //! <b>Effects</b>: Returns an iterator to the first element contained in the container. //! //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - iterator begin() BOOST_CONTAINER_NOEXCEPT; + iterator begin() BOOST_NOEXCEPT_OR_NOTHROW; //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container. //! //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator begin() const BOOST_CONTAINER_NOEXCEPT; + const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW; //! <b>Effects</b>: Returns an iterator to the end of the container. //! //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - iterator end() BOOST_CONTAINER_NOEXCEPT; + iterator end() BOOST_NOEXCEPT_OR_NOTHROW; //! <b>Effects</b>: Returns a const_iterator to the end of the container. //! //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator end() const BOOST_CONTAINER_NOEXCEPT; + const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW; //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning //! of the reversed container. @@ -298,7 +326,7 @@ class flat_set //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT; + reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW; //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning //! of the reversed container. @@ -306,7 +334,7 @@ class flat_set //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT; + const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW; //! <b>Effects</b>: Returns a reverse_iterator pointing to the end //! of the reversed container. @@ -314,7 +342,7 @@ class flat_set //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT; + reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW; //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end //! of the reversed container. @@ -322,21 +350,21 @@ class flat_set //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT; + const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW; //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container. //! //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT; + const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW; //! <b>Effects</b>: Returns a const_iterator to the end of the container. //! //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator cend() const BOOST_CONTAINER_NOEXCEPT; + const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW; //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning //! of the reversed container. @@ -344,7 +372,7 @@ class flat_set //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT; + const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW; //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end //! of the reversed container. @@ -352,28 +380,28 @@ class flat_set //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT; + const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW; //! <b>Effects</b>: Returns true if the container contains no elements. //! //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - bool empty() const BOOST_CONTAINER_NOEXCEPT; + bool empty() const BOOST_NOEXCEPT_OR_NOTHROW; //! <b>Effects</b>: Returns the number of the elements contained in the container. //! //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - size_type size() const BOOST_CONTAINER_NOEXCEPT; + size_type size() const BOOST_NOEXCEPT_OR_NOTHROW; //! <b>Effects</b>: Returns the largest possible size of the container. //! //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - size_type max_size() const BOOST_CONTAINER_NOEXCEPT; + size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW; //! <b>Effects</b>: Number of elements for which memory has been allocated. //! capacity() is always greater than or equal to size(). @@ -381,7 +409,7 @@ class flat_set //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - size_type capacity() const BOOST_CONTAINER_NOEXCEPT; + size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW; //! <b>Effects</b>: If n is less than or equal to capacity(), this call has no //! effect. Otherwise, it is a request for allocation of additional memory. @@ -410,7 +438,7 @@ class flat_set // ////////////////////////////////////////////// - #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) //! <b>Effects</b>: Inserts an object x of type Key constructed with //! std::forward<Args>(args)... if and only if there is no element in the container @@ -425,7 +453,7 @@ class flat_set //! //! <b>Note</b>: If an element is inserted it might invalidate elements. template <class... Args> - std::pair<iterator,bool> emplace(Args&&... args) + 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 @@ -441,26 +469,24 @@ class flat_set //! //! <b>Note</b>: If an element is inserted it might invalidate elements. template <class... Args> - iterator emplace_hint(const_iterator p, Args&&... args) + iterator emplace_hint(const_iterator p, BOOST_FWD_REF(Args)... args) { return this->base_t::emplace_hint_unique(p, boost::forward<Args>(args)...); } - #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING + #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - #define BOOST_PP_LOCAL_MACRO(n) \ - BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ - std::pair<iterator,bool> emplace(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ - { return this->base_t::emplace_unique(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); }\ - \ - BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ - iterator emplace_hint(const_iterator p \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ - { return this->base_t::emplace_hint_unique \ - (p BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); } \ - //! - #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) - #include BOOST_PP_LOCAL_ITERATE() + #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)\ + { 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)\ + { 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) + #undef BOOST_CONTAINER_FLAT_SET_EMPLACE_CODE - #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING + #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) //! <b>Effects</b>: Inserts x if and only if there is no element in the container @@ -613,14 +639,16 @@ class flat_set //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - void swap(flat_set& x); + void swap(flat_set& x) + BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value + && boost::container::container_detail::is_nothrow_swappable<Compare>::value ); //! <b>Effects</b>: erase(a.begin(),a.end()). //! //! <b>Postcondition</b>: size() == 0. //! //! <b>Complexity</b>: linear in size(). - void clear() BOOST_CONTAINER_NOEXCEPT; + void clear() BOOST_NOEXCEPT_OR_NOTHROW; //! <b>Effects</b>: Returns the comparison object out //! of which a was constructed. @@ -640,12 +668,63 @@ class flat_set //! <b>Complexity</b>: Logarithmic. iterator find(const key_type& x); - //! <b>Returns</b>: Allocator const_iterator pointing to an element with the key + //! <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; + //! <b>Requires</b>: size() >= n. + //! + //! <b>Effects</b>: Returns an iterator to the nth element + //! from the beginning of the container. Returns end() + //! if n == size(). + //! + //! <b>Throws</b>: Nothing. + //! + //! <b>Complexity</b>: Constant. + //! + //! <b>Note</b>: Non-standard extension + iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW; + + //! <b>Requires</b>: size() >= n. + //! + //! <b>Effects</b>: Returns a const_iterator to the nth element + //! from the beginning of the container. Returns end() + //! if n == size(). + //! + //! <b>Throws</b>: Nothing. + //! + //! <b>Complexity</b>: Constant. + //! + //! <b>Note</b>: Non-standard extension + const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW; + + //! <b>Requires</b>: size() >= n. + //! + //! <b>Effects</b>: Returns an iterator to the nth element + //! from the beginning of the container. Returns end() + //! if n == size(). + //! + //! <b>Throws</b>: Nothing. + //! + //! <b>Complexity</b>: Constant. + //! + //! <b>Note</b>: Non-standard extension + size_type index_of(iterator p) BOOST_NOEXCEPT_OR_NOTHROW; + + //! <b>Requires</b>: begin() <= p <= end(). + //! + //! <b>Effects</b>: Returns the index of the element pointed by p + //! and size() if p == end(). + //! + //! <b>Throws</b>: Nothing. + //! + //! <b>Complexity</b>: Constant. + //! + //! <b>Note</b>: Non-standard extension + size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW; + #endif // #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) //! <b>Returns</b>: The number of elements with key equivalent to x. @@ -661,7 +740,7 @@ class flat_set //! <b>Complexity</b>: Logarithmic iterator lower_bound(const key_type& x); - //! <b>Returns</b>: Allocator const iterator pointing to the first element with key not + //! <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 @@ -673,7 +752,7 @@ class flat_set //! <b>Complexity</b>: Logarithmic iterator upper_bound(const key_type& x); - //! <b>Returns</b>: Allocator const iterator pointing to the first element with key not + //! <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 @@ -750,10 +829,13 @@ class flat_set //!has_trivial_destructor_after_move<> == true_type //!specialization for optimizations -template <class Key, class C, class Allocator> -struct has_trivial_destructor_after_move<boost::container::flat_set<Key, C, Allocator> > +template <class Key, class Compare, class Allocator> +struct has_trivial_destructor_after_move<boost::container::flat_set<Key, Compare, Allocator> > { - static const bool value = has_trivial_destructor_after_move<Allocator>::value &&has_trivial_destructor_after_move<C>::value; + typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer; + static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value && + ::boost::has_trivial_destructor_after_move<pointer>::value && + ::boost::has_trivial_destructor_after_move<Compare>::value; }; namespace container { @@ -777,7 +859,7 @@ namespace container { //! \tparam Compare is the comparison functor used to order keys //! \tparam Allocator is the allocator to be used to allocate memory for this container #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED -template <class Key, class Compare = std::less<Key>, class Allocator = std::allocator<Key> > +template <class Key, class Compare = std::less<Key>, class Allocator = new_allocator<Key> > #else template <class Key, class Compare, class Allocator> #endif @@ -840,6 +922,12 @@ class flat_multiset : base_t(false, first, last, comp, a) {} + //! @copydoc ::boost::container::flat_set::flat_set(InputIterator, InputIterator, const allocator_type&) + template <class InputIterator> + flat_multiset(InputIterator first, InputIterator last, const allocator_type& a) + : base_t(false, first, last, Compare(), a) + {} + //! <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 //! is more efficient than the normal range creation for ordered ranges. @@ -863,6 +951,11 @@ class flat_multiset : 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) + {} + //! @copydoc ::boost::container::flat_set::flat_set(ordered_unique_range_t, std::initializer_list<value_type>, const Compare& comp, const allocator_type&) flat_multiset(ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp = Compare(), const allocator_type& a = allocator_type()) @@ -876,8 +969,8 @@ class flat_multiset {} //! @copydoc ::boost::container::flat_set(flat_set &&) - flat_multiset(BOOST_RV_REF(flat_multiset) mx) - : base_t(boost::move(static_cast<base_t&>(mx))) + flat_multiset(BOOST_RV_REF(flat_multiset) x) + : base_t(boost::move(static_cast<base_t&>(x))) {} //! @copydoc ::boost::container::flat_set(const flat_set &, const allocator_type &) @@ -886,8 +979,8 @@ class flat_multiset {} //! @copydoc ::boost::container::flat_set(flat_set &&, const allocator_type &) - flat_multiset(BOOST_RV_REF(flat_multiset) mx, const allocator_type &a) - : base_t(boost::move(static_cast<base_t&>(mx)), a) + 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 &) @@ -895,9 +988,10 @@ class flat_multiset { 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) mx) - BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value) - { return static_cast<flat_multiset&>(this->base_t::operator=(boost::move(static_cast<base_t&>(mx)))); } + flat_multiset& operator=(BOOST_RV_REF(flat_multiset) x) + BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value + && boost::container::container_detail::is_nothrow_move_assignable<Compare>::value ) + { return static_cast<flat_multiset&>(this->base_t::operator=(BOOST_MOVE_BASE(base_t, x))); } #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) //! @copydoc ::boost::container::flat_set::operator=(std::initializer_list<value_type>) @@ -912,61 +1006,61 @@ class flat_multiset #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) //! @copydoc ::boost::container::flat_set::get_allocator() - allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT; + allocator_type get_allocator() const BOOST_NOEXCEPT_OR_NOTHROW; //! @copydoc ::boost::container::flat_set::get_stored_allocator() - stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT; + stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW; //! @copydoc ::boost::container::flat_set::get_stored_allocator() const - const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT; + const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW; //! @copydoc ::boost::container::flat_set::begin() - iterator begin() BOOST_CONTAINER_NOEXCEPT; + iterator begin() BOOST_NOEXCEPT_OR_NOTHROW; //! @copydoc ::boost::container::flat_set::begin() const const_iterator begin() const; //! @copydoc ::boost::container::flat_set::cbegin() const - const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT; + const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW; //! @copydoc ::boost::container::flat_set::end() - iterator end() BOOST_CONTAINER_NOEXCEPT; + iterator end() BOOST_NOEXCEPT_OR_NOTHROW; //! @copydoc ::boost::container::flat_set::end() const - const_iterator end() const BOOST_CONTAINER_NOEXCEPT; + const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW; //! @copydoc ::boost::container::flat_set::cend() const - const_iterator cend() const BOOST_CONTAINER_NOEXCEPT; + const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW; //! @copydoc ::boost::container::flat_set::rbegin() - reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT; + reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW; //! @copydoc ::boost::container::flat_set::rbegin() const - const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT; + const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW; //! @copydoc ::boost::container::flat_set::crbegin() const - const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT; + const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW; //! @copydoc ::boost::container::flat_set::rend() - reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT; + reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW; //! @copydoc ::boost::container::flat_set::rend() const - const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT; + const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW; //! @copydoc ::boost::container::flat_set::crend() const - const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT; + const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW; //! @copydoc ::boost::container::flat_set::empty() const - bool empty() const BOOST_CONTAINER_NOEXCEPT; + bool empty() const BOOST_NOEXCEPT_OR_NOTHROW; //! @copydoc ::boost::container::flat_set::size() const - size_type size() const BOOST_CONTAINER_NOEXCEPT; + size_type size() const BOOST_NOEXCEPT_OR_NOTHROW; //! @copydoc ::boost::container::flat_set::max_size() const - size_type max_size() const BOOST_CONTAINER_NOEXCEPT; + size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW; //! @copydoc ::boost::container::flat_set::capacity() const - size_type capacity() const BOOST_CONTAINER_NOEXCEPT; + size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW; //! @copydoc ::boost::container::flat_set::reserve(size_type) void reserve(size_type cnt); @@ -982,7 +1076,7 @@ class flat_multiset // ////////////////////////////////////////////// - #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) //! <b>Effects</b>: Inserts an object of type Key constructed with //! std::forward<Args>(args)... and returns the iterator pointing to the @@ -993,7 +1087,7 @@ class flat_multiset //! //! <b>Note</b>: If an element is inserted it might invalidate elements. template <class... Args> - iterator emplace(Args&&... args) + 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 @@ -1008,26 +1102,24 @@ class flat_multiset //! //! <b>Note</b>: If an element is inserted it might invalidate elements. template <class... Args> - iterator emplace_hint(const_iterator p, Args&&... args) + iterator emplace_hint(const_iterator p, BOOST_FWD_REF(Args)... args) { return this->base_t::emplace_hint_equal(p, boost::forward<Args>(args)...); } - #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING + #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - #define BOOST_PP_LOCAL_MACRO(n) \ - BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ - iterator emplace(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ - { return this->base_t::emplace_equal(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); } \ - \ - BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ - iterator emplace_hint(const_iterator p \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ - { return this->base_t::emplace_hint_equal \ - (p BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); } \ - //! - #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) - #include BOOST_PP_LOCAL_ITERATE() + #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)\ + { 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)\ + { 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) + #undef BOOST_CONTAINER_FLAT_MULTISET_EMPLACE_CODE - #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING + #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) //! <b>Effects</b>: Inserts x and returns the iterator pointing to the @@ -1140,10 +1232,12 @@ class flat_multiset iterator erase(const_iterator first, const_iterator last); //! @copydoc ::boost::container::flat_set::swap - void swap(flat_multiset& x); + void swap(flat_multiset& x) + BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value + && boost::container::container_detail::is_nothrow_swappable<Compare>::value ); //! @copydoc ::boost::container::flat_set::clear - void clear() BOOST_CONTAINER_NOEXCEPT; + void clear() BOOST_NOEXCEPT_OR_NOTHROW; //! @copydoc ::boost::container::flat_set::key_comp key_compare key_comp() const; @@ -1157,6 +1251,18 @@ class flat_multiset //! @copydoc ::boost::container::flat_set::find(const key_type& ) const const_iterator find(const key_type& x) const; + //! @copydoc ::boost::container::flat_set::nth(size_type) + iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW; + + //! @copydoc ::boost::container::flat_set::nth(size_type) const + const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW; + + //! @copydoc ::boost::container::flat_set::index_of(iterator) + size_type index_of(iterator p) BOOST_NOEXCEPT_OR_NOTHROW; + + //! @copydoc ::boost::container::flat_set::index_of(const_iterator) const + size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW; + //! @copydoc ::boost::container::flat_set::count(const key_type& ) const size_type count(const key_type& x) const; @@ -1233,10 +1339,13 @@ class flat_multiset //!has_trivial_destructor_after_move<> == true_type //!specialization for optimizations -template <class Key, class C, class Allocator> -struct has_trivial_destructor_after_move<boost::container::flat_multiset<Key, C, Allocator> > +template <class Key, class Compare, class Allocator> +struct has_trivial_destructor_after_move<boost::container::flat_multiset<Key, Compare, Allocator> > { - static const bool value = has_trivial_destructor_after_move<Allocator>::value && has_trivial_destructor_after_move<C>::value; + typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer; + static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value && + ::boost::has_trivial_destructor_after_move<pointer>::value && + ::boost::has_trivial_destructor_after_move<Compare>::value; }; namespace container { @@ -1247,4 +1356,4 @@ namespace container { #include <boost/container/detail/config_end.hpp> -#endif /* BOOST_CONTAINER_FLAT_SET_HPP */ +#endif // BOOST_CONTAINER_FLAT_SET_HPP diff --git a/boost/container/list.hpp b/boost/container/list.hpp index 33cc6ee0f8..54da6df518 100644 --- a/boost/container/list.hpp +++ b/boost/container/list.hpp @@ -6,48 +6,53 @@ // // See http://www.boost.org/libs/container for documentation. // - +////////////////////////////////////////////////////////////////////////////// #ifndef BOOST_CONTAINER_LIST_HPP #define BOOST_CONTAINER_LIST_HPP -#if defined(_MSC_VER) +#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> + +// container #include <boost/container/container_fwd.hpp> -#include <boost/container/detail/version_type.hpp> +#include <boost/container/new_allocator.hpp> //new_allocator +#include <boost/container/throw_exception.hpp> +// container/detail +#include <boost/container/detail/algorithm.hpp> +#include <boost/container/detail/compare_functors.hpp> +#include <boost/container/detail/iterator.hpp> #include <boost/container/detail/iterators.hpp> #include <boost/container/detail/mpl.hpp> -#include <boost/container/throw_exception.hpp> +#include <boost/container/detail/node_alloc_holder.hpp> +#include <boost/container/detail/version_type.hpp> +// move #include <boost/move/utility_core.hpp> #include <boost/move/iterator.hpp> -#include <boost/move/detail/move_helpers.hpp> #include <boost/move/traits.hpp> +// move/detail +#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +# include <boost/move/detail/fwd_macros.hpp> +#endif +#include <boost/move/detail/move_helpers.hpp> + +// intrusive #include <boost/intrusive/pointer_traits.hpp> -#include <boost/container/detail/utilities.hpp> -#include <boost/container/detail/algorithms.hpp> #include <boost/intrusive/list.hpp> +// other #include <boost/assert.hpp> -#include <boost/container/detail/node_alloc_holder.hpp> - -#if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) -#else -//Preprocessor library to emulate perfect forwarding -#include <boost/container/detail/preprocessor.hpp> -#endif - +// std #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) #include <initializer_list> #endif -#include <iterator> -#include <utility> -#include <memory> -#include <functional> -#include <algorithm> - namespace boost { namespace container { @@ -124,7 +129,7 @@ struct intrusive_list_type //! \tparam T The type of object that is stored in the list //! \tparam Allocator The allocator used for all internal memory management #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED -template <class T, class Allocator = std::allocator<T> > +template <class T, class Allocator = new_allocator<T> > #else template <class T, class Allocator> #endif @@ -141,44 +146,14 @@ class list typedef typename AllocHolder::ValAlloc ValAlloc; typedef typename AllocHolder::Node Node; typedef container_detail::allocator_destroyer<NodeAlloc> Destroyer; - typedef typename AllocHolder::allocator_v1 allocator_v1; - typedef typename AllocHolder::allocator_v2 allocator_v2; typedef typename AllocHolder::alloc_version alloc_version; typedef boost::container::allocator_traits<Allocator> allocator_traits_type; - - class equal_to_value - { - typedef typename AllocHolder::value_type value_type; - const value_type &t_; - - public: - equal_to_value(const value_type &t) - : t_(t) - {} - - bool operator()(const value_type &t)const - { return t_ == t; } - }; - - template<class Pred> - struct ValueCompareToNodeCompare - : Pred - { - ValueCompareToNodeCompare(Pred pred) - : Pred(pred) - {} - - bool operator()(const Node &a, const Node &b) const - { return static_cast<const Pred&>(*this)(a.m_data, b.m_data); } - - bool operator()(const Node &a) const - { return static_cast<const Pred&>(*this)(a.m_data); } - }; + typedef boost::container::equal_to_value<Allocator> equal_to_value_type; BOOST_COPYABLE_AND_MOVABLE(list) - typedef container_detail::iterator<typename Icont::iterator, false> iterator_impl; - typedef container_detail::iterator<typename Icont::iterator, true> const_iterator_impl; + typedef container_detail::iterator_from_iiterator<typename Icont::iterator, false> iterator_impl; + typedef container_detail::iterator_from_iiterator<typename Icont::iterator, true> const_iterator_impl; #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED public: @@ -199,8 +174,8 @@ class list typedef BOOST_CONTAINER_IMPDEF(NodeAlloc) stored_allocator_type; typedef BOOST_CONTAINER_IMPDEF(iterator_impl) iterator; typedef BOOST_CONTAINER_IMPDEF(const_iterator_impl) const_iterator; - typedef BOOST_CONTAINER_IMPDEF(container_detail::reverse_iterator<iterator>) reverse_iterator; - typedef BOOST_CONTAINER_IMPDEF(container_detail::reverse_iterator<const_iterator>) const_reverse_iterator; + typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<iterator>) reverse_iterator; + typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<const_iterator>) const_reverse_iterator; ////////////////////////////////////////////// // @@ -222,12 +197,12 @@ class list //! <b>Throws</b>: Nothing //! //! <b>Complexity</b>: Constant. - explicit list(const allocator_type &a) BOOST_CONTAINER_NOEXCEPT + explicit list(const allocator_type &a) BOOST_NOEXCEPT_OR_NOTHROW : AllocHolder(a) {} - //! <b>Effects</b>: Constructs a list that will use a copy of allocator a - //! and inserts n copies of value. + //! <b>Effects</b>: Constructs a list + //! and inserts n value-initialized value_types. //! //! <b>Throws</b>: If allocator_type's default constructor //! throws or T's default or copy constructor throws. @@ -244,6 +219,17 @@ class list //! throws or T's default or copy constructor throws. //! //! <b>Complexity</b>: Linear to n. + list(size_type n, const allocator_type &a) + : AllocHolder(a) + { this->resize(n); } + + //! <b>Effects</b>: Constructs a list that will use a copy of allocator a + //! and inserts n copies of value. + //! + //! <b>Throws</b>: If allocator_type's default constructor + //! throws or T's default or copy constructor throws. + //! + //! <b>Complexity</b>: Linear to n. list(size_type n, const T& value, const Allocator& a = Allocator()) : AllocHolder(a) { this->insert(this->cbegin(), n, value); } @@ -259,13 +245,13 @@ class list : AllocHolder(x) { this->insert(this->cbegin(), x.begin(), x.end()); } - //! <b>Effects</b>: Move constructor. Moves mx's resources to *this. + //! <b>Effects</b>: Move constructor. Moves x's resources to *this. //! //! <b>Throws</b>: If allocator_type's copy constructor throws. //! //! <b>Complexity</b>: Constant. list(BOOST_RV_REF(list) x) - : AllocHolder(boost::move(static_cast<AllocHolder&>(x))) + : AllocHolder(BOOST_MOVE_BASE(AllocHolder, x)) {} //! <b>Effects</b>: Copy constructs a list using the specified allocator. @@ -280,7 +266,7 @@ class list { this->insert(this->cbegin(), x.begin(), x.end()); } //! <b>Effects</b>: Move constructor sing the specified allocator. - //! Moves mx's resources to *this. + //! Moves x's resources to *this. //! //! <b>Throws</b>: If allocation or value_type's copy constructor throws. //! @@ -292,7 +278,7 @@ class list this->icont().swap(x.icont()); } else{ - this->insert(this->cbegin(), x.begin(), x.end()); + this->insert(this->cbegin(), boost::make_move_iterator(x.begin()), boost::make_move_iterator(x.end())); } } @@ -329,7 +315,7 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Linear to the number of elements. - ~list() BOOST_CONTAINER_NOEXCEPT + ~list() BOOST_NOEXCEPT_OR_NOTHROW {} //AllocHolder clears the list //! <b>Effects</b>: Makes *this contain the same elements as x. @@ -368,7 +354,8 @@ class list //! propagate_on_container_move_assignment is true or //! this->get>allocator() == x.get_allocator(). Linear otherwise. list& operator=(BOOST_RV_REF(list) x) - BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value) + BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value + || allocator_traits_type::is_always_equal::value) { BOOST_ASSERT(this != &x); NodeAlloc &this_alloc = this->node_alloc(); @@ -463,7 +450,7 @@ class list //! <b>Throws</b>: If allocator's copy constructor throws. //! //! <b>Complexity</b>: Constant. - allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT + allocator_type get_allocator() const BOOST_NOEXCEPT_OR_NOTHROW { return allocator_type(this->node_alloc()); } //! <b>Effects</b>: Returns a reference to the internal allocator. @@ -473,7 +460,7 @@ class list //! <b>Complexity</b>: Constant. //! //! <b>Note</b>: Non-standard extension. - stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT + stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW { return this->node_alloc(); } //! <b>Effects</b>: Returns a reference to the internal allocator. @@ -483,7 +470,7 @@ class list //! <b>Complexity</b>: Constant. //! //! <b>Note</b>: Non-standard extension. - const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT + const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW { return this->node_alloc(); } ////////////////////////////////////////////// @@ -497,7 +484,7 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - iterator begin() BOOST_CONTAINER_NOEXCEPT + iterator begin() BOOST_NOEXCEPT_OR_NOTHROW { return iterator(this->icont().begin()); } //! <b>Effects</b>: Returns a const_iterator to the first element contained in the list. @@ -505,7 +492,7 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator begin() const BOOST_CONTAINER_NOEXCEPT + const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW { return this->cbegin(); } //! <b>Effects</b>: Returns an iterator to the end of the list. @@ -513,7 +500,7 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - iterator end() BOOST_CONTAINER_NOEXCEPT + iterator end() BOOST_NOEXCEPT_OR_NOTHROW { return iterator(this->icont().end()); } //! <b>Effects</b>: Returns a const_iterator to the end of the list. @@ -521,7 +508,7 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator end() const BOOST_CONTAINER_NOEXCEPT + const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW { return this->cend(); } //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning @@ -530,7 +517,7 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT + reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW { return reverse_iterator(end()); } //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning @@ -539,7 +526,7 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT + const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW { return this->crbegin(); } //! <b>Effects</b>: Returns a reverse_iterator pointing to the end @@ -548,7 +535,7 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT + reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW { return reverse_iterator(begin()); } //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end @@ -557,7 +544,7 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT + const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW { return this->crend(); } //! <b>Effects</b>: Returns a const_iterator to the first element contained in the list. @@ -565,7 +552,7 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT + const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW { return const_iterator(this->non_const_icont().begin()); } //! <b>Effects</b>: Returns a const_iterator to the end of the list. @@ -573,7 +560,7 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator cend() const BOOST_CONTAINER_NOEXCEPT + const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW { return const_iterator(this->non_const_icont().end()); } //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning @@ -582,7 +569,7 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT + const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW { return const_reverse_iterator(this->cend()); } //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end @@ -591,7 +578,7 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT + const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW { return const_reverse_iterator(this->cbegin()); } ////////////////////////////////////////////// @@ -605,7 +592,7 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - bool empty() const BOOST_CONTAINER_NOEXCEPT + bool empty() const BOOST_NOEXCEPT_OR_NOTHROW { return !this->size(); } //! <b>Effects</b>: Returns the number of the elements contained in the list. @@ -613,7 +600,7 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - size_type size() const BOOST_CONTAINER_NOEXCEPT + size_type size() const BOOST_NOEXCEPT_OR_NOTHROW { return this->icont().size(); } //! <b>Effects</b>: Returns the largest possible size of the list. @@ -621,7 +608,7 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - size_type max_size() const BOOST_CONTAINER_NOEXCEPT + size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW { return AllocHolder::max_size(); } //! <b>Effects</b>: Inserts or erases elements at the end such that @@ -665,7 +652,7 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - reference front() BOOST_CONTAINER_NOEXCEPT + reference front() BOOST_NOEXCEPT_OR_NOTHROW { return *this->begin(); } //! <b>Requires</b>: !empty() @@ -676,7 +663,7 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reference front() const BOOST_CONTAINER_NOEXCEPT + const_reference front() const BOOST_NOEXCEPT_OR_NOTHROW { return *this->begin(); } //! <b>Requires</b>: !empty() @@ -687,7 +674,7 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - reference back() BOOST_CONTAINER_NOEXCEPT + reference back() BOOST_NOEXCEPT_OR_NOTHROW { return *(--this->end()); } //! <b>Requires</b>: !empty() @@ -698,7 +685,7 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reference back() const BOOST_CONTAINER_NOEXCEPT + const_reference back() const BOOST_NOEXCEPT_OR_NOTHROW { return *(--this->end()); } ////////////////////////////////////////////// @@ -707,7 +694,7 @@ class list // ////////////////////////////////////////////// - #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) //! <b>Effects</b>: Inserts an object of type T constructed with //! std::forward<Args>(args)... in the end of the list. @@ -717,7 +704,7 @@ class list //! //! <b>Complexity</b>: Constant template <class... Args> - void emplace_back(Args&&... args) + void emplace_back(BOOST_FWD_REF(Args)... args) { this->emplace(this->cend(), boost::forward<Args>(args)...); } //! <b>Effects</b>: Inserts an object of type T constructed with @@ -728,7 +715,7 @@ class list //! //! <b>Complexity</b>: Constant template <class... Args> - void emplace_front(Args&&... args) + void emplace_front(BOOST_FWD_REF(Args)... args) { this->emplace(this->cbegin(), boost::forward<Args>(args)...); } //! <b>Effects</b>: Inserts an object of type T constructed with @@ -739,42 +726,34 @@ class list //! //! <b>Complexity</b>: Constant template <class... Args> - iterator emplace(const_iterator p, Args&&... args) + iterator emplace(const_iterator p, BOOST_FWD_REF(Args)... args) { NodePtr pnode(AllocHolder::create_node(boost::forward<Args>(args)...)); return iterator(this->icont().insert(p.get(), *pnode)); } - #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING - - #define BOOST_PP_LOCAL_MACRO(n) \ - BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ - void emplace_back(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ - { \ - this->emplace(this->cend() \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \ - } \ - \ - BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ - void emplace_front(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ - { \ - this->emplace(this->cbegin() \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \ - } \ - \ - BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ - iterator emplace(const_iterator p \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ - { \ - NodePtr pnode (AllocHolder::create_node \ - (BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \ - return iterator(this->icont().insert(p.get(), *pnode)); \ - } \ - //! - #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) - #include BOOST_PP_LOCAL_ITERATE() - - #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING + #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + + #define BOOST_CONTAINER_LIST_EMPLACE_CODE(N) \ + BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ + void emplace_back(BOOST_MOVE_UREF##N)\ + { this->emplace(this->cend() BOOST_MOVE_I##N BOOST_MOVE_FWD##N); }\ + \ + BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ + void emplace_front(BOOST_MOVE_UREF##N)\ + { this->emplace(this->cbegin() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);}\ + \ + BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ + iterator emplace(const_iterator p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ + {\ + NodePtr pnode (AllocHolder::create_node(BOOST_MOVE_FWD##N));\ + return iterator(this->icont().insert(p.get(), *pnode));\ + }\ + // + BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_LIST_EMPLACE_CODE) + #undef BOOST_CONTAINER_LIST_EMPLACE_CODE + + #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) //! <b>Effects</b>: Inserts a copy of x at the beginning of the list. @@ -786,7 +765,7 @@ class list void push_front(const T &x); //! <b>Effects</b>: Constructs a new element in the beginning of the list - //! and moves the resources of mx to this new element. + //! and moves the resources of x to this new element. //! //! <b>Throws</b>: If memory allocation throws. //! @@ -806,7 +785,7 @@ class list void push_back(const T &x); //! <b>Effects</b>: Constructs a new element in the end of the list - //! and moves the resources of mx to this new element. + //! and moves the resources of x to this new element. //! //! <b>Throws</b>: If memory allocation throws. //! @@ -830,7 +809,7 @@ class list //! <b>Requires</b>: p must be a valid iterator of *this. //! - //! <b>Effects</b>: Insert a new element before p with mx's resources. + //! <b>Effects</b>: Insert a new element before p with x's resources. //! //! <b>Returns</b>: an iterator to the inserted element. //! @@ -866,14 +845,14 @@ class list //! <b>Throws</b>: If memory allocation throws, T's constructor from a //! dereferenced InpIt throws. //! - //! <b>Complexity</b>: Linear to std::distance [first, last). + //! <b>Complexity</b>: Linear to distance [first, last). template <class InpIt> iterator insert(const_iterator p, InpIt first, InpIt last #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) , typename container_detail::enable_if_c < !container_detail::is_convertible<InpIt, size_type>::value && (container_detail::is_input_iterator<InpIt>::value - || container_detail::is_same<alloc_version, allocator_v1>::value + || container_detail::is_same<alloc_version, version_1>::value ) >::type * = 0 #endif @@ -897,7 +876,7 @@ class list , typename container_detail::enable_if_c < !container_detail::is_convertible<FwdIt, size_type>::value && !(container_detail::is_input_iterator<FwdIt>::value - || container_detail::is_same<alloc_version, allocator_v1>::value + || container_detail::is_same<alloc_version, version_1>::value ) >::type * = 0 ) @@ -906,7 +885,7 @@ class list insertion_functor func(this->icont(), p.get()); iterator before_p(p.get()); --before_p; - this->allocate_many_and_construct(first, std::distance(first, last), func); + this->allocate_many_and_construct(first, boost::container::iterator_distance(first, last), func); return ++before_p; } #endif @@ -921,7 +900,7 @@ class list //! <b>Throws</b>: If memory allocation throws, T's constructor from a //! dereferenced std::initializer_list iterator throws. //! - //! <b>Complexity</b>: Linear to std::distance [il.begin(), il.end()). + //! <b>Complexity</b>: Linear to distance [il.begin(), il.end()). iterator insert(const_iterator p, std::initializer_list<value_type> il) { return insert(p, il.begin(), il.end()); } #endif @@ -931,7 +910,7 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Amortized constant time. - void pop_front() BOOST_CONTAINER_NOEXCEPT + void pop_front() BOOST_NOEXCEPT_OR_NOTHROW { this->erase(this->cbegin()); } //! <b>Effects</b>: Removes the last element from the list. @@ -939,7 +918,7 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Amortized constant time. - void pop_back() BOOST_CONTAINER_NOEXCEPT + void pop_back() BOOST_NOEXCEPT_OR_NOTHROW { const_iterator tmp = this->cend(); this->erase(--tmp); } //! <b>Requires</b>: p must be a valid iterator of *this. @@ -949,7 +928,7 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Amortized constant time. - iterator erase(const_iterator p) BOOST_CONTAINER_NOEXCEPT + iterator erase(const_iterator p) BOOST_NOEXCEPT_OR_NOTHROW { return iterator(this->icont().erase_and_dispose(p.get(), Destroyer(this->node_alloc()))); } //! <b>Requires</b>: first and last must be valid iterator to elements in *this. @@ -959,7 +938,7 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Linear to the distance between first and last. - iterator erase(const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT + iterator erase(const_iterator first, const_iterator last) BOOST_NOEXCEPT_OR_NOTHROW { return iterator(AllocHolder::erase_range(first.get(), last.get(), alloc_version())); } //! <b>Effects</b>: Swaps the contents of *this and x. @@ -968,6 +947,8 @@ class list //! //! <b>Complexity</b>: Constant. void swap(list& x) + BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_swap::value + || allocator_traits_type::is_always_equal::value) { AllocHolder::swap(x); } //! <b>Effects</b>: Erases all the elements of the list. @@ -975,7 +956,7 @@ class list //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Linear to the number of elements in the list. - void clear() BOOST_CONTAINER_NOEXCEPT + void clear() BOOST_NOEXCEPT_OR_NOTHROW { AllocHolder::clear(alloc_version()); } ////////////////////////////////////////////// @@ -996,7 +977,7 @@ class list //! //! <b>Note</b>: Iterators of values obtained from list x now point to elements of //! this list. Iterators of this list and all the references are not invalidated. - void splice(const_iterator p, list& x) BOOST_CONTAINER_NOEXCEPT + void splice(const_iterator p, list& x) BOOST_NOEXCEPT_OR_NOTHROW { BOOST_ASSERT(this != &x); BOOST_ASSERT(this->node_alloc() == x.node_alloc()); @@ -1015,7 +996,7 @@ class list //! //! <b>Note</b>: Iterators of values obtained from list x now point to elements of //! this list. Iterators of this list and all the references are not invalidated. - void splice(const_iterator p, BOOST_RV_REF(list) x) BOOST_CONTAINER_NOEXCEPT + void splice(const_iterator p, BOOST_RV_REF(list) x) BOOST_NOEXCEPT_OR_NOTHROW { this->splice(p, static_cast<list&>(x)); } //! <b>Requires</b>: p must point to an element contained @@ -1032,7 +1013,7 @@ class list //! //! <b>Note</b>: Iterators of values obtained from list x now point to elements of this //! list. Iterators of this list and all the references are not invalidated. - void splice(const_iterator p, list &x, const_iterator i) BOOST_CONTAINER_NOEXCEPT + void splice(const_iterator p, list &x, const_iterator i) BOOST_NOEXCEPT_OR_NOTHROW { //BOOST_ASSERT(this != &x); BOOST_ASSERT(this->node_alloc() == x.node_alloc()); @@ -1053,7 +1034,7 @@ class list //! //! <b>Note</b>: Iterators of values obtained from list x now point to elements of this //! list. Iterators of this list and all the references are not invalidated. - void splice(const_iterator p, BOOST_RV_REF(list) x, const_iterator i) BOOST_CONTAINER_NOEXCEPT + void splice(const_iterator p, BOOST_RV_REF(list) x, const_iterator i) BOOST_NOEXCEPT_OR_NOTHROW { this->splice(p, static_cast<list&>(x), i); } //! <b>Requires</b>: p must point to an element contained @@ -1069,7 +1050,7 @@ class list //! //! <b>Note</b>: Iterators of values obtained from list x now point to elements of this //! list. Iterators of this list and all the references are not invalidated. - void splice(const_iterator p, list &x, const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT + void splice(const_iterator p, list &x, const_iterator first, const_iterator last) BOOST_NOEXCEPT_OR_NOTHROW { BOOST_ASSERT(this->node_alloc() == x.node_alloc()); this->icont().splice(p.get(), x.icont(), first.get(), last.get()); @@ -1088,12 +1069,12 @@ class list //! //! <b>Note</b>: Iterators of values obtained from list x now point to elements of this //! list. Iterators of this list and all the references are not invalidated. - void splice(const_iterator p, BOOST_RV_REF(list) x, const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT + void splice(const_iterator p, BOOST_RV_REF(list) x, const_iterator first, const_iterator last) BOOST_NOEXCEPT_OR_NOTHROW { this->splice(p, static_cast<list&>(x), first, last); } //! <b>Requires</b>: p must point to an element contained //! by this list. first and last must point to elements contained in list x. - //! n == std::distance(first, last). this' allocator and x's allocator shall compare equal + //! n == distance(first, last). this' allocator and x's allocator shall compare equal //! //! <b>Effects</b>: Transfers the range pointed by first and last from list x to this list, //! before the the element pointed by p. No destructors or copy constructors are called. @@ -1106,7 +1087,7 @@ class list //! list. Iterators of this list and all the references are not invalidated. //! //! <b>Note</b>: Non-standard extension - void splice(const_iterator p, list &x, const_iterator first, const_iterator last, size_type n) BOOST_CONTAINER_NOEXCEPT + void splice(const_iterator p, list &x, const_iterator first, const_iterator last, size_type n) BOOST_NOEXCEPT_OR_NOTHROW { BOOST_ASSERT(this->node_alloc() == x.node_alloc()); this->icont().splice(p.get(), x.icont(), first.get(), last.get(), n); @@ -1114,7 +1095,7 @@ class list //! <b>Requires</b>: p must point to an element contained //! by this list. first and last must point to elements contained in list x. - //! n == std::distance(first, last). this' allocator and x's allocator shall compare equal + //! n == distance(first, last). this' allocator and x's allocator shall compare equal //! //! <b>Effects</b>: Transfers the range pointed by first and last from list x to this list, //! before the the element pointed by p. No destructors or copy constructors are called. @@ -1127,7 +1108,7 @@ class list //! list. Iterators of this list and all the references are not invalidated. //! //! <b>Note</b>: Non-standard extension - void splice(const_iterator p, BOOST_RV_REF(list) x, const_iterator first, const_iterator last, size_type n) BOOST_CONTAINER_NOEXCEPT + void splice(const_iterator p, BOOST_RV_REF(list) x, const_iterator first, const_iterator last, size_type n) BOOST_NOEXCEPT_OR_NOTHROW { this->splice(p, static_cast<list&>(x), first, last, n); } //! <b>Effects</b>: Removes all the elements that compare equal to value. @@ -1139,7 +1120,7 @@ class list //! <b>Note</b>: The relative order of elements that are not removed is unchanged, //! and iterators to elements that are not removed remain valid. void remove(const T& value) - { this->remove_if(equal_to_value(value)); } + { this->remove_if(equal_to_value_type(value)); } //! <b>Effects</b>: Removes all the elements for which a specified //! predicate is satisfied. @@ -1153,8 +1134,8 @@ class list template <class Pred> void remove_if(Pred pred) { - typedef ValueCompareToNodeCompare<Pred> Predicate; - this->icont().remove_and_dispose_if(Predicate(pred), Destroyer(this->node_alloc())); + typedef value_to_node_compare<Node, Pred> value_to_node_compare_type; + this->icont().remove_and_dispose_if(value_to_node_compare_type(pred), Destroyer(this->node_alloc())); } //! <b>Effects</b>: Removes adjacent duplicate elements or adjacent @@ -1181,8 +1162,8 @@ class list template <class BinaryPredicate> void unique(BinaryPredicate binary_pred) { - typedef ValueCompareToNodeCompare<BinaryPredicate> Predicate; - this->icont().unique_and_dispose(Predicate(binary_pred), Destroyer(this->node_alloc())); + typedef value_to_node_compare<Node, BinaryPredicate> value_to_node_compare_type; + this->icont().unique_and_dispose(value_to_node_compare_type(binary_pred), Destroyer(this->node_alloc())); } //! <b>Requires</b>: The lists x and *this must be distinct. @@ -1231,8 +1212,8 @@ class list void merge(list &x, const StrictWeakOrdering &comp) { BOOST_ASSERT(this->node_alloc() == x.node_alloc()); - this->icont().merge(x.icont(), - ValueCompareToNodeCompare<StrictWeakOrdering>(comp)); + typedef value_to_node_compare<Node, StrictWeakOrdering> value_to_node_compare_type; + this->icont().merge(x.icont(), value_to_node_compare_type(comp)); } //! <b>Requires</b>: p must be a comparison function that induces a strict weak @@ -1280,7 +1261,8 @@ class list // nothing if the list has length 0 or 1. if (this->size() < 2) return; - this->icont().sort(ValueCompareToNodeCompare<StrictWeakOrdering>(comp)); + typedef value_to_node_compare<Node, StrictWeakOrdering> value_to_node_compare_type; + this->icont().sort(value_to_node_compare_type(comp)); } //! <b>Effects</b>: Reverses the order of elements in the list. @@ -1290,28 +1272,14 @@ class list //! <b>Complexity</b>: This function is linear time. //! //! <b>Note</b>: Iterators and references are not invalidated - void reverse() BOOST_CONTAINER_NOEXCEPT + void reverse() BOOST_NOEXCEPT_OR_NOTHROW { this->icont().reverse(); } //! <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 list& x, const list& y) - { - if(x.size() != y.size()){ - return false; - } - typedef typename list::const_iterator const_iterator; - const_iterator end1 = x.end(); - - const_iterator i1 = x.begin(); - const_iterator i2 = y.begin(); - while (i1 != end1 && *i1 == *i2) { - ++i1; - ++i2; - } - return i1 == end1; - } + { 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 //! @@ -1323,7 +1291,7 @@ class list //! //! <b>Complexity</b>: Linear to the number of elements in the container. friend bool operator<(const list& x, const list& y) - { return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } + { 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 //! @@ -1448,8 +1416,11 @@ class list //!specialization for optimizations template <class T, class Allocator> struct has_trivial_destructor_after_move<boost::container::list<T, Allocator> > - : public ::boost::has_trivial_destructor_after_move<Allocator> -{}; +{ + typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer; + static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value && + ::boost::has_trivial_destructor_after_move<pointer>::value; +}; namespace container { diff --git a/boost/container/map.hpp b/boost/container/map.hpp index 6abfa1a346..4dc6096e1e 100644 --- a/boost/container/map.hpp +++ b/boost/container/map.hpp @@ -7,36 +7,45 @@ // See http://www.boost.org/libs/container for documentation. // ////////////////////////////////////////////////////////////////////////////// - #ifndef BOOST_CONTAINER_MAP_HPP #define BOOST_CONTAINER_MAP_HPP -#if defined(_MSC_VER) +#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> +// container #include <boost/container/container_fwd.hpp> -#include <utility> -#include <functional> -#include <memory> +#include <boost/container/new_allocator.hpp> //new_allocator +#include <boost/container/throw_exception.hpp> +// container/detail +#include <boost/container/detail/mpl.hpp> #include <boost/container/detail/tree.hpp> +#include <boost/container/detail/type_traits.hpp> #include <boost/container/detail/value_init.hpp> -#include <boost/type_traits/has_trivial_destructor.hpp> -#include <boost/container/detail/mpl.hpp> -#include <boost/container/detail/utilities.hpp> #include <boost/container/detail/pair.hpp> -#include <boost/container/detail/type_traits.hpp> -#include <boost/container/throw_exception.hpp> +// move +#include <boost/move/traits.hpp> #include <boost/move/utility_core.hpp> +// move/detail +#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +#include <boost/move/detail/fwd_macros.hpp> +#endif #include <boost/move/detail/move_helpers.hpp> -#include <boost/move/traits.hpp> +// intrusive/detail +#include <boost/intrusive/detail/minimal_pair_header.hpp> //pair +#include <boost/intrusive/detail/minimal_less_equal_header.hpp>//less, equal +// other #include <boost/static_assert.hpp> -#include <boost/container/detail/value_init.hpp> #include <boost/core/no_exceptions_support.hpp> - +// std #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) #include <initializer_list> #endif @@ -55,13 +64,13 @@ namespace container { //! by this container is the value_type is std::pair<const Key, T>. //! //! \tparam Key is the key_type of the map -//! \tparam Value is the <code>mapped_type</code> +//! \tparam T is the <code>mapped_type</code> //! \tparam Compare is the ordering function for Keys (e.g. <i>std::less<Key></i>). //! \tparam Allocator is the allocator to allocate the <code>value_type</code>s //! (e.g. <i>allocator< std::pair<const Key, T> > </i>). //! \tparam MapOptions is an packed option type generated using using boost::container::tree_assoc_options. template < class Key, class T, class Compare = std::less<Key> - , class Allocator = std::allocator< std::pair< const Key, T> >, class MapOptions = tree_assoc_defaults > + , class Allocator = new_allocator< std::pair< const Key, T> >, class MapOptions = tree_assoc_defaults > #else template <class Key, class T, class Compare, class Allocator, class MapOptions> #endif @@ -93,10 +102,10 @@ 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 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>::pointer pointer; typedef typename boost::container::allocator_traits<Allocator>::const_pointer const_pointer; typedef typename boost::container::allocator_traits<Allocator>::reference reference; @@ -126,7 +135,7 @@ class map map() : base_t() { - //Allocator type must be std::pair<CONST Key, 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)); } @@ -134,11 +143,10 @@ class map //! and allocator. //! //! <b>Complexity</b>: Constant. - explicit map(const Compare& comp, - const allocator_type& a = allocator_type()) + explicit map(const Compare& comp, const allocator_type& a = allocator_type()) : base_t(comp, a) { - //Allocator type must be std::pair<CONST Key, 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)); } @@ -148,7 +156,7 @@ class map explicit map(const allocator_type& a) : base_t(a) { - //Allocator type must be std::pair<CONST Key, 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)); } @@ -162,7 +170,20 @@ class map const allocator_type& a = allocator_type()) : base_t(true, first, last, comp, a) { - //Allocator type must be std::pair<CONST Key, 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 + //! 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> + 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)); } @@ -181,7 +202,7 @@ class map , const Compare& comp = Compare(), const allocator_type& a = allocator_type()) : base_t(ordered_range, first, last, comp, a) { - //Allocator type must be std::pair<CONST Key, 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)); } @@ -194,15 +215,37 @@ class map 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) { - //Allocator type must be std::pair<CONST Key, 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 + //! 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(). + 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 + //! 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. + //! + //! <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. map(ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp = Compare(), const allocator_type& a = allocator_type()) : base_t(ordered_range, il.begin(), il.end(), comp, a) { - //Allocator type must be std::pair<CONST Key, 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)); } #endif @@ -213,7 +256,7 @@ class map map(const map& x) : base_t(static_cast<const base_t&>(x)) { - //Allocator type must be std::pair<CONST Key, 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)); } @@ -223,9 +266,9 @@ class map //! //! <b>Postcondition</b>: x is emptied. map(BOOST_RV_REF(map) x) - : base_t(boost::move(static_cast<base_t&>(x))) + : base_t(BOOST_MOVE_BASE(base_t, x)) { - //Allocator type must be std::pair<CONST Key, 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)); } @@ -235,7 +278,7 @@ class map map(const map& x, const allocator_type &a) : base_t(static_cast<const base_t&>(x), a) { - //Allocator type must be std::pair<CONST Key, 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)); } @@ -246,9 +289,9 @@ class map //! //! <b>Postcondition</b>: x is emptied. map(BOOST_RV_REF(map) x, const allocator_type &a) - : base_t(boost::move(static_cast<base_t&>(x)), a) + : base_t(BOOST_MOVE_BASE(base_t, x), a) { - //Allocator type must be std::pair<CONST Key, 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)); } @@ -267,8 +310,10 @@ class map //! propagate_on_container_move_assignment is true or //! this->get>allocator() == x.get_allocator(). Linear otherwise. map& operator=(BOOST_RV_REF(map) x) - BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value) - { return static_cast<map&>(this->base_t::operator=(boost::move(static_cast<base_t&>(x)))); } + BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value + && boost::container::container_detail::is_nothrow_move_assignable<Compare>::value ) + + { return static_cast<map&>(this->base_t::operator=(BOOST_MOVE_BASE(base_t, x))); } #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) //! <b>Effects</b>: Assign content of il to *this. @@ -283,7 +328,7 @@ class map #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) - //! <b>Effects</b>: Returns a copy of the Allocator that + //! <b>Effects</b>: Returns a copy of the allocator that //! was passed to the object's constructor. //! //! <b>Complexity</b>: Constant. @@ -296,7 +341,7 @@ class map //! <b>Complexity</b>: Constant. //! //! <b>Note</b>: Non-standard extension. - stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT; + stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW; //! <b>Effects</b>: Returns a reference to the internal allocator. //! @@ -305,49 +350,49 @@ class map //! <b>Complexity</b>: Constant. //! //! <b>Note</b>: Non-standard extension. - const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT; + const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW; //! <b>Effects</b>: Returns an iterator to the first element contained in the container. //! //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - iterator begin() BOOST_CONTAINER_NOEXCEPT; + iterator begin() BOOST_NOEXCEPT_OR_NOTHROW; //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container. //! //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator begin() const BOOST_CONTAINER_NOEXCEPT; + const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW; //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container. //! //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT; + const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW; //! <b>Effects</b>: Returns an iterator to the end of the container. //! //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - iterator end() BOOST_CONTAINER_NOEXCEPT; + iterator end() BOOST_NOEXCEPT_OR_NOTHROW; //! <b>Effects</b>: Returns a const_iterator to the end of the container. //! //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator end() const BOOST_CONTAINER_NOEXCEPT; + const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW; //! <b>Effects</b>: Returns a const_iterator to the end of the container. //! //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator cend() const BOOST_CONTAINER_NOEXCEPT; + const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW; //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning //! of the reversed container. @@ -355,7 +400,7 @@ class map //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT; + reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW; //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning //! of the reversed container. @@ -363,7 +408,7 @@ class map //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT; + const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW; //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning //! of the reversed container. @@ -371,7 +416,7 @@ class map //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT; + const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW; //! <b>Effects</b>: Returns a reverse_iterator pointing to the end //! of the reversed container. @@ -379,7 +424,7 @@ class map //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT; + reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW; //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end //! of the reversed container. @@ -387,7 +432,7 @@ class map //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT; + const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW; //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end //! of the reversed container. @@ -395,28 +440,28 @@ class map //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT; + const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW; //! <b>Effects</b>: Returns true if the container contains no elements. //! //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - bool empty() const BOOST_CONTAINER_NOEXCEPT; + bool empty() const BOOST_NOEXCEPT_OR_NOTHROW; //! <b>Effects</b>: Returns the number of the elements contained in the container. //! //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - size_type size() const BOOST_CONTAINER_NOEXCEPT; + size_type size() const BOOST_NOEXCEPT_OR_NOTHROW; //! <b>Effects</b>: Returns the largest possible size of the container. //! //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - size_type max_size() const BOOST_CONTAINER_NOEXCEPT; + size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW; #endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) @@ -424,7 +469,7 @@ class map //! Effects: If there is no key equivalent to x in the map, inserts //! value_type(x, T()) into the map. //! - //! Returns: Allocator reference to the mapped_type corresponding to x in *this. + //! Returns: A reference to the mapped_type corresponding to x in *this. //! //! Complexity: Logarithmic. mapped_type& operator[](const key_type &k); @@ -432,7 +477,7 @@ class map //! Effects: If there is no key equivalent to x in the map, inserts //! value_type(boost::move(x), T()) into the map (the key is move-constructed) //! - //! Returns: Allocator reference to the mapped_type corresponding to x in *this. + //! Returns: A reference to the mapped_type corresponding to x in *this. //! //! Complexity: Logarithmic. mapped_type& operator[](key_type &&k); @@ -440,7 +485,7 @@ class map BOOST_MOVE_CONVERSION_AWARE_CATCH( operator[] , key_type, mapped_type&, this->priv_subscript) #endif - //! Returns: Allocator reference to the element whose key is equivalent to x. + //! Returns: A reference to the element whose key is equivalent to x. //! Throws: An exception object of type out_of_range if no such element is present. //! Complexity: logarithmic. T& at(const key_type& k) @@ -452,7 +497,7 @@ class map return i->second; } - //! Returns: Allocator reference to the element whose key is equivalent to x. + //! Returns: A reference to the element whose key is equivalent to x. //! Throws: An exception object of type out_of_range if no such element is present. //! Complexity: logarithmic. const T& at(const key_type& k) const @@ -598,7 +643,7 @@ class map { this->base_t::insert_unique(il.begin(), il.end()); } #endif - #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) //! <b>Effects</b>: Inserts an object x of type T constructed with //! std::forward<Args>(args)... in the container if and only if there is @@ -612,7 +657,7 @@ class map //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t //! is inserted right before p. template <class... Args> - std::pair<iterator,bool> emplace(Args&&... args) + 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 T constructed with @@ -626,26 +671,24 @@ class map //! <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, Args&&... args) + iterator emplace_hint(const_iterator p, BOOST_FWD_REF(Args)... args) { return this->base_t::emplace_hint_unique(p, boost::forward<Args>(args)...); } - #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING + #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - #define BOOST_PP_LOCAL_MACRO(n) \ - BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ - std::pair<iterator,bool> emplace(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ - { return this->base_t::emplace_unique(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); }\ - \ - BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ - iterator emplace_hint(const_iterator p \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ - { return this->base_t::emplace_hint_unique(p \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _));} \ - //! - #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) - #include BOOST_PP_LOCAL_ITERATE() + #define BOOST_CONTAINER_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)\ + { 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)\ + { return this->base_t::emplace_hint_unique(hint BOOST_MOVE_I##N BOOST_MOVE_FWD##N); }\ + // + BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_MAP_EMPLACE_CODE) + #undef BOOST_CONTAINER_MAP_EMPLACE_CODE - #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING + #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) @@ -656,35 +699,37 @@ class map //! returns end(). //! //! <b>Complexity</b>: Amortized constant time - iterator erase(const_iterator p) BOOST_CONTAINER_NOEXCEPT; + iterator erase(const_iterator p) BOOST_NOEXCEPT_OR_NOTHROW; //! <b>Effects</b>: Erases all elements in the container with key equivalent to x. //! //! <b>Returns</b>: Returns the number of erased elements. //! //! <b>Complexity</b>: log(size()) + count(k) - size_type erase(const key_type& x) BOOST_CONTAINER_NOEXCEPT; + size_type erase(const key_type& x) BOOST_NOEXCEPT_OR_NOTHROW; //! <b>Effects</b>: Erases all the elements in the range [first, last). //! //! <b>Returns</b>: Returns last. //! //! <b>Complexity</b>: log(size())+N where N is the distance from first to last. - iterator erase(const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT; + iterator erase(const_iterator first, const_iterator last) BOOST_NOEXCEPT_OR_NOTHROW; //! <b>Effects</b>: Swaps the contents of *this and x. //! //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - void swap(map& x); + void swap(map& x) + BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value + && boost::container::container_detail::is_nothrow_swappable<Compare>::value ) //! <b>Effects</b>: erase(a.begin(),a.end()). //! //! <b>Postcondition</b>: size() == 0. //! //! <b>Complexity</b>: linear in size(). - void clear() BOOST_CONTAINER_NOEXCEPT; + void clear() BOOST_NOEXCEPT_OR_NOTHROW; //! <b>Effects</b>: Returns the comparison object out //! of which a was constructed. @@ -704,7 +749,7 @@ class map //! <b>Complexity</b>: Logarithmic. iterator find(const key_type& x); - //! <b>Returns</b>: Allocator const_iterator pointing to an element with the key + //! <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. @@ -726,7 +771,7 @@ class map //! <b>Complexity</b>: Logarithmic iterator lower_bound(const key_type& x); - //! <b>Returns</b>: Allocator const iterator pointing to the first element with key not + //! <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 @@ -738,7 +783,7 @@ class map //! <b>Complexity</b>: Logarithmic iterator upper_bound(const key_type& x); - //! <b>Returns</b>: Allocator const iterator pointing to the first element with key not + //! <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 @@ -835,10 +880,13 @@ class map //!has_trivial_destructor_after_move<> == true_type //!specialization for optimizations -template <class K, class T, class C, class Allocator> -struct has_trivial_destructor_after_move<boost::container::map<K, T, C, Allocator> > +template <class Key, class T, class Compare, class Allocator> +struct has_trivial_destructor_after_move<boost::container::map<Key, T, Compare, Allocator> > { - static const bool value = has_trivial_destructor_after_move<Allocator>::value && has_trivial_destructor_after_move<C>::value; + typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer; + static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value && + ::boost::has_trivial_destructor_after_move<pointer>::value && + ::boost::has_trivial_destructor_after_move<Compare>::value; }; namespace container { @@ -863,7 +911,7 @@ namespace container { //! (e.g. <i>allocator< std::pair<const Key, T> > </i>). //! \tparam MultiMapOptions is an packed option type generated using using boost::container::tree_assoc_options. template < class Key, class T, class Compare = std::less<Key> - , class Allocator = std::allocator< std::pair< const Key, T> >, class MultiMapOptions = tree_assoc_defaults> + , class Allocator = new_allocator< std::pair< const Key, T> >, class MultiMapOptions = tree_assoc_defaults> #else template <class Key, class T, class Compare, class Allocator, class MultiMapOptions> #endif @@ -888,6 +936,8 @@ class multimap > value_compare_impl; #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED + typedef ::boost::container::allocator_traits<Allocator> allocator_traits_type; + public: ////////////////////////////////////////////// // @@ -927,7 +977,7 @@ class multimap multimap() : base_t() { - //Allocator type must be std::pair<CONST Key, 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)); } @@ -937,7 +987,7 @@ class multimap explicit multimap(const Compare& comp, const allocator_type& a = allocator_type()) : base_t(comp, a) { - //Allocator type must be std::pair<CONST Key, 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)); } @@ -948,7 +998,7 @@ class multimap explicit multimap(const allocator_type& a) : base_t(a) { - //Allocator type must be std::pair<CONST Key, 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)); } @@ -963,7 +1013,20 @@ class multimap const allocator_type& a = allocator_type()) : base_t(false, first, last, comp, a) { - //Allocator type must be std::pair<CONST Key, 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, 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> + 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)); } @@ -992,15 +1055,36 @@ class multimap const allocator_type& a = allocator_type()) : base_t(false, il.begin(), il.end(), comp, a) { - //Allocator type must be std::pair<CONST Key, 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, 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(). + 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 set using the specified comparison object and + //! allocator, 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. multimap(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp = Compare(), const allocator_type& a = allocator_type()) : base_t(ordered_range, il.begin(), il.end(), comp, a) { - //Allocator type must be std::pair<CONST Key, 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)); } #endif @@ -1011,7 +1095,7 @@ class multimap multimap(const multimap& x) : base_t(static_cast<const base_t&>(x)) { - //Allocator type must be std::pair<CONST Key, 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)); } @@ -1021,9 +1105,9 @@ class multimap //! //! <b>Postcondition</b>: x is emptied. multimap(BOOST_RV_REF(multimap) x) - : base_t(boost::move(static_cast<base_t&>(x))) + : base_t(BOOST_MOVE_BASE(base_t, x)) { - //Allocator type must be std::pair<CONST Key, 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)); } @@ -1033,7 +1117,7 @@ class multimap multimap(const multimap& x, const allocator_type &a) : base_t(static_cast<const base_t&>(x), a) { - //Allocator type must be std::pair<CONST Key, 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)); } @@ -1043,9 +1127,9 @@ class multimap //! //! <b>Postcondition</b>: x is emptied. multimap(BOOST_RV_REF(multimap) x, const allocator_type &a) - : base_t(boost::move(static_cast<base_t&>(x)), a) + : base_t(BOOST_MOVE_BASE(base_t, x), a) { - //Allocator type must be std::pair<CONST Key, 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)); } @@ -1059,7 +1143,9 @@ class multimap //! //! <b>Complexity</b>: Constant. multimap& operator=(BOOST_RV_REF(multimap) x) - { return static_cast<multimap&>(this->base_t::operator=(boost::move(static_cast<base_t&>(x)))); } + BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value + && boost::container::container_detail::is_nothrow_move_assignable<Compare>::value ) + { return static_cast<multimap&>(this->base_t::operator=(BOOST_MOVE_BASE(base_t, x))); } #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) //! <b>Effects</b>: Assign content of il to *this. @@ -1093,31 +1179,31 @@ class multimap const_iterator cbegin() const; //! @copydoc ::boost::container::set::end() - iterator end() BOOST_CONTAINER_NOEXCEPT; + iterator end() BOOST_NOEXCEPT_OR_NOTHROW; //! @copydoc ::boost::container::set::end() const - const_iterator end() const BOOST_CONTAINER_NOEXCEPT; + const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW; //! @copydoc ::boost::container::set::cend() const - const_iterator cend() const BOOST_CONTAINER_NOEXCEPT; + const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW; //! @copydoc ::boost::container::set::rbegin() - reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT; + reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW; //! @copydoc ::boost::container::set::rbegin() const - const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT; + const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW; //! @copydoc ::boost::container::set::crbegin() const - const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT; + const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW; //! @copydoc ::boost::container::set::rend() - reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT; + reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW; //! @copydoc ::boost::container::set::rend() const - const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT; + const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW; //! @copydoc ::boost::container::set::crend() const - const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT; + const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW; //! @copydoc ::boost::container::set::empty() const bool empty() const; @@ -1130,7 +1216,7 @@ class multimap #endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) - #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) //! <b>Effects</b>: Inserts an object of type T constructed with //! std::forward<Args>(args)... in the container. @@ -1142,7 +1228,7 @@ class multimap //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t //! is inserted right before p. template <class... Args> - iterator emplace(Args&&... args) + 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 T constructed with @@ -1155,26 +1241,24 @@ class multimap //! <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, Args&&... args) + iterator emplace_hint(const_iterator p, BOOST_FWD_REF(Args)... args) { return this->base_t::emplace_hint_equal(p, boost::forward<Args>(args)...); } - #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING + #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - #define BOOST_PP_LOCAL_MACRO(n) \ - BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ - iterator emplace(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ - { return this->base_t::emplace_equal(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); } \ - \ - BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ - iterator emplace_hint(const_iterator p \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ - { return this->base_t::emplace_hint_equal(p \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _));} \ - //! - #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) - #include BOOST_PP_LOCAL_ITERATE() + #define BOOST_CONTAINER_MULTIMAP_EMPLACE_CODE(N) \ + BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ + 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)\ + { return this->base_t::emplace_hint_equal(hint BOOST_MOVE_I##N BOOST_MOVE_FWD##N); }\ + // + BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_MULTIMAP_EMPLACE_CODE) + #undef BOOST_CONTAINER_MULTIMAP_EMPLACE_CODE - #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING + #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) //! <b>Effects</b>: Inserts x and returns the iterator pointing to the //! newly inserted element. @@ -1277,10 +1361,12 @@ class multimap iterator erase(const_iterator first, const_iterator last); //! @copydoc ::boost::container::set::swap - void swap(flat_multiset& x); + void swap(multiset& x) + BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value + && boost::container::container_detail::is_nothrow_swappable<Compare>::value ); //! @copydoc ::boost::container::set::clear - void clear() BOOST_CONTAINER_NOEXCEPT; + void clear() BOOST_NOEXCEPT_OR_NOTHROW; //! @copydoc ::boost::container::set::key_comp key_compare key_comp() const; @@ -1294,7 +1380,7 @@ class multimap //! <b>Complexity</b>: Logarithmic. iterator find(const key_type& x); - //! <b>Returns</b>: Allocator const iterator pointing to an element with the key + //! <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. @@ -1311,7 +1397,7 @@ class multimap //! <b>Complexity</b>: Logarithmic iterator lower_bound(const key_type& x); - //! <b>Returns</b>: Allocator const iterator pointing to the first element with key not + //! <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 @@ -1323,7 +1409,7 @@ class multimap //! <b>Complexity</b>: Logarithmic iterator upper_bound(const key_type& x); - //! <b>Returns</b>: Allocator const iterator pointing to the first element with key not + //! <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 @@ -1388,10 +1474,13 @@ class multimap //!has_trivial_destructor_after_move<> == true_type //!specialization for optimizations -template <class K, class T, class C, class Allocator> -struct has_trivial_destructor_after_move<boost::container::multimap<K, T, C, Allocator> > +template <class Key, class T, class Compare, class Allocator> +struct has_trivial_destructor_after_move<boost::container::multimap<Key, T, Compare, Allocator> > { - static const bool value = has_trivial_destructor_after_move<Allocator>::value && has_trivial_destructor_after_move<C>::value; + typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer; + static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value && + ::boost::has_trivial_destructor_after_move<pointer>::value && + ::boost::has_trivial_destructor_after_move<Compare>::value; }; namespace container { @@ -1402,5 +1491,5 @@ namespace container { #include <boost/container/detail/config_end.hpp> -#endif /* BOOST_CONTAINER_MAP_HPP */ +#endif // BOOST_CONTAINER_MAP_HPP diff --git a/boost/container/new_allocator.hpp b/boost/container/new_allocator.hpp new file mode 100644 index 0000000000..1ac15d8a25 --- /dev/null +++ b/boost/container/new_allocator.hpp @@ -0,0 +1,175 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_NEW_ALLOCATOR_HPP +#define BOOST_CONTAINER_NEW_ALLOCATOR_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> +#include <boost/container/throw_exception.hpp> +#include <cstddef> + +//!\file + +namespace boost { +namespace container { + +template<bool Value> +struct new_allocator_bool +{ static const bool value = Value; }; + +template<class T> +class new_allocator; + +//! Specialization of new_allocator for void types +template<> +class new_allocator<void> +{ + public: + typedef void value_type; + typedef void * pointer; + typedef const void* const_pointer; + //!A integral constant of type bool with value true + typedef BOOST_CONTAINER_IMPDEF(new_allocator_bool<true>) propagate_on_container_move_assignment; + //!A integral constant of type bool with value true + typedef BOOST_CONTAINER_IMPDEF(new_allocator_bool<true>) is_always_equal; + // reference-to-void members are impossible + + //!Obtains an new_allocator that allocates + //!objects of type T2 + template<class T2> + struct rebind + { + typedef new_allocator< T2> other; + }; + + //!Default constructor + //!Never throws + new_allocator() BOOST_NOEXCEPT_OR_NOTHROW + {} + + //!Constructor from other new_allocator. + //!Never throws + new_allocator(const new_allocator &) BOOST_NOEXCEPT_OR_NOTHROW + {} + + //!Constructor from related new_allocator. + //!Never throws + template<class T2> + new_allocator(const new_allocator<T2> &) BOOST_NOEXCEPT_OR_NOTHROW + {} + + //!Swaps two allocators, does nothing + //!because this new_allocator is stateless + friend void swap(new_allocator &, new_allocator &) BOOST_NOEXCEPT_OR_NOTHROW + {} + + //!An new_allocator always compares to true, as memory allocated with one + //!instance can be deallocated by another instance + friend bool operator==(const new_allocator &, const new_allocator &) BOOST_NOEXCEPT_OR_NOTHROW + { return true; } + + //!An new_allocator always compares to false, as memory allocated with one + //!instance can be deallocated by another instance + friend bool operator!=(const new_allocator &, const new_allocator &) BOOST_NOEXCEPT_OR_NOTHROW + { return false; } +}; + + +//! This class is a reduced STL-compatible allocator that allocates memory using operator new +template<class T> +class new_allocator +{ + public: + typedef T value_type; + typedef T * pointer; + typedef const T * const_pointer; + typedef T & reference; + typedef const T & const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + //!A integral constant of type bool with value true + typedef BOOST_CONTAINER_IMPDEF(new_allocator_bool<true>) propagate_on_container_move_assignment; + //!A integral constant of type bool with value true + typedef BOOST_CONTAINER_IMPDEF(new_allocator_bool<true>) is_always_equal; + + //!Obtains an new_allocator that allocates + //!objects of type T2 + template<class T2> + struct rebind + { + typedef new_allocator<T2> other; + }; + + //!Default constructor + //!Never throws + new_allocator() BOOST_NOEXCEPT_OR_NOTHROW + {} + + //!Constructor from other new_allocator. + //!Never throws + new_allocator(const new_allocator &) BOOST_NOEXCEPT_OR_NOTHROW + {} + + //!Constructor from related new_allocator. + //!Never throws + template<class T2> + new_allocator(const new_allocator<T2> &) BOOST_NOEXCEPT_OR_NOTHROW + {} + + //!Allocates memory for an array of count elements. + //!Throws std::bad_alloc if there is no enough memory + pointer allocate(size_type count) + { + if(BOOST_UNLIKELY(count > this->max_size())) + throw_bad_alloc(); + return static_cast<T*>(::operator new(count*sizeof(T))); + } + + //!Deallocates previously allocated memory. + //!Never throws + void deallocate(pointer ptr, size_type) BOOST_NOEXCEPT_OR_NOTHROW + { ::operator delete((void*)ptr); } + + //!Returns the maximum number of elements that could be allocated. + //!Never throws + size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW + { return size_type(-1)/sizeof(T); } + + //!Swaps two allocators, does nothing + //!because this new_allocator is stateless + friend void swap(new_allocator &, new_allocator &) BOOST_NOEXCEPT_OR_NOTHROW + {} + + //!An new_allocator always compares to true, as memory allocated with one + //!instance can be deallocated by another instance + friend bool operator==(const new_allocator &, const new_allocator &) BOOST_NOEXCEPT_OR_NOTHROW + { return true; } + + //!An new_allocator always compares to false, as memory allocated with one + //!instance can be deallocated by another instance + friend bool operator!=(const new_allocator &, const new_allocator &) BOOST_NOEXCEPT_OR_NOTHROW + { return false; } +}; + +} //namespace container { +} //namespace boost { + +#include <boost/container/detail/config_end.hpp> + +#endif //BOOST_CONTAINER_ALLOCATOR_HPP diff --git a/boost/container/node_allocator.hpp b/boost/container/node_allocator.hpp index 8004339eb8..afd6f98a8d 100644 --- a/boost/container/node_allocator.hpp +++ b/boost/container/node_allocator.hpp @@ -11,7 +11,11 @@ #ifndef BOOST_CONTAINER_POOLED_NODE_ALLOCATOR_HPP #define BOOST_CONTAINER_POOLED_NODE_ALLOCATOR_HPP -#if defined(_MSC_VER) && (_MSC_VER >= 1200) +#ifndef BOOST_CONFIG_HPP +# include <boost/config.hpp> +#endif + +#if defined(BOOST_HAS_PRAGMA_ONCE) # pragma once #endif @@ -26,10 +30,7 @@ #include <boost/container/detail/singleton.hpp> #include <boost/assert.hpp> -#include <boost/utility/addressof.hpp> #include <boost/static_assert.hpp> -#include <memory> -#include <algorithm> #include <cstddef> namespace boost { @@ -116,11 +117,11 @@ class node_allocator public: //!Default constructor - node_allocator() BOOST_CONTAINER_NOEXCEPT + node_allocator() BOOST_NOEXCEPT_OR_NOTHROW {} //!Copy constructor from other node_allocator. - node_allocator(const node_allocator &) BOOST_CONTAINER_NOEXCEPT + node_allocator(const node_allocator &) BOOST_NOEXCEPT_OR_NOTHROW {} //!Copy constructor from related node_allocator. @@ -130,11 +131,11 @@ class node_allocator #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED , Version #endif - > &) BOOST_CONTAINER_NOEXCEPT + > &) BOOST_NOEXCEPT_OR_NOTHROW {} //!Destructor - ~node_allocator() BOOST_CONTAINER_NOEXCEPT + ~node_allocator() BOOST_NOEXCEPT_OR_NOTHROW {} //!Returns the number of elements that could be allocated. @@ -146,7 +147,7 @@ class node_allocator //!Throws std::bad_alloc if there is no enough memory pointer allocate(size_type count, const void * = 0) { - if(count > this->max_size()) + if(BOOST_UNLIKELY(count > this->max_size())) boost::container::throw_bad_alloc(); if(Version == 1 && count == 1){ @@ -157,7 +158,7 @@ class node_allocator } else{ void *ret = boost_cont_malloc(count*sizeof(T)); - if(!ret) + if(BOOST_UNLIKELY(!ret)) boost::container::throw_bad_alloc(); return static_cast<pointer>(ret); } @@ -165,7 +166,7 @@ class node_allocator //!Deallocate allocated memory. //!Never throws - void deallocate(const pointer &ptr, size_type count) BOOST_CONTAINER_NOEXCEPT + void deallocate(const pointer &ptr, size_type count) BOOST_NOEXCEPT_OR_NOTHROW { (void)count; if(Version == 1 && count == 1){ @@ -180,7 +181,7 @@ class node_allocator } //!Deallocates all free blocks of the pool - static void deallocate_free_blocks() BOOST_CONTAINER_NOEXCEPT + static void deallocate_free_blocks() BOOST_NOEXCEPT_OR_NOTHROW { typedef container_detail::shared_node_pool <sizeof(T), NodesPerBlock> shared_pool_t; @@ -188,23 +189,19 @@ class node_allocator singleton_t::instance().deallocate_free_blocks(); } - std::pair<pointer, bool> - allocation_command(allocation_type command, - size_type limit_size, - size_type preferred_size, - size_type &received_size, pointer reuse = pointer()) + pointer allocation_command + (allocation_type command, size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse) { BOOST_STATIC_ASSERT(( Version > 1 )); - std::pair<pointer, bool> ret = - priv_allocation_command(command, limit_size, preferred_size, received_size, reuse); - if(!ret.first && !(command & BOOST_CONTAINER_NOTHROW_ALLOCATION)) + pointer ret = this->priv_allocation_command(command, limit_size, prefer_in_recvd_out_size, reuse); + if(BOOST_UNLIKELY(!ret && !(command & BOOST_CONTAINER_NOTHROW_ALLOCATION))) boost::container::throw_bad_alloc(); return ret; } //!Returns maximum the number of objects the previously allocated memory //!pointed by p can hold. - size_type size(pointer p) const BOOST_CONTAINER_NOEXCEPT + size_type size(pointer p) const BOOST_NOEXCEPT_OR_NOTHROW { BOOST_STATIC_ASSERT(( Version > 1 )); return boost_cont_size(p); @@ -238,7 +235,7 @@ class node_allocator //!Deallocates memory previously allocated with allocate_one(). //!You should never use deallocate_one to deallocate memory allocated //!with other functions different from allocate_one(). Never throws - void deallocate_one(pointer p) BOOST_CONTAINER_NOEXCEPT + void deallocate_one(pointer p) BOOST_NOEXCEPT_OR_NOTHROW { BOOST_STATIC_ASSERT(( Version > 1 )); typedef container_detail::shared_node_pool @@ -247,7 +244,7 @@ class node_allocator singleton_t::instance().deallocate_node(p); } - void deallocate_individual(multiallocation_chain &chain) BOOST_CONTAINER_NOEXCEPT + void deallocate_individual(multiallocation_chain &chain) BOOST_NOEXCEPT_OR_NOTHROW { BOOST_STATIC_ASSERT(( Version > 1 )); typedef container_detail::shared_node_pool @@ -264,7 +261,7 @@ class node_allocator BOOST_STATIC_ASSERT(( Version > 1 )); boost_cont_memchain ch; BOOST_CONTAINER_MEMCHAIN_INIT(&ch); - if(!boost_cont_multialloc_nodes(n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch)){ + if(BOOST_UNLIKELY(!boost_cont_multialloc_nodes(n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch))){ boost::container::throw_bad_alloc(); } chain.incorporate_after( chain.before_begin() @@ -280,7 +277,7 @@ class node_allocator BOOST_STATIC_ASSERT(( Version > 1 )); boost_cont_memchain ch; boost_cont_multialloc_arrays(n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch); - if(BOOST_CONTAINER_MEMCHAIN_EMPTY(&ch)){ + if(BOOST_UNLIKELY(BOOST_CONTAINER_MEMCHAIN_EMPTY(&ch))){ boost::container::throw_bad_alloc(); } chain.incorporate_after( chain.before_begin() @@ -289,7 +286,7 @@ class node_allocator , BOOST_CONTAINER_MEMCHAIN_SIZE(&ch)); } - void deallocate_many(multiallocation_chain &chain) BOOST_CONTAINER_NOEXCEPT + void deallocate_many(multiallocation_chain &chain) BOOST_NOEXCEPT_OR_NOTHROW { BOOST_STATIC_ASSERT(( Version > 1 )); void *first = &*chain.begin(); @@ -302,37 +299,40 @@ class node_allocator //!Swaps allocators. Does not throw. If each allocator is placed in a //!different memory segment, the result is undefined. - friend void swap(self_t &, self_t &) BOOST_CONTAINER_NOEXCEPT + friend void swap(self_t &, self_t &) BOOST_NOEXCEPT_OR_NOTHROW {} //!An allocator always compares to true, as memory allocated with one //!instance can be deallocated by another instance - friend bool operator==(const node_allocator &, const node_allocator &) BOOST_CONTAINER_NOEXCEPT + friend bool operator==(const node_allocator &, const node_allocator &) BOOST_NOEXCEPT_OR_NOTHROW { return true; } //!An allocator always compares to false, as memory allocated with one //!instance can be deallocated by another instance - friend bool operator!=(const node_allocator &, const node_allocator &) BOOST_CONTAINER_NOEXCEPT + friend bool operator!=(const node_allocator &, const node_allocator &) BOOST_NOEXCEPT_OR_NOTHROW { return false; } private: - std::pair<pointer, bool> priv_allocation_command + pointer priv_allocation_command (allocation_type command, std::size_t limit_size - ,std::size_t preferred_size,std::size_t &received_size, void *reuse_ptr) + ,size_type &prefer_in_recvd_out_size + ,pointer &reuse) { + std::size_t const preferred_size = prefer_in_recvd_out_size; boost_cont_command_ret_t ret = {0 , 0}; - if(limit_size > this->max_size() || preferred_size > this->max_size()){ - //ret.first = 0; - return std::pair<pointer, bool>(pointer(), false); + if((limit_size > this->max_size()) | (preferred_size > this->max_size())){ + return pointer(); } std::size_t l_size = limit_size*sizeof(T); std::size_t p_size = preferred_size*sizeof(T); std::size_t r_size; { - ret = boost_cont_allocation_command(command, sizeof(T), l_size, p_size, &r_size, reuse_ptr); + void* reuse_ptr_void = reuse; + ret = boost_cont_allocation_command(command, sizeof(T), l_size, p_size, &r_size, reuse_ptr_void); + reuse = static_cast<T*>(reuse_ptr_void); } - received_size = r_size/sizeof(T); - return std::pair<pointer, bool>(static_cast<pointer>(ret.first), !!ret.second); + prefer_in_recvd_out_size = r_size/sizeof(T); + return (pointer)ret.first; } }; diff --git a/boost/container/options.hpp b/boost/container/options.hpp index c36ad30143..da8b6a7952 100644 --- a/boost/container/options.hpp +++ b/boost/container/options.hpp @@ -13,7 +13,11 @@ #ifndef BOOST_CONTAINER_OPTIONS_HPP #define BOOST_CONTAINER_OPTIONS_HPP -#if defined(_MSC_VER) +#ifndef BOOST_CONFIG_HPP +# include <boost/config.hpp> +#endif + +#if defined(BOOST_HAS_PRAGMA_ONCE) # pragma once #endif diff --git a/boost/container/scoped_allocator.hpp b/boost/container/scoped_allocator.hpp index 0a2987194f..55514aae21 100644 --- a/boost/container/scoped_allocator.hpp +++ b/boost/container/scoped_allocator.hpp @@ -23,24 +23,31 @@ #include <boost/container/detail/config_begin.hpp> #include <boost/container/detail/workaround.hpp> -#include <boost/container/scoped_allocator_fwd.hpp> -#include <boost/type_traits/integral_constant.hpp> + #include <boost/container/allocator_traits.hpp> -#include <boost/container/detail/type_traits.hpp> -#include <boost/container/detail/utilities.hpp> -#include <utility> +#include <boost/container/scoped_allocator_fwd.hpp> + +#include <boost/container/detail/addressof.hpp> +#include <boost/container/detail/mpl.hpp> #include <boost/container/detail/pair.hpp> +#include <boost/container/detail/type_traits.hpp> + +#include <boost/move/adl_move_swap.hpp> +#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +#include <boost/move/detail/fwd_macros.hpp> +#endif #include <boost/move/utility_core.hpp> + #include <boost/core/no_exceptions_support.hpp> namespace boost { namespace container { -//! <b>Remark</b>: if a specialization is derived from true_type, indicates that T may be constructed +//! <b>Remark</b>: if a specialization constructible_with_allocator_suffix<X>::value is true, indicates that T may be constructed //! with an allocator as its last constructor argument. Ideally, all constructors of T (including the //! copy and move constructors) should have a variant that accepts a final argument of //! allocator_type. //! -//! <b>Requires</b>: if a specialization is derived from true_type, T must have a nested type, +//! <b>Requires</b>: if a specialization constructible_with_allocator_suffix<X>::value is true, T must have a nested type, //! allocator_type and at least one constructor for which allocator_type is the last //! parameter. If not all constructors of T can be called with a final allocator_type argument, //! and if T is used in a context where a container must call such a constructor, then the program is @@ -63,10 +70,10 @@ namespace boost { namespace container { //! // Specialize trait for class template Z //! template <class T, class Allocator = allocator<T> > //! struct constructible_with_allocator_suffix<Z<T,Allocator> > -//! : ::boost::true_type { }; +//! { static const bool value = true; }; //! </code> //! -//! <b>Note</b>: This trait is a workaround inspired by "N2554: The Scoped Allocator Model (Rev 2)" +//! <b>Note</b>: This trait is a workaround inspired by "N2554: The Scoped A Model (Rev 2)" //! (Pablo Halpern, 2008-02-29) to backport the scoped allocator model to C++03, as //! in C++03 there is no mechanism to detect if a type can be constructed from arbitrary arguments. //! Applications aiming portability with several compilers should always define this trait. @@ -76,15 +83,14 @@ namespace boost { namespace container { //! to detect if a type should be constructed with suffix or prefix allocator arguments. template <class T> struct constructible_with_allocator_suffix - : ::boost::false_type -{}; +{ static const bool value = false; }; -//! <b>Remark</b>: if a specialization is derived from true_type, indicates that T may be constructed +//! <b>Remark</b>: if a specialization constructible_with_allocator_prefix<X>::value is true, indicates that T may be constructed //! with allocator_arg and T::allocator_type as its first two constructor arguments. //! Ideally, all constructors of T (including the copy and move constructors) should have a variant //! that accepts these two initial arguments. //! -//! <b>Requires</b>: if a specialization is derived from true_type, T must have a nested type, +//! <b>Requires</b>: specialization constructible_with_allocator_prefix<X>::value is true, T must have a nested type, //! allocator_type and at least one constructor for which allocator_arg_t is the first //! parameter and allocator_type is the second parameter. If not all constructors of T can be //! called with these initial arguments, and if T is used in a context where a container must call such @@ -107,13 +113,13 @@ struct constructible_with_allocator_suffix //! // Variadic constructor and allocator-extended variadic constructor //! template<class ...Args> Y(Args&& args...); //! template<class ...Args> -//! Y(allocator_arg_t, const allocator_type& a, Args&&... args); +//! Y(allocator_arg_t, const allocator_type& a, BOOST_FWD_REF(Args)... args); //! }; //! //! // Specialize trait for class template Y //! template <class T, class Allocator = allocator<T> > //! struct constructible_with_allocator_prefix<Y<T,Allocator> > -//! : ::boost::true_type { }; +//! { static const bool value = true; }; //! //! </code> //! @@ -127,34 +133,34 @@ struct constructible_with_allocator_suffix //! to detect if a type should be constructed with suffix or prefix allocator arguments. template <class T> struct constructible_with_allocator_prefix - : ::boost::false_type -{}; +{ static const bool value = false; }; #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED namespace container_detail { -template<typename T, typename Alloc> +template<typename T, typename Allocator> struct uses_allocator_imp { // Use SFINAE (Substitution Failure Is Not An Error) to detect the - // presence of an 'allocator_type' nested type convertilble from Alloc. - + // presence of an 'allocator_type' nested type convertilble from Allocator. private: + typedef char yes_type; + struct no_type{ char dummy[2]; }; + // Match this function if TypeT::allocator_type exists and is - // implicitly convertible from Alloc - template <typename U> - static char test(int, typename U::allocator_type); + // implicitly convertible from Allocator + template <class U> + static yes_type test(typename U::allocator_type); // Match this function if TypeT::allocator_type does not exist or is - // not convertible from Alloc. + // not convertible from Allocator. template <typename U> - static int test(LowPriorityConversion<int>, LowPriorityConversion<Alloc>); - - static Alloc alloc; // Declared but not defined + static no_type test(...); + static Allocator alloc; // Declared but not defined public: - enum { value = sizeof(test<T>(0, alloc)) == sizeof(char) }; + static const bool value = sizeof(test<T>(alloc)) == sizeof(yes_type); }; } //namespace container_detail { @@ -162,31 +168,34 @@ struct uses_allocator_imp #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED //! <b>Remark</b>: Automatically detects if T has a nested allocator_type that is convertible from -//! Alloc. Meets the BinaryTypeTrait requirements ([meta.rqmts] 20.4.1). A program may -//! specialize this type to derive from true_type for a T of user-defined type if T does not -//! have a nested allocator_type but is nonetheless constructible using the specified Alloc. +//! Allocator. Meets the BinaryTypeTrait requirements ([meta.rqmts] 20.4.1). A program may +//! specialize this type to define uses_allocator<X>::value as true for a T of user-defined type if T does not +//! have a nested allocator_type but is nonetheless constructible using the specified Allocator. //! -//! <b>Result</b>: derived from true_type if Convertible<Alloc,T::allocator_type> and -//! derived from false_type otherwise. -template <typename T, typename Alloc> +//! <b>Result</b>: uses_allocator<T, Allocator>::value== true if Convertible<Allocator,T::allocator_type>, +//! false otherwise. +template <typename T, typename Allocator> struct uses_allocator - : boost::integral_constant<bool, container_detail::uses_allocator_imp<T, Alloc>::value> + : container_detail::uses_allocator_imp<T, Allocator> {}; #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED namespace container_detail { -template <typename Alloc> +template <typename Allocator> struct is_scoped_allocator_imp { + typedef char yes_type; + struct no_type{ char dummy[2]; }; + template <typename T> - static char test(int, typename T::outer_allocator_type*); + static yes_type test(typename T::outer_allocator_type*); template <typename T> - static int test(LowPriorityConversion<int>, void*); + static int test(...); - static const bool value = (sizeof(char) == sizeof(test<Alloc>(0, 0))); + static const bool value = (sizeof(yes_type) == sizeof(test<Allocator>(0))); }; template<class MaybeScopedAlloc, bool = is_scoped_allocator_imp<MaybeScopedAlloc>::value > @@ -229,40 +238,38 @@ struct outermost_allocator_imp<MaybeScopedAlloc, true> } //namespace container_detail { -template <typename Alloc> +template <typename Allocator> struct is_scoped_allocator - : boost::integral_constant<bool, container_detail::is_scoped_allocator_imp<Alloc>::value> + : container_detail::is_scoped_allocator_imp<Allocator> {}; -template <typename Alloc> +template <typename Allocator> struct outermost_allocator - : container_detail::outermost_allocator_imp<Alloc> + : container_detail::outermost_allocator_imp<Allocator> {}; -template <typename Alloc> -typename container_detail::outermost_allocator_imp<Alloc>::type & - get_outermost_allocator(Alloc &a) -{ return container_detail::outermost_allocator_imp<Alloc>::get(a); } +template <typename Allocator> +typename container_detail::outermost_allocator_imp<Allocator>::type & + get_outermost_allocator(Allocator &a) +{ return container_detail::outermost_allocator_imp<Allocator>::get(a); } -template <typename Alloc> -const typename container_detail::outermost_allocator_imp<Alloc>::type & - get_outermost_allocator(const Alloc &a) -{ return container_detail::outermost_allocator_imp<Alloc>::get(a); } +template <typename Allocator> +const typename container_detail::outermost_allocator_imp<Allocator>::type & + get_outermost_allocator(const Allocator &a) +{ return container_detail::outermost_allocator_imp<Allocator>::get(a); } namespace container_detail { // Check if we can detect is_convertible using advanced SFINAE expressions -#if !defined(BOOST_NO_SFINAE_EXPR) +#if !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) //! Code inspired by Mathias Gaunard's is_convertible.cpp found in the Boost mailing list //! http://boost.2283326.n4.nabble.com/type-traits-is-constructible-when-decltype-is-supported-td3575452.html //! Thanks Mathias! //With variadic templates, we need a single class to implement the trait - #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - template<class T, class ...Args> - struct is_constructible_impl + struct is_constructible { typedef char yes_type; struct no_type @@ -272,7 +279,7 @@ namespace container_detail { struct dummy; template<class X> - static yes_type test(dummy<sizeof(X(boost::move_detail::declval<Args>()...))>*); + static decltype(X(boost::move_detail::declval<Args>()...), true_type()) test(int); template<class X> static no_type test(...); @@ -280,148 +287,39 @@ namespace container_detail { static const bool value = sizeof(test<T>(0)) == sizeof(yes_type); }; - template<class T, class ...Args> - struct is_constructible - : boost::integral_constant<bool, is_constructible_impl<T, Args...>::value> - {}; - template <class T, class InnerAlloc, class ...Args> struct is_constructible_with_allocator_prefix : is_constructible<T, allocator_arg_t, InnerAlloc, Args...> {}; - #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - - //Without variadic templates, we need to use the preprocessor to generate - //some specializations. - - #define BOOST_CONTAINER_MAX_IS_CONSTRUCTIBLE_PARAMETERS \ - BOOST_PP_ADD(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, 3) - //! - - //Generate N+1 template parameters so that we can specialize N - template<class T - BOOST_PP_ENUM_TRAILING( BOOST_PP_ADD(BOOST_CONTAINER_MAX_IS_CONSTRUCTIBLE_PARAMETERS, 1) - , BOOST_CONTAINER_PP_TEMPLATE_PARAM_WITH_DEFAULT - , void) - > - struct is_constructible_impl; - - //Generate N specializations, from 0 to - //BOOST_CONTAINER_MAX_IS_CONSTRUCTIBLE_PARAMETERS parameters - #define BOOST_PP_LOCAL_MACRO(n) \ - template<class T BOOST_PP_ENUM_TRAILING_PARAMS(n, class P)> \ - struct is_constructible_impl \ - <T BOOST_PP_ENUM_TRAILING_PARAMS(n, P) \ - BOOST_PP_ENUM_TRAILING \ - ( BOOST_PP_SUB(BOOST_CONTAINER_MAX_IS_CONSTRUCTIBLE_PARAMETERS, n) \ - , BOOST_CONTAINER_PP_IDENTITY, void) \ - , void> \ - { \ - typedef char yes_type; \ - struct no_type \ - { char padding[2]; }; \ - \ - template<std::size_t N> \ - struct dummy; \ - \ - template<class X> \ - static yes_type test(dummy<sizeof(X(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_DECLVAL, ~)))>*); \ - \ - template<class X> \ - static no_type test(...); \ - \ - static const bool value = sizeof(test<T>(0)) == sizeof(yes_type); \ - }; \ - //! - - #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_IS_CONSTRUCTIBLE_PARAMETERS) - #include BOOST_PP_LOCAL_ITERATE() - - //Finally just inherit from the implementation to define he trait - template< class T - BOOST_PP_ENUM_TRAILING( BOOST_CONTAINER_MAX_IS_CONSTRUCTIBLE_PARAMETERS - , BOOST_CONTAINER_PP_TEMPLATE_PARAM_WITH_DEFAULT - , void) - > - struct is_constructible - : boost::integral_constant - < bool - , is_constructible_impl - < T - BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_IS_CONSTRUCTIBLE_PARAMETERS, P) - , void>::value - > - {}; - - //Finally just inherit from the implementation to define he trait - template <class T - ,class InnerAlloc - BOOST_PP_ENUM_TRAILING( BOOST_PP_SUB(BOOST_CONTAINER_MAX_IS_CONSTRUCTIBLE_PARAMETERS, 2) - , BOOST_CONTAINER_PP_TEMPLATE_PARAM_WITH_DEFAULT - , void) - > - struct is_constructible_with_allocator_prefix - : is_constructible - < T, allocator_arg_t, InnerAlloc - BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_SUB(BOOST_CONTAINER_MAX_IS_CONSTRUCTIBLE_PARAMETERS, 2), P) - > - {}; -/* - template <class T - ,class InnerAlloc - BOOST_PP_ENUM_TRAILING( BOOST_PP_SUB(BOOST_CONTAINER_MAX_IS_CONSTRUCTIBLE_PARAMETERS, 1) - , BOOST_CONTAINER_PP_TEMPLATE_PARAM_WITH_DEFAULT - , void) - > - struct is_constructible_with_allocator_suffix - : is_constructible - < T - BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_SUB(BOOST_CONTAINER_MAX_IS_CONSTRUCTIBLE_PARAMETERS, 1), P) - , InnerAlloc - > - {};*/ - - #endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - -#else // #if !defined(BOOST_NO_SFINAE_EXPR) +#else // #if !defined(BOOST_NO_SFINAE_EXPR) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) //Without advanced SFINAE expressions, we can't use is_constructible //so backup to constructible_with_allocator_xxx #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - template < class T, class InnerAlloc, class ...Args> + template <class T, class InnerAlloc, class ...Args> struct is_constructible_with_allocator_prefix : constructible_with_allocator_prefix<T> {}; -/* - template < class T, class InnerAlloc, class ...Args> + + template <class T, class InnerAlloc, class ...Args> struct is_constructible_with_allocator_suffix : constructible_with_allocator_suffix<T> - {};*/ + {}; #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - template < class T - , class InnerAlloc - BOOST_PP_ENUM_TRAILING( BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS - , BOOST_CONTAINER_PP_TEMPLATE_PARAM_WITH_DEFAULT - , void) - > + template <class T, class InnerAlloc, BOOST_MOVE_CLASSDFLT9> struct is_constructible_with_allocator_prefix : constructible_with_allocator_prefix<T> {}; -/* - template < class T - , class InnerAlloc - BOOST_PP_ENUM_TRAILING( BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS - , BOOST_CONTAINER_PP_TEMPLATE_PARAM_WITH_DEFAULT - , void) - > + + template <class T, class InnerAlloc, BOOST_MOVE_CLASSDFLT9> struct is_constructible_with_allocator_suffix : constructible_with_allocator_suffix<T> - {};*/ + {}; #endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) @@ -429,13 +327,14 @@ namespace container_detail { #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +// allocator_arg_t template < typename OutermostAlloc , typename InnerAlloc , typename T , class ...Args > inline void dispatch_allocator_prefix_suffix - ( boost::true_type use_alloc_prefix, OutermostAlloc& outermost_alloc + ( true_type use_alloc_prefix, OutermostAlloc& outermost_alloc , InnerAlloc& inner_alloc, T* p, BOOST_FWD_REF(Args) ...args) { (void)use_alloc_prefix; @@ -443,13 +342,14 @@ inline void dispatch_allocator_prefix_suffix ( outermost_alloc, p, allocator_arg, inner_alloc, ::boost::forward<Args>(args)...); } +// allocator suffix template < typename OutermostAlloc , typename InnerAlloc , typename T , class ...Args > inline void dispatch_allocator_prefix_suffix - ( boost::false_type use_alloc_prefix, OutermostAlloc& outermost_alloc + ( false_type use_alloc_prefix, OutermostAlloc& outermost_alloc , InnerAlloc &inner_alloc, T* p, BOOST_FWD_REF(Args)...args) { (void)use_alloc_prefix; @@ -463,14 +363,14 @@ template < typename OutermostAlloc , class ...Args > inline void dispatch_uses_allocator - ( boost::true_type uses_allocator, OutermostAlloc& outermost_alloc + ( true_type uses_allocator, OutermostAlloc& outermost_alloc , InnerAlloc& inner_alloc, T* p, BOOST_FWD_REF(Args)...args) { (void)uses_allocator; //BOOST_STATIC_ASSERT((is_constructible_with_allocator_prefix<T, InnerAlloc, Args...>::value || // is_constructible_with_allocator_suffix<T, InnerAlloc, Args...>::value )); dispatch_allocator_prefix_suffix - ( is_constructible_with_allocator_prefix<T, InnerAlloc, Args...>() + ( bool_< is_constructible_with_allocator_prefix<T, InnerAlloc, Args...>::value>() , outermost_alloc, inner_alloc, p, ::boost::forward<Args>(args)...); } @@ -480,7 +380,7 @@ template < typename OutermostAlloc , class ...Args > inline void dispatch_uses_allocator - ( boost::false_type uses_allocator, OutermostAlloc & outermost_alloc + ( false_type uses_allocator, OutermostAlloc & outermost_alloc , InnerAlloc & inner_alloc ,T* p, BOOST_FWD_REF(Args)...args) { @@ -491,78 +391,53 @@ inline void dispatch_uses_allocator #else //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) -#define BOOST_PP_LOCAL_MACRO(n) \ -template < typename OutermostAlloc \ - , typename InnerAlloc \ - , typename T \ - BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) \ - > \ -inline void dispatch_allocator_prefix_suffix( \ - boost::true_type use_alloc_prefix, \ - OutermostAlloc& outermost_alloc, \ - InnerAlloc& inner_alloc, \ - T* p \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ -{ \ - (void)use_alloc_prefix, \ - allocator_traits<OutermostAlloc>::construct \ - (outermost_alloc, p, allocator_arg, inner_alloc \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \ -} \ - \ -template < typename OutermostAlloc \ - , typename InnerAlloc \ - , typename T \ - BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) \ - > \ -inline void dispatch_allocator_prefix_suffix( \ - boost::false_type use_alloc_prefix, \ - OutermostAlloc& outermost_alloc, \ - InnerAlloc& inner_alloc, \ - T* p BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ -{ \ - (void)use_alloc_prefix; \ - allocator_traits<OutermostAlloc>::construct \ - (outermost_alloc, p \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) \ - , inner_alloc); \ -} \ - \ -template < typename OutermostAlloc \ - , typename InnerAlloc \ - , typename T \ - BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) \ - > \ -inline void dispatch_uses_allocator(boost::true_type uses_allocator, \ - OutermostAlloc& outermost_alloc, \ - InnerAlloc& inner_alloc, \ - T* p BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ -{ \ - (void)uses_allocator; \ - dispatch_allocator_prefix_suffix \ - (is_constructible_with_allocator_prefix \ - < T, InnerAlloc BOOST_PP_ENUM_TRAILING_PARAMS(n, P)>() \ - , outermost_alloc, inner_alloc, p \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \ -} \ - \ -template < typename OutermostAlloc \ - , typename InnerAlloc \ - , typename T \ - BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) \ - > \ -inline void dispatch_uses_allocator(boost::false_type uses_allocator \ - ,OutermostAlloc & outermost_alloc \ - ,InnerAlloc & inner_alloc \ - ,T* p BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ -{ \ - (void)uses_allocator; (void)inner_alloc; \ - allocator_traits<OutermostAlloc>::construct \ - (outermost_alloc, p BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \ -} \ -//! -#define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) -#include BOOST_PP_LOCAL_ITERATE() +#define BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE(N) \ +template < typename OutermostAlloc, typename InnerAlloc, typename T\ + BOOST_MOVE_I##N BOOST_MOVE_CLASS##N > \ +inline void dispatch_allocator_prefix_suffix\ + (true_type use_alloc_prefix, OutermostAlloc& outermost_alloc,\ + InnerAlloc& inner_alloc, T* p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ +{\ + (void)use_alloc_prefix,\ + allocator_traits<OutermostAlloc>::construct\ + (outermost_alloc, p, allocator_arg, inner_alloc BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\ +}\ +\ +template < typename OutermostAlloc, typename InnerAlloc, typename T\ + BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\ +inline void dispatch_allocator_prefix_suffix\ + (false_type use_alloc_prefix, OutermostAlloc& outermost_alloc,\ + InnerAlloc& inner_alloc, T* p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ +{\ + (void)use_alloc_prefix;\ + allocator_traits<OutermostAlloc>::construct\ + (outermost_alloc, p BOOST_MOVE_I##N BOOST_MOVE_FWD##N, inner_alloc);\ +}\ +\ +template < typename OutermostAlloc, typename InnerAlloc, typename T\ + BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\ +inline void dispatch_uses_allocator\ + (true_type uses_allocator, OutermostAlloc& outermost_alloc,\ + InnerAlloc& inner_alloc, T* p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ +{\ + (void)uses_allocator;\ + dispatch_allocator_prefix_suffix\ + ( bool_< is_constructible_with_allocator_prefix<T, InnerAlloc BOOST_MOVE_I##N BOOST_MOVE_TARG##N>::value >()\ + , outermost_alloc, inner_alloc, p BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\ +}\ +\ +template < typename OutermostAlloc, typename InnerAlloc, typename T\ + BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\ +inline void dispatch_uses_allocator\ + (false_type uses_allocator, OutermostAlloc &outermost_alloc,\ + InnerAlloc &inner_alloc, T* p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ +{\ + (void)uses_allocator; (void)inner_alloc;\ + allocator_traits<OutermostAlloc>::construct(outermost_alloc, p BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\ +}\ +// +BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE) +#undef BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE #endif //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) @@ -587,21 +462,22 @@ class scoped_allocator_adaptor_base typedef allocator_traits<inner_allocator_type> inner_traits_type; typedef scoped_allocator_adaptor <OuterAlloc, InnerAllocs...> scoped_allocator_type; - typedef boost::integral_constant< - bool, + typedef container_detail::bool_< outer_traits_type::propagate_on_container_copy_assignment::value || inner_allocator_type::propagate_on_container_copy_assignment::value > propagate_on_container_copy_assignment; - typedef boost::integral_constant< - bool, + typedef container_detail::bool_< outer_traits_type::propagate_on_container_move_assignment::value || inner_allocator_type::propagate_on_container_move_assignment::value > propagate_on_container_move_assignment; - typedef boost::integral_constant< - bool, + typedef container_detail::bool_< outer_traits_type::propagate_on_container_swap::value || inner_allocator_type::propagate_on_container_swap::value > propagate_on_container_swap; + typedef container_detail::bool_< + outer_traits_type::is_always_equal::value && + inner_allocator_type::is_always_equal::value + > is_always_equal; scoped_allocator_adaptor_base() {} @@ -668,23 +544,23 @@ class scoped_allocator_adaptor_base void swap(scoped_allocator_adaptor_base &r) { - boost::container::swap_dispatch(this->outer_allocator(), r.outer_allocator()); - boost::container::swap_dispatch(this->m_inner, r.inner_allocator()); + boost::adl_move_swap(this->outer_allocator(), r.outer_allocator()); + boost::adl_move_swap(this->m_inner, r.inner_allocator()); } friend void swap(scoped_allocator_adaptor_base &l, scoped_allocator_adaptor_base &r) { l.swap(r); } - inner_allocator_type& inner_allocator() BOOST_CONTAINER_NOEXCEPT + inner_allocator_type& inner_allocator() BOOST_NOEXCEPT_OR_NOTHROW { return m_inner; } - inner_allocator_type const& inner_allocator() const BOOST_CONTAINER_NOEXCEPT + inner_allocator_type const& inner_allocator() const BOOST_NOEXCEPT_OR_NOTHROW { return m_inner; } - outer_allocator_type & outer_allocator() BOOST_CONTAINER_NOEXCEPT + outer_allocator_type & outer_allocator() BOOST_NOEXCEPT_OR_NOTHROW { return static_cast<outer_allocator_type&>(*this); } - const outer_allocator_type &outer_allocator() const BOOST_CONTAINER_NOEXCEPT + const outer_allocator_type &outer_allocator() const BOOST_NOEXCEPT_OR_NOTHROW { return static_cast<const outer_allocator_type&>(*this); } scoped_allocator_type select_on_container_copy_construction() const @@ -704,186 +580,157 @@ class scoped_allocator_adaptor_base //Let's add a dummy first template parameter to allow creating //specializations up to maximum InnerAlloc count -template < - typename OuterAlloc - , bool Dummy - BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, class Q) - > +template <typename OuterAlloc, bool Dummy, BOOST_MOVE_CLASSDFLT9> class scoped_allocator_adaptor_base; //Specializations for the adaptor with InnerAlloc allocators -#define BOOST_PP_LOCAL_MACRO(n) \ -template <typename OuterAlloc \ -BOOST_PP_ENUM_TRAILING_PARAMS(n, class Q) \ -> \ -class scoped_allocator_adaptor_base<OuterAlloc, true \ - BOOST_PP_ENUM_TRAILING_PARAMS(n, Q) \ - BOOST_PP_ENUM_TRAILING( BOOST_PP_SUB(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, n) \ - , BOOST_CONTAINER_PP_IDENTITY, nat) \ - > \ - : public OuterAlloc \ -{ \ - typedef allocator_traits<OuterAlloc> outer_traits_type; \ - BOOST_COPYABLE_AND_MOVABLE(scoped_allocator_adaptor_base) \ - \ - public: \ - template <class OuterA2> \ - struct rebind_base \ - { \ - typedef scoped_allocator_adaptor_base<OuterA2, true BOOST_PP_ENUM_TRAILING_PARAMS(n, Q) \ - BOOST_PP_ENUM_TRAILING \ - ( BOOST_PP_SUB(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, n) \ - , BOOST_CONTAINER_PP_IDENTITY, nat) \ - > other; \ - }; \ - \ - typedef OuterAlloc outer_allocator_type; \ - typedef scoped_allocator_adaptor<BOOST_PP_ENUM_PARAMS(n, Q) \ - BOOST_PP_ENUM_TRAILING \ - ( BOOST_PP_SUB(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, n) \ - , BOOST_CONTAINER_PP_IDENTITY, nat) \ - > inner_allocator_type; \ - typedef scoped_allocator_adaptor<OuterAlloc, BOOST_PP_ENUM_PARAMS(n, Q) \ - BOOST_PP_ENUM_TRAILING \ - ( BOOST_PP_SUB(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, n) \ - , BOOST_CONTAINER_PP_IDENTITY, nat) \ - > scoped_allocator_type; \ - typedef allocator_traits<inner_allocator_type> inner_traits_type; \ - typedef boost::integral_constant< \ - bool, \ - outer_traits_type::propagate_on_container_copy_assignment::value || \ - inner_allocator_type::propagate_on_container_copy_assignment::value \ - > propagate_on_container_copy_assignment; \ - typedef boost::integral_constant< \ - bool, \ - outer_traits_type::propagate_on_container_move_assignment::value || \ - inner_allocator_type::propagate_on_container_move_assignment::value \ - > propagate_on_container_move_assignment; \ - typedef boost::integral_constant< \ - bool, \ - outer_traits_type::propagate_on_container_swap::value || \ - inner_allocator_type::propagate_on_container_swap::value \ - > propagate_on_container_swap; \ - \ - scoped_allocator_adaptor_base() \ - {} \ - \ - template <class OuterA2> \ - scoped_allocator_adaptor_base(BOOST_FWD_REF(OuterA2) outerAlloc \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_CONST_REF_PARAM_LIST_Q, _)) \ - : outer_allocator_type(::boost::forward<OuterA2>(outerAlloc)) \ - , m_inner(BOOST_PP_ENUM_PARAMS(n, q)) \ - {} \ - \ - scoped_allocator_adaptor_base(const scoped_allocator_adaptor_base& other) \ - : outer_allocator_type(other.outer_allocator()) \ - , m_inner(other.inner_allocator()) \ - {} \ - \ - scoped_allocator_adaptor_base(BOOST_RV_REF(scoped_allocator_adaptor_base) other) \ - : outer_allocator_type(::boost::move(other.outer_allocator())) \ - , m_inner(::boost::move(other.inner_allocator())) \ - {} \ - \ - template <class OuterA2> \ - scoped_allocator_adaptor_base(const scoped_allocator_adaptor_base<OuterA2, true \ - BOOST_PP_ENUM_TRAILING_PARAMS(n, Q) \ - BOOST_PP_ENUM_TRAILING \ - ( BOOST_PP_SUB(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, n) \ - , BOOST_CONTAINER_PP_IDENTITY, nat) \ - >& other) \ - : outer_allocator_type(other.outer_allocator()) \ - , m_inner(other.inner_allocator()) \ - {} \ - \ - template <class OuterA2> \ - scoped_allocator_adaptor_base \ - (BOOST_RV_REF_BEG scoped_allocator_adaptor_base<OuterA2, true \ - BOOST_PP_ENUM_TRAILING_PARAMS(n, Q) \ - BOOST_PP_ENUM_TRAILING \ - ( BOOST_PP_SUB(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, n) \ - , BOOST_CONTAINER_PP_IDENTITY, nat) \ - > BOOST_RV_REF_END other) \ - : outer_allocator_type(other.outer_allocator()) \ - , m_inner(other.inner_allocator()) \ - {} \ - \ - public: \ - struct internal_type_t{}; \ - \ - template <class OuterA2> \ - scoped_allocator_adaptor_base \ - ( internal_type_t \ - , BOOST_FWD_REF(OuterA2) outerAlloc \ - , const inner_allocator_type &inner) \ - : outer_allocator_type(::boost::forward<OuterA2>(outerAlloc)) \ - , m_inner(inner) \ - {} \ - \ - public: \ - scoped_allocator_adaptor_base &operator= \ - (BOOST_COPY_ASSIGN_REF(scoped_allocator_adaptor_base) other) \ - { \ - outer_allocator_type::operator=(other.outer_allocator()); \ - m_inner = other.inner_allocator(); \ - return *this; \ - } \ - \ - scoped_allocator_adaptor_base &operator=(BOOST_RV_REF(scoped_allocator_adaptor_base) other) \ - { \ - outer_allocator_type::operator=(boost::move(other.outer_allocator())); \ - m_inner = ::boost::move(other.inner_allocator()); \ - return *this; \ - } \ - \ - void swap(scoped_allocator_adaptor_base &r) \ - { \ - boost::container::swap_dispatch(this->outer_allocator(), r.outer_allocator()); \ - boost::container::swap_dispatch(this->m_inner, r.inner_allocator()); \ - } \ - \ - friend void swap(scoped_allocator_adaptor_base &l, scoped_allocator_adaptor_base &r) \ - { l.swap(r); } \ - \ - inner_allocator_type& inner_allocator() \ - { return m_inner; } \ - \ - inner_allocator_type const& inner_allocator() const \ - { return m_inner; } \ - \ - outer_allocator_type & outer_allocator() \ - { return static_cast<outer_allocator_type&>(*this); } \ - \ - const outer_allocator_type &outer_allocator() const \ - { return static_cast<const outer_allocator_type&>(*this); } \ - \ - scoped_allocator_type select_on_container_copy_construction() const \ - { \ - return scoped_allocator_type \ - (internal_type_t() \ - ,outer_traits_type::select_on_container_copy_construction(this->outer_allocator()) \ - ,inner_traits_type::select_on_container_copy_construction(this->inner_allocator()) \ - ); \ - } \ - private: \ - inner_allocator_type m_inner; \ -}; \ +#define BOOST_CONTAINER_SCOPED_ALLOCATOR_ADAPTOR_BASE_CODE(N)\ +template <typename OuterAlloc BOOST_MOVE_I##N BOOST_MOVE_CLASS##N>\ +class scoped_allocator_adaptor_base<OuterAlloc, true, BOOST_MOVE_TARG##N>\ + : public OuterAlloc\ +{\ + typedef allocator_traits<OuterAlloc> outer_traits_type;\ + BOOST_COPYABLE_AND_MOVABLE(scoped_allocator_adaptor_base)\ + \ + public:\ + template <class OuterA2>\ + struct rebind_base\ + {\ + typedef scoped_allocator_adaptor_base<OuterA2, true, BOOST_MOVE_TARG##N> other;\ + };\ + \ + typedef OuterAlloc outer_allocator_type;\ + typedef scoped_allocator_adaptor<BOOST_MOVE_TARG##N> inner_allocator_type;\ + typedef scoped_allocator_adaptor<OuterAlloc, BOOST_MOVE_TARG##N> scoped_allocator_type;\ + typedef allocator_traits<inner_allocator_type> inner_traits_type;\ + typedef container_detail::bool_<\ + outer_traits_type::propagate_on_container_copy_assignment::value ||\ + inner_allocator_type::propagate_on_container_copy_assignment::value\ + > propagate_on_container_copy_assignment;\ + typedef container_detail::bool_<\ + outer_traits_type::propagate_on_container_move_assignment::value ||\ + inner_allocator_type::propagate_on_container_move_assignment::value\ + > propagate_on_container_move_assignment;\ + typedef container_detail::bool_<\ + outer_traits_type::propagate_on_container_swap::value ||\ + inner_allocator_type::propagate_on_container_swap::value\ + > propagate_on_container_swap;\ + \ + typedef container_detail::bool_<\ + outer_traits_type::is_always_equal::value &&\ + inner_allocator_type::is_always_equal::value\ + > is_always_equal;\ + \ + scoped_allocator_adaptor_base(){}\ + \ + template <class OuterA2>\ + scoped_allocator_adaptor_base(BOOST_FWD_REF(OuterA2) outerAlloc, BOOST_MOVE_CREF##N)\ + : outer_allocator_type(::boost::forward<OuterA2>(outerAlloc))\ + , m_inner(BOOST_MOVE_ARG##N)\ + {}\ + \ + scoped_allocator_adaptor_base(const scoped_allocator_adaptor_base& other)\ + : outer_allocator_type(other.outer_allocator())\ + , m_inner(other.inner_allocator())\ + {}\ + \ + scoped_allocator_adaptor_base(BOOST_RV_REF(scoped_allocator_adaptor_base) other)\ + : outer_allocator_type(::boost::move(other.outer_allocator()))\ + , m_inner(::boost::move(other.inner_allocator()))\ + {}\ + \ + template <class OuterA2>\ + scoped_allocator_adaptor_base\ + (const scoped_allocator_adaptor_base<OuterA2, true, BOOST_MOVE_TARG##N>& other)\ + : outer_allocator_type(other.outer_allocator())\ + , m_inner(other.inner_allocator())\ + {}\ + \ + template <class OuterA2>\ + scoped_allocator_adaptor_base\ + (BOOST_RV_REF_BEG scoped_allocator_adaptor_base<OuterA2, true, BOOST_MOVE_TARG##N> BOOST_RV_REF_END other)\ + : outer_allocator_type(other.outer_allocator())\ + , m_inner(other.inner_allocator())\ + {}\ + \ + public:\ + struct internal_type_t{};\ + \ + template <class OuterA2>\ + scoped_allocator_adaptor_base\ + ( internal_type_t, BOOST_FWD_REF(OuterA2) outerAlloc, const inner_allocator_type &inner)\ + : outer_allocator_type(::boost::forward<OuterA2>(outerAlloc))\ + , m_inner(inner)\ + {}\ + \ + public:\ + scoped_allocator_adaptor_base &operator=\ + (BOOST_COPY_ASSIGN_REF(scoped_allocator_adaptor_base) other)\ + {\ + outer_allocator_type::operator=(other.outer_allocator());\ + m_inner = other.inner_allocator();\ + return *this;\ + }\ + \ + scoped_allocator_adaptor_base &operator=(BOOST_RV_REF(scoped_allocator_adaptor_base) other)\ + {\ + outer_allocator_type::operator=(boost::move(other.outer_allocator()));\ + m_inner = ::boost::move(other.inner_allocator());\ + return *this;\ + }\ + \ + void swap(scoped_allocator_adaptor_base &r)\ + {\ + boost::adl_move_swap(this->outer_allocator(), r.outer_allocator());\ + boost::adl_move_swap(this->m_inner, r.inner_allocator());\ + }\ + \ + friend void swap(scoped_allocator_adaptor_base &l, scoped_allocator_adaptor_base &r)\ + { l.swap(r); }\ + \ + inner_allocator_type& inner_allocator()\ + { return m_inner; }\ + \ + inner_allocator_type const& inner_allocator() const\ + { return m_inner; }\ + \ + outer_allocator_type & outer_allocator()\ + { return static_cast<outer_allocator_type&>(*this); }\ + \ + const outer_allocator_type &outer_allocator() const\ + { return static_cast<const outer_allocator_type&>(*this); }\ + \ + scoped_allocator_type select_on_container_copy_construction() const\ + {\ + return scoped_allocator_type\ + (internal_type_t()\ + ,outer_traits_type::select_on_container_copy_construction(this->outer_allocator())\ + ,inner_traits_type::select_on_container_copy_construction(this->inner_allocator())\ + );\ + }\ + private:\ + inner_allocator_type m_inner;\ +};\ //! -#define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) -#include BOOST_PP_LOCAL_ITERATE() +BOOST_MOVE_ITERATE_1TO9(BOOST_CONTAINER_SCOPED_ALLOCATOR_ADAPTOR_BASE_CODE) +#undef BOOST_CONTAINER_SCOPED_ALLOCATOR_ADAPTOR_BASE_CODE #endif //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + #define BOOST_CONTAINER_SCOPEDALLOC_DUMMYTRUE ,true + #define BOOST_CONTAINER_SCOPEDALLOC_ALLINNER BOOST_MOVE_TARG9 + #define BOOST_CONTAINER_SCOPEDALLOC_ALLINNERCLASS BOOST_MOVE_CLASS9 +#else + #define BOOST_CONTAINER_SCOPEDALLOC_DUMMYTRUE + #define BOOST_CONTAINER_SCOPEDALLOC_ALLINNER InnerAllocs... + #define BOOST_CONTAINER_SCOPEDALLOC_ALLINNERCLASS typename... InnerAllocs +#endif + //Specialization for adaptor without any InnerAlloc template <typename OuterAlloc> -class scoped_allocator_adaptor_base - < OuterAlloc - #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - , true - BOOST_PP_ENUM_TRAILING(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, BOOST_CONTAINER_PP_IDENTITY, nat) - #endif - > +class scoped_allocator_adaptor_base< OuterAlloc BOOST_CONTAINER_SCOPEDALLOC_DUMMYTRUE> : public OuterAlloc { BOOST_COPYABLE_AND_MOVABLE(scoped_allocator_adaptor_base) @@ -894,11 +741,7 @@ class scoped_allocator_adaptor_base { typedef scoped_allocator_adaptor_base <typename allocator_traits<OuterAlloc>::template portable_rebind_alloc<U>::type - #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - , true - BOOST_PP_ENUM_TRAILING(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, BOOST_CONTAINER_PP_IDENTITY, container_detail::nat) - #endif - > other; + BOOST_CONTAINER_SCOPEDALLOC_DUMMYTRUE > other; }; typedef OuterAlloc outer_allocator_type; @@ -912,6 +755,8 @@ class scoped_allocator_adaptor_base propagate_on_container_move_assignment propagate_on_container_move_assignment; typedef typename outer_traits_type:: propagate_on_container_swap propagate_on_container_swap; + typedef typename outer_traits_type:: + is_always_equal is_always_equal; scoped_allocator_adaptor_base() {} @@ -931,25 +776,13 @@ class scoped_allocator_adaptor_base template <class OuterA2> scoped_allocator_adaptor_base - (const scoped_allocator_adaptor_base< - OuterA2 - #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - , true - BOOST_PP_ENUM_TRAILING(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, BOOST_CONTAINER_PP_IDENTITY, container_detail::nat) - #endif - >& other) + (const scoped_allocator_adaptor_base<OuterA2 BOOST_CONTAINER_SCOPEDALLOC_DUMMYTRUE>& other) : outer_allocator_type(other.outer_allocator()) {} template <class OuterA2> scoped_allocator_adaptor_base - (BOOST_RV_REF_BEG scoped_allocator_adaptor_base< - OuterA2 - #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - , true - BOOST_PP_ENUM_TRAILING(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, BOOST_CONTAINER_PP_IDENTITY, container_detail::nat) - #endif - > BOOST_RV_REF_END other) + (BOOST_RV_REF_BEG scoped_allocator_adaptor_base<OuterA2 BOOST_CONTAINER_SCOPEDALLOC_DUMMYTRUE> BOOST_RV_REF_END other) : outer_allocator_type(other.outer_allocator()) {} @@ -976,7 +809,7 @@ class scoped_allocator_adaptor_base void swap(scoped_allocator_adaptor_base &r) { - boost::container::swap_dispatch(this->outer_allocator(), r.outer_allocator()); + boost::adl_move_swap(this->outer_allocator(), r.outer_allocator()); } friend void swap(scoped_allocator_adaptor_base &l, scoped_allocator_adaptor_base &r) @@ -1013,78 +846,65 @@ class scoped_allocator_adaptor_base //Scoped allocator #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) - #if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST) +#if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST) - //! This class is a C++03-compatible implementation of std::scoped_allocator_adaptor. - //! The class template scoped_allocator_adaptor is an allocator template that specifies - //! the memory resource (the outer allocator) to be used by a container (as any other - //! allocator does) and also specifies an inner allocator resource to be passed to - //! the constructor of every element within the container. - //! - //! This adaptor is - //! instantiated with one outer and zero or more inner allocator types. If - //! instantiated with only one allocator type, the inner allocator becomes the - //! scoped_allocator_adaptor itself, thus using the same allocator resource for the - //! container and every element within the container and, if the elements themselves - //! are containers, each of their elements recursively. If instantiated with more than - //! one allocator, the first allocator is the outer allocator for use by the container, - //! the second allocator is passed to the constructors of the container's elements, - //! and, if the elements themselves are containers, the third allocator is passed to - //! the elements' elements, and so on. If containers are nested to a depth greater - //! than the number of allocators, the last allocator is used repeatedly, as in the - //! single-allocator case, for any remaining recursions. - //! - //! [<b>Note</b>: The - //! scoped_allocator_adaptor is derived from the outer allocator type so it can be - //! substituted for the outer allocator type in most expressions. -end note] - //! - //! In the construct member functions, <code>OUTERMOST(x)</code> is x if x does not have - //! an <code>outer_allocator()</code> member function and - //! <code>OUTERMOST(x.outer_allocator())</code> otherwise; <code>OUTERMOST_ALLOC_TRAITS(x)</code> is - //! <code>allocator_traits<decltype(OUTERMOST(x))></code>. - //! - //! [<b>Note</b>: <code>OUTERMOST(x)</code> and - //! <code>OUTERMOST_ALLOC_TRAITS(x)</code> are recursive operations. It is incumbent upon - //! the definition of <code>outer_allocator()</code> to ensure that the recursion terminates. - //! It will terminate for all instantiations of scoped_allocator_adaptor. -end note] - template <typename OuterAlloc, typename ...InnerAllocs> - class scoped_allocator_adaptor +//! This class is a C++03-compatible implementation of std::scoped_allocator_adaptor. +//! The class template scoped_allocator_adaptor is an allocator template that specifies +//! the memory resource (the outer allocator) to be used by a container (as any other +//! allocator does) and also specifies an inner allocator resource to be passed to +//! the constructor of every element within the container. +//! +//! This adaptor is +//! instantiated with one outer and zero or more inner allocator types. If +//! instantiated with only one allocator type, the inner allocator becomes the +//! scoped_allocator_adaptor itself, thus using the same allocator resource for the +//! container and every element within the container and, if the elements themselves +//! are containers, each of their elements recursively. If instantiated with more than +//! one allocator, the first allocator is the outer allocator for use by the container, +//! the second allocator is passed to the constructors of the container's elements, +//! and, if the elements themselves are containers, the third allocator is passed to +//! the elements' elements, and so on. If containers are nested to a depth greater +//! than the number of allocators, the last allocator is used repeatedly, as in the +//! single-allocator case, for any remaining recursions. +//! +//! [<b>Note</b>: The +//! scoped_allocator_adaptor is derived from the outer allocator type so it can be +//! substituted for the outer allocator type in most expressions. -end note] +//! +//! In the construct member functions, <code>OUTERMOST(x)</code> is x if x does not have +//! an <code>outer_allocator()</code> member function and +//! <code>OUTERMOST(x.outer_allocator())</code> otherwise; <code>OUTERMOST_ALLOC_TRAITS(x)</code> is +//! <code>allocator_traits<decltype(OUTERMOST(x))></code>. +//! +//! [<b>Note</b>: <code>OUTERMOST(x)</code> and +//! <code>OUTERMOST_ALLOC_TRAITS(x)</code> are recursive operations. It is incumbent upon +//! the definition of <code>outer_allocator()</code> to ensure that the recursion terminates. +//! It will terminate for all instantiations of scoped_allocator_adaptor. -end note] +template <typename OuterAlloc, typename ...InnerAllocs> +class scoped_allocator_adaptor - #else // #if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST) +#else // #if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST) - template <typename OuterAlloc, typename ...InnerAllocs> - class scoped_allocator_adaptor<OuterAlloc, InnerAllocs...> +template <typename OuterAlloc, typename ...InnerAllocs> +class scoped_allocator_adaptor<OuterAlloc, InnerAllocs...> - #endif // #if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST) +#endif // #if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST) #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) -template <typename OuterAlloc - BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, class Q) - > +template <typename OuterAlloc, BOOST_MOVE_CLASS9> class scoped_allocator_adaptor #endif + : public container_detail::scoped_allocator_adaptor_base - <OuterAlloc - #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) - , InnerAllocs... - #else - , true BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q) - #endif - > + <OuterAlloc BOOST_CONTAINER_SCOPEDALLOC_DUMMYTRUE, BOOST_CONTAINER_SCOPEDALLOC_ALLINNER> { BOOST_COPYABLE_AND_MOVABLE(scoped_allocator_adaptor) public: #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED typedef container_detail::scoped_allocator_adaptor_base - <OuterAlloc - #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) - , InnerAllocs... - #else - , true BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q) - #endif - > base_type; + <OuterAlloc BOOST_CONTAINER_SCOPEDALLOC_DUMMYTRUE, BOOST_CONTAINER_SCOPEDALLOC_ALLINNER> base_type; typedef typename base_type::internal_type_t internal_type_t; #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED typedef OuterAlloc outer_allocator_type; @@ -1102,19 +922,29 @@ class scoped_allocator_adaptor typedef typename outer_traits_type::const_pointer const_pointer; typedef typename outer_traits_type::void_pointer void_pointer; typedef typename outer_traits_type::const_void_pointer const_void_pointer; - //! Type: <code>true_type</code> if <code>allocator_traits<Allocator>::propagate_on_container_copy_assignment::value</code> is - //! true for any <code>Allocator</code> in the set of <code>OuterAlloc</code> and <code>InnerAllocs...</code>; otherwise, false_type. + //! Type: A type with a constant boolean <code>value</code> == true if + //!`allocator_traits<Allocator>::propagate_on_container_copy_assignment::value` is + //! true for any <code>Allocator</code> in the set of <code>OuterAlloc</code> and <code>InnerAllocs...</code>, false otherwise. typedef typename base_type:: propagate_on_container_copy_assignment propagate_on_container_copy_assignment; - //! Type: <code>true_type</code> if <code>allocator_traits<Allocator>::propagate_on_container_move_assignment::value</code> is - //! true for any <code>Allocator</code> in the set of <code>OuterAlloc</code> and <code>InnerAllocs...</code>; otherwise, false_type. + //! Type: A type with a constant boolean <code>value</code> == true if + //!`allocator_traits<Allocator>::propagate_on_container_move_assignment::value` is + //! true for any <code>Allocator</code> in the set of <code>OuterAlloc</code> and <code>InnerAllocs...</code>, false otherwise. typedef typename base_type:: propagate_on_container_move_assignment propagate_on_container_move_assignment; - //! Type: <code>true_type</code> if <code>allocator_traits<Allocator>::propagate_on_container_swap::value</code> is true for any - //! <code>Allocator</code> in the set of <code>OuterAlloc</code> and <code>InnerAllocs...</code>; otherwise, false_type. + + //! Type: A type with a constant boolean <code>value</code> == true if + //! `allocator_traits<Allocator>::propagate_on_container_swap::value` is + //! true for any <code>Allocator</code> in the set of <code>OuterAlloc</code> and <code>InnerAllocs...</code>, false otherwise. typedef typename base_type:: propagate_on_container_swap propagate_on_container_swap; + //! Type: A type with a constant boolean <code>value</code> == true if + //!`allocator_traits<Allocator>::is_always_equal::value` is + //! true for all <code>Allocator</code> in the set of <code>OuterAlloc</code> and <code>InnerAllocs...</code>, false otherwise. + typedef typename base_type:: + is_always_equal is_always_equal; + //! Type: Rebinds scoped allocator to //! <code>typedef scoped_allocator_adaptor //! < typename outer_traits_type::template portable_rebind_alloc<U>::type @@ -1124,12 +954,7 @@ class scoped_allocator_adaptor { typedef scoped_allocator_adaptor < typename outer_traits_type::template portable_rebind_alloc<U>::type - #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) - , InnerAllocs... - #else - BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q) - #endif - > other; + , BOOST_CONTAINER_SCOPEDALLOC_ALLINNER> other; }; //! <b>Effects</b>: value-initializes the OuterAlloc base class @@ -1165,17 +990,14 @@ class scoped_allocator_adaptor {} #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) - #define BOOST_PP_LOCAL_MACRO(n) \ - template <class OuterA2> \ - scoped_allocator_adaptor(BOOST_FWD_REF(OuterA2) outerAlloc \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_CONST_REF_PARAM_LIST_Q, _)) \ - : base_type(::boost::forward<OuterA2>(outerAlloc) \ - BOOST_PP_ENUM_TRAILING_PARAMS(n, q) \ - ) \ - {} \ - //! - #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) - #include BOOST_PP_LOCAL_ITERATE() + #define BOOST_CONTAINER_SCOPED_ALLOCATOR_ADAPTOR_RELATED_ALLOCATOR_CONSTRUCTOR_CODE(N)\ + template <class OuterA2>\ + scoped_allocator_adaptor(BOOST_FWD_REF(OuterA2) outerAlloc BOOST_MOVE_I##N BOOST_MOVE_CREF##N)\ + : base_type(::boost::forward<OuterA2>(outerAlloc) BOOST_MOVE_I##N BOOST_MOVE_ARG##N)\ + {}\ + // + BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SCOPED_ALLOCATOR_ADAPTOR_RELATED_ALLOCATOR_CONSTRUCTOR_CODE) + #undef BOOST_CONTAINER_SCOPED_ALLOCATOR_ADAPTOR_RELATED_ALLOCATOR_CONSTRUCTOR_CODE #endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) @@ -1183,13 +1005,7 @@ class scoped_allocator_adaptor //! //! <b>Effects</b>: initializes each allocator within the adaptor with the corresponding allocator from other. template <class OuterA2> - scoped_allocator_adaptor(const scoped_allocator_adaptor<OuterA2 - #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) - , InnerAllocs... - #else - BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q) - #endif - > &other) + scoped_allocator_adaptor(const scoped_allocator_adaptor<OuterA2, BOOST_CONTAINER_SCOPEDALLOC_ALLINNER> &other) : base_type(other.base()) {} @@ -1198,13 +1014,8 @@ class scoped_allocator_adaptor //! <b>Effects</b>: initializes each allocator within the adaptor with the corresponding allocator //! rvalue from other. template <class OuterA2> - scoped_allocator_adaptor(BOOST_RV_REF_BEG scoped_allocator_adaptor<OuterA2 - #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) - , InnerAllocs... - #else - BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q) - #endif - > BOOST_RV_REF_END other) + scoped_allocator_adaptor(BOOST_RV_REF_BEG scoped_allocator_adaptor + <OuterA2, BOOST_CONTAINER_SCOPEDALLOC_ALLINNER> BOOST_RV_REF_END other) : base_type(::boost::move(other.base())) {} @@ -1212,7 +1023,7 @@ class scoped_allocator_adaptor { return static_cast<scoped_allocator_adaptor&>(base_type::operator=(static_cast<const base_type &>(other))); } scoped_allocator_adaptor &operator=(BOOST_RV_REF(scoped_allocator_adaptor) other) - { return static_cast<scoped_allocator_adaptor&>(base_type::operator=(boost::move(static_cast<base_type&>(other)))); } + { return static_cast<scoped_allocator_adaptor&>(base_type::operator=(boost::move(other.base()))); } #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED //! <b>Effects</b>: swaps *this with r. @@ -1225,33 +1036,31 @@ class scoped_allocator_adaptor //! <b>Returns</b>: //! <code>static_cast<OuterAlloc&>(*this)</code>. - outer_allocator_type & outer_allocator() BOOST_CONTAINER_NOEXCEPT; + outer_allocator_type & outer_allocator() BOOST_NOEXCEPT_OR_NOTHROW; //! <b>Returns</b>: //! <code>static_cast<const OuterAlloc&>(*this)</code>. - const outer_allocator_type &outer_allocator() const BOOST_CONTAINER_NOEXCEPT; + const outer_allocator_type &outer_allocator() const BOOST_NOEXCEPT_OR_NOTHROW; //! <b>Returns</b>: //! *this if <code>sizeof...(InnerAllocs)</code> is zero; otherwise, inner. - inner_allocator_type& inner_allocator() BOOST_CONTAINER_NOEXCEPT; + inner_allocator_type& inner_allocator() BOOST_NOEXCEPT_OR_NOTHROW; //! <b>Returns</b>: //! *this if <code>sizeof...(InnerAllocs)</code> is zero; otherwise, inner. - inner_allocator_type const& inner_allocator() const BOOST_CONTAINER_NOEXCEPT; + inner_allocator_type const& inner_allocator() const BOOST_NOEXCEPT_OR_NOTHROW; #endif //BOOST_CONTAINER_DOXYGEN_INVOKED //! <b>Returns</b>: //! <code>allocator_traits<OuterAlloc>::max_size(outer_allocator())</code>. - size_type max_size() const BOOST_CONTAINER_NOEXCEPT - { - return outer_traits_type::max_size(this->outer_allocator()); - } + size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW + { return outer_traits_type::max_size(this->outer_allocator()); } //! <b>Effects</b>: //! calls <code>OUTERMOST_ALLOC_TRAITS(*this)::destroy(OUTERMOST(*this), p)</code>. template <class T> - void destroy(T* p) BOOST_CONTAINER_NOEXCEPT + void destroy(T* p) BOOST_NOEXCEPT_OR_NOTHROW { allocator_traits<typename outermost_allocator<OuterAlloc>::type> ::destroy(get_outermost_allocator(this->outer_allocator()), p); @@ -1260,27 +1069,21 @@ class scoped_allocator_adaptor //! <b>Returns</b>: //! <code>allocator_traits<OuterAlloc>::allocate(outer_allocator(), n)</code>. pointer allocate(size_type n) - { - return outer_traits_type::allocate(this->outer_allocator(), n); - } + { return outer_traits_type::allocate(this->outer_allocator(), n); } //! <b>Returns</b>: //! <code>allocator_traits<OuterAlloc>::allocate(outer_allocator(), n, hint)</code>. pointer allocate(size_type n, const_void_pointer hint) - { - return outer_traits_type::allocate(this->outer_allocator(), n, hint); - } + { return outer_traits_type::allocate(this->outer_allocator(), n, hint); } //! <b>Effects</b>: //! <code>allocator_traits<OuterAlloc>::deallocate(outer_allocator(), p, n)</code>. void deallocate(pointer p, size_type n) - { - outer_traits_type::deallocate(this->outer_allocator(), p, n); - } + { outer_traits_type::deallocate(this->outer_allocator(), p, n); } #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED - //! <b>Returns</b>: Allocator new scoped_allocator_adaptor object where each allocator - //! A in the adaptor is initialized from the result of calling + //! <b>Returns</b>: A new scoped_allocator_adaptor object where each allocator + //! Allocator in the adaptor is initialized from the result of calling //! <code>allocator_traits<Allocator>::select_on_container_copy_construction()</code> on //! the corresponding allocator in *this. scoped_allocator_adaptor select_on_container_copy_construction() const; @@ -1331,7 +1134,7 @@ class scoped_allocator_adaptor construct(T* p, BOOST_FWD_REF(Args)...args) { container_detail::dispatch_uses_allocator - ( uses_allocator<T, inner_allocator_type>() + ( container_detail::bool_<uses_allocator<T, inner_allocator_type>::value>() , get_outermost_allocator(this->outer_allocator()) , this->inner_allocator() , p, ::boost::forward<Args>(args)...); @@ -1341,22 +1144,19 @@ class scoped_allocator_adaptor //Disable this overload if the first argument is pair as some compilers have //overload selection problems when the first parameter is a pair. - #define BOOST_PP_LOCAL_MACRO(n) \ - template < typename T \ - BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) \ - > \ - typename container_detail::enable_if_c<!container_detail::is_pair<T>::value, void>::type \ - construct(T* p BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ - { \ - container_detail::dispatch_uses_allocator \ - ( uses_allocator<T, inner_allocator_type>() \ - , get_outermost_allocator(this->outer_allocator()) \ - , this->inner_allocator() \ - , p BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \ - } \ - //! - #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) - #include BOOST_PP_LOCAL_ITERATE() + #define BOOST_CONTAINER_SCOPED_ALLOCATOR_CONSTRUCT_CODE(N) \ + template < typename T BOOST_MOVE_I##N BOOST_MOVE_CLASSQ##N >\ + typename container_detail::enable_if_c<!container_detail::is_pair<T>::value, void>::type\ + construct(T* p BOOST_MOVE_I##N BOOST_MOVE_UREFQ##N)\ + {\ + container_detail::dispatch_uses_allocator\ + ( container_detail::bool_<uses_allocator<T, inner_allocator_type>::value>()\ + , get_outermost_allocator(this->outer_allocator())\ + , this->inner_allocator(), p BOOST_MOVE_I##N BOOST_MOVE_FWDQ##N);\ + }\ + // + BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SCOPED_ALLOCATOR_CONSTRUCT_CODE) + #undef BOOST_CONTAINER_SCOPED_ALLOCATOR_CONSTRUCT_CODE #endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) @@ -1427,31 +1227,11 @@ class scoped_allocator_adaptor template <class Pair, class Pair2> void construct_pair(Pair* p, const Pair2& pr) - { - this->construct(container_detail::addressof(p->first), pr.first); - BOOST_TRY{ - this->construct(container_detail::addressof(p->second), pr.second); - } - BOOST_CATCH(...){ - this->destroy(container_detail::addressof(p->first)); - BOOST_RETHROW - } - BOOST_CATCH_END - } + { this->construct_pair(p, pr.first, pr.second); } template <class Pair, class Pair2> void construct_pair(Pair* p, BOOST_RV_REF(Pair2) pr) - { - this->construct(container_detail::addressof(p->first), ::boost::move(pr.first)); - BOOST_TRY{ - this->construct(container_detail::addressof(p->second), ::boost::move(pr.second)); - } - BOOST_CATCH(...){ - this->destroy(container_detail::addressof(p->first)); - BOOST_RETHROW - } - BOOST_CATCH_END - } + { this->construct_pair(p, ::boost::move(pr.first), ::boost::move(pr.second)); } //template <class T1, class T2, class... Args1, class... Args2> //void construct(pair<T1, T2>* p, piecewise_construct_t, tuple<Args1...> x, tuple<Args2...> y); @@ -1466,66 +1246,29 @@ class scoped_allocator_adaptor #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED }; -template <typename OuterA1, typename OuterA2 - #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) - , typename... InnerAllocs - #else - BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, class Q) - #endif - > -inline bool operator==( - const scoped_allocator_adaptor<OuterA1 - #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) - ,InnerAllocs... - #else - BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q) - #endif - >& a, - const scoped_allocator_adaptor<OuterA2 - #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) - ,InnerAllocs... - #else - BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q) - #endif - >& b) +template <typename OuterA1, typename OuterA2, BOOST_CONTAINER_SCOPEDALLOC_ALLINNERCLASS> +inline bool operator==(const scoped_allocator_adaptor<OuterA1, BOOST_CONTAINER_SCOPEDALLOC_ALLINNER>& a + ,const scoped_allocator_adaptor<OuterA2, BOOST_CONTAINER_SCOPEDALLOC_ALLINNER>& b) { #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) const bool has_zero_inner = sizeof...(InnerAllocs) == 0u; #else - const bool has_zero_inner = - boost::container::container_detail::is_same - <Q0, container_detail::nat>::value; + const bool has_zero_inner = boost::container::container_detail::is_same<P0, void>::value; #endif - - return a.outer_allocator() == b.outer_allocator() - && (has_zero_inner || a.inner_allocator() == b.inner_allocator()); + typedef typename scoped_allocator_adaptor<OuterA1, BOOST_CONTAINER_SCOPEDALLOC_ALLINNER> + ::outer_allocator_type outer_allocator_type; + typedef typename scoped_allocator_adaptor<OuterA1, BOOST_CONTAINER_SCOPEDALLOC_ALLINNER> + ::inner_allocator_type inner_allocator_type; + + return allocator_traits<outer_allocator_type>::equal(a.outer_allocator(), b.outer_allocator()) + && (has_zero_inner || + allocator_traits<inner_allocator_type>::equal(a.inner_allocator(), b.inner_allocator())); } -template <typename OuterA1, typename OuterA2 - #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) - , typename... InnerAllocs - #else - BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, class Q) - #endif - > -inline bool operator!=( - const scoped_allocator_adaptor<OuterA1 - #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) - ,InnerAllocs... - #else - BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q) - #endif - >& a, - const scoped_allocator_adaptor<OuterA2 - #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) - ,InnerAllocs... - #else - BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q) - #endif - >& b) -{ - return ! (a == b); -} +template <typename OuterA1, typename OuterA2, BOOST_CONTAINER_SCOPEDALLOC_ALLINNERCLASS> +inline bool operator!=(const scoped_allocator_adaptor<OuterA1, BOOST_CONTAINER_SCOPEDALLOC_ALLINNER>& a + ,const scoped_allocator_adaptor<OuterA2, BOOST_CONTAINER_SCOPEDALLOC_ALLINNER>& b) +{ return !(a == b); } }} // namespace boost { namespace container { diff --git a/boost/container/scoped_allocator_fwd.hpp b/boost/container/scoped_allocator_fwd.hpp index f19e27e885..003ed9f7f7 100644 --- a/boost/container/scoped_allocator_fwd.hpp +++ b/boost/container/scoped_allocator_fwd.hpp @@ -15,16 +15,20 @@ //! This header file forward declares boost::container::scoped_allocator_adaptor //! and defines the following types: -#if defined(_MSC_VER) +#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> +#include <boost/container/detail/std_fwd.hpp> #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) -#include <boost/container/detail/preprocessor.hpp> -#include <boost/container/detail/type_traits.hpp> +#include <boost/move/detail/fwd_macros.hpp> #endif namespace boost { namespace container { @@ -35,41 +39,48 @@ namespace boost { namespace container { #if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST) - template <typename OuterAlloc, typename ...InnerAllocs> - class scoped_allocator_adaptor; + template <typename OuterAlloc, typename ...InnerAllocs> + class scoped_allocator_adaptor; #else // #if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST) - template <typename ...InnerAllocs> - class scoped_allocator_adaptor; + template <typename ...InnerAllocs> + class scoped_allocator_adaptor; - template <typename OuterAlloc, typename ...InnerAllocs> - class scoped_allocator_adaptor<OuterAlloc, InnerAllocs...>; + template <typename OuterAlloc, typename ...InnerAllocs> + class scoped_allocator_adaptor<OuterAlloc, InnerAllocs...>; #endif // #if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST) - #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) -template <typename OuterAlloc -BOOST_PP_ENUM_TRAILING( BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS - , BOOST_CONTAINER_PP_TEMPLATE_PARAM_WITH_DEFAULT, container_detail::nat) -> -class scoped_allocator_adaptor; + template <typename OuterAlloc, BOOST_MOVE_CLASSDFLT9> + class scoped_allocator_adaptor; #endif + template <int Dummy = 0> + struct std_allocator_arg_holder + { + static ::std::allocator_arg_t *dummy; + }; + + template <int Dummy> + ::std::allocator_arg_t *std_allocator_arg_holder<Dummy>::dummy; + +#else //BOOST_CONTAINER_DOXYGEN_INVOKED + #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED //! The allocator_arg_t struct is an empty structure type used as a unique type to //! disambiguate constructor and function overloading. Specifically, several types //! have constructors with allocator_arg_t as the first argument, immediately followed -//! by an argument of a type that satisfies the Allocator requirements -struct allocator_arg_t{}; +//! by an argument of a type that satisfies Allocator requirements +typedef const std::allocator_arg_t & allocator_arg_t; //! A instance of type allocator_arg_t //! -static const allocator_arg_t allocator_arg = allocator_arg_t(); +static allocator_arg_t allocator_arg = BOOST_CONTAINER_DOC1ST(unspecified, *std_allocator_arg_holder<>::dummy); template <class T> struct constructible_with_allocator_suffix; @@ -77,7 +88,7 @@ struct constructible_with_allocator_suffix; template <class T> struct constructible_with_allocator_prefix; -template <typename T, typename Alloc> +template <typename T, typename Allocator> struct uses_allocator; }} // namespace boost { namespace container { diff --git a/boost/container/set.hpp b/boost/container/set.hpp index 3e2c2aad0d..79fa1aec66 100644 --- a/boost/container/set.hpp +++ b/boost/container/set.hpp @@ -11,27 +11,34 @@ #ifndef BOOST_CONTAINER_SET_HPP #define BOOST_CONTAINER_SET_HPP -#if defined(_MSC_VER) +#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> +// container #include <boost/container/container_fwd.hpp> - -#include <utility> -#include <functional> -#include <memory> - -#include <boost/move/utility_core.hpp> -#include <boost/move/detail/move_helpers.hpp> -#include <boost/move/traits.hpp> +// container/detail #include <boost/container/detail/mpl.hpp> #include <boost/container/detail/tree.hpp> +#include <boost/container/new_allocator.hpp> //new_allocator +// intrusive/detail +#include <boost/intrusive/detail/minimal_pair_header.hpp> //pair +#include <boost/intrusive/detail/minimal_less_equal_header.hpp>//less, equal +// move +#include <boost/move/traits.hpp> #include <boost/move/utility_core.hpp> -#ifndef BOOST_CONTAINER_PERFECT_FORWARDING -#include <boost/container/detail/preprocessor.hpp> +// move/detail +#include <boost/move/detail/move_helpers.hpp> +#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +#include <boost/move/detail/fwd_macros.hpp> #endif +// std #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) #include <initializer_list> #endif @@ -53,7 +60,7 @@ namespace container { //! \tparam Compare is the comparison functor used to order keys //! \tparam Allocator is the allocator to be used to allocate memory for this container //! \tparam SetOptions is an packed option type generated using using boost::container::tree_assoc_options. -template <class Key, class Compare = std::less<Key>, class Allocator = std::allocator<Key>, class SetOptions = tree_assoc_defaults > +template <class Key, class Compare = std::less<Key>, class Allocator = new_allocator<Key>, class SetOptions = tree_assoc_defaults > #else template <class Key, class Compare, class Allocator, class SetOptions> #endif @@ -134,6 +141,16 @@ class set : base_t(true, first, last, comp, a) {} + //! <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. + template <class InputIterator> + 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 comparison object and //! allocator, and inserts elements from the ordered unique range [first ,last). This function //! is more efficient than the normal range creation for ordered ranges. @@ -160,6 +177,15 @@ class set : base_t(true, il.begin(), il.end(), comp, a) {} + //! <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) + : base_t(true, il.begin(), il.end(), Compare(), a) + {} + //! <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. @@ -170,7 +196,8 @@ 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()) + set( ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp = Compare() + , const allocator_type& a = allocator_type()) : base_t(ordered_range, il.begin(), il.end(), comp, a) {} #endif @@ -188,7 +215,7 @@ class set //! //! <b>Postcondition</b>: x is emptied. set(BOOST_RV_REF(set) x) - : base_t(boost::move(static_cast<base_t&>(x))) + : base_t(BOOST_MOVE_BASE(base_t, x)) {} //! <b>Effects</b>: Copy constructs a set using the specified allocator. @@ -203,7 +230,7 @@ class set //! //! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise. set(BOOST_RV_REF(set) x, const allocator_type &a) - : base_t(boost::move(static_cast<base_t&>(x)), a) + : base_t(BOOST_MOVE_BASE(base_t, x), a) {} //! <b>Effects</b>: Makes *this a copy of x. @@ -221,8 +248,9 @@ class set //! 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_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value) - { return static_cast<set&>(this->base_t::operator=(boost::move(static_cast<base_t&>(x)))); } + BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value + && boost::container::container_detail::is_nothrow_move_assignable<Compare>::value ) + { return static_cast<set&>(this->base_t::operator=(BOOST_MOVE_BASE(base_t, x))); } #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) set& operator=(std::initializer_list<value_type> il) @@ -235,7 +263,7 @@ class set #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) - //! <b>Effects</b>: Returns a copy of the Allocator that + //! <b>Effects</b>: Returns a copy of the allocator that //! was passed to the object's constructor. //! //! <b>Complexity</b>: Constant. @@ -371,7 +399,7 @@ class set size_type max_size() const; #endif // #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) - #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) //! <b>Effects</b>: Inserts an object x of type Key constructed with //! std::forward<Args>(args)... if and only if there is @@ -388,7 +416,7 @@ class set //! //! <b>Complexity</b>: Logarithmic. template <class... Args> - std::pair<iterator,bool> emplace(Args&&... args) + 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 @@ -401,26 +429,24 @@ class set //! //! <b>Complexity</b>: Logarithmic. template <class... Args> - iterator emplace_hint(const_iterator p, Args&&... args) + iterator emplace_hint(const_iterator p, BOOST_FWD_REF(Args)... args) { return this->base_t::emplace_hint_unique(p, boost::forward<Args>(args)...); } - #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING + #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - #define BOOST_PP_LOCAL_MACRO(n) \ - BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ - std::pair<iterator,bool> emplace(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ - { return this->base_t::emplace_unique(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); }\ - \ - BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ - iterator emplace_hint(const_iterator p \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ - { return this->base_t::emplace_hint_unique(p \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _));} \ - //! - #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) - #include BOOST_PP_LOCAL_ITERATE() + #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)\ + { 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)\ + { 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) + #undef BOOST_CONTAINER_SET_EMPLACE_CODE - #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING + #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) //! <b>Effects</b>: Inserts x if and only if there is no element in the container @@ -521,7 +547,9 @@ class set //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - void swap(set& x); + void swap(set& x) + BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value + && boost::container::container_detail::is_nothrow_swappable<Compare>::value ); //! <b>Effects</b>: erase(a.begin(),a.end()). //! @@ -548,7 +576,7 @@ class set //! <b>Complexity</b>: Logarithmic. iterator find(const key_type& x); - //! <b>Returns</b>: Allocator const_iterator pointing to an element with the key + //! <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. @@ -576,7 +604,7 @@ class set //! <b>Complexity</b>: Logarithmic iterator lower_bound(const key_type& x); - //! <b>Returns</b>: Allocator const iterator pointing to the first element with key not + //! <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 @@ -588,7 +616,7 @@ class set //! <b>Complexity</b>: Logarithmic iterator upper_bound(const key_type& x); - //! <b>Returns</b>: Allocator const iterator pointing to the first element with key not + //! <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 @@ -680,10 +708,13 @@ class set //!has_trivial_destructor_after_move<> == true_type //!specialization for optimizations -template <class Key, class C, class SetOptions, class Allocator> -struct has_trivial_destructor_after_move<boost::container::set<Key, C, Allocator, SetOptions> > +template <class Key, class Compare, class SetOptions, class Allocator> +struct has_trivial_destructor_after_move<boost::container::set<Key, Compare, Allocator, SetOptions> > { - static const bool value = has_trivial_destructor_after_move<Allocator>::value && has_trivial_destructor_after_move<C>::value; + typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer; + static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value && + ::boost::has_trivial_destructor_after_move<pointer>::value && + ::boost::has_trivial_destructor_after_move<Compare>::value; }; namespace container { @@ -704,7 +735,7 @@ namespace container { //! \tparam Compare is the comparison functor used to order keys //! \tparam Allocator is the allocator to be used to allocate memory for this container //! \tparam MultiSetOptions is an packed option type generated using using boost::container::tree_assoc_options. -template <class Key, class Compare = std::less<Key>, class Allocator = std::allocator<Key>, class MultiSetOptions = tree_assoc_defaults > +template <class Key, class Compare = std::less<Key>, class Allocator = new_allocator<Key>, class MultiSetOptions = tree_assoc_defaults > #else template <class Key, class Compare, class Allocator, class MultiSetOptions> #endif @@ -776,6 +807,12 @@ class multiset : base_t(false, first, last, comp, a) {} + //! @copydoc ::boost::container::set::set(InputIterator, InputIterator, const allocator_type&) + template <class InputIterator> + multiset(InputIterator first, InputIterator last, const allocator_type& a) + : base_t(false, first, last, key_compare(), a) + {} + //! <b>Effects</b>: Constructs an empty multiset 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. @@ -798,13 +835,17 @@ class multiset : base_t(false, il.begin(), il.end(), comp, a) {} + //! @copydoc ::boost::container::set::set(std::initializer_list<value_type>, const allocator_type&) + 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()) : base_t(ordered_range, il.begin(), il.end(), comp, a) {} #endif - //! @copydoc ::boost::container::set::set(const set &) multiset(const multiset& x) : base_t(static_cast<const base_t&>(x)) @@ -812,7 +853,7 @@ class multiset //! @copydoc ::boost::container::set(set &&) multiset(BOOST_RV_REF(multiset) x) - : base_t(boost::move(static_cast<base_t&>(x))) + : base_t(BOOST_MOVE_BASE(base_t, x)) {} //! @copydoc ::boost::container::set(const set &, const allocator_type &) @@ -822,7 +863,7 @@ class multiset //! @copydoc ::boost::container::set(set &&, const allocator_type &) multiset(BOOST_RV_REF(multiset) x, const allocator_type &a) - : base_t(boost::move(static_cast<base_t&>(x)), a) + : base_t(BOOST_MOVE_BASE(base_t, x), a) {} //! @copydoc ::boost::container::set::operator=(const set &) @@ -831,7 +872,9 @@ class multiset //! @copydoc ::boost::container::set::operator=(set &&) multiset& operator=(BOOST_RV_REF(multiset) x) - { return static_cast<multiset&>(this->base_t::operator=(boost::move(static_cast<base_t&>(x)))); } + BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value + && boost::container::container_detail::is_nothrow_move_assignable<Compare>::value ) + { return static_cast<multiset&>(this->base_t::operator=(BOOST_MOVE_BASE(base_t, x))); } #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) //! @copydoc ::boost::container::set::operator=(std::initializer_list<value_type>) @@ -863,31 +906,31 @@ class multiset const_iterator cbegin() const; //! @copydoc ::boost::container::set::end() - iterator end() BOOST_CONTAINER_NOEXCEPT; + iterator end() BOOST_NOEXCEPT_OR_NOTHROW; //! @copydoc ::boost::container::set::end() const - const_iterator end() const BOOST_CONTAINER_NOEXCEPT; + const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW; //! @copydoc ::boost::container::set::cend() const - const_iterator cend() const BOOST_CONTAINER_NOEXCEPT; + const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW; //! @copydoc ::boost::container::set::rbegin() - reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT; + reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW; //! @copydoc ::boost::container::set::rbegin() const - const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT; + const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW; //! @copydoc ::boost::container::set::crbegin() const - const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT; + const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW; //! @copydoc ::boost::container::set::rend() - reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT; + reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW; //! @copydoc ::boost::container::set::rend() const - const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT; + const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW; //! @copydoc ::boost::container::set::crend() const - const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT; + const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW; //! @copydoc ::boost::container::set::empty() const bool empty() const; @@ -900,7 +943,7 @@ class multiset #endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) - #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) //! <b>Effects</b>: Inserts an object of type Key constructed with //! std::forward<Args>(args)... and returns the iterator pointing to the @@ -908,7 +951,7 @@ class multiset //! //! <b>Complexity</b>: Logarithmic. template <class... Args> - iterator emplace(Args&&... args) + 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 @@ -920,26 +963,24 @@ 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, Args&&... args) + iterator emplace_hint(const_iterator p, BOOST_FWD_REF(Args)... args) { return this->base_t::emplace_hint_equal(p, boost::forward<Args>(args)...); } - #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING + #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - #define BOOST_PP_LOCAL_MACRO(n) \ - BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ - iterator emplace(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ - { return this->base_t::emplace_equal(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); } \ - \ - BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ - iterator emplace_hint(const_iterator p \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ - { return this->base_t::emplace_hint_equal(p \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _));} \ - //! - #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) - #include BOOST_PP_LOCAL_ITERATE() + #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)\ + { 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)\ + { 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) + #undef BOOST_CONTAINER_MULTISET_EMPLACE_CODE - #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING + #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) //! <b>Effects</b>: Inserts x and returns the iterator pointing to the @@ -996,7 +1037,7 @@ class multiset #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) - { this->base_t::insert_unique(il.begin(), il.end()); } + { this->base_t::insert_equal(il.begin(), il.end()); } #endif #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) @@ -1011,10 +1052,12 @@ class multiset iterator erase(const_iterator first, const_iterator last); //! @copydoc ::boost::container::set::swap - void swap(flat_multiset& x); + void swap(multiset& x) + BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value + && boost::container::container_detail::is_nothrow_swappable<Compare>::value ); //! @copydoc ::boost::container::set::clear - void clear() BOOST_CONTAINER_NOEXCEPT; + void clear() BOOST_NOEXCEPT_OR_NOTHROW; //! @copydoc ::boost::container::set::key_comp key_compare key_comp() const; @@ -1108,10 +1151,13 @@ class multiset //!has_trivial_destructor_after_move<> == true_type //!specialization for optimizations -template <class Key, class C, class Allocator, class MultiSetOptions> -struct has_trivial_destructor_after_move<boost::container::multiset<Key, C, Allocator, MultiSetOptions> > +template <class Key, class Compare, class Allocator, class MultiSetOptions> +struct has_trivial_destructor_after_move<boost::container::multiset<Key, Compare, Allocator, MultiSetOptions> > { - static const bool value = has_trivial_destructor_after_move<Allocator>::value && has_trivial_destructor_after_move<C>::value; + typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer; + static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value && + ::boost::has_trivial_destructor_after_move<pointer>::value && + ::boost::has_trivial_destructor_after_move<Compare>::value; }; namespace container { @@ -1122,5 +1168,4 @@ namespace container { #include <boost/container/detail/config_end.hpp> -#endif /* BOOST_CONTAINER_SET_HPP */ - +#endif // BOOST_CONTAINER_SET_HPP diff --git a/boost/container/slist.hpp b/boost/container/slist.hpp index b6b4c388a2..b0901ef086 100644 --- a/boost/container/slist.hpp +++ b/boost/container/slist.hpp @@ -11,46 +11,48 @@ #ifndef BOOST_CONTAINER_SLIST_HPP #define BOOST_CONTAINER_SLIST_HPP -#if defined(_MSC_VER) +#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> +// container #include <boost/container/container_fwd.hpp> +#include <boost/container/new_allocator.hpp> //new_allocator #include <boost/container/throw_exception.hpp> -#include <boost/move/utility_core.hpp> -#include <boost/move/detail/move_helpers.hpp> -#include <boost/move/traits.hpp> -#include <boost/intrusive/pointer_traits.hpp> -#include <boost/container/detail/utilities.hpp> +// container/detail +#include <boost/container/detail/algorithm.hpp> //algo_equal(), algo_lexicographical_compare +#include <boost/container/detail/compare_functors.hpp> +#include <boost/container/detail/iterator.hpp> #include <boost/container/detail/iterators.hpp> #include <boost/container/detail/mpl.hpp> -#include <boost/container/detail/type_traits.hpp> -#include <boost/core/no_exceptions_support.hpp> #include <boost/container/detail/node_alloc_holder.hpp> +#include <boost/container/detail/type_traits.hpp> +// intrusive +#include <boost/intrusive/pointer_traits.hpp> #include <boost/intrusive/slist.hpp> -#include <iterator> - - -#if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) -//Preprocessor library to emulate perfect forwarding -#else -#include <boost/container/detail/preprocessor.hpp> +// move +#include <boost/move/iterator.hpp> +#include <boost/move/traits.hpp> +#include <boost/move/utility_core.hpp> +// move/detail +#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +#include <boost/move/detail/fwd_macros.hpp> #endif - -#include <iterator> -#include <utility> -#include <memory> -#include <functional> -#include <algorithm> - +#include <boost/move/detail/move_helpers.hpp> +// other +#include <boost/core/no_exceptions_support.hpp> +// std #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) #include <initializer_list> #endif - namespace boost { namespace container { @@ -155,7 +157,7 @@ struct intrusive_slist_type //! \tparam T The type of object that is stored in the list //! \tparam Allocator The allocator used for all internal memory management #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED -template <class T, class Allocator = std::allocator<T> > +template <class T, class Allocator = new_allocator<T> > #else template <class T, class Allocator> #endif @@ -167,48 +169,19 @@ class slist typedef typename container_detail::intrusive_slist_type<Allocator>::type Icont; typedef container_detail::node_alloc_holder<Allocator, Icont> AllocHolder; - typedef typename AllocHolder::NodePtr NodePtr; - typedef typename AllocHolder::NodeAlloc NodeAlloc; - typedef typename AllocHolder::ValAlloc ValAlloc; - typedef typename AllocHolder::Node Node; - typedef container_detail::allocator_destroyer<NodeAlloc> Destroyer; - typedef typename AllocHolder::allocator_v1 allocator_v1; - typedef typename AllocHolder::allocator_v2 allocator_v2; - typedef typename AllocHolder::alloc_version alloc_version; - typedef boost::container::allocator_traits<Allocator> allocator_traits_type; - - class equal_to_value - { - typedef typename AllocHolder::value_type value_type; - const value_type &t_; - - public: - equal_to_value(const value_type &t) - : t_(t) - {} - - bool operator()(const value_type &t)const - { return t_ == t; } - }; - - template<class Pred> - struct ValueCompareToNodeCompare - : Pred - { - ValueCompareToNodeCompare(Pred pred) - : Pred(pred) - {} - - bool operator()(const Node &a, const Node &b) const - { return static_cast<const Pred&>(*this)(a.m_data, b.m_data); } - - bool operator()(const Node &a) const - { return static_cast<const Pred&>(*this)(a.m_data); } - }; + typedef typename AllocHolder::NodePtr NodePtr; + typedef typename AllocHolder::NodeAlloc NodeAlloc; + typedef typename AllocHolder::ValAlloc ValAlloc; + typedef typename AllocHolder::Node Node; + typedef container_detail::allocator_destroyer<NodeAlloc> Destroyer; + typedef typename AllocHolder::alloc_version alloc_version; + typedef boost::container:: + allocator_traits<Allocator> allocator_traits_type; + typedef boost::container::equal_to_value<Allocator> equal_to_value_type; BOOST_COPYABLE_AND_MOVABLE(slist) - typedef container_detail::iterator<typename Icont::iterator, false> iterator_impl; - typedef container_detail::iterator<typename Icont::iterator, true > const_iterator_impl; + typedef container_detail::iterator_from_iiterator<typename Icont::iterator, false> iterator_impl; + typedef container_detail::iterator_from_iiterator<typename Icont::iterator, true > const_iterator_impl; #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED public: @@ -252,10 +225,17 @@ class slist //! <b>Throws</b>: Nothing //! //! <b>Complexity</b>: Constant. - explicit slist(const allocator_type& a) BOOST_CONTAINER_NOEXCEPT + explicit slist(const allocator_type& a) BOOST_NOEXCEPT_OR_NOTHROW : AllocHolder(a) {} + //! <b>Effects</b>: Constructs a list + //! and inserts n value-initialized value_types. + //! + //! <b>Throws</b>: If allocator_type's default constructor + //! throws or T's default or copy constructor throws. + //! + //! <b>Complexity</b>: Linear to n. explicit slist(size_type n) : AllocHolder(allocator_type()) { this->resize(n); } @@ -267,6 +247,17 @@ class slist //! throws or T's default or copy constructor throws. //! //! <b>Complexity</b>: Linear to n. + slist(size_type n, const allocator_type &a) + : AllocHolder(a) + { this->resize(n); } + + //! <b>Effects</b>: Constructs a list that will use a copy of allocator a + //! and inserts n copies of value. + //! + //! <b>Throws</b>: If allocator_type's default constructor + //! throws or T's default or copy constructor throws. + //! + //! <b>Complexity</b>: Linear to n. explicit slist(size_type n, const value_type& x, const allocator_type& a = allocator_type()) : AllocHolder(a) { this->insert_after(this->cbefore_begin(), n, x); } @@ -307,13 +298,13 @@ class slist : AllocHolder(x) { this->insert_after(this->cbefore_begin(), x.begin(), x.end()); } - //! <b>Effects</b>: Move constructor. Moves mx's resources to *this. + //! <b>Effects</b>: Move constructor. Moves x's resources to *this. //! //! <b>Throws</b>: If allocator_type's copy constructor throws. //! //! <b>Complexity</b>: Constant. slist(BOOST_RV_REF(slist) x) - : AllocHolder(boost::move(static_cast<AllocHolder&>(x))) + : AllocHolder(BOOST_MOVE_BASE(AllocHolder, x)) {} //! <b>Effects</b>: Copy constructs a list using the specified allocator. @@ -340,7 +331,7 @@ class slist this->icont().swap(x.icont()); } else{ - this->insert_after(this->cbefore_begin(), x.begin(), x.end()); + this->insert_after(this->cbefore_begin(), boost::make_move_iterator(x.begin()), boost::make_move_iterator(x.end())); } } @@ -350,7 +341,7 @@ class slist //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Linear to the number of elements. - ~slist() BOOST_CONTAINER_NOEXCEPT + ~slist() BOOST_NOEXCEPT_OR_NOTHROW {} //AllocHolder clears the slist //! <b>Effects</b>: Makes *this contain the same elements as x. @@ -389,7 +380,8 @@ class slist //! propagate_on_container_move_assignment is true or //! this->get>allocator() == x.get_allocator(). Linear otherwise. slist& operator= (BOOST_RV_REF(slist) x) - BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value) + BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value + || allocator_traits_type::is_always_equal::value) { BOOST_ASSERT(this != &x); NodeAlloc &this_alloc = this->node_alloc(); @@ -489,7 +481,7 @@ class slist //! <b>Throws</b>: If allocator's copy constructor throws. //! //! <b>Complexity</b>: Constant. - allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT + allocator_type get_allocator() const BOOST_NOEXCEPT_OR_NOTHROW { return allocator_type(this->node_alloc()); } //! <b>Effects</b>: Returns a reference to the internal allocator. @@ -499,7 +491,7 @@ class slist //! <b>Complexity</b>: Constant. //! //! <b>Note</b>: Non-standard extension. - stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT + stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW { return this->node_alloc(); } //! <b>Effects</b>: Returns a reference to the internal allocator. @@ -509,7 +501,7 @@ class slist //! <b>Complexity</b>: Constant. //! //! <b>Note</b>: Non-standard extension. - const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT + const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW { return this->node_alloc(); } ////////////////////////////////////////////// @@ -525,7 +517,7 @@ class slist //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - iterator before_begin() BOOST_CONTAINER_NOEXCEPT + iterator before_begin() BOOST_NOEXCEPT_OR_NOTHROW { return iterator(end()); } //! <b>Effects</b>: Returns a non-dereferenceable const_iterator @@ -535,7 +527,7 @@ class slist //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator before_begin() const BOOST_CONTAINER_NOEXCEPT + const_iterator before_begin() const BOOST_NOEXCEPT_OR_NOTHROW { return this->cbefore_begin(); } //! <b>Effects</b>: Returns an iterator to the first element contained in the list. @@ -543,7 +535,7 @@ class slist //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - iterator begin() BOOST_CONTAINER_NOEXCEPT + iterator begin() BOOST_NOEXCEPT_OR_NOTHROW { return iterator(this->icont().begin()); } //! <b>Effects</b>: Returns a const_iterator to the first element contained in the list. @@ -551,7 +543,7 @@ class slist //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator begin() const BOOST_CONTAINER_NOEXCEPT + const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW { return this->cbegin(); } //! <b>Effects</b>: Returns an iterator to the end of the list. @@ -559,7 +551,7 @@ class slist //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - iterator end() BOOST_CONTAINER_NOEXCEPT + iterator end() BOOST_NOEXCEPT_OR_NOTHROW { return iterator(this->icont().end()); } //! <b>Effects</b>: Returns a const_iterator to the end of the list. @@ -567,7 +559,7 @@ class slist //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator end() const BOOST_CONTAINER_NOEXCEPT + const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW { return this->cend(); } //! <b>Effects</b>: Returns a non-dereferenceable const_iterator @@ -577,7 +569,7 @@ class slist //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator cbefore_begin() const BOOST_CONTAINER_NOEXCEPT + const_iterator cbefore_begin() const BOOST_NOEXCEPT_OR_NOTHROW { return const_iterator(end()); } //! <b>Effects</b>: Returns a const_iterator to the first element contained in the list. @@ -585,7 +577,7 @@ class slist //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT + const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW { return const_iterator(this->non_const_icont().begin()); } //! <b>Effects</b>: Returns a const_iterator to the end of the list. @@ -593,7 +585,7 @@ class slist //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator cend() const BOOST_CONTAINER_NOEXCEPT + const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW { return const_iterator(this->non_const_icont().end()); } //! <b>Returns</b>: The iterator to the element before i in the sequence. @@ -605,7 +597,7 @@ class slist //! <b>Complexity</b>: Linear to the number of elements before i. //! //! <b>Note</b>: Non-standard extension. - iterator previous(iterator p) BOOST_CONTAINER_NOEXCEPT + iterator previous(iterator p) BOOST_NOEXCEPT_OR_NOTHROW { return iterator(this->icont().previous(p.get())); } //! <b>Returns</b>: The const_iterator to the element before i in the sequence. @@ -713,7 +705,7 @@ class slist // ////////////////////////////////////////////// - #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) //! <b>Effects</b>: Inserts an object of type T constructed with //! std::forward<Args>(args)... in the front of the list @@ -723,7 +715,7 @@ class slist //! //! <b>Complexity</b>: Amortized constant time. template <class... Args> - void emplace_front(Args&&... args) + void emplace_front(BOOST_FWD_REF(Args)... args) { this->emplace_after(this->cbefore_begin(), boost::forward<Args>(args)...); } //! <b>Effects</b>: Inserts an object of type T constructed with @@ -734,35 +726,30 @@ class slist //! //! <b>Complexity</b>: Constant template <class... Args> - iterator emplace_after(const_iterator prev, Args&&... args) + iterator emplace_after(const_iterator prev, BOOST_FWD_REF(Args)... args) { NodePtr pnode(AllocHolder::create_node(boost::forward<Args>(args)...)); return iterator(this->icont().insert_after(prev.get(), *pnode)); } - #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING - - #define BOOST_PP_LOCAL_MACRO(n) \ - BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ - void emplace_front(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ - { \ - this->emplace(this->cbegin() \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \ - } \ - \ - BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ - iterator emplace_after(const_iterator prev \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ - { \ - NodePtr pnode (AllocHolder::create_node \ - (BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \ - return iterator(this->icont().insert_after(prev.get(), *pnode)); \ - } \ - //! - #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) - #include BOOST_PP_LOCAL_ITERATE() - - #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING + #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + + #define BOOST_CONTAINER_SLIST_EMPLACE_CODE(N) \ + BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ + void emplace_front(BOOST_MOVE_UREF##N)\ + { this->emplace_after(this->cbefore_begin() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);}\ + \ + BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ + iterator emplace_after(const_iterator p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ + {\ + NodePtr pnode (AllocHolder::create_node(BOOST_MOVE_FWD##N));\ + return iterator(this->icont().insert_after(p.get(), *pnode));\ + }\ + // + BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SLIST_EMPLACE_CODE) + #undef BOOST_CONTAINER_SLIST_EMPLACE_CODE + + #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) //! <b>Effects</b>: Inserts a copy of x at the beginning of the list. @@ -774,7 +761,7 @@ class slist void push_front(const T &x); //! <b>Effects</b>: Constructs a new element in the beginning of the list - //! and moves the resources of mx to this new element. + //! and moves the resources of x to this new element. //! //! <b>Throws</b>: If memory allocation throws. //! @@ -856,7 +843,7 @@ class slist , typename container_detail::enable_if_c < !container_detail::is_convertible<InpIt, size_type>::value && (container_detail::is_input_iterator<InpIt>::value - || container_detail::is_same<alloc_version, allocator_v1>::value + || container_detail::is_same<alloc_version, version_1>::value ) >::type * = 0 #endif @@ -894,14 +881,14 @@ class slist , typename container_detail::enable_if_c < !container_detail::is_convertible<FwdIt, size_type>::value && !(container_detail::is_input_iterator<FwdIt>::value - || container_detail::is_same<alloc_version, allocator_v1>::value + || container_detail::is_same<alloc_version, version_1>::value ) >::type * = 0 ) { //Optimized allocation and construction insertion_functor func(this->icont(), prev.get()); - this->allocate_many_and_construct(first, std::distance(first, last), func); + this->allocate_many_and_construct(first, boost::container::iterator_distance(first, last), func); return iterator(func.inserted_first()); } #endif @@ -952,6 +939,8 @@ class slist //! //! <b>Complexity</b>: Linear to the number of elements on *this and x. void swap(slist& x) + BOOST_NOEXCEPT_IF( allocator_traits_type::propagate_on_container_swap::value + || allocator_traits_type::is_always_equal::value) { AllocHolder::swap(x); } //! <b>Effects</b>: Erases all the elements of the list. @@ -981,7 +970,7 @@ class slist //! //! <b>Note</b>: Iterators of values obtained from list x now point to elements of //! this list. Iterators of this list and all the references are not invalidated. - void splice_after(const_iterator prev_p, slist& x) BOOST_CONTAINER_NOEXCEPT + void splice_after(const_iterator prev_p, slist& x) BOOST_NOEXCEPT_OR_NOTHROW { BOOST_ASSERT(this != &x); BOOST_ASSERT(this->node_alloc() == x.node_alloc()); @@ -1001,7 +990,7 @@ class slist //! //! <b>Note</b>: Iterators of values obtained from list x now point to elements of //! this list. Iterators of this list and all the references are not invalidated. - void splice_after(const_iterator prev_p, BOOST_RV_REF(slist) x) BOOST_CONTAINER_NOEXCEPT + void splice_after(const_iterator prev_p, BOOST_RV_REF(slist) x) BOOST_NOEXCEPT_OR_NOTHROW { this->splice_after(prev_p, static_cast<slist&>(x)); } //! <b>Requires</b>: prev_p must be a valid iterator of this. @@ -1018,7 +1007,7 @@ class slist //! //! <b>Note</b>: Iterators of values obtained from list x now point to elements of this //! list. Iterators of this list and all the references are not invalidated. - void splice_after(const_iterator prev_p, slist& x, const_iterator prev) BOOST_CONTAINER_NOEXCEPT + void splice_after(const_iterator prev_p, slist& x, const_iterator prev) BOOST_NOEXCEPT_OR_NOTHROW { BOOST_ASSERT(this->node_alloc() == x.node_alloc()); this->icont().splice_after(prev_p.get(), x.icont(), prev.get()); @@ -1038,7 +1027,7 @@ class slist //! //! <b>Note</b>: Iterators of values obtained from list x now point to elements of this //! list. Iterators of this list and all the references are not invalidated. - void splice_after(const_iterator prev_p, BOOST_RV_REF(slist) x, const_iterator prev) BOOST_CONTAINER_NOEXCEPT + void splice_after(const_iterator prev_p, BOOST_RV_REF(slist) x, const_iterator prev) BOOST_NOEXCEPT_OR_NOTHROW { this->splice_after(prev_p, static_cast<slist&>(x), prev); } //! <b>Requires</b>: prev_p must be a valid iterator of this. @@ -1056,7 +1045,7 @@ class slist //! <b>Note</b>: Iterators of values obtained from list x now point to elements of this //! list. Iterators of this list and all the references are not invalidated. void splice_after(const_iterator prev_p, slist& x, - const_iterator before_first, const_iterator before_last) BOOST_CONTAINER_NOEXCEPT + const_iterator before_first, const_iterator before_last) BOOST_NOEXCEPT_OR_NOTHROW { BOOST_ASSERT(this->node_alloc() == x.node_alloc()); this->icont().splice_after @@ -1078,13 +1067,13 @@ class slist //! <b>Note</b>: Iterators of values obtained from list x now point to elements of this //! list. Iterators of this list and all the references are not invalidated. void splice_after(const_iterator prev_p, BOOST_RV_REF(slist) x, - const_iterator before_first, const_iterator before_last) BOOST_CONTAINER_NOEXCEPT + const_iterator before_first, const_iterator before_last) BOOST_NOEXCEPT_OR_NOTHROW { this->splice_after(prev_p, static_cast<slist&>(x), before_first, before_last); } //! <b>Requires</b>: prev_p must be a valid iterator of this. //! before_first and before_last must be valid iterators of x. //! prev_p must not be contained in [before_first, before_last) range. - //! n == std::distance(before_first, before_last). + //! n == distance(before_first, before_last). //! this' allocator and x's allocator shall compare equal. //! //! <b>Effects</b>: Transfers the range [before_first + 1, before_last + 1) @@ -1098,7 +1087,7 @@ class slist //! list. Iterators of this list and all the references are not invalidated. void splice_after(const_iterator prev_p, slist& x, const_iterator before_first, const_iterator before_last, - size_type n) BOOST_CONTAINER_NOEXCEPT + size_type n) BOOST_NOEXCEPT_OR_NOTHROW { BOOST_ASSERT(this->node_alloc() == x.node_alloc()); this->icont().splice_after @@ -1108,7 +1097,7 @@ class slist //! <b>Requires</b>: prev_p must be a valid iterator of this. //! before_first and before_last must be valid iterators of x. //! prev_p must not be contained in [before_first, before_last) range. - //! n == std::distance(before_first, before_last). + //! n == distance(before_first, before_last). //! this' allocator and x's allocator shall compare equal. //! //! <b>Effects</b>: Transfers the range [before_first + 1, before_last + 1) @@ -1122,7 +1111,7 @@ class slist //! list. Iterators of this list and all the references are not invalidated. void splice_after(const_iterator prev_p, BOOST_RV_REF(slist) x, const_iterator before_first, const_iterator before_last, - size_type n) BOOST_CONTAINER_NOEXCEPT + size_type n) BOOST_NOEXCEPT_OR_NOTHROW { this->splice_after(prev_p, static_cast<slist&>(x), before_first, before_last, n); } //! <b>Effects</b>: Removes all the elements that compare equal to value. @@ -1134,7 +1123,7 @@ class slist //! <b>Note</b>: The relative order of elements that are not removed is unchanged, //! and iterators to elements that are not removed remain valid. void remove(const T& value) - { this->remove_if(equal_to_value(value)); } + { this->remove_if(equal_to_value_type(value)); } //! <b>Effects</b>: Removes all the elements for which a specified //! predicate is satisfied. @@ -1148,8 +1137,8 @@ class slist template <class Pred> void remove_if(Pred pred) { - typedef ValueCompareToNodeCompare<Pred> Predicate; - this->icont().remove_and_dispose_if(Predicate(pred), Destroyer(this->node_alloc())); + typedef value_to_node_compare<Node, Pred> value_to_node_compare_type; + this->icont().remove_and_dispose_if(value_to_node_compare_type(pred), Destroyer(this->node_alloc())); } //! <b>Effects</b>: Removes adjacent duplicate elements or adjacent @@ -1176,8 +1165,8 @@ class slist template <class Pred> void unique(Pred pred) { - typedef ValueCompareToNodeCompare<Pred> Predicate; - this->icont().unique_and_dispose(Predicate(pred), Destroyer(this->node_alloc())); + typedef value_to_node_compare<Node, Pred> value_to_node_compare_type; + this->icont().unique_and_dispose(value_to_node_compare_type(pred), Destroyer(this->node_alloc())); } //! <b>Requires</b>: The lists x and *this must be distinct. @@ -1225,9 +1214,9 @@ class slist template <class StrictWeakOrdering> void merge(slist& x, StrictWeakOrdering comp) { + typedef value_to_node_compare<Node, StrictWeakOrdering> value_to_node_compare_type; BOOST_ASSERT(this->node_alloc() == x.node_alloc()); - this->icont().merge(x.icont(), - ValueCompareToNodeCompare<StrictWeakOrdering>(comp)); + this->icont().merge(x.icont(), value_to_node_compare_type(comp)); } //! <b>Requires</b>: p must be a comparison function that induces a strict weak @@ -1272,10 +1261,11 @@ class slist template <class StrictWeakOrdering> void sort(StrictWeakOrdering comp) { + typedef value_to_node_compare<Node, StrictWeakOrdering> value_to_node_compare_type; // nothing if the slist has length 0 or 1. if (this->size() < 2) return; - this->icont().sort(ValueCompareToNodeCompare<StrictWeakOrdering>(comp)); + this->icont().sort(value_to_node_compare_type(comp)); } //! <b>Effects</b>: Reverses the order of elements in the list. @@ -1285,7 +1275,7 @@ class slist //! <b>Complexity</b>: This function is linear time. //! //! <b>Note</b>: Iterators and references are not invalidated - void reverse() BOOST_CONTAINER_NOEXCEPT + void reverse() BOOST_NOEXCEPT_OR_NOTHROW { this->icont().reverse(); } ////////////////////////////////////////////// @@ -1294,7 +1284,7 @@ class slist // ////////////////////////////////////////////// - #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) //! <b>Effects</b>: Inserts an object of type T constructed with //! std::forward<Args>(args)... before p @@ -1304,24 +1294,22 @@ class slist //! //! <b>Complexity</b>: Linear to the elements before p template <class... Args> - iterator emplace(const_iterator p, Args&&... args) + iterator emplace(const_iterator p, BOOST_FWD_REF(Args)... args) { return this->emplace_after(this->previous(p), boost::forward<Args>(args)...); } - #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING + #else - #define BOOST_PP_LOCAL_MACRO(n) \ - BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ - iterator emplace (const_iterator p \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ - { \ - return this->emplace_after \ - (this->previous(p) \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \ - } \ - //! - #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) - #include BOOST_PP_LOCAL_ITERATE() - #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING + #define BOOST_CONTAINER_SLIST_EMPLACE_CODE(N) \ + BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ + iterator emplace(const_iterator p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ + {\ + return this->emplace_after(this->previous(p) BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\ + }\ + // + BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SLIST_EMPLACE_CODE) + #undef BOOST_CONTAINER_SLIST_EMPLACE_CODE + + #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) //! <b>Requires</b>: p must be a valid iterator of *this. @@ -1337,7 +1325,7 @@ class slist //! <b>Requires</b>: p must be a valid iterator of *this. //! - //! <b>Effects</b>: Insert a new element before p with mx's resources. + //! <b>Effects</b>: Insert a new element before p with x's resources. //! //! <b>Returns</b>: an iterator to the inserted element. //! @@ -1374,7 +1362,7 @@ class slist //! <b>Throws</b>: If memory allocation throws, T's constructor from a //! dereferenced InpIt throws. //! - //! <b>Complexity</b>: Linear to std::distance [first, last) plus + //! <b>Complexity</b>: Linear to distance [first, last) plus //! linear to the elements before p. template <class InIter> iterator insert(const_iterator p, InIter first, InIter last) @@ -1409,7 +1397,7 @@ class slist //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Linear to the number of elements before p. - iterator erase(const_iterator p) BOOST_CONTAINER_NOEXCEPT + iterator erase(const_iterator p) BOOST_NOEXCEPT_OR_NOTHROW { return iterator(this->erase_after(previous(p))); } //! <b>Requires</b>: first and last must be valid iterator to elements in *this. @@ -1420,7 +1408,7 @@ class slist //! //! <b>Complexity</b>: Linear to the distance between first and last plus //! linear to the elements before first. - iterator erase(const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT + iterator erase(const_iterator first, const_iterator last) BOOST_NOEXCEPT_OR_NOTHROW { return iterator(this->erase_after(previous(first), last)); } //! <b>Requires</b>: p must point to an element contained @@ -1435,7 +1423,7 @@ class slist //! //! <b>Note</b>: Iterators of values obtained from list x now point to elements of //! this list. Iterators of this list and all the references are not invalidated. - void splice(const_iterator p, slist& x) BOOST_CONTAINER_NOEXCEPT + void splice(const_iterator p, slist& x) BOOST_NOEXCEPT_OR_NOTHROW { this->splice_after(this->previous(p), x); } //! <b>Requires</b>: p must point to an element contained @@ -1450,7 +1438,7 @@ class slist //! //! <b>Note</b>: Iterators of values obtained from list x now point to elements of //! this list. Iterators of this list and all the references are not invalidated. - void splice(const_iterator p, BOOST_RV_REF(slist) x) BOOST_CONTAINER_NOEXCEPT + void splice(const_iterator p, BOOST_RV_REF(slist) x) BOOST_NOEXCEPT_OR_NOTHROW { this->splice(p, static_cast<slist&>(x)); } //! <b>Requires</b>: p must point to an element contained @@ -1467,7 +1455,7 @@ class slist //! //! <b>Note</b>: Iterators of values obtained from list x now point to elements of this //! list. Iterators of this list and all the references are not invalidated. - void splice(const_iterator p, slist& x, const_iterator i) BOOST_CONTAINER_NOEXCEPT + void splice(const_iterator p, slist& x, const_iterator i) BOOST_NOEXCEPT_OR_NOTHROW { this->splice_after(this->previous(p), x, this->previous(i)); } //! <b>Requires</b>: p must point to an element contained @@ -1484,7 +1472,7 @@ class slist //! //! <b>Note</b>: Iterators of values obtained from list x now point to elements of this //! list. Iterators of this list and all the references are not invalidated. - void splice(const_iterator p, BOOST_RV_REF(slist) x, const_iterator i) BOOST_CONTAINER_NOEXCEPT + void splice(const_iterator p, BOOST_RV_REF(slist) x, const_iterator i) BOOST_NOEXCEPT_OR_NOTHROW { this->splice(p, static_cast<slist&>(x), i); } //! <b>Requires</b>: p must point to an element contained @@ -1501,7 +1489,7 @@ class slist //! //! <b>Note</b>: Iterators of values obtained from list x now point to elements of this //! list. Iterators of this list and all the references are not invalidated. - void splice(const_iterator p, slist& x, const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT + void splice(const_iterator p, slist& x, const_iterator first, const_iterator last) BOOST_NOEXCEPT_OR_NOTHROW { this->splice_after(this->previous(p), x, this->previous(first), this->previous(last)); } //! <b>Requires</b>: p must point to an element contained @@ -1518,28 +1506,14 @@ class slist //! //! <b>Note</b>: Iterators of values obtained from list x now point to elements of this //! list. Iterators of this list and all the references are not invalidated. - void splice(const_iterator p, BOOST_RV_REF(slist) x, const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT + void splice(const_iterator p, BOOST_RV_REF(slist) x, const_iterator first, const_iterator last) BOOST_NOEXCEPT_OR_NOTHROW { this->splice(p, static_cast<slist&>(x), first, last); } //! <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 slist& x, const slist& y) - { - if(x.size() != y.size()){ - return false; - } - typedef typename slist<T,Allocator>::const_iterator const_iterator; - const_iterator end1 = x.end(); - - const_iterator i1 = x.begin(); - const_iterator i2 = y.begin(); - while (i1 != end1 && *i1 == *i2){ - ++i1; - ++i2; - } - return i1 == end1; - } + { 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 //! @@ -1551,7 +1525,7 @@ class slist //! //! <b>Complexity</b>: Linear to the number of elements in the container. friend bool operator<(const slist& x, const slist& y) - { return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } + { 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 //! @@ -1672,8 +1646,11 @@ namespace boost { //!specialization for optimizations template <class T, class Allocator> struct has_trivial_destructor_after_move<boost::container::slist<T, Allocator> > - : public ::boost::has_trivial_destructor_after_move<Allocator> -{}; +{ + typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer; + static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value && + ::boost::has_trivial_destructor_after_move<pointer>::value; +}; namespace container { @@ -1686,9 +1663,13 @@ namespace container { #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED -//Ummm, I don't like to define things in namespace std, but -//there is no other way -namespace std { +#if defined(__clang__) && defined(_LIBCPP_VERSION) + #define BOOST_CONTAINER_CLANG_INLINE_STD_NS + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wc++11-extensions" +#endif + +BOOST_CONTAINER_STD_NS_BEG template <class T, class Allocator> class insert_iterator<boost::container::slist<T, Allocator> > @@ -1721,7 +1702,12 @@ class insert_iterator<boost::container::slist<T, Allocator> > insert_iterator<Container>& operator++(int){ return *this; } }; -} //namespace std; +BOOST_CONTAINER_STD_NS_END + +#ifdef BOOST_CONTAINER_CLANG_INLINE_STD_NS + #pragma GCC diagnostic pop + #undef BOOST_CONTAINER_CLANG_INLINE_STD_NS +#endif //BOOST_CONTAINER_CLANG_INLINE_STD_NS #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED diff --git a/boost/container/small_vector.hpp b/boost/container/small_vector.hpp new file mode 100644 index 0000000000..7ef0c238a3 --- /dev/null +++ b/boost/container/small_vector.hpp @@ -0,0 +1,565 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2015-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_CONTAINER_SMALL_VECTOR_HPP +#define BOOST_CONTAINER_CONTAINER_SMALL_VECTOR_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> + +// container +#include <boost/container/container_fwd.hpp> +#include <boost/container/vector.hpp> +#include <boost/container/allocator_traits.hpp> +#include <boost/container/new_allocator.hpp> //new_allocator +// container/detail +#include <boost/container/detail/type_traits.hpp> +#include <boost/container/detail/version_type.hpp> + +//move +#include <boost/move/adl_move_swap.hpp> +#include <boost/move/iterator.hpp> + +//move/detail +#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +#include <boost/move/detail/fwd_macros.hpp> +#endif + +//std +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) +#include <initializer_list> //for std::initializer_list +#endif + +namespace boost { +namespace container { + +#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED + +template <class T, class Allocator = new_allocator<T> > +class small_vector_base; + +#endif + +//! A non-standard allocator used to implement `small_vector`. +//! Users should never use it directly. It is described here +//! for documentation purposes. +//! +//! This allocator inherits from a standard-conforming allocator +//! and forwards member functiond to the standard allocator except +//! when internal storage is being used as memory source. +//! +//! This allocator is a "partially_propagable" allocator and +//! defines `is_partially_propagable` as true_type. +//! +//! A partially propagable allocator means that not all storage +//! allocatod by an instance of `small_vector_allocator` can be +//! deallocated by another instance of this type, even is both +//! instances compare equal or an instance is propagated to another +//! one using the copy/move constructor or assignment. The storage that +//! can never be propagated is identified by `storage_is_unpropagable(p)`. +//! +//! `boost::container::vector` supports partially propagable allocators +//! fallbacking to deep copy/swap/move operations when internal storage +//! is being used to store vector elements. +//! +//! `small_vector_allocator` assumes that will be instantiated as +//! `boost::container::vector< T, small_vector_allocator<Allocator> >` +//! and internal storage can be obtained downcasting that vector +//! to `small_vector_base<T>`. +template<class Allocator> +class small_vector_allocator + : public Allocator +{ + typedef unsigned int allocation_type; + #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED + private: + + BOOST_COPYABLE_AND_MOVABLE(small_vector_allocator) + + const Allocator &as_base() const + { return static_cast<const Allocator&>(*this); } + + Allocator &as_base() + { return static_cast<Allocator&>(*this); } + + #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED + + public: + #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED + typedef allocator_traits<Allocator> allocator_traits_type; + #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED + + typedef typename allocator_traits<Allocator>::value_type value_type; + typedef typename allocator_traits<Allocator>::pointer pointer; + typedef typename allocator_traits<Allocator>::const_pointer const_pointer; + typedef typename allocator_traits<Allocator>::reference reference; + typedef typename allocator_traits<Allocator>::const_reference const_reference; + typedef typename allocator_traits<Allocator>::size_type size_type; + typedef typename allocator_traits<Allocator>::difference_type difference_type; + typedef typename allocator_traits<Allocator>::void_pointer void_pointer; + typedef typename allocator_traits<Allocator>::const_void_pointer const_void_pointer; + + typedef typename allocator_traits<Allocator>::propagate_on_container_copy_assignment propagate_on_container_copy_assignment; + typedef typename allocator_traits<Allocator>::propagate_on_container_move_assignment propagate_on_container_move_assignment; + typedef typename allocator_traits<Allocator>::propagate_on_container_swap propagate_on_container_swap; + //! An integral constant with member `::value == false` + typedef BOOST_CONTAINER_IMPDEF(container_detail::bool_<false>) is_always_equal; + //! An integral constant with member `::value == true` + typedef BOOST_CONTAINER_IMPDEF(container_detail::bool_<true>) is_partially_propagable; + + BOOST_CONTAINER_DOCIGN(typedef container_detail::version_type<small_vector_allocator BOOST_CONTAINER_I 1> version;) + + //!Obtains an small_vector_allocator that allocates + //!objects of type T2 + template<class T2> + struct rebind + { + typedef typename allocator_traits<Allocator>::template rebind_alloc<T2>::type other; + }; + + #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + //!Constructor from arbitrary arguments + template<class ...Args> + explicit small_vector_allocator(BOOST_FWD_REF(Args) ...args) + : Allocator(::boost::forward<Args>(args)...) + {} + #else + #define BOOST_CONTAINER_SMALL_VECTOR_ALLOCATOR_CTOR_CODE(N) \ + BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ + explicit small_vector_allocator(BOOST_MOVE_UREF##N)\ + : Allocator(BOOST_MOVE_FWD##N)\ + {}\ + // + BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SMALL_VECTOR_ALLOCATOR_CTOR_CODE) + #undef BOOST_CONTAINER_SMALL_VECTOR_ALLOCATOR_CTOR_CODE + #endif + + //!Constructor from other small_vector_allocator. + //!Never throws + small_vector_allocator(const small_vector_allocator &other) BOOST_NOEXCEPT_OR_NOTHROW + : Allocator(other.as_base()) + {} + + //!Move constructor from small_vector_allocator. + //!Never throws + small_vector_allocator(BOOST_RV_REF(small_vector_allocator) other) BOOST_NOEXCEPT_OR_NOTHROW + : Allocator(::boost::move(other.as_base())) + {} + + //!Constructor from related small_vector_allocator. + //!Never throws + template<class OtherAllocator> + small_vector_allocator(const small_vector_allocator<OtherAllocator> &other) BOOST_NOEXCEPT_OR_NOTHROW + : Allocator(other.as_base()) + {} + + //!Move constructor from related small_vector_allocator. + //!Never throws + template<class OtherAllocator> + small_vector_allocator(BOOST_RV_REF(small_vector_allocator<OtherAllocator>) other) BOOST_NOEXCEPT_OR_NOTHROW + : Allocator(::boost::move(other.as_base())) + {} + + //!Assignment from other small_vector_allocator. + //!Never throws + small_vector_allocator & operator=(BOOST_COPY_ASSIGN_REF(small_vector_allocator) other) BOOST_NOEXCEPT_OR_NOTHROW + { return static_cast<small_vector_allocator&>(this->Allocator::operator=(other.as_base())); } + + //!Move constructor from other small_vector_allocator. + //!Never throws + small_vector_allocator & operator=(BOOST_RV_REF(small_vector_allocator) other) BOOST_NOEXCEPT_OR_NOTHROW + { return static_cast<small_vector_allocator&>(this->Allocator::operator=(::boost::move(other.as_base()))); } + + //!Assignment from related small_vector_allocator. + //!Never throws + template<class OtherAllocator> + small_vector_allocator & operator=(BOOST_COPY_ASSIGN_REF(small_vector_allocator<OtherAllocator>) other) BOOST_NOEXCEPT_OR_NOTHROW + { return static_cast<small_vector_allocator&>(this->Allocator::operator=(other.as_base())); } + + //!Move assignment from related small_vector_allocator. + //!Never throws + template<class OtherAllocator> + small_vector_allocator & operator=(BOOST_RV_REF(small_vector_allocator<OtherAllocator>) other) BOOST_NOEXCEPT_OR_NOTHROW + { return static_cast<small_vector_allocator&>(this->Allocator::operator=(::boost::move(other.as_base()))); } + + //!Allocates storage from the standard-conforming allocator + pointer allocate(size_type count, const_void_pointer hint = const_void_pointer()) + { return allocator_traits_type::allocate(this->as_base(), count, hint); } + + //!Deallocates previously allocated memory. + //!Never throws + void deallocate(pointer ptr, size_type n) BOOST_NOEXCEPT_OR_NOTHROW + { + if(!this->is_internal_storage(ptr)) + allocator_traits_type::deallocate(this->as_base(), ptr, n); + } + + //!Returns the maximum number of elements that could be allocated. + //!Never throws + size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW + { return allocator_traits_type::max_size(this->as_base()); } + + small_vector_allocator select_on_container_copy_construction() const + { return small_vector_allocator(allocator_traits_type::select_on_container_copy_construction(this->as_base())); } + + bool storage_is_unpropagable(pointer p) const + { return this->is_internal_storage(p) || allocator_traits_type::storage_is_unpropagable(this->as_base(), p); } + + //!Swaps two allocators, does nothing + //!because this small_vector_allocator is stateless + friend void swap(small_vector_allocator &l, small_vector_allocator &r) BOOST_NOEXCEPT_OR_NOTHROW + { boost::adl_move_swap(l.as_base(), r.as_base()); } + + //!An small_vector_allocator always compares to true, as memory allocated with one + //!instance can be deallocated by another instance (except for unpropagable storage) + friend bool operator==(const small_vector_allocator &l, const small_vector_allocator &r) BOOST_NOEXCEPT_OR_NOTHROW + { return allocator_traits_type::equal(l.as_base(), r.as_base()); } + + //!An small_vector_allocator always compares to false, as memory allocated with one + //!instance can be deallocated by another instance + friend bool operator!=(const small_vector_allocator &l, const small_vector_allocator &r) BOOST_NOEXCEPT_OR_NOTHROW + { return !(l == r); } + + #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED + /* + //!An advanced function that offers in-place expansion shrink to fit and new allocation + //!capabilities. Memory allocated with this function can only be deallocated with deallocate() + //!or deallocate_many(). + //!This function is available only with Version == 2 + pointer allocation_command(allocation_type command, + size_type limit_size, + size_type &prefer_in_recvd_out_size, + pointer &reuse) + { return allocator_traits_type::allocation_command(command, limit_size, prefer_in_recvd_out_size, reuse); } + + //!Returns maximum the number of objects the previously allocated memory + //!pointed by p can hold. + //!Memory must not have been allocated with + //!allocate_one or allocate_individual. + //!This function is available only with Version == 2 + size_type size(pointer p) const BOOST_NOEXCEPT_OR_NOTHROW + { return allocator_traits_type::size(p); } + */ + private: + /* + //!Allocates just one object. Memory allocated with this function + //!must be deallocated only with deallocate_one(). + //!Throws bad_alloc if there is no enough memory + //!This function is available only with Version == 2 + using Allocator::allocate_one; + using Allocator::allocate_individual; + using Allocator::deallocate_one; + using Allocator::deallocate_individual; + using Allocator::allocate_many; + using Allocator::deallocate_many;*/ + + bool is_internal_storage(pointer p) const + { return this->internal_storage() == p; } + + pointer internal_storage() const + { + typedef typename Allocator::value_type value_type; + typedef container_detail::vector_alloc_holder< small_vector_allocator<Allocator> > vector_alloc_holder_t; + typedef vector<value_type, small_vector_allocator<Allocator> > vector_base; + typedef small_vector_base<value_type, Allocator> derived_type; + // + const vector_alloc_holder_t &v_holder = static_cast<const vector_alloc_holder_t &>(*this); + const vector_base &v_base = reinterpret_cast<const vector_base &>(v_holder); + const derived_type &d_base = static_cast<const derived_type &>(v_base); + return d_base.internal_storage(); + } + #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED +}; + +//! This class consists of common code from all small_vector<T, N> types that don't depend on the +//! "N" template parameter. This class is non-copyable and non-destructible, so this class tipically +//! used as reference argument to functions that read or write small vectors. Since `small_vector<T, N>` +//! derives from `small_vector_base<T>`, the conversion to `small_vector_base` is implicit: +//! <code> +//! +//! //Clients can pass any small_vector<Foo, N>. +//! void read_any_small_vector_of_foo(const small_vector_base<Foo> &in_parameter); +//! void modify_any_small_vector_of_foo(small_vector_base<Foo> &out_parameter); +//! +//! void some_function() +//! { +//! small_vector<Foo, 8> myvector; +//! read_any_small_vector_of_foo(myvector); // Reads myvector +//! modify_any_small_vector_of_foo(myvector); // Modifies myvector +//! } +//! </code> +//! +//! All `boost::container:vector` member functions are inherited. See `vector` documentation for details. +//! +template <class T, class SecondaryAllocator> +class small_vector_base + : public vector<T, small_vector_allocator<SecondaryAllocator> > +{ + #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED + typedef typename allocator_traits<SecondaryAllocator>::pointer pointer; + + BOOST_COPYABLE_AND_MOVABLE(small_vector_base) + + friend class small_vector_allocator<SecondaryAllocator>; + + pointer internal_storage() const BOOST_NOEXCEPT_OR_NOTHROW + { + return boost::intrusive::pointer_traits<pointer>::pointer_to + (*const_cast<T*>(static_cast<const T*>(static_cast<const void*>(&m_storage_start)))); + } + + typedef vector<T, small_vector_allocator<SecondaryAllocator> > base_type; + base_type &as_base() { return static_cast<base_type&>(*this); } + const base_type &as_base() const { return static_cast<const base_type&>(*this); } + + public: + typedef typename container_detail::aligned_storage + <sizeof(T), container_detail::alignment_of<T>::value>::type storage_type; + typedef small_vector_allocator<SecondaryAllocator> allocator_type; + + protected: + typedef typename base_type::initial_capacity_t initial_capacity_t; + + explicit small_vector_base(initial_capacity_t, std::size_t initial_capacity) + : base_type(initial_capacity_t(), this->internal_storage(), initial_capacity) + {} + + template<class AllocFwd> + explicit small_vector_base(initial_capacity_t, std::size_t capacity, BOOST_FWD_REF(AllocFwd) a) + : base_type(initial_capacity_t(), this->internal_storage(), capacity, ::boost::forward<AllocFwd>(a)) + {} + + ~small_vector_base(){} + + using base_type::is_propagable_from; + using base_type::steal_resources; + + private: + //The only member + storage_type m_storage_start; + + #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED + + public: + small_vector_base& operator=(BOOST_COPY_ASSIGN_REF(small_vector_base) other) + { return static_cast<small_vector_base&>(this->base_type::operator=(static_cast<base_type const&>(other))); } + + small_vector_base& operator=(BOOST_RV_REF(small_vector_base) other) + { return static_cast<small_vector_base&>(this->base_type::operator=(BOOST_MOVE_BASE(base_type, other))); } + + void swap(small_vector_base &other) + { return this->base_type::swap(other); } +}; + +#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED + +///////////////////////////////////////////////////// +// +// small_vector_storage_calculator +// +///////////////////////////////////////////////////// +template<std::size_t Needed, std::size_t Hdr, std::size_t SSize, bool NeedsZero = (0u == Needed || Needed <= Hdr)> +struct small_vector_storage_calculator_helper +{ + static const std::size_t value = (Needed - Hdr - 1u)/SSize + 1u; +}; + +template<std::size_t Needed, std::size_t Hdr, std::size_t SSize> +struct small_vector_storage_calculator_helper<Needed, Hdr, SSize, true> +{ + static const std::size_t value = 0u; +}; + +template<class Storage, class Allocator, class T, std::size_t N> +struct small_vector_storage_calculator +{ + typedef small_vector_base<T, Allocator> svh_type; + typedef vector<T, small_vector_allocator<Allocator> > svhb_type; + static const std::size_t s_align = container_detail::alignment_of<Storage>::value; + static const std::size_t s_size = sizeof(Storage); + static const std::size_t svh_sizeof = sizeof(svh_type); + static const std::size_t svhb_sizeof = sizeof(svhb_type); + static const std::size_t s_start = ((svhb_sizeof-1)/s_align+1)*s_align; + static const std::size_t header_bytes = svh_sizeof-s_start; + static const std::size_t needed_bytes = sizeof(T)*N; + static const std::size_t needed_extra_storages = + small_vector_storage_calculator_helper<needed_bytes, header_bytes, s_size>::value; +}; + +///////////////////////////////////////////////////// +// +// small_vector_storage_definer +// +///////////////////////////////////////////////////// +template<class Storage, std::size_t N> +struct small_vector_storage +{ + Storage m_rest_of_storage[N]; +}; + +template<class Storage> +struct small_vector_storage<Storage, 0> +{}; + +template<class Allocator, std::size_t N> +struct small_vector_storage_definer +{ + typedef typename Allocator::value_type value_type; + typedef typename small_vector_base<value_type, Allocator>::storage_type storage_type; + static const std::size_t needed_extra_storages = + small_vector_storage_calculator<storage_type, Allocator, value_type, N>::needed_extra_storages; + typedef small_vector_storage<storage_type, needed_extra_storages> type; +}; + +#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED + +//! small_vector a vector-like container optimized for the case when it contains few elements. +//! It contains some preallocated elements in-place, which allows it to avoid the use of dynamic storage allocation +//! when the actual number of elements is below that preallocated threshold. +//! +//! `small_vector<T, N, Allocator>` is convertible to `small_vector_base<T, Allocator>` that is independent +//! from the preallocated element capacity, so client code does not need to be templated on that N argument. +//! +//! All `boost::container::vector` member functions are inherited. See `vector` documentation for details. +//! +//! \tparam T The type of object that is stored in the small_vector +//! \tparam N The number of preallocated elements stored inside small_vector. It shall be less than Allocator::max_size(); +//! \tparam Allocator The allocator used for memory management when the number of elements exceeds N. +template <class T, std::size_t N, class Allocator BOOST_CONTAINER_DOCONLY(= new_allocator<T>) > +class small_vector : public small_vector_base<T, Allocator> + #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED + , private small_vector_storage_definer<Allocator, N>::type + #endif +{ + #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED + typedef small_vector_base<T, Allocator> base_type; + typedef typename small_vector_storage_definer<Allocator, N>::type remaining_storage_holder; + + BOOST_COPYABLE_AND_MOVABLE(small_vector) + + typedef typename base_type::initial_capacity_t initial_capacity_t; + typedef allocator_traits<typename base_type::allocator_type> allocator_traits_type; + + public: + typedef small_vector_storage_calculator< typename small_vector_base<T, Allocator> + ::storage_type, Allocator, T, N> storage_test; + + static const std::size_t needed_extra_storages = storage_test::needed_extra_storages; + static const std::size_t needed_bytes = storage_test::needed_bytes; + static const std::size_t header_bytes = storage_test::header_bytes; + static const std::size_t s_start = storage_test::s_start; + + typedef typename base_type::allocator_type allocator_type; + typedef typename base_type::size_type size_type; + typedef typename base_type::value_type value_type; + + static std::size_t internal_capacity() + { return (sizeof(small_vector) - storage_test::s_start)/sizeof(T); } + + #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED + + public: + small_vector() + : base_type(initial_capacity_t(), internal_capacity()) + {} + + explicit small_vector(size_type n) + : base_type(initial_capacity_t(), internal_capacity()) + { this->resize(n); } + + explicit small_vector(const allocator_type &a) + : base_type(initial_capacity_t(), internal_capacity(), a) + {} + + small_vector(size_type n, const allocator_type &a) + : base_type(initial_capacity_t(), internal_capacity(), a) + { this->resize(n); } + + small_vector(const small_vector &other) + : base_type( initial_capacity_t(), internal_capacity() + , allocator_traits_type::select_on_container_copy_construction(other.get_stored_allocator())) + { this->assign(other.cbegin(), other.cend()); } + + small_vector(const small_vector &other, const allocator_type &a) + : base_type(initial_capacity_t(), internal_capacity(), a) + { this->assign(other.cbegin(), other.cend()); } + + small_vector(BOOST_RV_REF(small_vector) other) + : base_type(initial_capacity_t(), internal_capacity(), ::boost::move(other.get_stored_allocator())) + { this->move_construct_impl(other, other.get_stored_allocator()); } + + small_vector(BOOST_RV_REF(small_vector) other, const allocator_type &a) + : base_type(initial_capacity_t(), internal_capacity(), a) + { this->move_construct_impl(other, a); } + + #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + small_vector(std::initializer_list<value_type> il, const allocator_type& a = allocator_type()) + : base_type(initial_capacity_t(), internal_capacity(), a) + { + this->assign(il.begin(), il.end()); + } + #endif + + small_vector& operator=(BOOST_COPY_ASSIGN_REF(small_vector) other) + { return static_cast<small_vector&>(this->base_type::operator=(static_cast<base_type const&>(other))); } + + small_vector& operator=(BOOST_RV_REF(small_vector) other) + { return static_cast<small_vector&>(this->base_type::operator=(BOOST_MOVE_BASE(base_type, other))); } + + void swap(small_vector &other) + { return this->base_type::swap(other); } + + #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED + private: + void move_construct_impl(small_vector &x, const allocator_type &a) + { + if(base_type::is_propagable_from(x.get_stored_allocator(), x.data(), a, true)){ + 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 ())) + ); + } + } + #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED +}; + +}} + +#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED +/* +namespace boost { + +//!has_trivial_destructor_after_move<> == true_type +//!specialization for optimizations +template <class T, class Allocator> +struct has_trivial_destructor_after_move<boost::container::vector<T, Allocator> > +{ + typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer; + static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value && + ::boost::has_trivial_destructor_after_move<pointer>::value; +}; + +} +*/ +#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED + +#include <boost/container/detail/config_end.hpp> + +#endif // #ifndef BOOST_CONTAINER_CONTAINER_SMALL_VECTOR_HPP diff --git a/boost/container/stable_vector.hpp b/boost/container/stable_vector.hpp index b8b415758e..76c9e9f07b 100644 --- a/boost/container/stable_vector.hpp +++ b/boost/container/stable_vector.hpp @@ -19,48 +19,59 @@ #ifndef BOOST_CONTAINER_STABLE_VECTOR_HPP #define BOOST_CONTAINER_STABLE_VECTOR_HPP -#if defined(_MSC_VER) +#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> + +// container +#include <boost/container/allocator_traits.hpp> #include <boost/container/container_fwd.hpp> -#include <boost/assert.hpp> +#include <boost/container/new_allocator.hpp> //new_allocator #include <boost/container/throw_exception.hpp> +// container/detail +#include <boost/container/detail/addressof.hpp> +#include <boost/container/detail/algorithm.hpp> //algo_equal(), algo_lexicographical_compare +#include <boost/container/detail/alloc_helpers.hpp> #include <boost/container/detail/allocator_version_traits.hpp> -#include <boost/container/detail/utilities.hpp> +#include <boost/container/detail/construct_in_place.hpp> +#include <boost/container/detail/iterator.hpp> #include <boost/container/detail/iterators.hpp> -#include <boost/container/detail/algorithms.hpp> -#include <boost/container/allocator_traits.hpp> -#include <boost/container/throw_exception.hpp> +#include <boost/container/detail/placement_new.hpp> +#include <boost/container/detail/to_raw_pointer.hpp> +#include <boost/container/detail/type_traits.hpp> +// intrusive #include <boost/intrusive/pointer_traits.hpp> -#include <boost/core/no_exceptions_support.hpp> -#include <boost/aligned_storage.hpp> +// intrusive/detail +#include <boost/intrusive/detail/minimal_pair_header.hpp> //pair +// move #include <boost/move/utility_core.hpp> #include <boost/move/iterator.hpp> +#include <boost/move/adl_move_swap.hpp> +// move/detail #include <boost/move/detail/move_helpers.hpp> -#include <boost/container/detail/placement_new.hpp> -#include <algorithm> - - -#include <memory> +// other +#include <boost/assert.hpp> +#include <boost/core/no_exceptions_support.hpp> +// std +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) +#include <initializer_list> +#endif #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED - -#include <boost/container/vector.hpp> - -//#define STABLE_VECTOR_ENABLE_INVARIANT_CHECKING - + #include <boost/container/vector.hpp> + //#define STABLE_VECTOR_ENABLE_INVARIANT_CHECKING #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED namespace boost { namespace container { -#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) -#include <initializer_list> -#endif - #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED namespace stable_vector_detail{ @@ -261,103 +272,103 @@ class stable_vector_iterator public: - explicit stable_vector_iterator(node_base_ptr p) BOOST_CONTAINER_NOEXCEPT + explicit stable_vector_iterator(node_base_ptr p) BOOST_NOEXCEPT_OR_NOTHROW : m_pn(p) {} - stable_vector_iterator() BOOST_CONTAINER_NOEXCEPT + stable_vector_iterator() BOOST_NOEXCEPT_OR_NOTHROW : m_pn() //Value initialization to achieve "null iterators" (N3644) {} - stable_vector_iterator(stable_vector_iterator<Pointer, false> const& other) BOOST_CONTAINER_NOEXCEPT + stable_vector_iterator(stable_vector_iterator<Pointer, false> const& other) BOOST_NOEXCEPT_OR_NOTHROW : m_pn(other.node_pointer()) {} - node_ptr node_pointer() const BOOST_CONTAINER_NOEXCEPT + node_ptr node_pointer() const BOOST_NOEXCEPT_OR_NOTHROW { return node_ptr_traits::static_cast_from(m_pn); } public: //Pointer like operators - reference operator*() const BOOST_CONTAINER_NOEXCEPT + reference operator*() const BOOST_NOEXCEPT_OR_NOTHROW { return node_pointer()->value; } - pointer operator->() const BOOST_CONTAINER_NOEXCEPT + pointer operator->() const BOOST_NOEXCEPT_OR_NOTHROW { return ptr_traits::pointer_to(this->operator*()); } //Increment / Decrement - stable_vector_iterator& operator++() BOOST_CONTAINER_NOEXCEPT + stable_vector_iterator& operator++() BOOST_NOEXCEPT_OR_NOTHROW { node_base_ptr_ptr p(this->m_pn->up); this->m_pn = *(++p); return *this; } - stable_vector_iterator operator++(int) BOOST_CONTAINER_NOEXCEPT + stable_vector_iterator operator++(int) BOOST_NOEXCEPT_OR_NOTHROW { stable_vector_iterator tmp(*this); ++*this; return stable_vector_iterator(tmp); } - stable_vector_iterator& operator--() BOOST_CONTAINER_NOEXCEPT + stable_vector_iterator& operator--() BOOST_NOEXCEPT_OR_NOTHROW { node_base_ptr_ptr p(this->m_pn->up); this->m_pn = *(--p); return *this; } - stable_vector_iterator operator--(int) BOOST_CONTAINER_NOEXCEPT + stable_vector_iterator operator--(int) BOOST_NOEXCEPT_OR_NOTHROW { stable_vector_iterator tmp(*this); --*this; return stable_vector_iterator(tmp); } - reference operator[](difference_type off) const BOOST_CONTAINER_NOEXCEPT + reference operator[](difference_type off) const BOOST_NOEXCEPT_OR_NOTHROW { return node_ptr_traits::static_cast_from(this->m_pn->up[off])->value; } - stable_vector_iterator& operator+=(difference_type off) BOOST_CONTAINER_NOEXCEPT + stable_vector_iterator& operator+=(difference_type off) BOOST_NOEXCEPT_OR_NOTHROW { if(off) this->m_pn = this->m_pn->up[off]; return *this; } - friend stable_vector_iterator operator+(const stable_vector_iterator &left, difference_type off) BOOST_CONTAINER_NOEXCEPT + friend stable_vector_iterator operator+(const stable_vector_iterator &left, difference_type off) BOOST_NOEXCEPT_OR_NOTHROW { stable_vector_iterator tmp(left); tmp += off; return tmp; } - friend stable_vector_iterator operator+(difference_type off, const stable_vector_iterator& right) BOOST_CONTAINER_NOEXCEPT + friend stable_vector_iterator operator+(difference_type off, const stable_vector_iterator& right) BOOST_NOEXCEPT_OR_NOTHROW { stable_vector_iterator tmp(right); tmp += off; return tmp; } - stable_vector_iterator& operator-=(difference_type off) BOOST_CONTAINER_NOEXCEPT + stable_vector_iterator& operator-=(difference_type off) BOOST_NOEXCEPT_OR_NOTHROW { *this += -off; return *this; } - friend stable_vector_iterator operator-(const stable_vector_iterator &left, difference_type off) BOOST_CONTAINER_NOEXCEPT + friend stable_vector_iterator operator-(const stable_vector_iterator &left, difference_type off) BOOST_NOEXCEPT_OR_NOTHROW { stable_vector_iterator tmp(left); tmp -= off; return tmp; } - friend difference_type operator-(const stable_vector_iterator& left, const stable_vector_iterator& right) BOOST_CONTAINER_NOEXCEPT + friend difference_type operator-(const stable_vector_iterator& left, const stable_vector_iterator& right) BOOST_NOEXCEPT_OR_NOTHROW { return left.m_pn->up - right.m_pn->up; } //Comparison operators - friend bool operator== (const stable_vector_iterator& l, const stable_vector_iterator& r) BOOST_CONTAINER_NOEXCEPT + friend bool operator== (const stable_vector_iterator& l, const stable_vector_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW { return l.m_pn == r.m_pn; } - friend bool operator!= (const stable_vector_iterator& l, const stable_vector_iterator& r) BOOST_CONTAINER_NOEXCEPT + friend bool operator!= (const stable_vector_iterator& l, const stable_vector_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW { return l.m_pn != r.m_pn; } - friend bool operator< (const stable_vector_iterator& l, const stable_vector_iterator& r) BOOST_CONTAINER_NOEXCEPT + friend bool operator< (const stable_vector_iterator& l, const stable_vector_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW { return l.m_pn->up < r.m_pn->up; } - friend bool operator<= (const stable_vector_iterator& l, const stable_vector_iterator& r) BOOST_CONTAINER_NOEXCEPT + friend bool operator<= (const stable_vector_iterator& l, const stable_vector_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW { return l.m_pn->up <= r.m_pn->up; } - friend bool operator> (const stable_vector_iterator& l, const stable_vector_iterator& r) BOOST_CONTAINER_NOEXCEPT + friend bool operator> (const stable_vector_iterator& l, const stable_vector_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW { return l.m_pn->up > r.m_pn->up; } - friend bool operator>= (const stable_vector_iterator& l, const stable_vector_iterator& r) BOOST_CONTAINER_NOEXCEPT + friend bool operator>= (const stable_vector_iterator& l, const stable_vector_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW { return l.m_pn->up >= r.m_pn->up; } }; @@ -410,7 +421,7 @@ class stable_vector_iterator //! \tparam T The type of object that is stored in the stable_vector //! \tparam Allocator The allocator used for all internal memory management #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED -template <class T, class Allocator = std::allocator<T> > +template <class T, class Allocator = new_allocator<T> > #else template <class T, class Allocator> #endif @@ -453,10 +464,6 @@ class stable_vector typedef typename node_ptr_traits::reference node_reference; typedef typename const_node_ptr_traits::reference const_node_reference; - typedef ::boost::container::container_detail:: - integral_constant<unsigned, 1> allocator_v1; - typedef ::boost::container::container_detail:: - integral_constant<unsigned, 2> allocator_v2; typedef ::boost::container::container_detail::integral_constant <unsigned, boost::container::container_detail:: version<Allocator>::value> alloc_version; @@ -506,8 +513,8 @@ class stable_vector typedef node_allocator_type stored_allocator_type; typedef BOOST_CONTAINER_IMPDEF(iterator_impl) iterator; typedef BOOST_CONTAINER_IMPDEF(const_iterator_impl) const_iterator; - typedef BOOST_CONTAINER_IMPDEF(container_detail::reverse_iterator<iterator>) reverse_iterator; - typedef BOOST_CONTAINER_IMPDEF(container_detail::reverse_iterator<const_iterator>) const_reverse_iterator; + typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<iterator>) reverse_iterator; + typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<const_iterator>) const_reverse_iterator; #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED private: @@ -544,13 +551,13 @@ class stable_vector //! <b>Throws</b>: Nothing //! //! <b>Complexity</b>: Constant. - explicit stable_vector(const allocator_type& al) BOOST_CONTAINER_NOEXCEPT + explicit stable_vector(const allocator_type& al) BOOST_NOEXCEPT_OR_NOTHROW : internal_data(al), index(al) { STABLE_VECTOR_CHECK_INVARIANT; } - //! <b>Effects</b>: Constructs a stable_vector that will use a copy of allocator a + //! <b>Effects</b>: Constructs a stable_vector //! and inserts n value initialized values. //! //! <b>Throws</b>: If allocator_type's default constructor @@ -566,7 +573,7 @@ class stable_vector cod.release(); } - //! <b>Effects</b>: Constructs a stable_vector that will use a copy of allocator a + //! <b>Effects</b>: Constructs a stable_vector //! and inserts n default initialized values. //! //! <b>Throws</b>: If allocator_type's default constructor @@ -585,6 +592,40 @@ class stable_vector } //! <b>Effects</b>: Constructs a stable_vector that will use a copy of allocator a + //! and inserts n value initialized values. + //! + //! <b>Throws</b>: If allocator_type's default constructor + //! throws or T's default or copy constructor throws. + //! + //! <b>Complexity</b>: Linear to n. + explicit stable_vector(size_type n, const allocator_type &a) + : internal_data(), index(a) + { + stable_vector_detail::clear_on_destroy<stable_vector> cod(*this); + this->resize(n); + STABLE_VECTOR_CHECK_INVARIANT; + cod.release(); + } + + //! <b>Effects</b>: Constructs a stable_vector that will use a copy of allocator a + //! and inserts n default initialized values. + //! + //! <b>Throws</b>: If allocator_type's default constructor + //! throws or T's default or copy constructor throws. + //! + //! <b>Complexity</b>: Linear to n. + //! + //! <b>Note</b>: Non-standard extension + stable_vector(size_type n, default_init_t, const allocator_type &a) + : internal_data(), index(a) + { + stable_vector_detail::clear_on_destroy<stable_vector> cod(*this); + this->resize(n, default_init); + STABLE_VECTOR_CHECK_INVARIANT; + cod.release(); + } + + //! <b>Effects</b>: Constructs a stable_vector that will use a copy of allocator a //! and inserts n copies of value. //! //! <b>Throws</b>: If allocator_type's default constructor @@ -652,7 +693,7 @@ class stable_vector } #endif - //! <b>Effects</b>: Move constructor. Moves mx's resources to *this. + //! <b>Effects</b>: Move constructor. Moves x's resources to *this. //! //! <b>Throws</b>: If allocator_type's copy constructor throws. //! @@ -678,7 +719,7 @@ class stable_vector } //! <b>Effects</b>: Move constructor using the specified allocator. - //! Moves mx's resources to *this. + //! Moves x's resources to *this. //! //! <b>Throws</b>: If allocator_type's copy constructor throws. //! @@ -687,11 +728,12 @@ class stable_vector : internal_data(a), index(a) { if(this->priv_node_alloc() == x.priv_node_alloc()){ + this->index.swap(x.index); this->priv_swap_members(x); } else{ stable_vector_detail::clear_on_destroy<stable_vector> cod(*this); - this->insert(this->cend(), x.begin(), x.end()); + this->insert(this->cend(), boost::make_move_iterator(x.begin()), boost::make_move_iterator(x.end())); STABLE_VECTOR_CHECK_INVARIANT; cod.release(); } @@ -736,7 +778,7 @@ class stable_vector return *this; } - //! <b>Effects</b>: Move assignment. All mx's values are transferred to *this. + //! <b>Effects</b>: Move assignment. All x's values are transferred to *this. //! //! <b>Postcondition</b>: x.empty(). *this contains a the elements x had //! before the function. @@ -748,7 +790,8 @@ class stable_vector //! propagate_on_container_move_assignment is true or //! this->get>allocator() == x.get_allocator(). Linear otherwise. stable_vector& operator=(BOOST_RV_REF(stable_vector) x) - BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value) + BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value + || allocator_traits_type::is_always_equal::value) { //for move constructor, no aliasing (&x != this) is assummed. BOOST_ASSERT(this != &x); @@ -766,7 +809,7 @@ class stable_vector //Move allocator if needed container_detail::move_alloc(this_alloc, x_alloc, flag); //Take resources - this->index = boost::move(x.index); + this->index.swap(x.index); this->priv_swap_members(x); } //Else do a one by one move @@ -856,7 +899,7 @@ class stable_vector //! <b>Complexity</b>: Constant. //! //! <b>Note</b>: Non-standard extension. - const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT + const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW { return this->priv_node_alloc(); } //! <b>Effects</b>: Returns a reference to the internal allocator. @@ -866,7 +909,7 @@ class stable_vector //! <b>Complexity</b>: Constant. //! //! <b>Note</b>: Non-standard extension. - stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT + stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW { return this->priv_node_alloc(); } ////////////////////////////////////////////// @@ -880,7 +923,7 @@ class stable_vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - iterator begin() BOOST_CONTAINER_NOEXCEPT + iterator begin() BOOST_NOEXCEPT_OR_NOTHROW { return (this->index.empty()) ? this->end(): iterator(node_ptr_traits::static_cast_from(this->index.front())); } //! <b>Effects</b>: Returns a const_iterator to the first element contained in the stable_vector. @@ -888,7 +931,7 @@ class stable_vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator begin() const BOOST_CONTAINER_NOEXCEPT + const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW { return (this->index.empty()) ? this->cend() : const_iterator(node_ptr_traits::static_cast_from(this->index.front())) ; } //! <b>Effects</b>: Returns an iterator to the end of the stable_vector. @@ -896,7 +939,7 @@ class stable_vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - iterator end() BOOST_CONTAINER_NOEXCEPT + iterator end() BOOST_NOEXCEPT_OR_NOTHROW { return iterator(this->priv_get_end_node()); } //! <b>Effects</b>: Returns a const_iterator to the end of the stable_vector. @@ -904,7 +947,7 @@ class stable_vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator end() const BOOST_CONTAINER_NOEXCEPT + const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW { return const_iterator(this->priv_get_end_node()); } //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning @@ -913,7 +956,7 @@ class stable_vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT + reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW { return reverse_iterator(this->end()); } //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning @@ -922,7 +965,7 @@ class stable_vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT + const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW { return const_reverse_iterator(this->end()); } //! <b>Effects</b>: Returns a reverse_iterator pointing to the end @@ -931,7 +974,7 @@ class stable_vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT + reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW { return reverse_iterator(this->begin()); } //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end @@ -940,7 +983,7 @@ class stable_vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT + const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW { return const_reverse_iterator(this->begin()); } //! <b>Effects</b>: Returns a const_iterator to the first element contained in the stable_vector. @@ -948,7 +991,7 @@ class stable_vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT + const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW { return this->begin(); } //! <b>Effects</b>: Returns a const_iterator to the end of the stable_vector. @@ -956,7 +999,7 @@ class stable_vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator cend() const BOOST_CONTAINER_NOEXCEPT + const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW { return this->end(); } //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning @@ -965,7 +1008,7 @@ class stable_vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT + const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW { return this->rbegin(); } //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end @@ -974,7 +1017,7 @@ class stable_vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator crend()const BOOST_CONTAINER_NOEXCEPT + const_reverse_iterator crend()const BOOST_NOEXCEPT_OR_NOTHROW { return this->rend(); } ////////////////////////////////////////////// @@ -988,7 +1031,7 @@ class stable_vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - bool empty() const BOOST_CONTAINER_NOEXCEPT + bool empty() const BOOST_NOEXCEPT_OR_NOTHROW { return this->index.size() <= ExtraPointers; } //! <b>Effects</b>: Returns the number of the elements contained in the stable_vector. @@ -996,10 +1039,10 @@ class stable_vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - size_type size() const BOOST_CONTAINER_NOEXCEPT + size_type size() const BOOST_NOEXCEPT_OR_NOTHROW { const size_type index_size = this->index.size(); - return (index_size - ExtraPointers) & (std::size_t(0u) -std::size_t(index_size != 0)); + return (index_size - ExtraPointers) & (size_type(0u) -size_type(index_size != 0)); } //! <b>Effects</b>: Returns the largest possible size of the stable_vector. @@ -1007,7 +1050,7 @@ class stable_vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - size_type max_size() const BOOST_CONTAINER_NOEXCEPT + size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW { return this->index.max_size() - ExtraPointers; } //! <b>Effects</b>: Inserts or erases elements at the end such that @@ -1065,7 +1108,7 @@ class stable_vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - size_type capacity() const BOOST_CONTAINER_NOEXCEPT + size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW { const size_type index_size = this->index.size(); BOOST_ASSERT(!index_size || index_size >= ExtraPointers); @@ -1153,7 +1196,7 @@ class stable_vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - reference front() BOOST_CONTAINER_NOEXCEPT + reference front() BOOST_NOEXCEPT_OR_NOTHROW { return static_cast<node_reference>(*this->index.front()).value; } //! <b>Requires</b>: !empty() @@ -1164,7 +1207,7 @@ class stable_vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reference front() const BOOST_CONTAINER_NOEXCEPT + const_reference front() const BOOST_NOEXCEPT_OR_NOTHROW { return static_cast<const_node_reference>(*this->index.front()).value; } //! <b>Requires</b>: !empty() @@ -1175,7 +1218,7 @@ class stable_vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - reference back() BOOST_CONTAINER_NOEXCEPT + reference back() BOOST_NOEXCEPT_OR_NOTHROW { return static_cast<node_reference>(*this->index[this->size()-1u]).value; } //! <b>Requires</b>: !empty() @@ -1186,7 +1229,7 @@ class stable_vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reference back() const BOOST_CONTAINER_NOEXCEPT + const_reference back() const BOOST_NOEXCEPT_OR_NOTHROW { return static_cast<const_node_reference>(*this->index[this->size()-1u]).value; } //! <b>Requires</b>: size() > n. @@ -1197,7 +1240,7 @@ class stable_vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - reference operator[](size_type n) BOOST_CONTAINER_NOEXCEPT + reference operator[](size_type n) BOOST_NOEXCEPT_OR_NOTHROW { BOOST_ASSERT(n < this->size()); return static_cast<node_reference>(*this->index[n]).value; @@ -1211,12 +1254,73 @@ class stable_vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reference operator[](size_type n) const BOOST_CONTAINER_NOEXCEPT + const_reference operator[](size_type n) const BOOST_NOEXCEPT_OR_NOTHROW { BOOST_ASSERT(n < this->size()); return static_cast<const_node_reference>(*this->index[n]).value; } + //! <b>Requires</b>: size() >= n. + //! + //! <b>Effects</b>: Returns an iterator to the nth element + //! from the beginning of the container. Returns end() + //! if n == size(). + //! + //! <b>Throws</b>: Nothing. + //! + //! <b>Complexity</b>: Constant. + //! + //! <b>Note</b>: Non-standard extension + iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW + { + BOOST_ASSERT(this->size() >= n); + return (this->index.empty()) ? this->end() : iterator(node_ptr_traits::static_cast_from(this->index[n])); + } + + //! <b>Requires</b>: size() >= n. + //! + //! <b>Effects</b>: Returns a const_iterator to the nth element + //! from the beginning of the container. Returns end() + //! if n == size(). + //! + //! <b>Throws</b>: Nothing. + //! + //! <b>Complexity</b>: Constant. + //! + //! <b>Note</b>: Non-standard extension + const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW + { + BOOST_ASSERT(this->size() >= n); + return (this->index.empty()) ? this->cend() : iterator(node_ptr_traits::static_cast_from(this->index[n])); + } + + //! <b>Requires</b>: size() >= n. + //! + //! <b>Effects</b>: Returns an iterator to the nth element + //! from the beginning of the container. Returns end() + //! if n == size(). + //! + //! <b>Throws</b>: Nothing. + //! + //! <b>Complexity</b>: Constant. + //! + //! <b>Note</b>: Non-standard extension + size_type index_of(iterator p) BOOST_NOEXCEPT_OR_NOTHROW + { return this->priv_index_of(p.node_pointer()); } + + //! <b>Requires</b>: begin() <= p <= end(). + //! + //! <b>Effects</b>: Returns the index of the element pointed by p + //! and size() if p == end(). + //! + //! <b>Throws</b>: Nothing. + //! + //! <b>Complexity</b>: Constant. + //! + //! <b>Note</b>: Non-standard extension + size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW + { return this->priv_index_of(p.node_pointer()); } + //! <b>Requires</b>: size() > n. //! //! <b>Effects</b>: Returns a reference to the nth element @@ -1255,7 +1359,7 @@ class stable_vector // ////////////////////////////////////////////// - #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) //! <b>Effects</b>: Inserts an object of type T constructed with //! std::forward<Args>(args)... in the end of the stable_vector. @@ -1294,40 +1398,33 @@ class stable_vector #else - #define BOOST_PP_LOCAL_MACRO(n) \ - BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ - void emplace_back(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ - { \ - typedef BOOST_PP_CAT(BOOST_PP_CAT(emplace_functor, n), arg) \ - BOOST_PP_EXPR_IF(n, <) BOOST_PP_ENUM_PARAMS(n, P) BOOST_PP_EXPR_IF(n, >) \ - EmplaceFunctor; \ - typedef emplace_iterator<value_type, EmplaceFunctor, difference_type> EmplaceIterator; \ - EmplaceFunctor ef BOOST_PP_LPAREN_IF(n) \ - BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) \ - BOOST_PP_RPAREN_IF(n); \ - this->insert(this->cend() , EmplaceIterator(ef), EmplaceIterator()); \ - } \ - \ - BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ - iterator emplace(const_iterator p \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ - { \ - typedef BOOST_PP_CAT(BOOST_PP_CAT(emplace_functor, n), arg) \ - BOOST_PP_EXPR_IF(n, <) BOOST_PP_ENUM_PARAMS(n, P) BOOST_PP_EXPR_IF(n, >) \ - EmplaceFunctor; \ - typedef emplace_iterator<value_type, EmplaceFunctor, difference_type> EmplaceIterator; \ - EmplaceFunctor ef BOOST_PP_LPAREN_IF(n) \ - BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) \ - BOOST_PP_RPAREN_IF(n); \ - size_type pos_n = p - this->cbegin(); \ - this->insert(p, EmplaceIterator(ef), EmplaceIterator()); \ - return iterator(this->begin() + pos_n); \ - } \ - //! - #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) - #include BOOST_PP_LOCAL_ITERATE() - - #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING + #define BOOST_CONTAINER_STABLE_VECTOR_EMPLACE_CODE(N) \ + BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ + void emplace_back(BOOST_MOVE_UREF##N)\ + {\ + typedef emplace_functor##N\ + BOOST_MOVE_LT##N BOOST_MOVE_TARG##N BOOST_MOVE_GT##N EmplaceFunctor;\ + typedef emplace_iterator<value_type, EmplaceFunctor, difference_type> EmplaceIterator;\ + EmplaceFunctor ef BOOST_MOVE_LP##N BOOST_MOVE_FWD##N BOOST_MOVE_RP##N;\ + this->insert(this->cend() , EmplaceIterator(ef), EmplaceIterator());\ + }\ + \ + BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ + iterator emplace(const_iterator p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ + {\ + typedef emplace_functor##N\ + BOOST_MOVE_LT##N BOOST_MOVE_TARG##N BOOST_MOVE_GT##N EmplaceFunctor;\ + typedef emplace_iterator<value_type, EmplaceFunctor, difference_type> EmplaceIterator;\ + EmplaceFunctor ef BOOST_MOVE_LP##N BOOST_MOVE_FWD##N BOOST_MOVE_RP##N;\ + const size_type pos_n = p - this->cbegin();\ + this->insert(p, EmplaceIterator(ef), EmplaceIterator());\ + return this->begin() += pos_n;\ + }\ + // + BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_STABLE_VECTOR_EMPLACE_CODE) + #undef BOOST_CONTAINER_STABLE_VECTOR_EMPLACE_CODE + + #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) //! <b>Effects</b>: Inserts a copy of x at the end of the stable_vector. @@ -1339,7 +1436,7 @@ class stable_vector void push_back(const T &x); //! <b>Effects</b>: Constructs a new element in the end of the stable_vector - //! and moves the resources of mx to this new element. + //! and moves the resources of x to this new element. //! //! <b>Throws</b>: If memory allocation throws. //! @@ -1364,7 +1461,7 @@ class stable_vector //! <b>Requires</b>: p must be a valid iterator of *this. //! - //! <b>Effects</b>: Insert a new element before p with mx's resources. + //! <b>Effects</b>: Insert a new element before p with x's resources. //! //! <b>Returns</b>: an iterator to the inserted element. //! @@ -1401,7 +1498,7 @@ class stable_vector //! //! <b>Returns</b>: an iterator to the first inserted element or p if first == last. //! - //! <b>Complexity</b>: Linear to std::distance [il.begin(), il.end()). + //! <b>Complexity</b>: Linear to distance [il.begin(), il.end()). iterator insert(const_iterator p, std::initializer_list<value_type> il) { STABLE_VECTOR_CHECK_INVARIANT; @@ -1418,7 +1515,7 @@ class stable_vector //! <b>Throws</b>: If memory allocation throws, T's constructor from a //! dereferenced InpIt throws or T's copy constructor throws. //! - //! <b>Complexity</b>: Linear to std::distance [first, last). + //! <b>Complexity</b>: Linear to distance [first, last). template <class InputIterator> iterator insert(const_iterator p, InputIterator first, InputIterator last #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) @@ -1446,7 +1543,7 @@ class stable_vector >::type * = 0 ) { - const size_type num_new = static_cast<size_type>(std::distance(first, last)); + const size_type num_new = static_cast<size_type>(boost::container::iterator_distance(first, last)); const size_type idx = static_cast<size_type>(p - this->cbegin()); if(num_new){ //Fills the node pool and inserts num_new null pointers in idx. @@ -1483,7 +1580,7 @@ class stable_vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant time. - void pop_back() BOOST_CONTAINER_NOEXCEPT + void pop_back() BOOST_NOEXCEPT_OR_NOTHROW { this->erase(--this->cend()); } //! <b>Effects</b>: Erases the element at p. @@ -1492,7 +1589,7 @@ class stable_vector //! //! <b>Complexity</b>: Linear to the elements between p and the //! last element. Constant if p is the last element. - iterator erase(const_iterator p) BOOST_CONTAINER_NOEXCEPT + iterator erase(const_iterator p) BOOST_NOEXCEPT_OR_NOTHROW { STABLE_VECTOR_CHECK_INVARIANT; const size_type d = p - this->cbegin(); @@ -1509,7 +1606,7 @@ class stable_vector //! //! <b>Complexity</b>: Linear to the distance between first and last //! plus linear to the elements between p and the last element. - iterator erase(const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT + iterator erase(const_iterator first, const_iterator last) BOOST_NOEXCEPT_OR_NOTHROW { STABLE_VECTOR_CHECK_INVARIANT; const const_iterator cbeg(this->cbegin()); @@ -1541,6 +1638,8 @@ class stable_vector //! //! <b>Complexity</b>: Constant. void swap(stable_vector & x) + BOOST_NOEXCEPT_IF( allocator_traits_type::propagate_on_container_swap::value + || allocator_traits_type::is_always_equal::value) { STABLE_VECTOR_CHECK_INVARIANT; container_detail::bool_<allocator_traits_type::propagate_on_container_swap::value> flag; @@ -1555,14 +1654,14 @@ class stable_vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Linear to the number of elements in the stable_vector. - void clear() BOOST_CONTAINER_NOEXCEPT + void clear() BOOST_NOEXCEPT_OR_NOTHROW { this->erase(this->cbegin(),this->cend()); } //! <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 stable_vector& x, const stable_vector& y) - { return x.size() == y.size() && std::equal(x.begin(), x.end(), y.begin()); } + { 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 //! @@ -1574,7 +1673,7 @@ class stable_vector //! //! <b>Complexity</b>: Linear to the number of elements in the container. friend bool operator<(const stable_vector& x, const stable_vector& y) - { return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } + { 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 //! @@ -1603,6 +1702,14 @@ class stable_vector #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED private: + size_type priv_index_of(node_ptr p) const + { + //Check range + BOOST_ASSERT(this->index.empty() || (this->index.data() <= p->up)); + BOOST_ASSERT(this->index.empty() || p->up <= (this->index.data() + this->index.size())); + return this->index.empty() ? 0 : p->up - this->index.data(); + } + class insert_rollback { public: @@ -1844,7 +1951,7 @@ class stable_vector void priv_swap_members(stable_vector &x) { - boost::container::swap_dispatch(this->internal_data.pool_size, x.internal_data.pool_size); + boost::adl_move_swap(this->internal_data.pool_size, x.internal_data.pool_size); index_traits_type::readjust_end_node(this->index, this->internal_data.end_node); index_traits_type::readjust_end_node(x.index, x.internal_data.end_node); } @@ -1929,20 +2036,23 @@ class stable_vector #undef STABLE_VECTOR_CHECK_INVARIANT -#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED - -/* +} //namespace container { //!has_trivial_destructor_after_move<> == true_type //!specialization for optimizations template <class T, class Allocator> struct has_trivial_destructor_after_move<boost::container::stable_vector<T, Allocator> > - : public has_trivial_destructor_after_move<Allocator>::value -{}; +{ + typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer; + static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value && + ::boost::has_trivial_destructor_after_move<pointer>::value; +}; -*/ +namespace container { + +#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED -}} +}} //namespace boost{ namespace container { #include <boost/container/detail/config_end.hpp> diff --git a/boost/container/static_vector.hpp b/boost/container/static_vector.hpp index 1ae80114b3..c36832dfa3 100644 --- a/boost/container/static_vector.hpp +++ b/boost/container/static_vector.hpp @@ -11,14 +11,23 @@ #ifndef BOOST_CONTAINER_STATIC_VECTOR_HPP #define BOOST_CONTAINER_STATIC_VECTOR_HPP -#if defined(_MSC_VER) +#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> +#include <boost/container/detail/type_traits.hpp> #include <boost/container/vector.hpp> -#include <boost/aligned_storage.hpp> + +#include <cstddef> +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) +#include <initializer_list> +#endif namespace boost { namespace container { @@ -32,34 +41,33 @@ class static_storage_allocator public: typedef T value_type; - static_storage_allocator() BOOST_CONTAINER_NOEXCEPT + static_storage_allocator() BOOST_NOEXCEPT_OR_NOTHROW {} - static_storage_allocator(const static_storage_allocator &) BOOST_CONTAINER_NOEXCEPT + static_storage_allocator(const static_storage_allocator &) BOOST_NOEXCEPT_OR_NOTHROW {} - static_storage_allocator & operator=(const static_storage_allocator &) BOOST_CONTAINER_NOEXCEPT + static_storage_allocator & operator=(const static_storage_allocator &) BOOST_NOEXCEPT_OR_NOTHROW {} - T* internal_storage() const BOOST_CONTAINER_NOEXCEPT + T* internal_storage() const BOOST_NOEXCEPT_OR_NOTHROW { return const_cast<T*>(static_cast<const T*>(static_cast<const void*>(&storage))); } - T* internal_storage() BOOST_CONTAINER_NOEXCEPT + T* internal_storage() BOOST_NOEXCEPT_OR_NOTHROW { return static_cast<T*>(static_cast<void*>(&storage)); } static const std::size_t internal_capacity = N; typedef boost::container::container_detail::version_type<static_storage_allocator, 0> version; - friend bool operator==(const static_storage_allocator &, const static_storage_allocator &) BOOST_CONTAINER_NOEXCEPT + friend bool operator==(const static_storage_allocator &, const static_storage_allocator &) BOOST_NOEXCEPT_OR_NOTHROW { return false; } - friend bool operator!=(const static_storage_allocator &, const static_storage_allocator &) BOOST_CONTAINER_NOEXCEPT + friend bool operator!=(const static_storage_allocator &, const static_storage_allocator &) BOOST_NOEXCEPT_OR_NOTHROW { return true; } private: - typename boost::aligned_storage - <sizeof(T)*N, boost::alignment_of<T>::value>::type storage; + typename aligned_storage<sizeof(T)*N, alignment_of<T>::value>::type storage; }; } //namespace container_detail { @@ -135,7 +143,7 @@ public: //! //! @par Complexity //! Constant O(1). - static_vector() BOOST_CONTAINER_NOEXCEPT + static_vector() BOOST_NOEXCEPT_OR_NOTHROW : base_t() {} @@ -259,13 +267,13 @@ public: //! @param other The static_vector which content will be moved to this one. //! //! @par Throws - //! @li If \c boost::has_nothrow_move<Value>::value is \c true and Value's move constructor throws. - //! @li If \c boost::has_nothrow_move<Value>::value is \c false and Value's copy constructor throws. + //! @li If \c has_nothrow_move<Value>::value is \c true and Value's move constructor throws. + //! @li If \c has_nothrow_move<Value>::value is \c false and Value's copy constructor throws. //! //! @par Complexity //! Linear O(N). static_vector(BOOST_RV_REF(static_vector) other) - : base_t(boost::move(static_cast<base_t&>(other))) + : base_t(BOOST_MOVE_BASE(base_t, other)) {} //! @pre <tt>other.size() <= capacity()</tt> @@ -275,14 +283,14 @@ public: //! @param other The static_vector which content will be moved to this one. //! //! @par Throws - //! @li If \c boost::has_nothrow_move<Value>::value is \c true and Value's move constructor throws. - //! @li If \c boost::has_nothrow_move<Value>::value is \c false and Value's copy constructor throws. + //! @li If \c has_nothrow_move<Value>::value is \c true and Value's move constructor throws. + //! @li If \c has_nothrow_move<Value>::value is \c false and Value's copy constructor throws. //! //! @par Complexity //! Linear O(N). template <std::size_t C> static_vector(BOOST_RV_REF_BEG static_vector<value_type, C> BOOST_RV_REF_END other) - : base_t(boost::move(static_cast<typename static_vector<value_type, C>::base_t&>(other))) + : base_t(BOOST_MOVE_BASE(typename static_vector<value_type BOOST_MOVE_I C>::base_t, other)) {} //! @brief Copy assigns Values stored in the other static_vector to this one. @@ -310,9 +318,7 @@ public: //! @par Complexity //! Linear O(N). static_vector & operator=(std::initializer_list<value_type> il) - { - return static_cast<static_vector&>(base_t::operator=(il)); - } + { return static_cast<static_vector&>(base_t::operator=(il)); } #endif //! @pre <tt>other.size() <= capacity()</tt> @@ -338,14 +344,14 @@ public: //! @param other The static_vector which content will be moved to this one. //! //! @par Throws - //! @li If \c boost::has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws. - //! @li If \c boost::has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws. + //! @li If \c has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws. + //! @li If \c has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws. //! //! @par Complexity //! Linear O(N). static_vector & operator=(BOOST_RV_REF(static_vector) other) { - return static_cast<static_vector&>(base_t::operator=(boost::move(static_cast<base_t&>(other)))); + return static_cast<static_vector&>(base_t::operator=(BOOST_MOVE_BASE(base_t, other))); } //! @pre <tt>other.size() <= capacity()</tt> @@ -355,8 +361,8 @@ public: //! @param other The static_vector which content will be moved to this one. //! //! @par Throws - //! @li If \c boost::has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws. - //! @li If \c boost::has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws. + //! @li If \c has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws. + //! @li If \c has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws. //! //! @par Complexity //! Linear O(N). @@ -364,7 +370,7 @@ public: static_vector & operator=(BOOST_RV_REF_BEG static_vector<value_type, C> BOOST_RV_REF_END other) { return static_cast<static_vector&>(base_t::operator= - (boost::move(static_cast<typename static_vector<value_type, C>::base_t&>(other)))); + (BOOST_MOVE_BASE(typename static_vector<value_type BOOST_MOVE_I C>::base_t, other))); } #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED @@ -383,8 +389,8 @@ public: //! @param other The static_vector which content will be swapped with this one's content. //! //! @par Throws - //! @li If \c boost::has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws, - //! @li If \c boost::has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws, + //! @li If \c has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws, + //! @li If \c has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws, //! //! @par Complexity //! Linear O(N). @@ -397,8 +403,8 @@ public: //! @param other The static_vector which content will be swapped with this one's content. //! //! @par Throws - //! @li If \c boost::has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws, - //! @li If \c boost::has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws, + //! @li If \c has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws, + //! @li If \c has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws, //! //! @par Complexity //! Linear O(N). @@ -462,7 +468,7 @@ public: //! //! @par Complexity //! Linear O(N). - void reserve(size_type count) BOOST_CONTAINER_NOEXCEPT; + void reserve(size_type count) BOOST_NOEXCEPT_OR_NOTHROW; //! @pre <tt>size() < capacity()</tt> //! @@ -703,7 +709,7 @@ public: //! //! @par Complexity //! Constant O(1). - void clear() BOOST_CONTAINER_NOEXCEPT; + void clear() BOOST_NOEXCEPT_OR_NOTHROW; //! @pre <tt>i < size()</tt> //! @@ -769,6 +775,66 @@ public: //! Constant O(1). const_reference operator[](size_type i) const; + //! @pre <tt>i =< size()</tt> + //! + //! @brief Returns a iterator to the i-th element. + //! + //! @param i The element's index. + //! + //! @return a iterator to the i-th element. + //! + //! @par Throws + //! Nothing by default. + //! + //! @par Complexity + //! Constant O(1). + iterator nth(size_type i); + + //! @pre <tt>i =< size()</tt> + //! + //! @brief Returns a const_iterator to the i-th element. + //! + //! @param i The element's index. + //! + //! @return a const_iterator to the i-th element. + //! + //! @par Throws + //! Nothing by default. + //! + //! @par Complexity + //! Constant O(1). + const_iterator nth(size_type i) const; + + //! @pre <tt>begin() <= p <= end()</tt> + //! + //! @brief Returns the index of the element pointed by p. + //! + //! @param i The element's index. + //! + //! @return The index of the element pointed by p. + //! + //! @par Throws + //! Nothing by default. + //! + //! @par Complexity + //! Constant O(1). + size_type index_of(iterator p); + + //! @pre <tt>begin() <= p <= end()</tt> + //! + //! @brief Returns the index of the element pointed by p. + //! + //! @param i The index of the element pointed by p. + //! + //! @return a const_iterator to the i-th element. + //! + //! @par Throws + //! Nothing by default. + //! + //! @par Complexity + //! Constant O(1). + size_type index_of(const_iterator p) const; + //! @pre \c !empty() //! //! @brief Returns reference to the first element. @@ -833,7 +899,7 @@ public: //! //! @par Complexity //! Constant O(1). - Value * data() BOOST_CONTAINER_NOEXCEPT; + Value * data() BOOST_NOEXCEPT_OR_NOTHROW; //! @brief Const pointer such that <tt>[data(), data() + size())</tt> is a valid range. //! For a non-empty vector <tt>data() == &front()</tt>. @@ -843,7 +909,7 @@ public: //! //! @par Complexity //! Constant O(1). - const Value * data() const BOOST_CONTAINER_NOEXCEPT; + const Value * data() const BOOST_NOEXCEPT_OR_NOTHROW; //! @brief Returns iterator to the first element. //! @@ -854,7 +920,7 @@ public: //! //! @par Complexity //! Constant O(1). - iterator begin() BOOST_CONTAINER_NOEXCEPT; + iterator begin() BOOST_NOEXCEPT_OR_NOTHROW; //! @brief Returns const iterator to the first element. //! @@ -865,7 +931,7 @@ public: //! //! @par Complexity //! Constant O(1). - const_iterator begin() const BOOST_CONTAINER_NOEXCEPT; + const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW; //! @brief Returns const iterator to the first element. //! @@ -876,7 +942,7 @@ public: //! //! @par Complexity //! Constant O(1). - const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT; + const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW; //! @brief Returns iterator to the one after the last element. //! @@ -887,7 +953,7 @@ public: //! //! @par Complexity //! Constant O(1). - iterator end() BOOST_CONTAINER_NOEXCEPT; + iterator end() BOOST_NOEXCEPT_OR_NOTHROW; //! @brief Returns const iterator to the one after the last element. //! @@ -898,7 +964,7 @@ public: //! //! @par Complexity //! Constant O(1). - const_iterator end() const BOOST_CONTAINER_NOEXCEPT; + const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW; //! @brief Returns const iterator to the one after the last element. //! @@ -909,7 +975,7 @@ public: //! //! @par Complexity //! Constant O(1). - const_iterator cend() const BOOST_CONTAINER_NOEXCEPT; + const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW; //! @brief Returns reverse iterator to the first element of the reversed container. //! @@ -921,7 +987,7 @@ public: //! //! @par Complexity //! Constant O(1). - reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT; + reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW; //! @brief Returns const reverse iterator to the first element of the reversed container. //! @@ -933,7 +999,7 @@ public: //! //! @par Complexity //! Constant O(1). - const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT; + const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW; //! @brief Returns const reverse iterator to the first element of the reversed container. //! @@ -945,7 +1011,7 @@ public: //! //! @par Complexity //! Constant O(1). - const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT; + const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW; //! @brief Returns reverse iterator to the one after the last element of the reversed container. //! @@ -957,7 +1023,7 @@ public: //! //! @par Complexity //! Constant O(1). - reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT; + reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW; //! @brief Returns const reverse iterator to the one after the last element of the reversed container. //! @@ -969,7 +1035,7 @@ public: //! //! @par Complexity //! Constant O(1). - const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT; + const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW; //! @brief Returns const reverse iterator to the one after the last element of the reversed container. //! @@ -981,7 +1047,7 @@ public: //! //! @par Complexity //! Constant O(1). - const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT; + const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW; //! @brief Returns container's capacity. //! @@ -992,7 +1058,7 @@ public: //! //! @par Complexity //! Constant O(1). - static size_type capacity() BOOST_CONTAINER_NOEXCEPT; + static size_type capacity() BOOST_NOEXCEPT_OR_NOTHROW; //! @brief Returns container's capacity. //! @@ -1003,7 +1069,7 @@ public: //! //! @par Complexity //! Constant O(1). - static size_type max_size() BOOST_CONTAINER_NOEXCEPT; + static size_type max_size() BOOST_NOEXCEPT_OR_NOTHROW; //! @brief Returns the number of stored elements. //! @@ -1014,7 +1080,7 @@ public: //! //! @par Complexity //! Constant O(1). - size_type size() const BOOST_CONTAINER_NOEXCEPT; + size_type size() const BOOST_NOEXCEPT_OR_NOTHROW; //! @brief Queries if the container contains elements. //! @@ -1026,7 +1092,7 @@ public: //! //! @par Complexity //! Constant O(1). - bool empty() const BOOST_CONTAINER_NOEXCEPT; + bool empty() const BOOST_NOEXCEPT_OR_NOTHROW; #else friend void swap(static_vector &x, static_vector &y) diff --git a/boost/container/string.hpp b/boost/container/string.hpp index 1c3cf3bbc8..e5ec287cf8 100644 --- a/boost/container/string.hpp +++ b/boost/container/string.hpp @@ -11,36 +11,44 @@ #ifndef BOOST_CONTAINER_STRING_HPP #define BOOST_CONTAINER_STRING_HPP -#if defined(_MSC_VER) +#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> - -#include <boost/container/detail/workaround.hpp> #include <boost/container/container_fwd.hpp> -#include <boost/container/throw_exception.hpp> -#include <boost/container/detail/utilities.hpp> -#include <boost/container/detail/iterators.hpp> -#include <boost/container/detail/algorithms.hpp> -#include <boost/container/detail/version_type.hpp> -#include <boost/container/detail/allocation_type.hpp> +// container #include <boost/container/allocator_traits.hpp> +#include <boost/container/new_allocator.hpp> //new_allocator +#include <boost/container/throw_exception.hpp> +// container/detail +#include <boost/container/detail/alloc_helpers.hpp> #include <boost/container/detail/allocator_version_traits.hpp> +#include <boost/container/detail/allocation_type.hpp> +#include <boost/container/detail/iterator.hpp> +#include <boost/container/detail/iterators.hpp> +#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/container/detail/version_type.hpp> + #include <boost/move/utility_core.hpp> +#include <boost/move/adl_move_swap.hpp> #include <boost/static_assert.hpp> -#include <boost/functional/hash.hpp> #include <boost/intrusive/pointer_traits.hpp> #include <boost/core/no_exceptions_support.hpp> +#include <boost/container/detail/minimal_char_traits_header.hpp> +#include <boost/functional/hash.hpp> + -#include <functional> -#include <string> -#include <utility> -#include <iterator> -#include <memory> #include <algorithm> +#include <functional> //bind2nd, etc. #include <iosfwd> #include <istream> #include <ostream> @@ -49,8 +57,6 @@ #include <cstddef> #include <climits> #include <boost/container/detail/type_traits.hpp> -#include <boost/type_traits/has_trivial_destructor.hpp> -#include <boost/aligned_storage.hpp> #include <boost/move/traits.hpp> namespace boost { @@ -152,8 +158,8 @@ class basic_string_base //This type has the same alignment and size as long_t but it's POD //so, unlike long_t, it can be placed in a union - typedef typename boost::aligned_storage< sizeof(long_t), - container_detail::alignment_of<long_t>::value>::type long_raw_t; + typedef typename container_detail::aligned_storage + <sizeof(long_t), container_detail::alignment_of<long_t>::value>::type long_raw_t; protected: static const size_type MinInternalBufferChars = 8; @@ -250,23 +256,20 @@ class basic_string_base protected: - typedef container_detail::integral_constant<unsigned, 1> allocator_v1; - typedef container_detail::integral_constant<unsigned, 2> allocator_v2; typedef container_detail::integral_constant<unsigned, boost::container::container_detail::version<Allocator>::value> alloc_version; - std::pair<pointer, bool> - allocation_command(allocation_type command, + pointer allocation_command(allocation_type command, size_type limit_size, - size_type preferred_size, - size_type &received_size, pointer reuse = 0) + size_type &prefer_in_recvd_out_size, + pointer &reuse) { if(this->is_short() && (command & (expand_fwd | expand_bwd)) ){ - reuse = pointer(); + reuse = 0; command &= ~(expand_fwd | expand_bwd); } return container_detail::allocator_version_traits<Allocator>::allocation_command - (this->alloc(), command, limit_size, preferred_size, received_size, reuse); + (this->alloc(), command, limit_size, prefer_in_recvd_out_size, reuse); } size_type next_capacity(size_type additional_objects) const @@ -313,7 +316,8 @@ class basic_string_base if (n <= this->max_size()) { if(n > InternalBufferChars){ size_type new_cap = this->next_capacity(n); - pointer p = this->allocation_command(allocate_new, n, new_cap, new_cap).first; + pointer reuse = 0; + pointer p = this->allocation_command(allocate_new, n, new_cap, reuse); this->is_short(false); this->priv_long_addr(p); this->priv_long_size(0); @@ -411,7 +415,9 @@ class basic_string_base { if(this->is_short()){ if(other.is_short()){ - std::swap(this->members_.m_repr, other.members_.m_repr); + repr_t tmp(this->members_.m_repr); + this->members_.m_repr = other.members_.m_repr; + other.members_.m_repr = tmp; } else{ short_t short_backup(this->members_.m_repr.short_repr()); @@ -432,7 +438,7 @@ class basic_string_base this->members_.m_repr.short_repr() = short_backup; } else{ - boost::container::swap_dispatch(this->members_.m_repr.long_repr(), other.members_.m_repr.long_repr()); + boost::adl_move_swap(this->members_.m_repr.long_repr(), other.members_.m_repr.long_repr()); } } } @@ -475,7 +481,7 @@ class basic_string_base //! \tparam Traits The Character Traits type, which encapsulates basic character operations //! \tparam Allocator The allocator, used for internal memory management. #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED -template <class CharT, class Traits = std::char_traits<CharT>, class Allocator = std::allocator<CharT> > +template <class CharT, class Traits = std::char_traits<CharT>, class Allocator = new_allocator<CharT> > #else template <class CharT, class Traits, class Allocator> #endif @@ -543,15 +549,13 @@ class basic_string typedef BOOST_CONTAINER_IMPDEF(allocator_type) stored_allocator_type; typedef BOOST_CONTAINER_IMPDEF(pointer) iterator; typedef BOOST_CONTAINER_IMPDEF(const_pointer) const_iterator; - typedef BOOST_CONTAINER_IMPDEF(container_detail::reverse_iterator<iterator>) reverse_iterator; - typedef BOOST_CONTAINER_IMPDEF(container_detail::reverse_iterator<const_iterator>) const_reverse_iterator; + typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<iterator>) reverse_iterator; + typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<const_iterator>) const_reverse_iterator; static const size_type npos = size_type(-1); #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED private: typedef constant_iterator<CharT, difference_type> cvalue_iterator; - typedef typename base_t::allocator_v1 allocator_v1; - typedef typename base_t::allocator_v2 allocator_v2; typedef typename base_t::alloc_version alloc_version; typedef ::boost::intrusive::pointer_traits<pointer> pointer_traits; #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED @@ -586,7 +590,7 @@ class basic_string //! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter. //! //! <b>Throws</b>: Nothing - explicit basic_string(const allocator_type& a) BOOST_CONTAINER_NOEXCEPT + explicit basic_string(const allocator_type& a) BOOST_NOEXCEPT_OR_NOTHROW : base_t(a) { this->priv_terminate_string(); } @@ -607,7 +611,7 @@ class basic_string //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - basic_string(BOOST_RV_REF(basic_string) s) BOOST_CONTAINER_NOEXCEPT + basic_string(BOOST_RV_REF(basic_string) s) BOOST_NOEXCEPT_OR_NOTHROW : base_t(boost::move(s.alloc())) { if(s.alloc() == this->alloc()){ @@ -713,7 +717,7 @@ class basic_string //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - ~basic_string() BOOST_CONTAINER_NOEXCEPT + ~basic_string() BOOST_NOEXCEPT_OR_NOTHROW {} //! <b>Effects</b>: Copy constructs a string. @@ -751,7 +755,8 @@ class basic_string //! propagate_on_container_move_assignment is true or //! this->get>allocator() == x.get_allocator(). Linear otherwise. basic_string& operator=(BOOST_RV_REF(basic_string) x) - BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value) + BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value + || allocator_traits_type::is_always_equal::value) { //for move constructor, no aliasing (&x != this) is assummed. BOOST_ASSERT(this != &x); @@ -791,7 +796,7 @@ class basic_string //! <b>Throws</b>: If allocator's copy constructor throws. //! //! <b>Complexity</b>: Constant. - allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT + allocator_type get_allocator() const BOOST_NOEXCEPT_OR_NOTHROW { return this->alloc(); } //! <b>Effects</b>: Returns a reference to the internal allocator. @@ -801,7 +806,7 @@ class basic_string //! <b>Complexity</b>: Constant. //! //! <b>Note</b>: Non-standard extension. - stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT + stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW { return this->alloc(); } //! <b>Effects</b>: Returns a reference to the internal allocator. @@ -811,7 +816,7 @@ class basic_string //! <b>Complexity</b>: Constant. //! //! <b>Note</b>: Non-standard extension. - const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT + const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW { return this->alloc(); } ////////////////////////////////////////////// @@ -825,7 +830,7 @@ class basic_string //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - iterator begin() BOOST_CONTAINER_NOEXCEPT + iterator begin() BOOST_NOEXCEPT_OR_NOTHROW { return this->priv_addr(); } //! <b>Effects</b>: Returns a const_iterator to the first element contained in the vector. @@ -833,7 +838,7 @@ class basic_string //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator begin() const BOOST_CONTAINER_NOEXCEPT + const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW { return this->priv_addr(); } //! <b>Effects</b>: Returns an iterator to the end of the vector. @@ -841,7 +846,7 @@ class basic_string //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - iterator end() BOOST_CONTAINER_NOEXCEPT + iterator end() BOOST_NOEXCEPT_OR_NOTHROW { return this->priv_end_addr(); } //! <b>Effects</b>: Returns a const_iterator to the end of the vector. @@ -849,7 +854,7 @@ class basic_string //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator end() const BOOST_CONTAINER_NOEXCEPT + const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW { return this->priv_end_addr(); } //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning @@ -858,7 +863,7 @@ class basic_string //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT + reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW { return reverse_iterator(this->priv_end_addr()); } //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning @@ -867,7 +872,7 @@ class basic_string //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT + const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW { return this->crbegin(); } //! <b>Effects</b>: Returns a reverse_iterator pointing to the end @@ -876,7 +881,7 @@ class basic_string //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT + reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW { return reverse_iterator(this->priv_addr()); } //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end @@ -885,7 +890,7 @@ class basic_string //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT + const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW { return this->crend(); } //! <b>Effects</b>: Returns a const_iterator to the first element contained in the vector. @@ -893,7 +898,7 @@ class basic_string //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT + const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW { return this->priv_addr(); } //! <b>Effects</b>: Returns a const_iterator to the end of the vector. @@ -901,7 +906,7 @@ class basic_string //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator cend() const BOOST_CONTAINER_NOEXCEPT + const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW { return this->priv_end_addr(); } //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning @@ -910,7 +915,7 @@ class basic_string //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT + const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW { return const_reverse_iterator(this->priv_end_addr()); } //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end @@ -919,7 +924,7 @@ class basic_string //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT + const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW { return const_reverse_iterator(this->priv_addr()); } ////////////////////////////////////////////// @@ -933,7 +938,7 @@ class basic_string //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - bool empty() const BOOST_CONTAINER_NOEXCEPT + bool empty() const BOOST_NOEXCEPT_OR_NOTHROW { return !this->priv_size(); } //! <b>Effects</b>: Returns the number of the elements contained in the vector. @@ -941,7 +946,7 @@ class basic_string //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - size_type size() const BOOST_CONTAINER_NOEXCEPT + size_type size() const BOOST_NOEXCEPT_OR_NOTHROW { return this->priv_size(); } //! <b>Effects</b>: Returns the number of the elements contained in the vector. @@ -949,7 +954,7 @@ class basic_string //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - size_type length() const BOOST_CONTAINER_NOEXCEPT + size_type length() const BOOST_NOEXCEPT_OR_NOTHROW { return this->size(); } //! <b>Effects</b>: Returns the largest possible size of the vector. @@ -957,7 +962,7 @@ class basic_string //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - size_type max_size() const BOOST_CONTAINER_NOEXCEPT + size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW { return base_t::max_size(); } //! <b>Effects</b>: Inserts or erases elements at the end such that @@ -1009,7 +1014,7 @@ class basic_string //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - size_type capacity() const BOOST_CONTAINER_NOEXCEPT + size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW { return this->priv_capacity(); } //! <b>Effects</b>: If n is less than or equal to capacity(), this call has no @@ -1066,7 +1071,7 @@ class basic_string //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - reference operator[](size_type n) BOOST_CONTAINER_NOEXCEPT + reference operator[](size_type n) BOOST_NOEXCEPT_OR_NOTHROW { return *(this->priv_addr() + n); } //! <b>Requires</b>: size() > n. @@ -1077,7 +1082,7 @@ class basic_string //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reference operator[](size_type n) const BOOST_CONTAINER_NOEXCEPT + const_reference operator[](size_type n) const BOOST_NOEXCEPT_OR_NOTHROW { return *(this->priv_addr() + n); } //! <b>Requires</b>: size() > n. @@ -1220,7 +1225,7 @@ class basic_string //! <b>Throws</b>: Nothing //! //! <b>Returns</b>: *this - basic_string& assign(BOOST_RV_REF(basic_string) ms) BOOST_CONTAINER_NOEXCEPT + basic_string& assign(BOOST_RV_REF(basic_string) ms) BOOST_NOEXCEPT_OR_NOTHROW { return this->swap_data(ms), *this; } //! <b>Requires</b>: pos <= str.size() @@ -1458,27 +1463,28 @@ class basic_string { const size_type n_pos = p - this->cbegin(); if (first != last) { - const size_type n = std::distance(first, last); + const size_type n = boost::container::iterator_distance(first, last); const size_type old_size = this->priv_size(); const size_type remaining = this->capacity() - old_size; const pointer old_start = this->priv_addr(); bool enough_capacity = false; - std::pair<pointer, bool> allocation_ret; size_type new_cap = 0; //Check if we have enough capacity + pointer hint = pointer(); + pointer allocation_ret = pointer(); if (remaining >= n){ enough_capacity = true; } else { //Otherwise expand current buffer or allocate new storage new_cap = this->next_capacity(n); + hint = old_start; allocation_ret = this->allocation_command - (allocate_new | expand_fwd | expand_bwd, old_size + n + 1, - new_cap, new_cap, old_start); + (allocate_new | expand_fwd | expand_bwd, old_size + n + 1, new_cap, hint); //Check forward expansion - if(old_start == allocation_ret.first){ + if(old_start == allocation_ret){ enough_capacity = true; this->priv_storage(new_cap); } @@ -1501,7 +1507,7 @@ class basic_string } else { ForwardIter mid = first; - std::advance(mid, elems_after + 1); + boost::container::iterator_advance(mid, elems_after + 1); priv_uninitialized_copy(mid, last, old_start + old_size + 1); const size_type newer_size = old_size + (n - elems_after); @@ -1514,8 +1520,8 @@ class basic_string } } else{ - pointer new_start = allocation_ret.first; - if(!allocation_ret.second){ + pointer new_start = allocation_ret; + if(!hint){ //Copy data to new buffer size_type new_length = 0; //This can't throw, since characters are POD @@ -1585,7 +1591,7 @@ class basic_string //! //! <b>Returns</b>: An iterator which points to the element immediately following p prior to the element being //! erased. If no such element exists, end() is returned. - iterator erase(const_iterator p) BOOST_CONTAINER_NOEXCEPT + 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)); @@ -1605,7 +1611,7 @@ class basic_string //! //! <b>Returns</b>: An iterator which points to the element pointed to by last prior to //! the other elements being erased. If no such element exists, end() is returned. - iterator erase(const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT + iterator erase(const_iterator first, const_iterator last) BOOST_NOEXCEPT_OR_NOTHROW { CharT * f = const_cast<CharT*>(container_detail::to_raw_pointer(first)); if (first != last) { // The move includes the terminating null. @@ -1625,7 +1631,7 @@ class basic_string //! <b>Throws</b>: Nothing //! //! <b>Effects</b>: Equivalent to erase(size() - 1, 1). - void pop_back() BOOST_CONTAINER_NOEXCEPT + void pop_back() BOOST_NOEXCEPT_OR_NOTHROW { const size_type old_size = this->priv_size(); Traits::assign(this->priv_addr()[old_size-1], CharT(0)); @@ -1637,7 +1643,7 @@ class basic_string //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Linear to the number of elements in the vector. - void clear() BOOST_CONTAINER_NOEXCEPT + void clear() BOOST_NOEXCEPT_OR_NOTHROW { if (!this->empty()) { Traits::assign(*this->priv_addr(), CharT(0)); @@ -1850,7 +1856,7 @@ class basic_string >::type * = 0 ) { - difference_type n = std::distance(j1, j2); + 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))); @@ -1858,7 +1864,7 @@ class basic_string } else { ForwardIter m = j1; - std::advance(m, len); + boost::container::iterator_advance(m, len); this->priv_copy(j1, m, const_cast<CharT*>(container_detail::to_raw_pointer(i1))); this->insert(i2, m, j2); } @@ -1891,6 +1897,8 @@ class basic_string //! //! <b>Throws</b>: Nothing void swap(basic_string& x) + BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_swap::value + || allocator_traits_type::is_always_equal::value) { this->base_t::swap_data(x); container_detail::bool_<allocator_traits_type::propagate_on_container_swap::value> flag; @@ -1905,18 +1913,18 @@ class basic_string //! <b>Requires</b>: The program shall not alter any of the values stored in the character array. //! - //! <b>Returns</b>: Allocator pointer p such that p + i == &operator[](i) for each i in [0,size()]. + //! <b>Returns</b>: A pointer p such that p + i == &operator[](i) for each i in [0,size()]. //! //! <b>Complexity</b>: constant time. - const CharT* c_str() const BOOST_CONTAINER_NOEXCEPT + const CharT* c_str() const BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::to_raw_pointer(this->priv_addr()); } //! <b>Requires</b>: The program shall not alter any of the values stored in the character array. //! - //! <b>Returns</b>: Allocator pointer p such that p + i == &operator[](i) for each i in [0,size()]. + //! <b>Returns</b>: A pointer p such that p + i == &operator[](i) for each i in [0,size()]. //! //! <b>Complexity</b>: constant time. - const CharT* data() const BOOST_CONTAINER_NOEXCEPT + const CharT* data() const BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::to_raw_pointer(this->priv_addr()); } ////////////////////////////////////////////// @@ -2357,8 +2365,8 @@ class basic_string if (this->capacity() < res_arg){ size_type n = container_detail::max_value(res_arg, this->size()) + 1; size_type new_cap = this->next_capacity(n); - pointer new_start = this->allocation_command - (allocate_new, n, new_cap, new_cap).first; + pointer reuse = 0; + pointer new_start = this->allocation_command(allocate_new, n, new_cap, reuse); size_type new_length = 0; const pointer addr = this->priv_addr(); @@ -2389,7 +2397,7 @@ class basic_string template<class AllocVersion> void priv_shrink_to_fit_dynamic_buffer ( AllocVersion - , typename container_detail::enable_if<container_detail::is_same<AllocVersion, allocator_v1> >::type* = 0) + , typename container_detail::enable_if<container_detail::is_same<AllocVersion, version_1> >::type* = 0) { //Allocate a new buffer. size_type real_cap = 0; @@ -2398,13 +2406,14 @@ class basic_string const size_type long_storage = this->priv_long_storage(); //We can make this nothrow as chars are always NoThrowCopyables BOOST_TRY{ - const std::pair<pointer, bool> ret = this->allocation_command - (allocate_new, long_size+1, long_size+1, real_cap, long_addr); + pointer reuse = 0; + 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.first) + Traits::copy( container_detail::to_raw_pointer(ret) , container_detail::to_raw_pointer(this->priv_long_addr()) , long_size+1); - this->priv_long_addr(ret.first); + this->priv_long_addr(ret); this->priv_storage(real_cap); //And release old buffer this->alloc().deallocate(long_addr, long_storage); @@ -2418,13 +2427,12 @@ class basic_string template<class AllocVersion> void priv_shrink_to_fit_dynamic_buffer ( AllocVersion - , typename container_detail::enable_if<container_detail::is_same<AllocVersion, allocator_v2> >::type* = 0) + , typename container_detail::enable_if<container_detail::is_same<AllocVersion, version_2> >::type* = 0) { - size_type received_size; + size_type received_size = this->priv_long_size()+1; + pointer hint = this->priv_long_addr(); if(this->alloc().allocation_command - ( shrink_in_place | nothrow_allocation - , this->priv_long_storage(), this->priv_long_size()+1 - , received_size, this->priv_long_addr()).first){ + ( shrink_in_place | nothrow_allocation, this->priv_long_storage(), received_size, hint)){ this->priv_storage(received_size); } } @@ -2504,7 +2512,7 @@ class basic_string InputIter f, InputIter l, container_detail::false_) { - typedef typename std::iterator_traits<InputIter>::iterator_category Category; + typedef typename boost::container::iterator_traits<InputIter>::iterator_category Category; return this->priv_replace(first, last, f, l, Category()); } @@ -2518,7 +2526,7 @@ class basic_string typedef basic_string <char ,std::char_traits<char> - ,std::allocator<char> > + ,new_allocator<char> > string; //!Typedef for a basic_string of @@ -2526,7 +2534,7 @@ string; typedef basic_string <wchar_t ,std::char_traits<wchar_t> - ,std::allocator<wchar_t> > + ,new_allocator<wchar_t> > wstring; #endif @@ -2552,29 +2560,29 @@ template <class CharT, class Traits, class Allocator> inline template <class CharT, class Traits, class Allocator> inline basic_string<CharT, Traits, Allocator> operator+ - ( BOOST_RV_REF_BEG basic_string<CharT, Traits, Allocator> BOOST_RV_REF_END mx - , BOOST_RV_REF_BEG basic_string<CharT, Traits, Allocator> BOOST_RV_REF_END my) + ( BOOST_RV_REF_BEG basic_string<CharT, Traits, Allocator> BOOST_RV_REF_END x + , BOOST_RV_REF_BEG basic_string<CharT, Traits, Allocator> BOOST_RV_REF_END y) { - mx += my; - return boost::move(mx); + x += y; + return boost::move(x); } template <class CharT, class Traits, class Allocator> inline basic_string<CharT, Traits, Allocator> operator+ - ( BOOST_RV_REF_BEG basic_string<CharT, Traits, Allocator> BOOST_RV_REF_END mx + ( BOOST_RV_REF_BEG basic_string<CharT, Traits, Allocator> BOOST_RV_REF_END x , const basic_string<CharT,Traits,Allocator>& y) { - mx += y; - return boost::move(mx); + x += y; + return boost::move(x); } template <class CharT, class Traits, class Allocator> inline basic_string<CharT, Traits, Allocator> operator+ (const basic_string<CharT,Traits,Allocator>& x - ,BOOST_RV_REF_BEG basic_string<CharT, Traits, Allocator> BOOST_RV_REF_END my) + ,BOOST_RV_REF_BEG basic_string<CharT, Traits, Allocator> BOOST_RV_REF_END y) { - my.insert(my.begin(), x.begin(), x.end()); - return boost::move(my); + y.insert(y.begin(), x.begin(), x.end()); + return boost::move(y); } template <class CharT, class Traits, class Allocator> inline @@ -2899,15 +2907,15 @@ inline std::size_t hash_value(basic_string<Ch, std::char_traits<Ch>, Allocator> namespace boost { -template <class T> -struct has_trivial_destructor_after_move; - //!has_trivial_destructor_after_move<> == true_type //!specialization for optimizations template <class C, class T, class Allocator> struct has_trivial_destructor_after_move<boost::container::basic_string<C, T, Allocator> > - : public ::boost::has_trivial_destructor_after_move<Allocator> -{}; +{ + typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer; + static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value && + ::boost::has_trivial_destructor_after_move<pointer>::value; +}; } diff --git a/boost/container/throw_exception.hpp b/boost/container/throw_exception.hpp index 02768856e5..2c893e95c8 100644 --- a/boost/container/throw_exception.hpp +++ b/boost/container/throw_exception.hpp @@ -11,7 +11,11 @@ #ifndef BOOST_CONTAINER_THROW_EXCEPTION_HPP #define BOOST_CONTAINER_THROW_EXCEPTION_HPP -#if defined(_MSC_VER) +#ifndef BOOST_CONFIG_HPP +# include <boost/config.hpp> +#endif + +#if defined(BOOST_HAS_PRAGMA_ONCE) # pragma once #endif diff --git a/boost/container/vector.hpp b/boost/container/vector.hpp index 765a2c6861..1b6d963934 100644 --- a/boost/container/vector.hpp +++ b/boost/container/vector.hpp @@ -11,51 +11,57 @@ #ifndef BOOST_CONTAINER_CONTAINER_VECTOR_HPP #define BOOST_CONTAINER_CONTAINER_VECTOR_HPP -#if defined(_MSC_VER) +#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> -#include <boost/container/container_fwd.hpp> - -//#include <cstddef> //Already included by container_fwd.hpp -#include <memory> //for std::allocator -#include <iterator> //for std::random_access_iterator_tag -#include <utility> //for std::pair,std::distance -#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) -#include <initializer_list> //for std::initializer_list -#endif - -#include <boost/core/no_exceptions_support.hpp> -#include <boost/assert.hpp> -#include <boost/move/utility_core.hpp> -#include <boost/move/iterator.hpp> -#include <boost/move/algorithm.hpp> -#include <boost/move/detail/move_helpers.hpp> -#include <boost/move/traits.hpp> -#include <boost/container/detail/version_type.hpp> -#include <boost/container/detail/allocation_type.hpp> -#include <boost/container/detail/utilities.hpp> -#include <boost/container/detail/iterators.hpp> -#include <boost/container/detail/algorithms.hpp> -#include <boost/container/detail/destroyers.hpp> +// container +#include <boost/container/container_fwd.hpp> #include <boost/container/allocator_traits.hpp> -#include <boost/container/detail/allocator_version_traits.hpp> +#include <boost/container/new_allocator.hpp> //new_allocator #include <boost/container/throw_exception.hpp> +// container detail +#include <boost/container/detail/advanced_insert_int.hpp> +#include <boost/container/detail/algorithm.hpp> //equal() +#include <boost/container/detail/alloc_helpers.hpp> +#include <boost/container/detail/allocation_type.hpp> +#include <boost/container/detail/copy_move_algo.hpp> +#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/container/detail/mpl.hpp> +#include <boost/container/detail/next_capacity.hpp> +#include <boost/container/detail/to_raw_pointer.hpp> #include <boost/container/detail/type_traits.hpp> -#include <boost/container/detail/advanced_insert_int.hpp> - +#include <boost/container/detail/version_type.hpp> +// intrusive #include <boost/intrusive/pointer_traits.hpp> +// move +#include <boost/move/adl_move_swap.hpp> +#include <boost/move/iterator.hpp> +#include <boost/move/traits.hpp> +#include <boost/move/utility_core.hpp> +// move/detail +#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +#include <boost/move/detail/fwd_macros.hpp> +#endif +#include <boost/move/detail/move_helpers.hpp> +// other +#include <boost/core/no_exceptions_support.hpp> +#include <boost/assert.hpp> -#include <boost/type_traits/has_trivial_destructor.hpp> -#include <boost/type_traits/has_trivial_copy.hpp> -#include <boost/type_traits/has_trivial_assign.hpp> -#include <boost/type_traits/has_nothrow_copy.hpp> -#include <boost/type_traits/has_nothrow_assign.hpp> -#include <boost/type_traits/has_nothrow_constructor.hpp> +//std +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) +#include <initializer_list> //for std::initializer_list +#endif namespace boost { namespace container { @@ -81,7 +87,7 @@ class vec_iterator rebind_pointer<const value_type>::type , Pointer >::type pointer; - typedef typename boost::intrusive::pointer_traits<Pointer> ptr_traits; + typedef typename boost::intrusive::pointer_traits<pointer> ptr_traits; typedef typename ptr_traits::reference reference; #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED @@ -89,13 +95,13 @@ class vec_iterator Pointer m_ptr; public: - const Pointer &get_ptr() const BOOST_CONTAINER_NOEXCEPT + const Pointer &get_ptr() const BOOST_NOEXCEPT_OR_NOTHROW { return m_ptr; } - Pointer &get_ptr() BOOST_CONTAINER_NOEXCEPT + Pointer &get_ptr() BOOST_NOEXCEPT_OR_NOTHROW { return m_ptr; } - explicit vec_iterator(Pointer ptr) BOOST_CONTAINER_NOEXCEPT + explicit vec_iterator(Pointer ptr) BOOST_NOEXCEPT_OR_NOTHROW : m_ptr(ptr) {} #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED @@ -103,84 +109,84 @@ class vec_iterator public: //Constructors - vec_iterator() BOOST_CONTAINER_NOEXCEPT + vec_iterator() BOOST_NOEXCEPT_OR_NOTHROW : m_ptr() //Value initialization to achieve "null iterators" (N3644) {} - vec_iterator(vec_iterator<Pointer, false> const& other) BOOST_CONTAINER_NOEXCEPT + vec_iterator(vec_iterator<Pointer, false> const& other) BOOST_NOEXCEPT_OR_NOTHROW : m_ptr(other.get_ptr()) {} //Pointer like operators - reference operator*() const BOOST_CONTAINER_NOEXCEPT + reference operator*() const BOOST_NOEXCEPT_OR_NOTHROW { return *m_ptr; } - pointer operator->() const BOOST_CONTAINER_NOEXCEPT + pointer operator->() const BOOST_NOEXCEPT_OR_NOTHROW { return ::boost::intrusive::pointer_traits<pointer>::pointer_to(this->operator*()); } - reference operator[](difference_type off) const BOOST_CONTAINER_NOEXCEPT + reference operator[](difference_type off) const BOOST_NOEXCEPT_OR_NOTHROW { return m_ptr[off]; } //Increment / Decrement - vec_iterator& operator++() BOOST_CONTAINER_NOEXCEPT + vec_iterator& operator++() BOOST_NOEXCEPT_OR_NOTHROW { ++m_ptr; return *this; } - vec_iterator operator++(int) BOOST_CONTAINER_NOEXCEPT + vec_iterator operator++(int) BOOST_NOEXCEPT_OR_NOTHROW { return vec_iterator(m_ptr++); } - vec_iterator& operator--() BOOST_CONTAINER_NOEXCEPT + vec_iterator& operator--() BOOST_NOEXCEPT_OR_NOTHROW { --m_ptr; return *this; } - vec_iterator operator--(int) BOOST_CONTAINER_NOEXCEPT + vec_iterator operator--(int) BOOST_NOEXCEPT_OR_NOTHROW { return vec_iterator(m_ptr--); } //Arithmetic - vec_iterator& operator+=(difference_type off) BOOST_CONTAINER_NOEXCEPT + vec_iterator& operator+=(difference_type off) BOOST_NOEXCEPT_OR_NOTHROW { m_ptr += off; return *this; } - vec_iterator& operator-=(difference_type off) BOOST_CONTAINER_NOEXCEPT + vec_iterator& operator-=(difference_type off) BOOST_NOEXCEPT_OR_NOTHROW { m_ptr -= off; return *this; } - friend vec_iterator operator+(const vec_iterator &x, difference_type off) BOOST_CONTAINER_NOEXCEPT + friend vec_iterator operator+(const vec_iterator &x, difference_type off) BOOST_NOEXCEPT_OR_NOTHROW { return vec_iterator(x.m_ptr+off); } - friend vec_iterator operator+(difference_type off, vec_iterator right) BOOST_CONTAINER_NOEXCEPT + friend vec_iterator operator+(difference_type off, vec_iterator right) BOOST_NOEXCEPT_OR_NOTHROW { right.m_ptr += off; return right; } - friend vec_iterator operator-(vec_iterator left, difference_type off) BOOST_CONTAINER_NOEXCEPT + friend vec_iterator operator-(vec_iterator left, difference_type off) BOOST_NOEXCEPT_OR_NOTHROW { left.m_ptr -= off; return left; } - friend difference_type operator-(const vec_iterator &left, const vec_iterator& right) BOOST_CONTAINER_NOEXCEPT + friend difference_type operator-(const vec_iterator &left, const vec_iterator& right) BOOST_NOEXCEPT_OR_NOTHROW { return left.m_ptr - right.m_ptr; } //Comparison operators - friend bool operator== (const vec_iterator& l, const vec_iterator& r) BOOST_CONTAINER_NOEXCEPT + friend bool operator== (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW { return l.m_ptr == r.m_ptr; } - friend bool operator!= (const vec_iterator& l, const vec_iterator& r) BOOST_CONTAINER_NOEXCEPT + friend bool operator!= (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW { return l.m_ptr != r.m_ptr; } - friend bool operator< (const vec_iterator& l, const vec_iterator& r) BOOST_CONTAINER_NOEXCEPT + friend bool operator< (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW { return l.m_ptr < r.m_ptr; } - friend bool operator<= (const vec_iterator& l, const vec_iterator& r) BOOST_CONTAINER_NOEXCEPT + friend bool operator<= (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW { return l.m_ptr <= r.m_ptr; } - friend bool operator> (const vec_iterator& l, const vec_iterator& r) BOOST_CONTAINER_NOEXCEPT + friend bool operator> (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW { return l.m_ptr > r.m_ptr; } - friend bool operator>= (const vec_iterator& l, const vec_iterator& r) BOOST_CONTAINER_NOEXCEPT + friend bool operator>= (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW { return l.m_ptr >= r.m_ptr; } }; } //namespace container_detail { template<class Pointer, bool IsConst> -const Pointer &vector_iterator_get_ptr(const container_detail::vec_iterator<Pointer, IsConst> &it) BOOST_CONTAINER_NOEXCEPT +const Pointer &vector_iterator_get_ptr(const container_detail::vec_iterator<Pointer, IsConst> &it) BOOST_NOEXCEPT_OR_NOTHROW { return it.get_ptr(); } template<class Pointer, bool IsConst> -Pointer &get_ptr(container_detail::vec_iterator<Pointer, IsConst> &it) BOOST_CONTAINER_NOEXCEPT +Pointer &get_ptr(container_detail::vec_iterator<Pointer, IsConst> &it) BOOST_NOEXCEPT_OR_NOTHROW { return it.get_ptr(); } namespace container_detail { @@ -199,7 +205,7 @@ struct vector_get_ptr_pointer_to_non_const typedef typename pointer_traits_t ::template rebind_pointer<non_const_element_type>::type return_type; - static return_type get_ptr(const const_pointer &ptr) BOOST_CONTAINER_NOEXCEPT + static return_type get_ptr(const const_pointer &ptr) BOOST_NOEXCEPT_OR_NOTHROW { return boost::intrusive::pointer_traits<return_type>::const_cast_from(ptr); } }; @@ -207,7 +213,7 @@ template<class Pointer> struct vector_get_ptr_pointer_to_non_const<Pointer, false> { typedef const Pointer & return_type; - static return_type get_ptr(const Pointer &ptr) BOOST_CONTAINER_NOEXCEPT + static return_type get_ptr(const Pointer &ptr) BOOST_NOEXCEPT_OR_NOTHROW { return ptr; } }; @@ -215,7 +221,7 @@ struct vector_get_ptr_pointer_to_non_const<Pointer, false> template<class MaybeConstPointer> typename container_detail::vector_get_ptr_pointer_to_non_const<MaybeConstPointer>::return_type - vector_iterator_get_ptr(const MaybeConstPointer &ptr) BOOST_CONTAINER_NOEXCEPT + vector_iterator_get_ptr(const MaybeConstPointer &ptr) BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::vector_get_ptr_pointer_to_non_const<MaybeConstPointer>::get_ptr(ptr); } @@ -230,12 +236,12 @@ static const uninitialized_size_t uninitialized_size = uninitialized_size_t(); template <class T> struct vector_value_traits_base { - static const bool trivial_dctr = boost::has_trivial_destructor<T>::value; - static const bool trivial_dctr_after_move = ::boost::has_trivial_destructor_after_move<T>::value; - static const bool trivial_copy = has_trivial_copy<T>::value; - static const bool nothrow_copy = has_nothrow_copy<T>::value || trivial_copy; - static const bool trivial_assign = has_trivial_assign<T>::value; - static const bool nothrow_assign = has_nothrow_assign<T>::value || trivial_assign; + static const bool trivial_dctr = is_trivially_destructible<T>::value; + static const bool trivial_dctr_after_move = has_trivial_destructor_after_move<T>::value; + static const bool trivial_copy = is_trivially_copy_constructible<T>::value; + static const bool nothrow_copy = is_nothrow_copy_constructible<T>::value || trivial_copy; + static const bool trivial_assign = is_trivially_copy_assignable<T>::value; + static const bool nothrow_assign = is_nothrow_copy_assignable<T>::value || trivial_assign; }; @@ -266,20 +272,38 @@ struct vector_alloc_holder BOOST_MOVABLE_BUT_NOT_COPYABLE(vector_alloc_holder) public: + typedef Allocator allocator_type; typedef boost::container::allocator_traits<Allocator> allocator_traits_type; typedef typename allocator_traits_type::pointer pointer; typedef typename allocator_traits_type::size_type size_type; typedef typename allocator_traits_type::value_type value_type; + static bool is_propagable_from(const allocator_type &from_alloc, pointer p, const allocator_type &to_alloc, bool const propagate_allocator) + { + (void)propagate_allocator; (void)p; (void)to_alloc; (void)from_alloc; + return (!allocator_traits_type::is_partially_propagable::value || + !allocator_traits_type::storage_is_unpropagable(from_alloc, p)) && + (propagate_allocator || allocator_traits_type::equal(from_alloc, to_alloc)); + } + + static bool are_swap_propagable(const allocator_type &l_a, pointer l_p, const allocator_type &r_a, pointer r_p, bool const propagate_allocator) + { + (void)propagate_allocator; (void)l_p; (void)r_p; (void)l_a; (void)r_a; + return (!allocator_traits_type::is_partially_propagable::value || + (!allocator_traits_type::storage_is_unpropagable(r_a, r_p) && + !allocator_traits_type::storage_is_unpropagable(l_a, l_p)) + ) && (propagate_allocator || allocator_traits_type::equal(l_a, r_a)); + } + //Constructor, does not throw vector_alloc_holder() - BOOST_CONTAINER_NOEXCEPT_IF(::boost::has_nothrow_default_constructor<Allocator>::value) + BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value) : Allocator(), m_start(), m_size(), m_capacity() {} //Constructor, does not throw template<class AllocConvertible> - explicit vector_alloc_holder(BOOST_FWD_REF(AllocConvertible) a) BOOST_CONTAINER_NOEXCEPT + explicit vector_alloc_holder(BOOST_FWD_REF(AllocConvertible) a) BOOST_NOEXCEPT_OR_NOTHROW : Allocator(boost::forward<AllocConvertible>(a)), m_start(), m_size(), m_capacity() {} @@ -292,7 +316,8 @@ struct vector_alloc_holder , m_capacity() { if(initial_size){ - m_start = this->allocation_command(allocate_new, initial_size, initial_size, m_capacity, m_start).first; + pointer reuse = 0; + m_start = this->allocation_command(allocate_new, initial_size, m_capacity = initial_size, reuse); } } @@ -304,13 +329,13 @@ struct vector_alloc_holder , m_capacity() { if(initial_size){ - m_start = this->allocation_command - (allocate_new, initial_size, initial_size, m_capacity, m_start).first; + pointer reuse = 0; + m_start = this->allocation_command(allocate_new, initial_size, m_capacity = initial_size, reuse); } } - vector_alloc_holder(BOOST_RV_REF(vector_alloc_holder) holder) BOOST_CONTAINER_NOEXCEPT - : Allocator(boost::move(static_cast<Allocator&>(holder))) + vector_alloc_holder(BOOST_RV_REF(vector_alloc_holder) holder) BOOST_NOEXCEPT_OR_NOTHROW + : Allocator(BOOST_MOVE_BASE(Allocator, holder)) , m_start(holder.m_start) , m_size(holder.m_size) , m_capacity(holder.m_capacity) @@ -319,35 +344,78 @@ struct vector_alloc_holder holder.m_size = holder.m_capacity = 0; } - void first_allocation(size_type cap) + vector_alloc_holder(pointer p, size_type capacity, BOOST_RV_REF(vector_alloc_holder) holder) + : Allocator(BOOST_MOVE_BASE(Allocator, holder)) + , m_start(p) + , m_size(holder.m_size) + , m_capacity(capacity) { - if(cap){ - m_start = this->allocation_command - (allocate_new, cap, cap, m_capacity, m_start).first; + allocator_type &this_alloc = this->alloc(); + allocator_type &x_alloc = holder.alloc(); + if(this->is_propagable_from(x_alloc, holder.start(), this_alloc, true)){ + if(this->m_capacity){ + this->alloc().deallocate(this->m_start, this->m_capacity); + } + m_start = holder.m_start; + m_capacity = holder.m_capacity; + holder.m_start = pointer(); + holder.m_capacity = holder.m_size = 0; + } + else if(this->m_capacity < holder.m_size){ + size_type const n = holder.m_size; + pointer reuse = pointer(); + m_start = this->allocation_command(allocate_new, n, m_capacity = n, reuse); #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS - ++this->num_alloc; + this->num_alloc += n != 0; #endif } } - void first_allocation_same_allocator_type(size_type cap) - { this->first_allocation(cap); } + vector_alloc_holder(pointer p, size_type n) + BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value) + : Allocator() + , m_start(p) + , m_size() + , m_capacity(n) + {} + + template<class AllocFwd> + vector_alloc_holder(pointer p, size_type n, BOOST_FWD_REF(AllocFwd) a) + : Allocator(::boost::forward<AllocFwd>(a)) + , m_start(p) + , m_size() + , m_capacity(n) + {} - ~vector_alloc_holder() BOOST_CONTAINER_NOEXCEPT + ~vector_alloc_holder() BOOST_NOEXCEPT_OR_NOTHROW { if(this->m_capacity){ this->alloc().deallocate(this->m_start, this->m_capacity); } } - std::pair<pointer, bool> - allocation_command(boost::container::allocation_type command, - size_type limit_size, - size_type preferred_size, - size_type &received_size, const pointer &reuse = pointer()) + pointer allocation_command(boost::container::allocation_type command, + size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse) { - return allocator_version_traits<Allocator>::allocation_command - (this->alloc(), command, limit_size, preferred_size, received_size, reuse); + typedef typename container_detail::version<Allocator>::type alloc_version; + return this->priv_allocation_command(alloc_version(), command, limit_size, prefer_in_recvd_out_size, reuse); + } + + bool try_expand_fwd(size_type at_least) + { + //There is not enough memory, try to expand the old one + const size_type new_cap = this->capacity() + at_least; + size_type real_cap = new_cap; + pointer reuse = this->start(); + bool const success = !!this->allocation_command(expand_fwd, new_cap, real_cap, reuse); + //Check for forward expansion + if(success){ + #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS + ++this->num_expand_fwd; + #endif + this->capacity(real_cap); + } + return success; } size_type next_capacity(size_type additional_objects) const @@ -362,37 +430,71 @@ struct vector_alloc_holder size_type m_size; size_type m_capacity; - void swap(vector_alloc_holder &x) BOOST_CONTAINER_NOEXCEPT + void swap_resources(vector_alloc_holder &x) BOOST_NOEXCEPT_OR_NOTHROW { - boost::container::swap_dispatch(this->m_start, x.m_start); - boost::container::swap_dispatch(this->m_size, x.m_size); - boost::container::swap_dispatch(this->m_capacity, x.m_capacity); + boost::adl_move_swap(this->m_start, x.m_start); + boost::adl_move_swap(this->m_size, x.m_size); + boost::adl_move_swap(this->m_capacity, x.m_capacity); } - void move_from_empty(vector_alloc_holder &x) BOOST_CONTAINER_NOEXCEPT + void steal_resources(vector_alloc_holder &x) BOOST_NOEXCEPT_OR_NOTHROW { - //this->m_size was previously initialized this->m_start = x.m_start; + this->m_size = x.m_size; this->m_capacity = x.m_capacity; x.m_start = pointer(); x.m_size = x.m_capacity = 0; } - Allocator &alloc() BOOST_CONTAINER_NOEXCEPT + Allocator &alloc() BOOST_NOEXCEPT_OR_NOTHROW { return *this; } - const Allocator &alloc() const BOOST_CONTAINER_NOEXCEPT + const Allocator &alloc() const BOOST_NOEXCEPT_OR_NOTHROW { return *this; } - const pointer &start() const BOOST_CONTAINER_NOEXCEPT { return m_start; } - const size_type &capacity() const BOOST_CONTAINER_NOEXCEPT { return m_capacity; } - void start(const pointer &p) BOOST_CONTAINER_NOEXCEPT { m_start = p; } - void capacity(const size_type &c) BOOST_CONTAINER_NOEXCEPT { m_capacity = c; } + const pointer &start() const BOOST_NOEXCEPT_OR_NOTHROW { return m_start; } + const size_type &capacity() const BOOST_NOEXCEPT_OR_NOTHROW { return m_capacity; } + void start(const pointer &p) BOOST_NOEXCEPT_OR_NOTHROW { m_start = p; } + void capacity(const size_type &c) BOOST_NOEXCEPT_OR_NOTHROW { m_capacity = c; } + + private: + void priv_first_allocation(size_type cap) + { + if(cap){ + pointer reuse = 0; + m_start = this->allocation_command(allocate_new, cap, cap, reuse); + m_capacity = cap; + #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS + ++this->num_alloc; + #endif + } + } + + pointer priv_allocation_command(version_1, boost::container::allocation_type command, + size_type , + size_type &prefer_in_recvd_out_size, + pointer &reuse) + { + (void)command; + BOOST_ASSERT( (command & allocate_new)); + BOOST_ASSERT(!(command & nothrow_allocation)); + pointer const p = allocator_traits_type::allocate(this->alloc(), prefer_in_recvd_out_size, reuse); + reuse = pointer(); + return p; + } + + pointer priv_allocation_command(version_2, boost::container::allocation_type command, + size_type limit_size, + size_type &prefer_in_recvd_out_size, + pointer &reuse) + { + return this->alloc().allocation_command(command, limit_size, prefer_in_recvd_out_size, reuse); + } }; //!This struct deallocates and allocated memory template <class Allocator> -struct vector_alloc_holder<Allocator, container_detail::integral_constant<unsigned, 0> > +struct vector_alloc_holder<Allocator, version_0> : public Allocator { private: @@ -409,13 +511,13 @@ struct vector_alloc_holder<Allocator, container_detail::integral_constant<unsign //Constructor, does not throw vector_alloc_holder() - BOOST_CONTAINER_NOEXCEPT_IF(::boost::has_nothrow_default_constructor<Allocator>::value) + BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value) : Allocator(), m_size() {} //Constructor, does not throw template<class AllocConvertible> - explicit vector_alloc_holder(BOOST_FWD_REF(AllocConvertible) a) BOOST_CONTAINER_NOEXCEPT + explicit vector_alloc_holder(BOOST_FWD_REF(AllocConvertible) a) BOOST_NOEXCEPT_OR_NOTHROW : Allocator(boost::forward<AllocConvertible>(a)), m_size() {} @@ -426,7 +528,7 @@ struct vector_alloc_holder<Allocator, container_detail::integral_constant<unsign , m_size(initial_size) //Size is initialized here... { //... and capacity here, so vector, must call uninitialized_xxx in the derived constructor - this->first_allocation(initial_size); + this->priv_first_allocation(initial_size); } //Constructor, does not throw @@ -435,11 +537,11 @@ struct vector_alloc_holder<Allocator, container_detail::integral_constant<unsign , m_size(initial_size) //Size is initialized here... { //... and capacity here, so vector, must call uninitialized_xxx in the derived constructor - this->first_allocation(initial_size); + this->priv_first_allocation(initial_size); } vector_alloc_holder(BOOST_RV_REF(vector_alloc_holder) holder) - : Allocator(boost::move(static_cast<Allocator&>(holder))) + : Allocator(BOOST_MOVE_BASE(Allocator, holder)) , m_size(holder.m_size) //Size is initialized here so vector should only call uninitialized_xxx after this { ::boost::container::uninitialized_move_alloc_n @@ -453,60 +555,62 @@ struct vector_alloc_holder<Allocator, container_detail::integral_constant<unsign { //Different allocator type so we must check we have enough storage const size_type n = holder.m_size; - this->first_allocation(n); + 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())); } - void first_allocation(size_type cap) + void priv_first_allocation(size_type cap) { if(cap > Allocator::internal_capacity){ throw_bad_alloc(); } } - void first_allocation_same_allocator_type(size_type) BOOST_CONTAINER_NOEXCEPT - {} - - //Destructor - ~vector_alloc_holder() BOOST_CONTAINER_NOEXCEPT - {} - - void swap(vector_alloc_holder &x) + void deep_swap(vector_alloc_holder &x) { - this->priv_swap_members_impl(x); + this->priv_deep_swap(x); } template<class OtherAllocator, class OtherAllocatorVersion> - void swap(vector_alloc_holder<OtherAllocator, OtherAllocatorVersion> &x) + void deep_swap(vector_alloc_holder<OtherAllocator, OtherAllocatorVersion> &x) { if(this->m_size > OtherAllocator::internal_capacity || x.m_size > Allocator::internal_capacity){ throw_bad_alloc(); } - this->priv_swap_members_impl(x); + this->priv_deep_swap(x); + } + + void swap_resources(vector_alloc_holder &x) BOOST_NOEXCEPT_OR_NOTHROW + { //Containers with version 0 allocators can't be moved without moving elements one by one + throw_bad_alloc(); } - void move_from_empty(vector_alloc_holder &) - { //Containers with version 0 allocators can't be moved without move elements one by one + + void steal_resources(vector_alloc_holder &) + { //Containers with version 0 allocators can't be moved without moving elements one by one throw_bad_alloc(); } - Allocator &alloc() BOOST_CONTAINER_NOEXCEPT + Allocator &alloc() BOOST_NOEXCEPT_OR_NOTHROW { return *this; } - const Allocator &alloc() const BOOST_CONTAINER_NOEXCEPT + const Allocator &alloc() const BOOST_NOEXCEPT_OR_NOTHROW { return *this; } - pointer start() const BOOST_CONTAINER_NOEXCEPT { return Allocator::internal_storage(); } - size_type capacity() const BOOST_CONTAINER_NOEXCEPT { return Allocator::internal_capacity; } + bool try_expand_fwd(size_type at_least) + { return !at_least; } + + pointer start() const BOOST_NOEXCEPT_OR_NOTHROW { return Allocator::internal_storage(); } + size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW { return Allocator::internal_capacity; } size_type m_size; private: template<class OtherAllocator, class OtherAllocatorVersion> - void priv_swap_members_impl(vector_alloc_holder<OtherAllocator, OtherAllocatorVersion> &x) + void priv_deep_swap(vector_alloc_holder<OtherAllocator, OtherAllocatorVersion> &x) { - const std::size_t MaxTmpStorage = sizeof(value_type)*Allocator::internal_capacity; + 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()); @@ -516,7 +620,7 @@ struct vector_alloc_holder<Allocator, container_detail::integral_constant<unsign else{ boost::container::deep_swap_alloc_n<MaxTmpStorage>(this->alloc(), first_x, x.m_size, first_this, this->m_size); } - boost::container::swap_dispatch(this->m_size, x.m_size); + boost::adl_move_swap(this->m_size, x.m_size); } }; @@ -531,23 +635,30 @@ struct vector_alloc_holder<Allocator, container_detail::integral_constant<unsign //! //! \tparam T The type of object that is stored in the vector //! \tparam Allocator The allocator used for all internal memory management -template <class T, class Allocator BOOST_CONTAINER_DOCONLY(= std::allocator<T>) > +template <class T, class Allocator BOOST_CONTAINER_DOCONLY(= new_allocator<T>) > class vector { #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED typedef typename container_detail::version<Allocator>::type alloc_version; - boost::container::container_detail::vector_alloc_holder - <Allocator, alloc_version> m_holder; + typedef boost::container::container_detail::vector_alloc_holder<Allocator> alloc_holder_t; + alloc_holder_t m_holder; typedef allocator_traits<Allocator> allocator_traits_type; template <class U, class UAllocator> friend class vector; - typedef typename ::boost::container::allocator_traits - <Allocator>::pointer pointer_impl; + typedef typename allocator_traits_type::pointer pointer_impl; typedef container_detail::vec_iterator<pointer_impl, false> iterator_impl; typedef container_detail::vec_iterator<pointer_impl, true > const_iterator_impl; + protected: + static bool is_propagable_from(const Allocator &from_alloc, pointer_impl p, const Allocator &to_alloc, bool const propagate_allocator) + { return alloc_holder_t::is_propagable_from(from_alloc, p, to_alloc, propagate_allocator); } + + static bool are_swap_propagable( const Allocator &l_a, pointer_impl l_p + , const Allocator &r_a, pointer_impl r_p, bool const propagate_allocator) + { return alloc_holder_t::are_swap_propagable(l_a, l_p, r_a, r_p, propagate_allocator); } + #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED public: ////////////////////////////////////////////// @@ -572,19 +683,30 @@ class vector typedef BOOST_CONTAINER_IMPDEF(iterator_impl) iterator; typedef BOOST_CONTAINER_IMPDEF(const_iterator_impl) const_iterator; #endif - typedef BOOST_CONTAINER_IMPDEF(container_detail::reverse_iterator<iterator>) reverse_iterator; - typedef BOOST_CONTAINER_IMPDEF(container_detail::reverse_iterator<const_iterator>) const_reverse_iterator; + typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<iterator>) reverse_iterator; + typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<const_iterator>) const_reverse_iterator; #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED private: BOOST_COPYABLE_AND_MOVABLE(vector) typedef container_detail::vector_value_traits<Allocator> value_traits; + typedef constant_iterator<T, difference_type> cvalue_iterator; - typedef container_detail::integral_constant<unsigned, 0> allocator_v0; - typedef container_detail::integral_constant<unsigned, 1> allocator_v1; - typedef container_detail::integral_constant<unsigned, 2> allocator_v2; + protected: + + void steal_resources(vector &x) + { return this->m_holder.steal_resources(x.m_holder); } + + struct initial_capacity_t{}; + template<class AllocFwd> + vector(initial_capacity_t, pointer initial_memory, size_type capacity, BOOST_FWD_REF(AllocFwd) a) + : m_holder(initial_memory, capacity, ::boost::forward<AllocFwd>(a)) + {} + + vector(initial_capacity_t, pointer initial_memory, size_type capacity) + : m_holder(initial_memory, capacity) + {} - typedef constant_iterator<T, difference_type> cvalue_iterator; #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED public: @@ -596,11 +718,10 @@ class vector //! <b>Effects</b>: Constructs a vector taking the allocator as parameter. //! - //! <b>Throws</b>: If allocator_type's default constructor throws. + //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - vector() - BOOST_CONTAINER_NOEXCEPT_IF(::boost::has_nothrow_default_constructor<Allocator>::value) + vector() BOOST_NOEXCEPT_OR_NOTHROW : m_holder() {} @@ -609,14 +730,13 @@ class vector //! <b>Throws</b>: Nothing //! //! <b>Complexity</b>: Constant. - explicit vector(const Allocator& a) BOOST_CONTAINER_NOEXCEPT + explicit vector(const allocator_type& a) BOOST_NOEXCEPT_OR_NOTHROW : m_holder(a) {} - //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a - //! and inserts n value initialized values. + //! <b>Effects</b>: Constructs a vector and inserts n value initialized values. //! - //! <b>Throws</b>: If allocator_type's default constructor or allocation + //! <b>Throws</b>: If allocator_type's allocation //! throws or T's value initialization throws. //! //! <b>Complexity</b>: Linear to n. @@ -633,7 +753,7 @@ class vector //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a //! and inserts n default initialized values. //! - //! <b>Throws</b>: If allocator_type's default constructor or allocation + //! <b>Throws</b>: If allocator_type's allocation //! throws or T's default initialization throws. //! //! <b>Complexity</b>: Linear to n. @@ -649,10 +769,46 @@ class vector (this->m_holder.alloc(), n, container_detail::to_raw_pointer(this->m_holder.start())); } + //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a + //! and inserts n value initialized values. + //! + //! <b>Throws</b>: If allocator_type's allocation + //! throws or T's value initialization throws. + //! + //! <b>Complexity</b>: Linear to n. + explicit vector(size_type n, const allocator_type &a) + : m_holder(container_detail::uninitialized_size, a, n) + { + #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS + this->num_alloc += n != 0; + #endif + boost::container::uninitialized_value_init_alloc_n + (this->m_holder.alloc(), n, container_detail::to_raw_pointer(this->m_holder.start())); + } + + //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a + //! and inserts n default initialized values. + //! + //! <b>Throws</b>: If allocator_type's allocation + //! throws or T's default initialization throws. + //! + //! <b>Complexity</b>: Linear to n. + //! + //! <b>Note</b>: Non-standard extension + vector(size_type n, default_init_t, const allocator_type &a) + : m_holder(container_detail::uninitialized_size, a, n) + { + #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS + this->num_alloc += n != 0; + #endif + boost::container::uninitialized_default_init_alloc_n + (this->m_holder.alloc(), n, container_detail::to_raw_pointer(this->m_holder.start())); + } + //! <b>Effects</b>: Constructs a vector //! and inserts n copies of value. //! - //! <b>Throws</b>: If allocator_type's default constructor or allocation + //! <b>Throws</b>: If allocator_type's allocation //! throws or T's copy constructor throws. //! //! <b>Complexity</b>: Linear to n. @@ -686,32 +842,32 @@ class vector //! <b>Effects</b>: Constructs a vector //! and inserts a copy of the range [first, last) in the vector. //! - //! <b>Throws</b>: If allocator_type's default constructor or allocation + //! <b>Throws</b>: If allocator_type's allocation //! throws or T's constructor taking a dereferenced InIt throws. //! //! <b>Complexity</b>: Linear to the range [first, last). template <class InIt> vector(InIt first, InIt last) : m_holder() - { this->insert(this->cend(), first, last); } + { this->assign(first, last); } //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a //! and inserts a copy of the range [first, last) in the vector. //! - //! <b>Throws</b>: If allocator_type's default constructor or allocation + //! <b>Throws</b>: If allocator_type's allocation //! throws or T's constructor taking a dereferenced InIt throws. //! //! <b>Complexity</b>: Linear to the range [first, last). template <class InIt> vector(InIt first, InIt last, const allocator_type& a) : m_holder(a) - { this->insert(this->cend(), first, last); } + { this->assign(first, last); } //! <b>Effects</b>: Copy constructs a vector. //! //! <b>Postcondition</b>: x == *this. //! - //! <b>Throws</b>: If allocator_type's default constructor or allocation + //! <b>Throws</b>: If allocator_type's allocation //! throws or T's copy constructor throws. //! //! <b>Complexity</b>: Linear to the elements x contains. @@ -728,30 +884,28 @@ class vector , x.size(), container_detail::to_raw_pointer(this->m_holder.start())); } -#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + //! <b>Effects</b>: Move constructor. Moves x's resources to *this. + //! + //! <b>Throws</b>: Nothing + //! + //! <b>Complexity</b>: Constant. + vector(BOOST_RV_REF(vector) x) BOOST_NOEXCEPT_OR_NOTHROW + : m_holder(boost::move(x.m_holder)) + { BOOST_STATIC_ASSERT((!allocator_traits_type::is_partially_propagable::value)); } + + #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a //! and inserts a copy of the range [il.begin(), il.last()) in the vector //! - //! <b>Throws</b>: If allocator_type's default constructor - //! throws or T's constructor taking a dereferenced initializer_list iterator throws. + //! <b>Throws</b>: If T's constructor taking a dereferenced initializer_list iterator throws. //! //! <b>Complexity</b>: Linear to the range [il.begin(), il.end()). vector(std::initializer_list<value_type> il, const allocator_type& a = allocator_type()) : m_holder(a) { - insert(cend(), il.begin(), il.end()); + this->assign(il.begin(), il.end()); } -#endif - - - //! <b>Effects</b>: Move constructor. Moves x's resources to *this. - //! - //! <b>Throws</b>: Nothing - //! - //! <b>Complexity</b>: Constant. - vector(BOOST_RV_REF(vector) x) BOOST_CONTAINER_NOEXCEPT - : m_holder(boost::move(x.m_holder)) - {} + #endif #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) @@ -799,17 +953,18 @@ class vector //! //! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise. vector(BOOST_RV_REF(vector) x, const allocator_type &a) - : m_holder(container_detail::uninitialized_size, a, x.size()) + : m_holder( container_detail::uninitialized_size, a + , is_propagable_from(x.get_stored_allocator(), x.m_holder.start(), a, true) ? 0 : x.size() + ) { - #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS - this->num_alloc += x.size() != 0; - #endif - if(x.m_holder.alloc() == a){ - this->m_holder.move_from_empty(x.m_holder); + if(is_propagable_from(x.get_stored_allocator(), x.m_holder.start(), a, true)){ + this->m_holder.steal_resources(x.m_holder); } else{ const size_type n = x.size(); - this->m_holder.first_allocation_same_allocator_type(n); + #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS + this->num_alloc += n != 0; + #endif ::boost::container::uninitialized_move_alloc_n_source ( this->m_holder.alloc(), container_detail::to_raw_pointer(x.m_holder.start()) , n, container_detail::to_raw_pointer(this->m_holder.start())); @@ -822,7 +977,7 @@ class vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Linear to the number of elements. - ~vector() BOOST_CONTAINER_NOEXCEPT + ~vector() BOOST_NOEXCEPT_OR_NOTHROW { boost::container::destroy_alloc_n (this->get_stored_allocator(), container_detail::to_raw_pointer(this->m_holder.start()), this->m_holder.m_size); @@ -845,16 +1000,16 @@ class vector return *this; } -#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) //! <b>Effects</b>: Make *this container contains elements from il. //! //! <b>Complexity</b>: Linear to the range [il.begin(), il.end()). vector& operator=(std::initializer_list<value_type> il) { - assign(il.begin(), il.end()); + this->assign(il.begin(), il.end()); return *this; } -#endif + #endif //! <b>Effects</b>: Move assignment. All x's values are transferred to *this. //! @@ -868,7 +1023,8 @@ class vector //! propagate_on_container_move_assignment is true or //! this->get>allocator() == x.get_allocator(). Linear otherwise. vector& operator=(BOOST_RV_REF(vector) x) - BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value) + BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value + || allocator_traits_type::is_always_equal::value) { this->priv_move_assign(boost::move(x)); return *this; @@ -928,10 +1084,10 @@ class vector //! <b>Complexity</b>: Linear to n. template <class InIt> void assign(InIt first, InIt last - BOOST_CONTAINER_DOCIGN(BOOST_CONTAINER_I typename container_detail::enable_if_c - < !container_detail::is_convertible<InIt BOOST_CONTAINER_I size_type>::value && + BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename container_detail::enable_if_c + < !container_detail::is_convertible<InIt BOOST_MOVE_I size_type>::value && ( container_detail::is_input_iterator<InIt>::value || - container_detail::is_same<alloc_version BOOST_CONTAINER_I allocator_v0>::value ) + container_detail::is_same<alloc_version BOOST_MOVE_I version_0>::value ) >::type * = 0) ) { //Overwrite all elements we can from [first, last) @@ -943,7 +1099,7 @@ class vector if (first == last){ //There are no more elements in the sequence, erase remaining - T* const end_pos = container_detail::to_raw_pointer(this->m_holder.start()) + this->m_holder.m_size; + T* const end_pos = this->back_raw(); const size_type n = static_cast<size_type>(end_pos - container_detail::iterator_to_raw_pointer(cur)); this->priv_destroy_last_n(n); } @@ -953,7 +1109,7 @@ class vector } } -#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) //! <b>Effects</b>: Assigns the the range [il.begin(), il.end()) to *this. //! //! <b>Throws</b>: If memory allocation throws or @@ -961,9 +1117,9 @@ class vector //! void assign(std::initializer_list<T> il) { - assign(il.begin(), il.end()); + this->assign(il.begin(), il.end()); } -#endif + #endif //! <b>Effects</b>: Assigns the the range [first, last) to *this. //! @@ -973,22 +1129,22 @@ class vector //! <b>Complexity</b>: Linear to n. template <class FwdIt> void assign(FwdIt first, FwdIt last - BOOST_CONTAINER_DOCIGN(BOOST_CONTAINER_I typename container_detail::enable_if_c - < !container_detail::is_convertible<FwdIt BOOST_CONTAINER_I size_type>::value && + BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename container_detail::enable_if_c + < !container_detail::is_convertible<FwdIt BOOST_MOVE_I size_type>::value && ( !container_detail::is_input_iterator<FwdIt>::value && - !container_detail::is_same<alloc_version BOOST_CONTAINER_I allocator_v0>::value ) + !container_detail::is_same<alloc_version BOOST_MOVE_I version_0>::value ) >::type * = 0) ) { //For Fwd iterators the standard only requires EmplaceConstructible and assignable from *first //so we can't do any backwards allocation - const size_type input_sz = static_cast<size_type>(std::distance(first, last)); + const size_type input_sz = static_cast<size_type>(boost::container::iterator_distance(first, last)); const size_type old_capacity = this->capacity(); if(input_sz > old_capacity){ //If input range is too big, we need to reallocate size_type real_cap = 0; - std::pair<pointer, bool> ret = - this->m_holder.allocation_command(allocate_new|expand_fwd, input_sz, input_sz, real_cap, this->m_holder.start()); - if(!ret.second){ //New allocation, just emplace new values + pointer reuse(this->m_holder.start()); + pointer const ret(this->m_holder.allocation_command(allocate_new|expand_fwd, input_sz, real_cap = input_sz, reuse)); + if(!reuse){ //New allocation, just emplace new values #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS ++this->num_alloc; #endif @@ -997,7 +1153,7 @@ class vector this->priv_destroy_all(); this->m_holder.alloc().deallocate(old_p, old_capacity); } - this->m_holder.start(ret.first); + this->m_holder.start(ret); this->m_holder.capacity(real_cap); this->m_holder.m_size = 0; this->priv_uninitialized_construct_at_end(first, last); @@ -1042,7 +1198,7 @@ class vector //! <b>Throws</b>: If allocator's copy constructor throws. //! //! <b>Complexity</b>: Constant. - allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT + allocator_type get_allocator() const BOOST_NOEXCEPT_OR_NOTHROW { return this->m_holder.alloc(); } //! <b>Effects</b>: Returns a reference to the internal allocator. @@ -1052,7 +1208,7 @@ class vector //! <b>Complexity</b>: Constant. //! //! <b>Note</b>: Non-standard extension. - stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT + stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW { return this->m_holder.alloc(); } //! <b>Effects</b>: Returns a reference to the internal allocator. @@ -1062,7 +1218,7 @@ class vector //! <b>Complexity</b>: Constant. //! //! <b>Note</b>: Non-standard extension. - const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT + const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW { return this->m_holder.alloc(); } ////////////////////////////////////////////// @@ -1076,7 +1232,7 @@ class vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - iterator begin() BOOST_CONTAINER_NOEXCEPT + iterator begin() BOOST_NOEXCEPT_OR_NOTHROW { return iterator(this->m_holder.start()); } //! <b>Effects</b>: Returns a const_iterator to the first element contained in the vector. @@ -1084,7 +1240,7 @@ class vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator begin() const BOOST_CONTAINER_NOEXCEPT + const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW { return const_iterator(this->m_holder.start()); } //! <b>Effects</b>: Returns an iterator to the end of the vector. @@ -1092,7 +1248,7 @@ class vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - iterator end() BOOST_CONTAINER_NOEXCEPT + iterator end() BOOST_NOEXCEPT_OR_NOTHROW { return iterator(this->m_holder.start() + this->m_holder.m_size); } //! <b>Effects</b>: Returns a const_iterator to the end of the vector. @@ -1100,7 +1256,7 @@ class vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator end() const BOOST_CONTAINER_NOEXCEPT + const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW { return this->cend(); } //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning @@ -1109,7 +1265,7 @@ class vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT + reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW { return reverse_iterator(this->end()); } //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning @@ -1118,7 +1274,7 @@ class vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT + const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW { return this->crbegin(); } //! <b>Effects</b>: Returns a reverse_iterator pointing to the end @@ -1127,7 +1283,7 @@ class vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT + reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW { return reverse_iterator(this->begin()); } //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end @@ -1136,7 +1292,7 @@ class vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT + const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW { return this->crend(); } //! <b>Effects</b>: Returns a const_iterator to the first element contained in the vector. @@ -1144,7 +1300,7 @@ class vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT + const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW { return const_iterator(this->m_holder.start()); } //! <b>Effects</b>: Returns a const_iterator to the end of the vector. @@ -1152,7 +1308,7 @@ class vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_iterator cend() const BOOST_CONTAINER_NOEXCEPT + const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW { return const_iterator(this->m_holder.start() + this->m_holder.m_size); } //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning @@ -1161,7 +1317,7 @@ class vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT + const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW { return const_reverse_iterator(this->end());} //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end @@ -1170,7 +1326,7 @@ class vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT + const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW { return const_reverse_iterator(this->begin()); } ////////////////////////////////////////////// @@ -1184,7 +1340,7 @@ class vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - bool empty() const BOOST_CONTAINER_NOEXCEPT + bool empty() const BOOST_NOEXCEPT_OR_NOTHROW { return !this->m_holder.m_size; } //! <b>Effects</b>: Returns the number of the elements contained in the vector. @@ -1192,7 +1348,7 @@ class vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - size_type size() const BOOST_CONTAINER_NOEXCEPT + size_type size() const BOOST_NOEXCEPT_OR_NOTHROW { return this->m_holder.m_size; } //! <b>Effects</b>: Returns the largest possible size of the vector. @@ -1200,7 +1356,7 @@ class vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - size_type max_size() const BOOST_CONTAINER_NOEXCEPT + size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW { return allocator_traits_type::max_size(this->m_holder.alloc()); } //! <b>Effects</b>: Inserts or erases elements at the end such that @@ -1238,7 +1394,7 @@ class vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - size_type capacity() const BOOST_CONTAINER_NOEXCEPT + size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW { return this->m_holder.capacity(); } //! <b>Effects</b>: If n is less than or equal to capacity(), this call has no @@ -1250,7 +1406,7 @@ class vector void reserve(size_type new_cap) { if (this->capacity() < new_cap){ - this->priv_reserve(new_cap, alloc_version()); + this->priv_reserve_no_capacity(new_cap, alloc_version()); } } @@ -1277,7 +1433,7 @@ class vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - reference front() BOOST_CONTAINER_NOEXCEPT + reference front() BOOST_NOEXCEPT_OR_NOTHROW { return *this->m_holder.start(); } //! <b>Requires</b>: !empty() @@ -1288,7 +1444,7 @@ class vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reference front() const BOOST_CONTAINER_NOEXCEPT + const_reference front() const BOOST_NOEXCEPT_OR_NOTHROW { return *this->m_holder.start(); } //! <b>Requires</b>: !empty() @@ -1299,8 +1455,11 @@ class vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - reference back() BOOST_CONTAINER_NOEXCEPT - { return this->m_holder.start()[this->m_holder.m_size - 1]; } + reference back() BOOST_NOEXCEPT_OR_NOTHROW + { + BOOST_ASSERT(this->m_holder.m_size > 0); + return this->m_holder.start()[this->m_holder.m_size - 1]; + } //! <b>Requires</b>: !empty() //! @@ -1310,8 +1469,11 @@ class vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reference back() const BOOST_CONTAINER_NOEXCEPT - { return this->m_holder.start()[this->m_holder.m_size - 1]; } + const_reference back() const BOOST_NOEXCEPT_OR_NOTHROW + { + BOOST_ASSERT(this->m_holder.m_size > 0); + return this->m_holder.start()[this->m_holder.m_size - 1]; + } //! <b>Requires</b>: size() > n. //! @@ -1321,8 +1483,11 @@ class vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - reference operator[](size_type n) BOOST_CONTAINER_NOEXCEPT - { return this->m_holder.start()[n]; } + reference operator[](size_type n) BOOST_NOEXCEPT_OR_NOTHROW + { + BOOST_ASSERT(this->m_holder.m_size > n); + return this->m_holder.start()[n]; + } //! <b>Requires</b>: size() > n. //! @@ -1332,8 +1497,71 @@ class vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const_reference operator[](size_type n) const BOOST_CONTAINER_NOEXCEPT - { return this->m_holder.start()[n]; } + const_reference operator[](size_type n) const BOOST_NOEXCEPT_OR_NOTHROW + { + return this->m_holder.start()[n]; + } + + //! <b>Requires</b>: size() >= n. + //! + //! <b>Effects</b>: Returns an iterator to the nth element + //! from the beginning of the container. Returns end() + //! if n == size(). + //! + //! <b>Throws</b>: Nothing. + //! + //! <b>Complexity</b>: Constant. + //! + //! <b>Note</b>: Non-standard extension + iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW + { + BOOST_ASSERT(this->m_holder.m_size >= n); + return iterator(this->m_holder.start()+n); + } + + //! <b>Requires</b>: size() >= n. + //! + //! <b>Effects</b>: Returns a const_iterator to the nth element + //! from the beginning of the container. Returns end() + //! if n == size(). + //! + //! <b>Throws</b>: Nothing. + //! + //! <b>Complexity</b>: Constant. + //! + //! <b>Note</b>: Non-standard extension + const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW + { + BOOST_ASSERT(this->m_holder.m_size >= n); + return const_iterator(this->m_holder.start()+n); + } + + //! <b>Requires</b>: size() >= n. + //! + //! <b>Effects</b>: Returns an iterator to the nth element + //! from the beginning of the container. Returns end() + //! if n == size(). + //! + //! <b>Throws</b>: Nothing. + //! + //! <b>Complexity</b>: Constant. + //! + //! <b>Note</b>: Non-standard extension + size_type index_of(iterator p) BOOST_NOEXCEPT_OR_NOTHROW + { return this->priv_index_of(vector_iterator_get_ptr(p)); } + + //! <b>Requires</b>: begin() <= p <= end(). + //! + //! <b>Effects</b>: Returns the index of the element pointed by p + //! and size() if p == end(). + //! + //! <b>Throws</b>: Nothing. + //! + //! <b>Complexity</b>: Constant. + //! + //! <b>Note</b>: Non-standard extension + size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW + { return this->priv_index_of(vector_iterator_get_ptr(p)); } //! <b>Requires</b>: size() > n. //! @@ -1363,22 +1591,22 @@ class vector // ////////////////////////////////////////////// - //! <b>Returns</b>: Allocator pointer such that [data(),data() + size()) is a valid range. + //! <b>Returns</b>: A pointer such that [data(),data() + size()) is a valid range. //! For a non-empty vector, data() == &front(). //! //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - T* data() BOOST_CONTAINER_NOEXCEPT + T* data() BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::to_raw_pointer(this->m_holder.start()); } - //! <b>Returns</b>: Allocator pointer such that [data(),data() + size()) is a valid range. + //! <b>Returns</b>: A pointer such that [data(),data() + size()) is a valid range. //! For a non-empty vector, data() == &front(). //! //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - const T * data() const BOOST_CONTAINER_NOEXCEPT + const T * data() const BOOST_NOEXCEPT_OR_NOTHROW { return container_detail::to_raw_pointer(this->m_holder.start()); } ////////////////////////////////////////////// @@ -1387,7 +1615,7 @@ class vector // ////////////////////////////////////////////// - #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) + #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) //! <b>Effects</b>: Inserts an object of type T constructed with //! std::forward<Args>(args)... in the end of the vector. //! @@ -1396,19 +1624,38 @@ class vector //! //! <b>Complexity</b>: Amortized constant time. template<class ...Args> - void emplace_back(Args &&...args) + void emplace_back(BOOST_FWD_REF(Args)...args) { - if (BOOST_LIKELY(this->m_holder.m_size < this->m_holder.capacity())){ - T* const back_pos = container_detail::to_raw_pointer(this->m_holder.start()) + this->m_holder.m_size; + if (BOOST_LIKELY(this->room_enough())){ //There is more memory, just construct a new object at the end - allocator_traits_type::construct(this->m_holder.alloc(), back_pos, ::boost::forward<Args>(args)...); + allocator_traits_type::construct(this->m_holder.alloc(), this->back_raw(), ::boost::forward<Args>(args)...); ++this->m_holder.m_size; } else{ typedef container_detail::insert_emplace_proxy<Allocator, T*, Args...> type; this->priv_forward_range_insert_no_capacity - (vector_iterator_get_ptr(this->cend()), 1, type(::boost::forward<Args>(args)...), alloc_version()); + (this->back_ptr(), 1, type(::boost::forward<Args>(args)...), alloc_version()); + } + } + + //! <b>Effects</b>: Inserts an object of type T constructed with + //! std::forward<Args>(args)... in the end of the vector. + //! + //! <b>Throws</b>: If the in-place constructor throws. + //! + //! <b>Complexity</b>: Constant time. + //! + //! <b>Note</b>: Non-standard extension. + template<class ...Args> + bool stable_emplace_back(BOOST_FWD_REF(Args)...args) + { + const bool is_room_enough = this->room_enough() || (alloc_version::value == 2 && this->m_holder.try_expand_fwd(1u)); + if (BOOST_LIKELY(is_room_enough)){ + //There is more memory, just construct a new object at the end + allocator_traits_type::construct(this->m_holder.alloc(), this->back_raw(), ::boost::forward<Args>(args)...); + ++this->m_holder.m_size; } + return is_room_enough; } //! <b>Requires</b>: position must be a valid iterator of *this. @@ -1422,51 +1669,55 @@ class vector //! <b>Complexity</b>: If position is end(), amortized constant time //! Linear time otherwise. template<class ...Args> - iterator emplace(const_iterator position, Args && ...args) + iterator emplace(const_iterator position, BOOST_FWD_REF(Args) ...args) { //Just call more general insert(pos, size, value) and return iterator typedef container_detail::insert_emplace_proxy<Allocator, T*, Args...> type; return this->priv_forward_range_insert( vector_iterator_get_ptr(position), 1 - , type(::boost::forward<Args>(args)...), alloc_version()); - } - - #else + , type(::boost::forward<Args>(args)...)); + } + + #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + + #define BOOST_CONTAINER_VECTOR_EMPLACE_CODE(N) \ + BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ + void emplace_back(BOOST_MOVE_UREF##N)\ + {\ + if (BOOST_LIKELY(this->room_enough())){\ + allocator_traits_type::construct (this->m_holder.alloc()\ + , this->back_raw() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\ + ++this->m_holder.m_size;\ + }\ + else{\ + typedef container_detail::insert_emplace_proxy_arg##N<Allocator, T* BOOST_MOVE_I##N BOOST_MOVE_TARG##N> type;\ + this->priv_forward_range_insert_no_capacity\ + ( this->back_ptr(), 1, type(BOOST_MOVE_FWD##N), alloc_version());\ + }\ + }\ + \ + BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ + bool stable_emplace_back(BOOST_MOVE_UREF##N)\ + {\ + const bool is_room_enough = this->room_enough() || (alloc_version::value == 2 && this->m_holder.try_expand_fwd(1u));\ + if (BOOST_LIKELY(is_room_enough)){\ + allocator_traits_type::construct (this->m_holder.alloc()\ + , this->back_raw() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\ + ++this->m_holder.m_size;\ + }\ + return is_room_enough;\ + }\ + \ + BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ + iterator emplace(const_iterator pos BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ + {\ + typedef container_detail::insert_emplace_proxy_arg##N<Allocator, T* BOOST_MOVE_I##N BOOST_MOVE_TARG##N> type;\ + return this->priv_forward_range_insert(vector_iterator_get_ptr(pos), 1, type(BOOST_MOVE_FWD##N));\ + }\ + // + BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_VECTOR_EMPLACE_CODE) + #undef BOOST_CONTAINER_VECTOR_EMPLACE_CODE - #define BOOST_PP_LOCAL_MACRO(n) \ - BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ - void emplace_back(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ - { \ - T* const back_pos = container_detail::to_raw_pointer \ - (this->m_holder.start()) + this->m_holder.m_size; \ - if (BOOST_LIKELY(this->m_holder.m_size < this->m_holder.capacity())){ \ - allocator_traits_type::construct (this->m_holder.alloc() \ - , back_pos BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \ - ++this->m_holder.m_size; \ - } \ - else{ \ - typedef container_detail::BOOST_PP_CAT(insert_emplace_proxy_arg, n) \ - <Allocator, T* BOOST_PP_ENUM_TRAILING_PARAMS(n, P)> type; \ - this->priv_forward_range_insert_no_capacity \ - ( vector_iterator_get_ptr(this->cend()), 1 \ - , type(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)), alloc_version()); \ - } \ - } \ - \ - BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ - iterator emplace(const_iterator pos \ - BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ - { \ - typedef container_detail::BOOST_PP_CAT(insert_emplace_proxy_arg, n) \ - <Allocator, T* BOOST_PP_ENUM_TRAILING_PARAMS(n, P)> type; \ - return this->priv_forward_range_insert \ - ( container_detail::to_raw_pointer(vector_iterator_get_ptr(pos)), 1 \ - , type(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)), alloc_version()); \ - } \ - //! - #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) - #include BOOST_PP_LOCAL_ITERATE() - - #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING + #endif #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) //! <b>Effects</b>: Inserts a copy of x at the end of the vector. @@ -1525,7 +1776,7 @@ class vector iterator insert(const_iterator p, size_type n, const T& x) { container_detail::insert_n_copies_proxy<Allocator, T*> proxy(x); - return this->priv_forward_range_insert(vector_iterator_get_ptr(p), n, proxy, alloc_version()); + return this->priv_forward_range_insert(vector_iterator_get_ptr(p), n, proxy); } //! <b>Requires</b>: p must be a valid iterator of *this. @@ -1537,11 +1788,11 @@ class vector //! <b>Throws</b>: If memory allocation throws, T's constructor from a //! dereferenced InpIt throws or T's copy/move constructor/assignment throws. //! - //! <b>Complexity</b>: Linear to std::distance [first, last). + //! <b>Complexity</b>: Linear to boost::container::iterator_distance [first, last). template <class InIt> iterator insert(const_iterator pos, InIt first, InIt last - BOOST_CONTAINER_DOCIGN(BOOST_CONTAINER_I typename container_detail::enable_if_c - < !container_detail::is_convertible<InIt BOOST_CONTAINER_I size_type>::value + BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename container_detail::enable_if_c + < !container_detail::is_convertible<InIt BOOST_MOVE_I size_type>::value && container_detail::is_input_iterator<InIt>::value >::type * = 0) ) @@ -1565,12 +1816,12 @@ class vector ) { container_detail::insert_range_proxy<Allocator, FwdIt, T*> proxy(first); - return this->priv_forward_range_insert(vector_iterator_get_ptr(pos), std::distance(first, last), proxy, alloc_version()); + return this->priv_forward_range_insert(vector_iterator_get_ptr(pos), boost::container::iterator_distance(first, last), proxy); } #endif //! <b>Requires</b>: p must be a valid iterator of *this. num, must - //! be equal to std::distance(first, last) + //! be equal to boost::container::iterator_distance(first, last) //! //! <b>Effects</b>: Insert a copy of the [first, last) range before pos. //! @@ -1579,9 +1830,9 @@ class vector //! <b>Throws</b>: If memory allocation throws, T's constructor from a //! dereferenced InpIt throws or T's copy/move constructor/assignment throws. //! - //! <b>Complexity</b>: Linear to std::distance [first, last). + //! <b>Complexity</b>: Linear to boost::container::iterator_distance [first, last). //! - //! <b>Note</b>: This function avoids a linear operation to calculate std::distance[first, last) + //! <b>Note</b>: This function avoids a linear operation to calculate boost::container::iterator_distance[first, last) //! for forward and bidirectional iterators, and a one by one insertion for input iterators. This is a //! a non-standard extension. #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) @@ -1589,14 +1840,14 @@ class vector iterator insert(const_iterator pos, size_type num, InIt first, InIt last) { BOOST_ASSERT(container_detail::is_input_iterator<InIt>::value || - num == static_cast<size_type>(std::distance(first, last))); + num == static_cast<size_type>(boost::container::iterator_distance(first, last))); (void)last; container_detail::insert_range_proxy<Allocator, InIt, T*> proxy(first); - return this->priv_forward_range_insert(vector_iterator_get_ptr(pos), num, proxy, alloc_version()); + return this->priv_forward_range_insert(vector_iterator_get_ptr(pos), num, proxy); } #endif -#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) //! <b>Requires</b>: position must be a valid iterator of *this. //! //! <b>Effects</b>: Insert a copy of the [il.begin(), il.end()) range before position. @@ -1606,16 +1857,16 @@ class vector //! <b>Complexity</b>: Linear to the range [il.begin(), il.end()). iterator insert(const_iterator position, std::initializer_list<value_type> il) { - return insert(position, il.begin(), il.end()); + return this->insert(position, il.begin(), il.end()); } -#endif + #endif //! <b>Effects</b>: Removes the last element from the vector. //! //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant time. - void pop_back() BOOST_CONTAINER_NOEXCEPT + void pop_back() BOOST_NOEXCEPT_OR_NOTHROW { //Destroy last element this->priv_destroy_last(); @@ -1632,7 +1883,7 @@ class vector const pointer p = vector_iterator_get_ptr(position); T *const pos_ptr = container_detail::to_raw_pointer(p); T *const beg_ptr = container_detail::to_raw_pointer(this->m_holder.start()); - T *const new_end_ptr = ::boost::move(pos_ptr + 1, beg_ptr + this->m_holder.m_size, pos_ptr); + 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 this->priv_destroy_last(pos_ptr == new_end_ptr); return iterator(p); @@ -1647,10 +1898,10 @@ class vector iterator erase(const_iterator first, const_iterator last) { if (first != last){ - T* const old_end_ptr = container_detail::to_raw_pointer(this->m_holder.start()) + this->m_holder.m_size; + T* const old_end_ptr = this->back_raw(); 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::move(last_ptr, old_end_ptr, first_ptr)); + 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)); this->priv_destroy_last_n(old_end_ptr - ptr, last_ptr == old_end_ptr); } return iterator(vector_iterator_get_ptr(first)); @@ -1661,13 +1912,12 @@ class vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - void swap(vector& x) BOOST_CONTAINER_NOEXCEPT_IF((!container_detail::is_version<Allocator, 0>::value)) + void swap(vector& x) + BOOST_NOEXCEPT_IF( ((allocator_traits_type::propagate_on_container_swap::value + || allocator_traits_type::is_always_equal::value) && + !container_detail::is_version<Allocator, 0>::value)) { - //Just swap internals in case of !allocator_v0. Otherwise, deep swap - this->m_holder.swap(x.m_holder); - //And now the allocator - container_detail::bool_<allocator_traits_type::propagate_on_container_swap::value> flag; - container_detail::swap_alloc(this->m_holder.alloc(), x.m_holder.alloc(), flag); + this->priv_swap(x, container_detail::bool_<container_detail::is_version<Allocator, 0>::value>()); } #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED @@ -1685,7 +1935,7 @@ class vector < container_detail::is_version<OtherAllocator, 0>::value && !container_detail::is_same<OtherAllocator, allocator_type>::value >::type * = 0 ) - { this->m_holder.swap(x.m_holder); } + { this->m_holder.deep_swap(x.m_holder); } #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED @@ -1694,28 +1944,14 @@ class vector //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Linear to the number of elements in the container. - void clear() BOOST_CONTAINER_NOEXCEPT + void clear() BOOST_NOEXCEPT_OR_NOTHROW { this->priv_destroy_all(); } //! <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 vector& x, const vector& y) - { - if(x.size() != y.size()){ - return false; - } - else{ - const_iterator first1(x.cbegin()), first2(y.cbegin()); - const const_iterator last1(x.cend()); - for (; first1 != last1; ++first1, ++first2) { - if (!(*first1 != *first2)) { - return false; - } - } - return true; - } - } + { 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 //! @@ -1773,24 +2009,8 @@ class vector //! <b>Note</b>: Non-standard extension. bool stable_reserve(size_type new_cap) { - const bool room_enough = this->capacity() < new_cap; - if(!room_enough && alloc_version::value < 2){ - return false; - } - else{ - //There is not enough memory, try to expand the old one - size_type real_cap = 0; - std::pair<pointer, bool> ret = this->m_holder.allocation_command - (expand_fwd, new_cap, new_cap, real_cap, this->m_holder.start()); - //Check for forward expansion - if(ret.second){ - #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS - ++this->num_expand_fwd; - #endif - this->m_holder.capacity(real_cap); - } - return ret.second; - } + const size_type cp = this->capacity(); + return cp >= new_cap || (alloc_version::value == 2 && this->m_holder.try_expand_fwd(new_cap - cp)); } //Absolutely experimental. This function might change, disappear or simply crash! @@ -1856,50 +2076,23 @@ class vector } } - #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) - //! <b>Effects</b>: Inserts an object of type T constructed with - //! std::forward<Args>(args)... in the end of the vector. - //! - //! <b>Throws</b>: If memory allocation throws or the in-place constructor throws or - //! T's copy/move constructor throws. - //! - //! <b>Complexity</b>: Amortized constant time. - template<class ...Args> - bool stable_emplace_back(Args &&...args) - { - const bool room_enough = this->m_holder.m_size < this->m_holder.capacity(); - if (BOOST_LIKELY(room_enough)){ - T* const back_pos = container_detail::to_raw_pointer(this->m_holder.start()) + this->m_holder.m_size; - //There is more memory, just construct a new object at the end - allocator_traits_type::construct(this->m_holder.alloc(), back_pos, ::boost::forward<Args>(args)...); - ++this->m_holder.m_size; - } - return room_enough; - } + private: - #else + bool room_enough() const + { return this->m_holder.m_size < this->m_holder.capacity(); } - #define BOOST_PP_LOCAL_MACRO(n) \ - BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ - bool stable_emplace_back(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ - { \ - const bool room_enough = this->m_holder.m_size < this->m_holder.capacity(); \ - if (BOOST_LIKELY(room_enough)){ \ - T* const back_pos = container_detail::to_raw_pointer \ - (this->m_holder.start()) + this->m_holder.m_size; \ - allocator_traits_type::construct (this->m_holder.alloc() \ - , back_pos BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \ - ++this->m_holder.m_size; \ - } \ - return room_enough; \ - } \ - //! - #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) - #include BOOST_PP_LOCAL_ITERATE() - - #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING + pointer back_ptr() const + { return this->m_holder.start() + this->m_holder.m_size; } - private: + T* back_raw() const + { return container_detail::to_raw_pointer(this->m_holder.start()) + this->m_holder.m_size; } + + size_type priv_index_of(pointer p) const + { + BOOST_ASSERT(this->m_holder.start() <= p); + BOOST_ASSERT(p <= (this->m_holder.start()+this->size())); + return static_cast<size_type>(p - this->m_holder.start()); + } template<class OtherAllocator> void priv_move_assign(BOOST_RV_REF_BEG vector<T, OtherAllocator> BOOST_RV_REF_END x @@ -1928,25 +2121,32 @@ class vector BOOST_ASSERT(this != &x); allocator_type &this_alloc = this->m_holder.alloc(); allocator_type &x_alloc = x.m_holder.alloc(); - const bool propagate_alloc = allocator_traits_type:: - propagate_on_container_move_assignment::value; - container_detail::bool_<propagate_alloc> flag; - const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal; + const bool propagate_alloc = allocator_traits_type::propagate_on_container_move_assignment::value; + + const bool is_propagable_from_x = is_propagable_from(x_alloc, x.m_holder.start(), this_alloc, propagate_alloc); + const bool is_propagable_from_t = is_propagable_from(this_alloc, m_holder.start(), x_alloc, propagate_alloc); + const bool are_both_propagable = is_propagable_from_x && is_propagable_from_t; + //Resources can be transferred if both allocators are //going to be equal after this function (either propagated or already equal) - if(propagate_alloc || allocators_equal){ + if(are_both_propagable){ //Destroy objects but retain memory in case x reuses it in the future this->clear(); - //Move allocator if needed - container_detail::move_alloc(this_alloc, x_alloc, flag); - //Nothrow swap - this->m_holder.swap(x.m_holder); + this->m_holder.swap_resources(x.m_holder); + } + else if(is_propagable_from_x){ + this->clear(); + this->m_holder.alloc().deallocate(this->m_holder.m_start, this->m_holder.m_capacity); + this->m_holder.steal_resources(x.m_holder); } //Else do a one by one move else{ - this->assign( boost::make_move_iterator(x.begin()) - , boost::make_move_iterator(x.end())); + 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() )) + ); } + //Move allocator if needed + container_detail::move_alloc(this_alloc, x_alloc, container_detail::bool_<propagate_alloc>()); } template<class OtherAllocator> @@ -1985,7 +2185,40 @@ class vector , container_detail::to_raw_pointer(x.m_holder.start() + x.m_holder.m_size)); } - void priv_reserve(size_type, allocator_v0) + template<class Vector> //Template it to avoid it in explicit instantiations + void priv_swap(Vector &x, container_detail::true_type) //version_0 + { this->m_holder.deep_swap(x.m_holder); } + + template<class Vector> //Template it to avoid it in explicit instantiations + void priv_swap(Vector &x, container_detail::false_type) //version_N + { + const bool propagate_alloc = allocator_traits_type::propagate_on_container_swap::value; + if(are_swap_propagable( this->get_stored_allocator(), this->m_holder.start() + , x.get_stored_allocator(), this->m_holder.start(), propagate_alloc)){ + //Just swap internals + this->m_holder.swap_resources(x.m_holder); + } + else{ + //Else swap element by element... + bool const t_smaller = this->size() < x.size(); + vector &sml = t_smaller ? *this : x; + vector &big = t_smaller ? x : *this; + + size_type const common_elements = sml.size(); + for(size_type i = 0; i != common_elements; ++i){ + boost::adl_move_swap(sml[i], big[i]); + } + //... 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())) + ); + } + //And now swap the allocator + container_detail::swap_alloc(this->m_holder.alloc(), x.m_holder.alloc(), container_detail::bool_<propagate_alloc>()); + } + + void priv_reserve_no_capacity(size_type, version_0) { throw_bad_alloc(); } container_detail::insert_range_proxy<Allocator, boost::move_iterator<T*>, T*> priv_dummy_empty_proxy() @@ -1994,28 +2227,27 @@ class vector (::boost::make_move_iterator((T *)0)); } - void priv_reserve(size_type new_cap, allocator_v1) + void priv_reserve_no_capacity(size_type new_cap, version_1) { //There is not enough memory, allocate a new buffer - pointer p = this->m_holder.allocate(new_cap); + //Pass the hint so that allocators can take advantage of this. + 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 - , container_detail::to_raw_pointer(this->m_holder.start()) + this->m_holder.m_size - , 0, this->priv_dummy_empty_proxy()); + ( container_detail::to_raw_pointer(p), new_cap, this->back_raw(), 0, this->priv_dummy_empty_proxy()); } - void priv_reserve(size_type new_cap, allocator_v2) + void priv_reserve_no_capacity(size_type new_cap, version_2) { //There is not enough memory, allocate a new //buffer or expand the old one. bool same_buffer_start; size_type real_cap = 0; - std::pair<pointer, bool> ret = this->m_holder.allocation_command - (allocate_new | expand_fwd | expand_bwd, new_cap, new_cap, real_cap, this->m_holder.start()); + pointer reuse = 0; + pointer const ret(this->m_holder.allocation_command(allocate_new | expand_fwd | expand_bwd, new_cap, real_cap = new_cap, reuse)); //Check for forward expansion - same_buffer_start = ret.second && this->m_holder.start() == ret.first; + same_buffer_start = reuse && this->m_holder.start() == ret; if(same_buffer_start){ #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS ++this->num_expand_fwd; @@ -2023,9 +2255,9 @@ 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.first); - T * const ins_pos = container_detail::to_raw_pointer(this->m_holder.start()) + this->m_holder.m_size; - if(ret.second){ //Backwards (and possibly forward) expansion + T * const new_mem = container_detail::to_raw_pointer(ret); + T * const ins_pos = this->back_raw(); + if(reuse){ //Backwards (and possibly forward) expansion #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS ++this->num_expand_bwd; #endif @@ -2042,26 +2274,26 @@ class vector } } - void priv_destroy_last() BOOST_CONTAINER_NOEXCEPT + void priv_destroy_last() BOOST_NOEXCEPT_OR_NOTHROW { if(!value_traits::trivial_dctr){ - value_type* const p = container_detail::to_raw_pointer(this->m_holder.start()) + this->m_holder.m_size - 1; + value_type* const p = this->back_raw() - 1; allocator_traits_type::destroy(this->get_stored_allocator(), p); } --this->m_holder.m_size; } - void priv_destroy_last(const bool moved) BOOST_CONTAINER_NOEXCEPT + void priv_destroy_last(const bool moved) BOOST_NOEXCEPT_OR_NOTHROW { (void)moved; if(!(value_traits::trivial_dctr || (value_traits::trivial_dctr_after_move && moved))){ - value_type* const p = container_detail::to_raw_pointer(this->m_holder.start()) + this->m_holder.m_size - 1; + value_type* const p = this->back_raw() - 1; allocator_traits_type::destroy(this->get_stored_allocator(), p); } --this->m_holder.m_size; } - void priv_destroy_last_n(const size_type n) BOOST_CONTAINER_NOEXCEPT + void priv_destroy_last_n(const size_type n) BOOST_NOEXCEPT_OR_NOTHROW { BOOST_ASSERT(n <= this->m_holder.m_size); if(!value_traits::trivial_dctr){ @@ -2071,7 +2303,7 @@ class vector this->m_holder.m_size -= n; } - void priv_destroy_last_n(const size_type n, const bool moved) BOOST_CONTAINER_NOEXCEPT + void priv_destroy_last_n(const size_type n, const bool moved) BOOST_NOEXCEPT_OR_NOTHROW { BOOST_ASSERT(n <= this->m_holder.m_size); (void)moved; @@ -2085,12 +2317,12 @@ class vector template<class InpIt> void priv_uninitialized_construct_at_end(InpIt first, InpIt last) { - T* const old_end_pos = container_detail::to_raw_pointer(this->m_holder.start()) + this->m_holder.m_size; + T* const old_end_pos = this->back_raw(); T* const new_end_pos = boost::container::uninitialized_copy_alloc(this->m_holder.alloc(), first, last, old_end_pos); this->m_holder.m_size += new_end_pos - old_end_pos; } - void priv_destroy_all() BOOST_CONTAINER_NOEXCEPT + void priv_destroy_all() BOOST_NOEXCEPT_OR_NOTHROW { boost::container::destroy_alloc_n (this->get_stored_allocator(), container_detail::to_raw_pointer(this->m_holder.start()), this->m_holder.m_size); @@ -2101,8 +2333,7 @@ class vector iterator priv_insert(const const_iterator &p, BOOST_FWD_REF(U) x) { return this->priv_forward_range_insert - ( vector_iterator_get_ptr(p), 1, container_detail::get_insert_value_proxy<T*, Allocator> - (::boost::forward<U>(x)), alloc_version()); + ( vector_iterator_get_ptr(p), 1, container_detail::get_insert_value_proxy<T*, Allocator>(::boost::forward<U>(x))); } container_detail::insert_copy_proxy<Allocator, T*> priv_single_insert_proxy(const T &x) @@ -2114,7 +2345,7 @@ class vector template <class U> void priv_push_back(BOOST_FWD_REF(U) u) { - if (BOOST_LIKELY(this->m_holder.m_size < this->m_holder.capacity())){ + if (BOOST_LIKELY(this->room_enough())){ //There is more memory, just construct a new object at the end allocator_traits_type::construct ( this->m_holder.alloc() @@ -2124,7 +2355,7 @@ class vector } else{ this->priv_forward_range_insert_no_capacity - ( vector_iterator_get_ptr(this->cend()), 1 + ( this->back_ptr(), 1 , this->priv_single_insert_proxy(::boost::forward<U>(u)), alloc_version()); } } @@ -2152,10 +2383,10 @@ class vector } } - void priv_shrink_to_fit(allocator_v0) BOOST_CONTAINER_NOEXCEPT + void priv_shrink_to_fit(version_0) BOOST_NOEXCEPT_OR_NOTHROW {} - void priv_shrink_to_fit(allocator_v1) + void priv_shrink_to_fit(version_1) { const size_type cp = this->m_holder.capacity(); if(cp){ @@ -2167,7 +2398,8 @@ class vector } else if(sz < cp){ //Allocate a new buffer. - pointer p = this->m_holder.allocate(sz); + //Pass the hint so that allocators can take advantage of this. + pointer const p = allocator_traits_type::allocate(this->m_holder.alloc(), sz, this->m_holder.m_start); //We will reuse insert code, so create a dummy input iterator #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS @@ -2181,7 +2413,7 @@ class vector } } - void priv_shrink_to_fit(allocator_v2) BOOST_CONTAINER_NOEXCEPT + void priv_shrink_to_fit(version_2) BOOST_NOEXCEPT_OR_NOTHROW { const size_type cp = this->m_holder.capacity(); if(cp){ @@ -2192,10 +2424,10 @@ class vector this->m_holder.m_capacity = 0; } else{ - size_type received_size; + size_type received_size = sz; + pointer reuse(this->m_holder.start()); if(this->m_holder.allocation_command - ( shrink_in_place | nothrow_allocation - , cp, sz, received_size, this->m_holder.start()).first){ + (shrink_in_place | nothrow_allocation, cp, received_size, reuse)){ this->m_holder.capacity(received_size); #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS ++this->num_shrink; @@ -2207,7 +2439,7 @@ class vector template <class InsertionProxy> iterator priv_forward_range_insert_no_capacity - (const pointer &pos, const size_type, const InsertionProxy , allocator_v0) + (const pointer &pos, const size_type, const InsertionProxy , version_0) { throw_bad_alloc(); return iterator(pos); @@ -2215,14 +2447,15 @@ class vector template <class InsertionProxy> iterator priv_forward_range_insert_no_capacity - (const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy, allocator_v1) + (const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy, version_1) { //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); const size_type new_cap = this->m_holder.next_capacity(n); - T * new_buf = container_detail::to_raw_pointer(this->m_holder.alloc().allocate(new_cap)); + //Pass the hint so that allocators can take advantage of this. + T * const new_buf = container_detail::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; #endif @@ -2233,23 +2466,23 @@ class vector template <class InsertionProxy> iterator priv_forward_range_insert_no_capacity - (const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy, allocator_v2) + (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); const size_type n_pos = raw_pos - container_detail::to_raw_pointer(this->m_holder.start()); - size_type real_cap = 0; //There is not enough memory, allocate a new //buffer or expand the old one. - std::pair<pointer, bool> ret = (this->m_holder.allocation_command - (allocate_new | expand_fwd | expand_bwd, - this->m_holder.m_size + n, this->m_holder.next_capacity(n), real_cap, this->m_holder.start())); + size_type real_cap = this->m_holder.next_capacity(n); + pointer reuse(this->m_holder.start()); + pointer const ret (this->m_holder.allocation_command + (allocate_new | expand_fwd | expand_bwd, this->m_holder.m_size + n, real_cap, reuse)); //Buffer reallocated - if(ret.second){ + if(reuse){ //Forward expansion, delay insertion - if(this->m_holder.start() == ret.first){ + if(this->m_holder.start() == ret){ #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS ++this->num_expand_fwd; #endif @@ -2263,8 +2496,7 @@ class vector ++this->num_expand_bwd; #endif this->priv_forward_range_insert_expand_backwards - ( container_detail::to_raw_pointer(ret.first) - , real_cap, raw_pos, n, insert_range_proxy); + (container_detail::to_raw_pointer(ret), real_cap, raw_pos, n, insert_range_proxy); } } //New buffer @@ -2273,8 +2505,7 @@ class vector ++this->num_alloc; #endif this->priv_forward_range_insert_new_allocation - ( container_detail::to_raw_pointer(ret.first) - , real_cap, raw_pos, n, insert_range_proxy); + ( container_detail::to_raw_pointer(ret), real_cap, raw_pos, n, insert_range_proxy); } return iterator(this->m_holder.start() + n_pos); @@ -2282,42 +2513,7 @@ class vector template <class InsertionProxy> iterator priv_forward_range_insert - (const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy, allocator_v0) - { - //Check if we have enough memory or try to expand current memory - const size_type remaining = this->m_holder.capacity() - this->m_holder.m_size; - - if (n > remaining){ - //This will trigger an error - throw_bad_alloc(); - } - const size_type n_pos = pos - this->m_holder.start(); - T *const raw_pos = container_detail::to_raw_pointer(pos); - this->priv_forward_range_insert_expand_forward(raw_pos, n, insert_range_proxy); - return iterator(this->m_holder.start() + n_pos); - } - - template <class InsertionProxy> - iterator priv_forward_range_insert - (const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy, allocator_v1) - { - //Check if we have enough memory or try to expand current memory - const size_type remaining = this->m_holder.capacity() - this->m_holder.m_size; - T *const raw_pos = container_detail::to_raw_pointer(pos); - - if (n <= remaining){ - const size_type n_pos = raw_pos - container_detail::to_raw_pointer(this->m_holder.start()); - this->priv_forward_range_insert_expand_forward(raw_pos, n, insert_range_proxy); - return iterator(this->m_holder.start() + n_pos); - } - else{ - return this->priv_forward_range_insert_no_capacity(pos, n, insert_range_proxy, alloc_version()); - } - } - - template <class InsertionProxy> - iterator priv_forward_range_insert - (const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy, allocator_v2) + (const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy) { BOOST_ASSERT(this->m_holder.capacity() >= this->m_holder.m_size); //Check if we have enough memory or try to expand current memory @@ -2338,7 +2534,7 @@ class vector template <class InsertionProxy> iterator priv_forward_range_insert_at_end - (const size_type n, const InsertionProxy insert_range_proxy, allocator_v0) + (const size_type n, const InsertionProxy insert_range_proxy, version_0) { //Check if we have enough memory or try to expand current memory const size_type remaining = this->m_holder.capacity() - this->m_holder.m_size; @@ -2351,18 +2547,11 @@ class vector return this->end(); } - template <class InsertionProxy> - iterator priv_forward_range_insert_at_end - (const size_type n, const InsertionProxy insert_range_proxy, allocator_v1) - { - return this->priv_forward_range_insert(vector_iterator_get_ptr(this->cend()), n, insert_range_proxy, allocator_v1()); - } - - template <class InsertionProxy> + template <class InsertionProxy, class AllocVersion> iterator priv_forward_range_insert_at_end - (const size_type n, const InsertionProxy insert_range_proxy, allocator_v2) + (const size_type n, const InsertionProxy insert_range_proxy, AllocVersion) { - return this->priv_forward_range_insert(vector_iterator_get_ptr(this->cend()), n, insert_range_proxy, allocator_v2()); + return this->priv_forward_range_insert(this->back_ptr(), n, insert_range_proxy); } //Absolutely experimental. This function might change, disappear or simply crash! @@ -2386,7 +2575,7 @@ class vector while(insertions_left){ if(do_skip){ size_type n = *(--last_skip_it); - std::advance(last_value_it, -difference_type(n)); + boost::container::iterator_advance(last_value_it, -difference_type(n)); } const size_type pos = static_cast<size_type>(*(--last_position_it)); BOOST_ASSERT(pos <= old_size_pos); @@ -2446,7 +2635,7 @@ class vector //| prefix | range | suffix |raw_mem ~ //|____________|_______|__________________|_____________~ // - //New situation in Case Allocator (hole_size == 0): + //New situation in Case A (hole_size == 0): // range is moved through move assignments // // first_pos last_pos limit_pos @@ -2493,7 +2682,7 @@ class vector //Case A: if((last_pos + shift_count) <= limit_pos){ //All move assigned - boost::move_backward(first_ptr, last_ptr, last_ptr + shift_count); + boost::container::move_backward(first_ptr, last_ptr, last_ptr + shift_count); } //Case B: else if((first_pos + shift_count) >= limit_pos){ @@ -2509,7 +2698,7 @@ class vector T* const boundary_ptr = limit_ptr - shift_count; ::boost::container::uninitialized_move_alloc(this->m_holder.alloc(), boundary_ptr, last_ptr, limit_ptr); //The rest is move assigned - boost::move_backward(first_ptr, boundary_ptr, limit_ptr); + boost::container::move_backward(first_ptr, boundary_ptr, limit_ptr); } return hole_size; } @@ -2518,7 +2707,7 @@ class vector template <class InsertionProxy> void priv_forward_range_insert_at_end_expand_forward(const size_type n, InsertionProxy insert_range_proxy) { - T* const old_finish = container_detail::to_raw_pointer(this->m_holder.start()) + this->m_holder.m_size; + T* const old_finish = this->back_raw(); insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), old_finish, n); this->m_holder.m_size += n; } @@ -2529,7 +2718,7 @@ class vector //n can't be 0, because there is nothing to do in that case if(!n) return; //There is enough memory - T* const old_finish = container_detail::to_raw_pointer(this->m_holder.start()) + this->m_holder.m_size; + T* const old_finish = this->back_raw(); const size_type elems_after = old_finish - pos; if (!elems_after){ @@ -2543,7 +2732,7 @@ class vector (this->m_holder.alloc(), old_finish - n, old_finish, old_finish); this->m_holder.m_size += n; //Copy previous to last objects to the initialized end - boost::move_backward(pos, old_finish - n, old_finish); + boost::container::move_backward(pos, old_finish - n, old_finish); //Insert new objects in the pos insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), pos, n); } @@ -2694,7 +2883,7 @@ class vector old_values_destroyer.shrink_forward(new_size-s_before); this->m_holder.m_size = new_size; //Now move remaining last objects in the old buffer begin - ::boost::move(pos + raw_gap, old_finish, old_start); + ::boost::container::move(pos + raw_gap, old_finish, old_start); //Once moved, avoid calling the destructors if trivial after move if(value_traits::trivial_dctr_after_move){ old_values_destroyer.release(); @@ -2778,14 +2967,14 @@ class vector } this->m_holder.m_size = old_size + new_1st_range; //Now copy the second part of old_begin overwriting itself - T *const next = ::boost::move(old_start + s_before, pos, old_start); + T *const next = ::boost::container::move(old_start + s_before, pos, old_start); //Now copy the new_beg elements insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), next, new_1st_range); //If there is no after work and the last old part needs to be moved to front, do it if(!do_after && (n != s_before)){ //Now displace old_end elements - ::boost::move(pos, old_finish, next + new_1st_range); + ::boost::container::move(pos, old_finish, next + new_1st_range); } } else { @@ -2835,7 +3024,7 @@ class vector insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), old_start, rest_new); T* const move_start = old_start + rest_new; //Displace old_end - T* const move_end = ::boost::move(pos, old_finish, move_start); + T* const move_end = ::boost::container::move(pos, old_finish, move_start); //Destroy remaining moved elements from old_end except if they //have trivial destructor after being moved size_type n_destroy = s_before - n; @@ -2887,7 +3076,7 @@ class vector (this->m_holder.alloc(), finish_n, old_finish, old_finish); this->m_holder.m_size += n_after; //Displace the rest of old_end to the new position - boost::move_backward(pos, finish_n, old_finish); + boost::container::move_backward(pos, finish_n, old_finish); //Now overwrite with new_end //The new_end part is [first + (n - n_after), last) insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), pos, n_after); @@ -2947,35 +3136,23 @@ class vector #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED }; -}} +}} //namespace boost::container #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED namespace boost { -/* //!has_trivial_destructor_after_move<> == true_type //!specialization for optimizations template <class T, class Allocator> struct has_trivial_destructor_after_move<boost::container::vector<T, Allocator> > - : public ::boost::has_trivial_destructor_after_move<Allocator> -{}; -*/ -} - -//#define BOOST_CONTAINER_PUT_SWAP_OVERLOAD_IN_NAMESPACE_STD - -#ifdef BOOST_CONTAINER_PUT_SWAP_OVERLOAD_IN_NAMESPACE_STD - -namespace std { - -template <class T, class Allocator> -inline void swap(boost::container::vector<T, Allocator>& x, boost::container::vector<T, Allocator>& y) -{ x.swap(y); } - -} //namespace std { +{ + typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer; + static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value && + ::boost::has_trivial_destructor_after_move<pointer>::value; +}; -#endif +} #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED |