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))) + |