Squashed 'third_party/boostorg/container/' content from commit 1ad6431
Change-Id: I7d095db3455264c03446268e5675b926bebedb0a
git-subtree-dir: third_party/boostorg/container
git-subtree-split: 1ad64316a432a7f021b4956acf88abc6aaa8a77e
diff --git a/include/boost/container/adaptive_pool.hpp b/include/boost/container/adaptive_pool.hpp
new file mode 100644
index 0000000..d1d77bc
--- /dev/null
+++ b/include/boost/container/adaptive_pool.hpp
@@ -0,0 +1,609 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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_ADAPTIVE_POOL_HPP
+#define BOOST_CONTAINER_ADAPTIVE_POOL_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/container_fwd.hpp>
+#include <boost/container/detail/version_type.hpp>
+#include <boost/container/throw_exception.hpp>
+#include <boost/container/detail/adaptive_node_pool.hpp>
+#include <boost/container/detail/multiallocation_chain.hpp>
+#include <boost/container/detail/mpl.hpp>
+#include <boost/container/detail/dlmalloc.hpp>
+#include <boost/container/detail/singleton.hpp>
+#include <boost/container/detail/placement_new.hpp>
+
+#include <boost/assert.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/move/utility_core.hpp>
+#include <cstddef>
+
+
+namespace boost {
+namespace container {
+
+//!An STL node allocator that uses a modified DLMalloc as memory
+//!source.
+//!
+//!This node allocator shares a segregated storage between all instances
+//!of adaptive_pool with equal sizeof(T).
+//!
+//!NodesPerBlock is the number of nodes allocated at once when the allocator
+//!needs runs out of nodes. MaxFreeBlocks is the maximum number of totally free blocks
+//!that the adaptive node pool will hold. The rest of the totally free blocks will be
+//!deallocated to the memory manager.
+//!
+//!OverheadPercent is the (approximated) maximum size overhead (1-20%) of the allocator:
+//!(memory usable for nodes / total memory allocated from the memory allocator)
+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_MOVE_I unsigned Version)
+ >
+class adaptive_pool
+{
+ //!If Version is 1, the allocator is a STL conforming allocator. If Version is 2,
+ //!the allocator offers advanced expand in place and burst allocation capabilities.
+ public:
+ typedef unsigned int allocation_type;
+ typedef adaptive_pool
+ <T, NodesPerBlock, MaxFreeBlocks, OverheadPercent
+ BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I Version)
+ > self_t;
+
+ static const std::size_t nodes_per_block = NodesPerBlock;
+ static const std::size_t max_free_blocks = MaxFreeBlocks;
+ static const std::size_t overhead_percent = OverheadPercent;
+ static const std::size_t real_nodes_per_block = NodesPerBlock;
+
+ BOOST_CONTAINER_DOCIGN(BOOST_STATIC_ASSERT((Version <=2)));
+
+ public:
+ //-------
+ typedef T value_type;
+ typedef T * pointer;
+ typedef const T * const_pointer;
+ typedef typename ::boost::container::
+ dtl::unvoid_ref<T>::type reference;
+ typedef typename ::boost::container::
+ dtl::unvoid_ref<const T>::type const_reference;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+
+ typedef boost::container::dtl::
+ version_type<self_t, Version> version;
+
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ typedef boost::container::dtl::
+ basic_multiallocation_chain<void*> multiallocation_chain_void;
+ typedef boost::container::dtl::
+ transform_multiallocation_chain
+ <multiallocation_chain_void, T> multiallocation_chain;
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ //!Obtains adaptive_pool from
+ //!adaptive_pool
+ template<class T2>
+ struct rebind
+ {
+ typedef adaptive_pool
+ < T2
+ , NodesPerBlock
+ , MaxFreeBlocks
+ , OverheadPercent
+ BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I Version)
+ > other;
+ };
+
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ private:
+ //!Not assignable from related adaptive_pool
+ template<class T2, std::size_t N2, std::size_t F2, std::size_t O2, unsigned Version2>
+ adaptive_pool& operator=
+ (const adaptive_pool<T2, N2, F2, O2, Version2>&);
+
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ public:
+ //!Default constructor
+ adaptive_pool() BOOST_NOEXCEPT_OR_NOTHROW
+ {}
+
+ //!Copy constructor from other adaptive_pool.
+ 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_MOVE_I Version)> &) BOOST_NOEXCEPT_OR_NOTHROW
+ {}
+
+ //!Destructor
+ ~adaptive_pool() BOOST_NOEXCEPT_OR_NOTHROW
+ {}
+
+ //!Returns the number of elements that could be allocated.
+ //!Never throws
+ 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(BOOST_UNLIKELY(count > this->max_size()))
+ boost::container::throw_bad_alloc();
+
+ if(Version == 1 && count == 1){
+ typedef typename dtl::shared_adaptive_node_pool
+ <sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
+ typedef dtl::singleton_default<shared_pool_t> singleton_t;
+ return pointer(static_cast<T*>(singleton_t::instance().allocate_node()));
+ }
+ else{
+ return static_cast<pointer>(dlmalloc_malloc(count*sizeof(T)));
+ }
+ }
+
+ //!Deallocate allocated memory.
+ //!Never throws
+ void deallocate(const pointer &ptr, size_type count) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ (void)count;
+ if(Version == 1 && count == 1){
+ typedef dtl::shared_adaptive_node_pool
+ <sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
+ typedef dtl::singleton_default<shared_pool_t> singleton_t;
+ singleton_t::instance().deallocate_node(ptr);
+ }
+ else{
+ dlmalloc_free(ptr);
+ }
+ }
+
+ pointer allocation_command(allocation_type command,
+ size_type limit_size,
+ size_type &prefer_in_recvd_out_size,
+ pointer &reuse)
+ {
+ 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_NOEXCEPT_OR_NOTHROW
+ { return dlmalloc_size(p); }
+
+ //!Allocates just one object. Memory allocated with this function
+ //!must be deallocated only with deallocate_one().
+ //!Throws bad_alloc if there is no enough memory
+ pointer allocate_one()
+ {
+ typedef dtl::shared_adaptive_node_pool
+ <sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
+ typedef dtl::singleton_default<shared_pool_t> singleton_t;
+ return (pointer)singleton_t::instance().allocate_node();
+ }
+
+ //!Allocates many elements of size == 1.
+ //!Elements must be individually deallocated with deallocate_one()
+ void allocate_individual(std::size_t num_elements, multiallocation_chain &chain)
+ {
+ typedef dtl::shared_adaptive_node_pool
+ <sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
+ typedef dtl::singleton_default<shared_pool_t> singleton_t;
+ singleton_t::instance().allocate_nodes(num_elements, static_cast<typename shared_pool_t::multiallocation_chain&>(chain));
+ //typename shared_pool_t::multiallocation_chain ch;
+ //singleton_t::instance().allocate_nodes(num_elements, ch);
+ //chain.incorporate_after
+ //(chain.before_begin(), (T*)&*ch.begin(), (T*)&*ch.last(), ch.size());
+ }
+
+ //!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_NOEXCEPT_OR_NOTHROW
+ {
+ typedef dtl::shared_adaptive_node_pool
+ <sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
+ typedef dtl::singleton_default<shared_pool_t> singleton_t;
+ singleton_t::instance().deallocate_node(p);
+ }
+
+ void deallocate_individual(multiallocation_chain &chain) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ typedef dtl::shared_adaptive_node_pool
+ <sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
+ typedef dtl::singleton_default<shared_pool_t> singleton_t;
+ //typename shared_pool_t::multiallocation_chain ch(&*chain.begin(), &*chain.last(), chain.size());
+ //singleton_t::instance().deallocate_nodes(ch);
+ singleton_t::instance().deallocate_nodes(chain);
+ }
+
+ //!Allocates many elements of size elem_size.
+ //!Elements must be individually deallocated with deallocate()
+ void allocate_many(size_type elem_size, std::size_t n_elements, multiallocation_chain &chain)
+ {
+ BOOST_STATIC_ASSERT(( Version > 1 ));/*
+ dlmalloc_memchain ch;
+ BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
+ if(BOOST_UNLIKELY(!dlmalloc_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_UNLIKELY(!dlmalloc_multialloc_nodes
+ (n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, reinterpret_cast<dlmalloc_memchain *>(&chain)))){
+ boost::container::throw_bad_alloc();
+ }
+ }
+
+ //!Allocates n_elements elements, each one of size elem_sizes[i]
+ //!Elements must be individually deallocated with deallocate()
+ void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain)
+ {
+ BOOST_STATIC_ASSERT(( Version > 1 ));/*
+ dlmalloc_memchain ch;
+ BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
+ if(BOOST_UNLIKELY(!dlmalloc_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_UNLIKELY(!dlmalloc_multialloc_arrays
+ (n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, reinterpret_cast<dlmalloc_memchain *>(&chain)))){
+ boost::container::throw_bad_alloc();
+ }
+ }
+
+ void deallocate_many(multiallocation_chain &chain) BOOST_NOEXCEPT_OR_NOTHROW
+ {/*
+ dlmalloc_memchain ch;
+ void *beg(&*chain.begin()), *last(&*chain.last());
+ size_t size(chain.size());
+ BOOST_CONTAINER_MEMCHAIN_INIT_FROM(&ch, beg, last, size);
+ dlmalloc_multidealloc(&ch);*/
+ dlmalloc_multidealloc(reinterpret_cast<dlmalloc_memchain *>(&chain));
+ }
+
+ //!Deallocates all free blocks of the pool
+ static void deallocate_free_blocks() BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ typedef dtl::shared_adaptive_node_pool
+ <sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
+ typedef dtl::singleton_default<shared_pool_t> singleton_t;
+ singleton_t::instance().deallocate_free_blocks();
+ }
+
+ //!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_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_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_NOEXCEPT_OR_NOTHROW
+ { return false; }
+
+ private:
+ 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;
+ dlmalloc_command_ret_t ret = {0 , 0};
+ 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;
+ {
+ void* reuse_ptr_void = reuse_ptr;
+ ret = dlmalloc_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;
+ }
+ prefer_in_recvd_out_size = r_size/sizeof(T);
+ return (pointer)ret.first;
+ }
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+template < class T
+ , std::size_t NodesPerBlock = ADP_nodes_per_block
+ , std::size_t MaxFreeBlocks = ADP_max_free_blocks
+ , std::size_t OverheadPercent = ADP_overhead_percent
+ , unsigned Version = 2
+ >
+class private_adaptive_pool
+{
+ //!If Version is 1, the allocator is a STL conforming allocator. If Version is 2,
+ //!the allocator offers advanced expand in place and burst allocation capabilities.
+ public:
+ typedef unsigned int allocation_type;
+ typedef private_adaptive_pool
+ <T, NodesPerBlock, MaxFreeBlocks, OverheadPercent
+ BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I Version)
+ > self_t;
+
+ static const std::size_t nodes_per_block = NodesPerBlock;
+ static const std::size_t max_free_blocks = MaxFreeBlocks;
+ static const std::size_t overhead_percent = OverheadPercent;
+ static const std::size_t real_nodes_per_block = NodesPerBlock;
+
+ BOOST_CONTAINER_DOCIGN(BOOST_STATIC_ASSERT((Version <=2)));
+
+ typedef dtl::private_adaptive_node_pool
+ <sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> pool_t;
+ pool_t m_pool;
+
+ public:
+ //-------
+ typedef T value_type;
+ typedef T * pointer;
+ typedef const T * const_pointer;
+ typedef typename ::boost::container::
+ dtl::unvoid_ref<T>::type reference;
+ typedef typename ::boost::container::
+ dtl::unvoid_ref<const T>::type const_reference;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+
+ typedef boost::container::dtl::
+ version_type<self_t, Version> version;
+
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ typedef boost::container::dtl::
+ basic_multiallocation_chain<void*> multiallocation_chain_void;
+ typedef boost::container::dtl::
+ transform_multiallocation_chain
+ <multiallocation_chain_void, T> multiallocation_chain;
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ //!Obtains private_adaptive_pool from
+ //!private_adaptive_pool
+ template<class T2>
+ struct rebind
+ {
+ typedef private_adaptive_pool
+ < T2
+ , NodesPerBlock
+ , MaxFreeBlocks
+ , OverheadPercent
+ BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I Version)
+ > other;
+ };
+
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ private:
+ //!Not assignable from related private_adaptive_pool
+ template<class T2, std::size_t N2, std::size_t F2, std::size_t O2, unsigned Version2>
+ private_adaptive_pool& operator=
+ (const private_adaptive_pool<T2, N2, F2, O2, Version2>&);
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ public:
+ //!Default constructor
+ private_adaptive_pool() BOOST_NOEXCEPT_OR_NOTHROW
+ {}
+
+ //!Copy constructor from other private_adaptive_pool.
+ private_adaptive_pool(const private_adaptive_pool &) BOOST_NOEXCEPT_OR_NOTHROW
+ {}
+
+ //!Copy constructor from related private_adaptive_pool.
+ template<class T2>
+ private_adaptive_pool
+ (const private_adaptive_pool<T2, NodesPerBlock, MaxFreeBlocks, OverheadPercent
+ BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I Version)> &) BOOST_NOEXCEPT_OR_NOTHROW
+ {}
+
+ //!Destructor
+ ~private_adaptive_pool() BOOST_NOEXCEPT_OR_NOTHROW
+ {}
+
+ //!Returns the number of elements that could be allocated.
+ //!Never throws
+ 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(BOOST_UNLIKELY(count > this->max_size()))
+ boost::container::throw_bad_alloc();
+
+ if(Version == 1 && count == 1){
+ return pointer(static_cast<T*>(m_pool.allocate_node()));
+ }
+ else{
+ return static_cast<pointer>(dlmalloc_malloc(count*sizeof(T)));
+ }
+ }
+
+ //!Deallocate allocated memory.
+ //!Never throws
+ void deallocate(const pointer &ptr, size_type count) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ (void)count;
+ if(Version == 1 && count == 1){
+ m_pool.deallocate_node(ptr);
+ }
+ else{
+ dlmalloc_free(ptr);
+ }
+ }
+
+ pointer allocation_command(allocation_type command,
+ size_type limit_size,
+ size_type &prefer_in_recvd_out_size,
+ pointer &reuse)
+ {
+ 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_NOEXCEPT_OR_NOTHROW
+ { return dlmalloc_size(p); }
+
+ //!Allocates just one object. Memory allocated with this function
+ //!must be deallocated only with deallocate_one().
+ //!Throws bad_alloc if there is no enough memory
+ pointer allocate_one()
+ {
+ return (pointer)m_pool.allocate_node();
+ }
+
+ //!Allocates many elements of size == 1.
+ //!Elements must be individually deallocated with deallocate_one()
+ void allocate_individual(std::size_t num_elements, multiallocation_chain &chain)
+ {
+ m_pool.allocate_nodes(num_elements, static_cast<typename pool_t::multiallocation_chain&>(chain));
+ }
+
+ //!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_NOEXCEPT_OR_NOTHROW
+ {
+ m_pool.deallocate_node(p);
+ }
+
+ void deallocate_individual(multiallocation_chain &chain) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ m_pool.deallocate_nodes(chain);
+ }
+
+ //!Allocates many elements of size elem_size.
+ //!Elements must be individually deallocated with deallocate()
+ void allocate_many(size_type elem_size, std::size_t n_elements, multiallocation_chain &chain)
+ {
+ BOOST_STATIC_ASSERT(( Version > 1 ));
+ if(BOOST_UNLIKELY(!dlmalloc_multialloc_nodes
+ (n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, reinterpret_cast<dlmalloc_memchain *>(&chain)))){
+ boost::container::throw_bad_alloc();
+ }
+ }
+
+ //!Allocates n_elements elements, each one of size elem_sizes[i]
+ //!Elements must be individually deallocated with deallocate()
+ void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain)
+ {
+ BOOST_STATIC_ASSERT(( Version > 1 ));
+ if(BOOST_UNLIKELY(!dlmalloc_multialloc_arrays
+ (n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, reinterpret_cast<dlmalloc_memchain *>(&chain)))){
+ boost::container::throw_bad_alloc();
+ }
+ }
+
+ void deallocate_many(multiallocation_chain &chain) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ dlmalloc_multidealloc(reinterpret_cast<dlmalloc_memchain *>(&chain));
+ }
+
+ //!Deallocates all free blocks of the pool
+ void deallocate_free_blocks() BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ m_pool.deallocate_free_blocks();
+ }
+
+ //!Swaps allocators. Does not throw. If each allocator is placed in a
+ //!different memory segment, the result is undefined.
+ friend void swap(private_adaptive_pool &, private_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 private_adaptive_pool &, const private_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 private_adaptive_pool &, const private_adaptive_pool &) BOOST_NOEXCEPT_OR_NOTHROW
+ { return false; }
+
+ private:
+ 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;
+ dlmalloc_command_ret_t ret = {0 , 0};
+ 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;
+ {
+ void* reuse_ptr_void = reuse_ptr;
+ ret = dlmalloc_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;
+ }
+ prefer_in_recvd_out_size = r_size/sizeof(T);
+ return (pointer)ret.first;
+ }
+};
+
+} //namespace container {
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_CONTAINER_ADAPTIVE_POOL_HPP
diff --git a/include/boost/container/allocator.hpp b/include/boost/container/allocator.hpp
new file mode 100644
index 0000000..c0deb0a
--- /dev/null
+++ b/include/boost/container/allocator.hpp
@@ -0,0 +1,368 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2007-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_HPP
+#define BOOST_CONTAINER_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/container_fwd.hpp>
+#include <boost/container/detail/version_type.hpp>
+#include <boost/container/throw_exception.hpp>
+#include <boost/container/detail/dlmalloc.hpp>
+#include <boost/container/detail/multiallocation_chain.hpp>
+#include <boost/static_assert.hpp>
+#include <cstddef>
+#include <cassert>
+
+//!\file
+
+namespace boost {
+namespace container {
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+template<unsigned Version, unsigned int AllocationDisableMask>
+class allocator<void, Version, AllocationDisableMask>
+{
+ typedef allocator<void, Version, AllocationDisableMask> self_t;
+ public:
+ typedef void value_type;
+ typedef void * pointer;
+ typedef const void* const_pointer;
+ typedef int & reference;
+ typedef const int & const_reference;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef boost::container::dtl::
+ version_type<self_t, Version> version;
+
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ typedef boost::container::dtl::
+ basic_multiallocation_chain<void*> multiallocation_chain;
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ //!Obtains an allocator that allocates
+ //!objects of type T2
+ template<class T2>
+ struct rebind
+ {
+ typedef allocator< T2
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ , Version, AllocationDisableMask
+ #endif
+ > other;
+ };
+
+ //!Default constructor
+ //!Never throws
+ allocator()
+ {}
+
+ //!Constructor from other allocator.
+ //!Never throws
+ allocator(const allocator &)
+ {}
+
+ //!Constructor from related allocator.
+ //!Never throws
+ template<class T2>
+ allocator(const allocator<T2, Version, AllocationDisableMask> &)
+ {}
+};
+
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+//! This class is an extended STL-compatible that offers advanced allocation mechanism
+//!(in-place expansion, shrinking, burst-allocation...)
+//!
+//! This allocator is a wrapper around a modified DLmalloc.
+//! If Version is 1, the allocator is a STL conforming allocator. If Version is 2,
+//! the allocator offers advanced expand in place and burst allocation capabilities.
+//!
+//! AllocationDisableMask works only if Version is 2 and it can be an inclusive OR
+//! of allocation types the user wants to disable.
+template< class T
+ , unsigned Version BOOST_CONTAINER_DOCONLY(=2)
+ , unsigned int AllocationDisableMask BOOST_CONTAINER_DOCONLY(=0)>
+class allocator
+{
+ typedef unsigned int allocation_type;
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ private:
+
+ //Self type
+ typedef allocator<T, Version, AllocationDisableMask> self_t;
+
+ //Not assignable from related allocator
+ template<class T2, unsigned int Version2, unsigned int AllocationDisableMask2>
+ allocator& operator=(const allocator<T2, Version2, AllocationDisableMask2>&);
+
+ static const unsigned int ForbiddenMask =
+ BOOST_CONTAINER_ALLOCATE_NEW | BOOST_CONTAINER_EXPAND_BWD | BOOST_CONTAINER_EXPAND_FWD ;
+
+ //The mask can't disable all the allocation types
+ BOOST_STATIC_ASSERT(( (AllocationDisableMask & ForbiddenMask) != ForbiddenMask ));
+
+ //The mask is only valid for version 2 allocators
+ BOOST_STATIC_ASSERT(( Version != 1 || (AllocationDisableMask == 0) ));
+
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ 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;
+
+ typedef boost::container::dtl::
+ version_type<self_t, Version> version;
+
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ typedef boost::container::dtl::
+ basic_multiallocation_chain<void*> void_multiallocation_chain;
+
+ typedef boost::container::dtl::
+ transform_multiallocation_chain
+ <void_multiallocation_chain, T> multiallocation_chain;
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ //!Obtains an allocator that allocates
+ //!objects of type T2
+ template<class T2>
+ struct rebind
+ {
+ typedef allocator<T2, Version, AllocationDisableMask> other;
+ };
+
+ //!Default constructor
+ //!Never throws
+ allocator() BOOST_NOEXCEPT_OR_NOTHROW
+ {}
+
+ //!Constructor from other allocator.
+ //!Never throws
+ allocator(const allocator &) BOOST_NOEXCEPT_OR_NOTHROW
+ {}
+
+ //!Constructor from related allocator.
+ //!Never throws
+ template<class T2>
+ allocator(const allocator<T2
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ , Version, AllocationDisableMask
+ #endif
+ > &) BOOST_NOEXCEPT_OR_NOTHROW
+ {}
+
+ //!Allocates memory for an array of count elements.
+ //!Throws std::bad_alloc if there is no enough memory
+ //!If Version is 2, this allocated memory can only be deallocated
+ //!with deallocate() or (for Version == 2) deallocate_many()
+ pointer allocate(size_type count, const void * hint= 0)
+ {
+ (void)hint;
+ if(count > this->max_size())
+ boost::container::throw_bad_alloc();
+ void *ret = dlmalloc_malloc(count*sizeof(T));
+ if(!ret)
+ boost::container::throw_bad_alloc();
+ return static_cast<pointer>(ret);
+ }
+
+ //!Deallocates previously allocated memory.
+ //!Never throws
+ void deallocate(pointer ptr, size_type) BOOST_NOEXCEPT_OR_NOTHROW
+ { dlmalloc_free(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 allocator is stateless
+ 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_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_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
+ pointer allocation_command(allocation_type command,
+ size_type limit_size,
+ size_type &prefer_in_recvd_out_size,
+ pointer &reuse)
+ {
+ BOOST_STATIC_ASSERT(( Version > 1 ));
+ const allocation_type mask(AllocationDisableMask);
+ command &= ~mask;
+ 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;
+ }
+
+ //!Returns maximum the number of objects the previously allocated memory
+ //!pointed by p can hold.
+ //!Memory must not have been allocated with
+ //!allocate_one or allocate_individual.
+ //!This function is available only with Version == 2
+ size_type size(pointer p) const BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_STATIC_ASSERT(( Version > 1 ));
+ return dlmalloc_size(p);
+ }
+
+ //!Allocates just one object. Memory allocated with this function
+ //!must be deallocated only with deallocate_one().
+ //!Throws bad_alloc if there is no enough memory
+ //!This function is available only with Version == 2
+ pointer allocate_one()
+ {
+ BOOST_STATIC_ASSERT(( Version > 1 ));
+ return this->allocate(1);
+ }
+
+ //!Allocates many elements of size == 1.
+ //!Elements must be individually deallocated with deallocate_one()
+ //!This function is available only with Version == 2
+ void allocate_individual(std::size_t num_elements, multiallocation_chain &chain)
+ {
+ BOOST_STATIC_ASSERT(( Version > 1 ));
+ this->allocate_many(1, num_elements, chain);
+ }
+
+ //!Deallocates memory previously allocated with allocate_one().
+ //!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_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_STATIC_ASSERT(( Version > 1 ));
+ return this->deallocate(p, 1);
+ }
+
+ //!Deallocates memory allocated with allocate_one() or allocate_individual().
+ //!This function is available only with Version == 2
+ void deallocate_individual(multiallocation_chain &chain) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_STATIC_ASSERT(( Version > 1 ));
+ return this->deallocate_many(chain);
+ }
+
+ //!Allocates many elements of size elem_size.
+ //!Elements must be individually deallocated with deallocate()
+ //!This function is available only with Version == 2
+ void allocate_many(size_type elem_size, std::size_t n_elements, multiallocation_chain &chain)
+ {
+ BOOST_STATIC_ASSERT(( Version > 1 ));/*
+ dlmalloc_memchain ch;
+ BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
+ if(!dlmalloc_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(!dlmalloc_multialloc_nodes(n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, reinterpret_cast<dlmalloc_memchain *>(&chain))){
+ boost::container::throw_bad_alloc();
+ }
+ }
+
+ //!Allocates n_elements elements, each one of size elem_sizes[i]
+ //!Elements must be individually deallocated with deallocate()
+ //!This function is available only with Version == 2
+ void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain)
+ {
+ BOOST_STATIC_ASSERT(( Version > 1 ));
+ dlmalloc_memchain ch;
+ BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
+ if(!dlmalloc_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(!dlmalloc_multialloc_arrays(n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, reinterpret_cast<dlmalloc_memchain *>(&chain))){
+ boost::container::throw_bad_alloc();
+ }*/
+ }
+
+ //!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_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_STATIC_ASSERT(( Version > 1 ));
+ dlmalloc_memchain ch;
+ void *beg(&*chain.begin()), *last(&*chain.last());
+ size_t size(chain.size());
+ BOOST_CONTAINER_MEMCHAIN_INIT_FROM(&ch, beg, last, size);
+ dlmalloc_multidealloc(&ch);
+ //dlmalloc_multidealloc(reinterpret_cast<dlmalloc_memchain *>(&chain));
+ }
+
+ private:
+
+ 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;
+ dlmalloc_command_ret_t ret = {0 , 0};
+ 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;
+ {
+ void* reuse_ptr_void = reuse_ptr;
+ ret = dlmalloc_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;
+ }
+ prefer_in_recvd_out_size = r_size/sizeof(T);
+ return (pointer)ret.first;
+ }
+};
+
+} //namespace container {
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //BOOST_CONTAINER_ALLOCATOR_HPP
+
diff --git a/include/boost/container/allocator_traits.hpp b/include/boost/container/allocator_traits.hpp
new file mode 100644
index 0000000..af32f18
--- /dev/null
+++ b/include/boost/container/allocator_traits.hpp
@@ -0,0 +1,477 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Pablo Halpern 2009. 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)
+//
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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_ALLOCATOR_TRAITS_HPP
+#define BOOST_CONTAINER_ALLOCATOR_ALLOCATOR_TRAITS_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+
+// container
+#include <boost/container/container_fwd.hpp>
+#include <boost/container/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/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 dtl {
+#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 dtl {
+#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 dtl {
+#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
+
+template<class Allocator>
+class small_vector_allocator;
+
+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)
+
+} //namespace allocator_traits_detail {
+
+namespace dtl {
+
+//workaround needed for C++03 compilers with no construct()
+//supporting rvalue references
+template<class Allocator>
+struct is_std_allocator
+{ static const bool value = false; };
+
+template<class T>
+struct is_std_allocator< std::allocator<T> >
+{ static const bool value = true; };
+
+template<class T>
+struct is_std_allocator< small_vector_allocator< std::allocator<T> > >
+{ static const bool value = true; };
+
+template<class Allocator>
+struct is_not_std_allocator
+{ static const bool value = !is_std_allocator<Allocator>::value; };
+
+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 dtl {
+
+#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 Allocator>
+struct allocator_traits
+{
+ //allocator_type
+ typedef Allocator allocator_type;
+ //value_type
+ typedef typename allocator_type::value_type value_type;
+
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ //! Allocator::pointer if such a type exists; otherwise, value_type*
+ //!
+ typedef unspecified pointer;
+ //! Allocator::const_pointer if such a type exists ; otherwise, pointer_traits<pointer>::rebind<const
+ //!
+ typedef see_documentation const_pointer;
+ //! Non-standard extension
+ //! Allocator::reference if such a type exists; otherwise, value_type&
+ typedef see_documentation reference;
+ //! Non-standard extension
+ //! Allocator::const_reference if such a type exists ; otherwise, const value_type&
+ typedef see_documentation const_reference;
+ //! Allocator::void_pointer if such a type exists ; otherwise, pointer_traits<pointer>::rebind<void>.
+ //!
+ typedef see_documentation void_pointer;
+ //! Allocator::const_void_pointer if such a type exists ; otherwis e, pointer_traits<pointer>::rebind<const
+ //!
+ typedef see_documentation const_void_pointer;
+ //! Allocator::difference_type if such a type exists ; otherwise, pointer_traits<pointer>::difference_type.
+ //!
+ typedef see_documentation difference_type;
+ //! Allocator::size_type if such a type exists ; otherwise, make_unsigned<difference_type>::type
+ //!
+ typedef see_documentation size_type;
+ //! 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;
+ //! 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;
+ //! 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;
+ //! 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
+ //! deduced by previously detailed rules.
+ template <class T> using rebind_alloc = see_documentation;
+
+ //! In C++03 compilers <code>rebind_traits</code> is a struct derived from
+ //! <code>allocator_traits<OtherAlloc></code>, where <code>OtherAlloc</code> is
+ //! the allocator deduced by rules explained in <code>rebind_alloc</code>.
+ 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 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::dtl::, Allocator,
+ pointer, value_type*)
+ pointer;
+ //const_pointer
+ typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_EVAL_DEFAULT(boost::container::dtl::, 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::dtl::, Allocator,
+ reference, typename dtl::unvoid_ref<value_type>::type)
+ reference;
+ //const_reference
+ typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::dtl::, Allocator,
+ const_reference, typename dtl::unvoid_ref<const value_type>::type)
+ const_reference;
+ //void_pointer
+ typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_EVAL_DEFAULT(boost::container::dtl::, 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::dtl::, 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::dtl::, Allocator,
+ difference_type, std::ptrdiff_t)
+ difference_type;
+ //size_type
+ typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::dtl::, Allocator,
+ size_type, std::size_t)
+ size_type;
+ //propagate_on_container_copy_assignment
+ typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::dtl::, Allocator,
+ propagate_on_container_copy_assignment, dtl::false_type)
+ propagate_on_container_copy_assignment;
+ //propagate_on_container_move_assignment
+ typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::dtl::, Allocator,
+ propagate_on_container_move_assignment, dtl::false_type)
+ propagate_on_container_move_assignment;
+ //propagate_on_container_swap
+ typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::dtl::, Allocator,
+ propagate_on_container_swap, dtl::false_type)
+ propagate_on_container_swap;
+ //is_always_equal
+ typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::dtl::, Allocator,
+ is_always_equal, dtl::is_empty<Allocator>)
+ is_always_equal;
+ //is_partially_propagable
+ typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::dtl::, Allocator,
+ is_partially_propagable, dtl::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<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<Allocator,T>::type
+ {
+ 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)...) {}
+ #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ #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<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<Allocator, T>::type type; };
+ #endif //BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ //! <b>Returns</b>: <code>a.allocate(n)</code>
+ //!
+ BOOST_CONTAINER_FORCEINLINE 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
+ BOOST_CONTAINER_FORCEINLINE 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>
+ BOOST_CONTAINER_FORCEINLINE static pointer allocate(Allocator &a, size_type n, const_void_pointer p)
+ {
+ const bool value = boost::container::dtl::
+ has_member_function_callable_with_allocate
+ <Allocator, const size_type, const const_void_pointer>::value;
+ dtl::bool_<value> flag;
+ return allocator_traits::priv_allocate(flag, a, n, p);
+ }
+
+ //! <b>Effects</b>: calls <code>a.destroy(p)</code> if that call is well-formed;
+ //! otherwise, invokes <code>p->~T()</code>.
+ template<class T>
+ BOOST_CONTAINER_FORCEINLINE static void destroy(Allocator &a, T*p) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ typedef T* destroy_pointer;
+ const bool value = boost::container::dtl::
+ has_member_function_callable_with_destroy
+ <Allocator, const destroy_pointer>::value;
+ dtl::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>.
+ BOOST_CONTAINER_FORCEINLINE static size_type max_size(const Allocator &a) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ const bool value = allocator_traits_detail::has_max_size<Allocator, size_type (Allocator::*)() const>::value;
+ dtl::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.
+ BOOST_CONTAINER_FORCEINLINE static BOOST_CONTAINER_DOC1ST(Allocator,
+ typename dtl::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 = allocator_traits_detail::has_select_on_container_copy_construction
+ <Allocator, Allocator (Allocator::*)() const>::value;
+ dtl::bool_<value> flag;
+ return allocator_traits::priv_select_on_container_copy_construction(flag, a);
+ }
+
+ #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ //! <b>Effects</b>: calls <code>a.construct(p, std::forward<Args>(args)...)</code> if that call is well-formed;
+ //! otherwise, invokes <code>`placement new` (static_cast<void*>(p)) T(std::forward<Args>(args)...)</code>
+ template <class T, class ...Args>
+ BOOST_CONTAINER_FORCEINLINE static void construct(Allocator & a, T* p, BOOST_FWD_REF(Args)... args)
+ {
+ static const bool value = ::boost::move_detail::and_
+ < dtl::is_not_std_allocator<Allocator>
+ , boost::container::dtl::has_member_function_callable_with_construct
+ < Allocator, T*, Args... >
+ >::value;
+ dtl::bool_<value> flag;
+ allocator_traits::priv_construct(flag, a, p, ::boost::forward<Args>(args)...);
+ }
+ #endif
+
+ //! <b>Returns</b>: <code>a.storage_is_unpropagable(p)</code> if is_partially_propagable::value is true; otherwise,
+ //! <code>false</code>.
+ BOOST_CONTAINER_FORCEINLINE static bool storage_is_unpropagable(const Allocator &a, pointer p) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ dtl::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>.
+ BOOST_CONTAINER_FORCEINLINE static bool equal(const Allocator &a, const Allocator &b) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ dtl::bool_<is_always_equal::value> flag;
+ return allocator_traits::priv_equal(flag, a, b);
+ }
+
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ private:
+ BOOST_CONTAINER_FORCEINLINE static pointer priv_allocate(dtl::true_type, Allocator &a, size_type n, const_void_pointer p)
+ { return a.allocate(n, p); }
+
+ BOOST_CONTAINER_FORCEINLINE static pointer priv_allocate(dtl::false_type, Allocator &a, size_type n, const_void_pointer)
+ { return a.allocate(n); }
+
+ template<class T>
+ BOOST_CONTAINER_FORCEINLINE static void priv_destroy(dtl::true_type, Allocator &a, T* p) BOOST_NOEXCEPT_OR_NOTHROW
+ { a.destroy(p); }
+
+ template<class T>
+ BOOST_CONTAINER_FORCEINLINE static void priv_destroy(dtl::false_type, Allocator &, T* p) BOOST_NOEXCEPT_OR_NOTHROW
+ { p->~T(); (void)p; }
+
+ BOOST_CONTAINER_FORCEINLINE static size_type priv_max_size(dtl::true_type, const Allocator &a) BOOST_NOEXCEPT_OR_NOTHROW
+ { return a.max_size(); }
+
+ BOOST_CONTAINER_FORCEINLINE static size_type priv_max_size(dtl::false_type, const Allocator &) BOOST_NOEXCEPT_OR_NOTHROW
+ { return size_type(-1)/sizeof(value_type); }
+
+ BOOST_CONTAINER_FORCEINLINE static Allocator priv_select_on_container_copy_construction(dtl::true_type, const Allocator &a)
+ { return a.select_on_container_copy_construction(); }
+
+ BOOST_CONTAINER_FORCEINLINE static const Allocator &priv_select_on_container_copy_construction(dtl::false_type, const Allocator &a) BOOST_NOEXCEPT_OR_NOTHROW
+ { return a; }
+
+ #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ template<class T, class ...Args>
+ BOOST_CONTAINER_FORCEINLINE static void priv_construct(dtl::true_type, Allocator &a, T *p, BOOST_FWD_REF(Args) ...args)
+ { a.construct( p, ::boost::forward<Args>(args)...); }
+
+ template<class T, class ...Args>
+ BOOST_CONTAINER_FORCEINLINE static void priv_construct(dtl::false_type, Allocator &, T *p, BOOST_FWD_REF(Args) ...args)
+ { ::new((void*)p, boost_container_new_t()) T(::boost::forward<Args>(args)...); }
+ #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 >\
+ BOOST_CONTAINER_FORCEINLINE static void construct(Allocator &a, T *p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ {\
+ static const bool value = ::boost::move_detail::and_ \
+ < dtl::is_not_std_allocator<Allocator> \
+ , boost::container::dtl::has_member_function_callable_with_construct \
+ < Allocator, T* BOOST_MOVE_I##N BOOST_MOVE_FWD_T##N > \
+ >::value; \
+ dtl::bool_<value> flag;\
+ (priv_construct)(flag, a, p BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
+ }\
+ //
+ BOOST_MOVE_ITERATE_0TO8(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 >\
+ BOOST_CONTAINER_FORCEINLINE static void priv_construct(dtl::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 >\
+ BOOST_CONTAINER_FORCEINLINE static void priv_construct(dtl::false_type, Allocator &, T *p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ { ::new((void*)p, boost_container_new_t()) T(BOOST_MOVE_FWD##N); }\
+ //
+ BOOST_MOVE_ITERATE_0TO8(BOOST_CONTAINER_ALLOCATOR_TRAITS_PRIV_CONSTRUCT_IMPL)
+ #undef BOOST_CONTAINER_ALLOCATOR_TRAITS_PRIV_CONSTRUCT_IMPL
+
+ #endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ template<class T>
+ BOOST_CONTAINER_FORCEINLINE static void priv_construct(dtl::false_type, Allocator &, T *p, const ::boost::container::default_init_t&)
+ { ::new((void*)p, boost_container_new_t()) T; }
+
+ BOOST_CONTAINER_FORCEINLINE static bool priv_storage_is_unpropagable(dtl::true_type, const Allocator &a, pointer p)
+ { return a.storage_is_unpropagable(p); }
+
+ BOOST_CONTAINER_FORCEINLINE static bool priv_storage_is_unpropagable(dtl::false_type, const Allocator &, pointer)
+ { return false; }
+
+ BOOST_CONTAINER_FORCEINLINE static bool priv_equal(dtl::true_type, const Allocator &, const Allocator &)
+ { return true; }
+
+ BOOST_CONTAINER_FORCEINLINE static bool priv_equal(dtl::false_type, const Allocator &a, const Allocator &b)
+ { return a == b; }
+
+ #endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+};
+
+} //namespace container {
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif // ! defined(BOOST_CONTAINER_ALLOCATOR_ALLOCATOR_TRAITS_HPP)
diff --git a/include/boost/container/container_fwd.hpp b/include/boost/container/container_fwd.hpp
new file mode 100644
index 0000000..e4fe6f8
--- /dev/null
+++ b/include/boost/container/container_fwd.hpp
@@ -0,0 +1,296 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-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_CONTAINER_FWD_HPP
+#define BOOST_CONTAINER_CONTAINER_FWD_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+//! \file
+//! This header file forward declares the following containers:
+//! - boost::container::vector
+//! - boost::container::stable_vector
+//! - boost::container::static_vector
+//! - boost::container::small_vector
+//! - boost::container::slist
+//! - boost::container::list
+//! - boost::container::set
+//! - boost::container::multiset
+//! - boost::container::map
+//! - boost::container::multimap
+//! - boost::container::flat_set
+//! - boost::container::flat_multiset
+//! - boost::container::flat_map
+//! - boost::container::flat_multimap
+//! - boost::container::basic_string
+//! - boost::container::string
+//! - boost::container::wstring
+//!
+//! Forward declares the following allocators:
+//! - boost::container::allocator
+//! - boost::container::node_allocator
+//! - boost::container::adaptive_pool
+//!
+//! Forward declares the following polymorphic resource classes:
+//! - boost::container::pmr::memory_resource
+//! - boost::container::pmr::polymorphic_allocator
+//! - boost::container::pmr::monotonic_buffer_resource
+//! - boost::container::pmr::pool_options
+//! - boost::container::pmr::unsynchronized_pool_resource
+//! - boost::container::pmr::synchronized_pool_resource
+//!
+//! And finally it defines the following types
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+//Std forward declarations
+#ifndef BOOST_CONTAINER_DETAIL_STD_FWD_HPP
+ #include <boost/container/detail/std_fwd.hpp>
+#endif
+
+namespace boost{
+namespace intrusive{
+namespace detail{
+ //Create namespace to avoid compilation errors
+}}}
+
+namespace boost{ namespace container{ namespace dtl{
+ namespace bi = boost::intrusive;
+ namespace bid = boost::intrusive::detail;
+}}}
+
+namespace boost{ namespace container{ namespace pmr{
+ namespace bi = boost::intrusive;
+ namespace bid = boost::intrusive::detail;
+}}}
+
+#include <cstddef>
+
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+//////////////////////////////////////////////////////////////////////////////
+// Containers
+//////////////////////////////////////////////////////////////////////////////
+
+namespace boost {
+namespace container {
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+template<class T>
+class new_allocator;
+
+template <class T
+ ,class Allocator = new_allocator<T>
+ ,class Options = void>
+class vector;
+
+template <class 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 = new_allocator<T> >
+class deque;
+
+template <class T
+ ,class Allocator = new_allocator<T> >
+class list;
+
+template <class T
+ ,class Allocator = new_allocator<T> >
+class slist;
+
+template <class Key
+ ,class Compare = std::less<Key>
+ ,class Allocator = new_allocator<Key>
+ ,class Options = void>
+class set;
+
+template <class Key
+ ,class Compare = std::less<Key>
+ ,class Allocator = new_allocator<Key>
+ ,class Options = void >
+class multiset;
+
+template <class Key
+ ,class T
+ ,class Compare = std::less<Key>
+ ,class Allocator = new_allocator<std::pair<const Key, T> >
+ ,class Options = void >
+class map;
+
+template <class Key
+ ,class T
+ ,class Compare = std::less<Key>
+ ,class Allocator = new_allocator<std::pair<const Key, T> >
+ ,class Options = void >
+class multimap;
+
+template <class Key
+ ,class Compare = std::less<Key>
+ ,class Allocator = new_allocator<Key> >
+class flat_set;
+
+template <class Key
+ ,class Compare = std::less<Key>
+ ,class Allocator = new_allocator<Key> >
+class flat_multiset;
+
+template <class Key
+ ,class T
+ ,class Compare = std::less<Key>
+ ,class Allocator = new_allocator<std::pair<Key, T> > >
+class flat_map;
+
+template <class Key
+ ,class T
+ ,class Compare = std::less<Key>
+ ,class Allocator = new_allocator<std::pair<Key, T> > >
+class flat_multimap;
+
+template <class CharT
+ ,class Traits = std::char_traits<CharT>
+ ,class Allocator = new_allocator<CharT> >
+class basic_string;
+
+typedef basic_string
+ <char
+ ,std::char_traits<char>
+ ,new_allocator<char> >
+string;
+
+typedef basic_string
+ <wchar_t
+ ,std::char_traits<wchar_t>
+ ,new_allocator<wchar_t> >
+wstring;
+
+static const std::size_t ADP_nodes_per_block = 256u;
+static const std::size_t ADP_max_free_blocks = 2u;
+static const std::size_t ADP_overhead_percent = 1u;
+static const std::size_t ADP_only_alignment = 0u;
+
+template < class T
+ , std::size_t NodesPerBlock = ADP_nodes_per_block
+ , std::size_t MaxFreeBlocks = ADP_max_free_blocks
+ , std::size_t OverheadPercent = ADP_overhead_percent
+ , unsigned Version = 2
+ >
+class adaptive_pool;
+
+template < class T
+ , unsigned Version = 2
+ , unsigned int AllocationDisableMask = 0>
+class allocator;
+
+static const std::size_t NodeAlloc_nodes_per_block = 256u;
+
+template
+ < class T
+ , std::size_t NodesPerBlock = NodeAlloc_nodes_per_block
+ , std::size_t Version = 2>
+class node_allocator;
+
+namespace pmr {
+
+class memory_resource;
+
+template<class T>
+class polymorphic_allocator;
+
+class monotonic_buffer_resource;
+
+struct pool_options;
+
+template <class Allocator>
+class resource_adaptor_imp;
+
+class unsynchronized_pool_resource;
+
+class synchronized_pool_resource;
+
+} //namespace pmr {
+
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+//! Type used to tag that the input range is
+//! guaranteed to be ordered
+struct ordered_range_t
+{};
+
+//! Value used to tag that the input range is
+//! guaranteed to be ordered
+static const ordered_range_t ordered_range = ordered_range_t();
+
+//! Type used to tag that the input range is
+//! guaranteed to be ordered and unique
+struct ordered_unique_range_t
+ : public ordered_range_t
+{};
+
+//! Value used to tag that the input range is
+//! guaranteed to be ordered and unique
+static const ordered_unique_range_t ordered_unique_range = ordered_unique_range_t();
+
+//! Type used to tag that the inserted values
+//! should be default initialized
+struct default_init_t
+{};
+
+//! Value used to tag that the inserted values
+//! should be default initialized
+static const default_init_t default_init = default_init_t();
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+//! Type used to tag that the inserted values
+//! should be value initialized
+struct value_init_t
+{};
+
+//! Value used to tag that the inserted values
+//! should be value initialized
+static const value_init_t value_init = value_init_t();
+
+namespace container_detail_really_deep_namespace {
+
+//Otherwise, gcc issues a warning of previously defined
+//anonymous_instance and unique_instance
+struct dummy
+{
+ dummy()
+ {
+ (void)ordered_range;
+ (void)ordered_unique_range;
+ (void)default_init;
+ }
+};
+
+} //detail_really_deep_namespace {
+
+
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+}} //namespace boost { namespace container {
+
+#endif //#ifndef BOOST_CONTAINER_CONTAINER_FWD_HPP
diff --git a/include/boost/container/deque.hpp b/include/boost/container/deque.hpp
new file mode 100644
index 0000000..f04ba49
--- /dev/null
+++ b/include/boost/container/deque.hpp
@@ -0,0 +1,2270 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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 http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#ifndef BOOST_CONTAINER_DEQUE_HPP
+#define BOOST_CONTAINER_DEQUE_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+// container
+#include <boost/container/allocator_traits.hpp>
+#include <boost/container/container_fwd.hpp>
+#include <boost/container/new_allocator.hpp> //new_allocator
+#include <boost/container/throw_exception.hpp>
+// container/detail
+#include <boost/container/detail/advanced_insert_int.hpp>
+#include <boost/container/detail/algorithm.hpp> //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/move/detail/iterator_to_raw_pointer.hpp>
+#include <boost/container/detail/iterators.hpp>
+#include <boost/container/detail/min_max.hpp>
+#include <boost/container/detail/mpl.hpp>
+#include <boost/move/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/traits.hpp>
+#include <boost/move/utility_core.hpp>
+// move/detail
+#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+#include <boost/move/detail/fwd_macros.hpp>
+#endif
+#include <boost/move/detail/move_helpers.hpp>
+// other
+#include <boost/assert.hpp>
+#include <boost/core/no_exceptions_support.hpp>
+// std
+#include <cstddef>
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+#include <initializer_list>
+#endif
+
+namespace boost {
+namespace container {
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+template <class T, class Allocator>
+class deque;
+
+template <class T>
+struct deque_value_traits
+{
+ typedef T value_type;
+ static const bool trivial_dctr = dtl::is_trivially_destructible<value_type>::value;
+ static const bool trivial_dctr_after_move = ::boost::has_trivial_destructor_after_move<value_type>::value;
+};
+
+// Note: this function is simply a kludge to work around several compilers'
+// bugs in handling constant expressions.
+template<class T>
+struct deque_buf_size
+{
+ static const std::size_t min_size = 512u;
+ static const std::size_t sizeof_t = sizeof(T);
+ static const std::size_t value = sizeof_t < min_size ? (min_size/sizeof_t) : std::size_t(1);
+};
+
+namespace dtl {
+
+// Class invariants:
+// For any nonsingular iterator i:
+// i.node is the address of an element in the map array. The
+// contents of i.node is a pointer to the beginning of a node.
+// i.first == //(i.node)
+// i.last == i.first + node_size
+// i.cur is a pointer in the range [i.first, i.last). NOTE:
+// the implication of this is that i.cur is always a dereferenceable
+// pointer, even if i is a past-the-end iterator.
+// Start and Finish are always nonsingular iterators. NOTE: this means
+// that an empty deque must have one node, and that a deque
+// with N elements, where N is the buffer size, must have two nodes.
+// For every node other than start.node and finish.node, every element
+// in the node is an initialized object. If start.node == finish.node,
+// then [start.cur, finish.cur) are initialized objects, and
+// the elements outside that range are uninitialized storage. Otherwise,
+// [start.cur, start.last) and [finish.first, finish.cur) are initialized
+// objects, and [start.first, start.cur) and [finish.cur, finish.last)
+// are uninitialized storage.
+// [map, map + map_size) is a valid, non-empty range.
+// [start.node, finish.node] is a valid range contained within
+// [map, map + map_size).
+// A pointer in the range [map, map + map_size) points to an allocated node
+// if and only if the pointer is in the range [start.node, finish.node].
+template<class Pointer, bool IsConst>
+class deque_iterator
+{
+ public:
+ typedef std::random_access_iterator_tag iterator_category;
+ typedef typename boost::intrusive::pointer_traits<Pointer>::element_type value_type;
+ typedef typename boost::intrusive::pointer_traits<Pointer>::difference_type difference_type;
+ typedef typename if_c
+ < IsConst
+ , typename boost::intrusive::pointer_traits<Pointer>::template
+ rebind_pointer<const value_type>::type
+ , Pointer
+ >::type pointer;
+ typedef typename if_c
+ < IsConst
+ , const value_type&
+ , value_type&
+ >::type reference;
+
+ static std::size_t s_buffer_size()
+ { return deque_buf_size<value_type>::value; }
+
+ typedef Pointer val_alloc_ptr;
+ typedef typename boost::intrusive::pointer_traits<Pointer>::
+ template rebind_pointer<Pointer>::type index_pointer;
+
+ Pointer m_cur;
+ Pointer m_first;
+ Pointer m_last;
+ index_pointer m_node;
+
+ public:
+
+ Pointer get_cur() const { return m_cur; }
+ Pointer get_first() const { return m_first; }
+ 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_NOEXCEPT_OR_NOTHROW
+ : m_cur(x), m_first(*y), m_last(*y + s_buffer_size()), m_node(y)
+ {}
+
+ 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_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_NOEXCEPT_OR_NOTHROW
+ : m_cur(cur), m_first(first), m_last(last), m_node(node)
+ {}
+
+ 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_NOEXCEPT_OR_NOTHROW
+ { return *this->m_cur; }
+
+ pointer operator->() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->m_cur; }
+
+ difference_type operator-(const deque_iterator& x) const BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ if(!this->m_cur && !x.m_cur){
+ return 0;
+ }
+ return difference_type(this->s_buffer_size()) * (this->m_node - x.m_node - 1) +
+ (this->m_cur - this->m_first) + (x.m_last - x.m_cur);
+ }
+
+ deque_iterator& operator++() BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ ++this->m_cur;
+ if (this->m_cur == this->m_last) {
+ this->priv_set_node(this->m_node + 1);
+ this->m_cur = this->m_first;
+ }
+ return *this;
+ }
+
+ deque_iterator operator++(int) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ deque_iterator tmp(*this);
+ ++*this;
+ return tmp;
+ }
+
+ deque_iterator& operator--() BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ if (this->m_cur == this->m_first) {
+ this->priv_set_node(this->m_node - 1);
+ this->m_cur = this->m_last;
+ }
+ --this->m_cur;
+ return *this;
+ }
+
+ deque_iterator operator--(int) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ deque_iterator tmp(*this);
+ --*this;
+ return tmp;
+ }
+
+ deque_iterator& operator+=(difference_type n) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ difference_type offset = n + (this->m_cur - this->m_first);
+ if (offset >= 0 && offset < difference_type(this->s_buffer_size()))
+ this->m_cur += n;
+ else {
+ difference_type node_offset =
+ offset > 0 ? offset / difference_type(this->s_buffer_size())
+ : -difference_type((-offset - 1) / this->s_buffer_size()) - 1;
+ this->priv_set_node(this->m_node + node_offset);
+ this->m_cur = this->m_first +
+ (offset - node_offset * difference_type(this->s_buffer_size()));
+ }
+ return *this;
+ }
+
+ 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_NOEXCEPT_OR_NOTHROW
+ { return *this += -n; }
+
+ 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_NOEXCEPT_OR_NOTHROW
+ { return *(*this + n); }
+
+ 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_NOEXCEPT_OR_NOTHROW
+ { return l.m_cur != r.m_cur; }
+
+ 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_NOEXCEPT_OR_NOTHROW
+ { return r < l; }
+
+ 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_NOEXCEPT_OR_NOTHROW
+ { return !(l < r); }
+
+ 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_NOEXCEPT_OR_NOTHROW
+ { return x += n; }
+};
+
+} //namespace dtl {
+
+// Deque base class. It has two purposes. First, its constructor
+// and destructor allocate (but don't initialize) storage. This makes
+// exception safety easier.
+template <class Allocator>
+class deque_base
+{
+ BOOST_COPYABLE_AND_MOVABLE(deque_base)
+ public:
+ typedef allocator_traits<Allocator> val_alloc_traits_type;
+ typedef typename val_alloc_traits_type::value_type val_alloc_val;
+ typedef typename val_alloc_traits_type::pointer val_alloc_ptr;
+ typedef typename val_alloc_traits_type::const_pointer val_alloc_cptr;
+ typedef typename val_alloc_traits_type::reference val_alloc_ref;
+ typedef typename val_alloc_traits_type::const_reference val_alloc_cref;
+ typedef typename val_alloc_traits_type::difference_type val_alloc_diff;
+ typedef typename val_alloc_traits_type::size_type val_alloc_size;
+ typedef typename val_alloc_traits_type::template
+ portable_rebind_alloc<val_alloc_ptr>::type ptr_alloc_t;
+ typedef allocator_traits<ptr_alloc_t> ptr_alloc_traits_type;
+ typedef typename ptr_alloc_traits_type::value_type ptr_alloc_val;
+ typedef typename ptr_alloc_traits_type::pointer ptr_alloc_ptr;
+ typedef typename ptr_alloc_traits_type::const_pointer ptr_alloc_cptr;
+ typedef typename ptr_alloc_traits_type::reference ptr_alloc_ref;
+ typedef typename ptr_alloc_traits_type::const_reference ptr_alloc_cref;
+ typedef Allocator allocator_type;
+ typedef allocator_type stored_allocator_type;
+ typedef val_alloc_size size_type;
+
+ protected:
+
+ typedef deque_value_traits<val_alloc_val> traits_t;
+ typedef ptr_alloc_t map_allocator_type;
+
+ 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_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_NOEXCEPT_OR_NOTHROW
+ { this->ptr_alloc().deallocate(p, n); }
+
+ typedef dtl::deque_iterator<val_alloc_ptr, false> iterator;
+ typedef dtl::deque_iterator<val_alloc_ptr, true > const_iterator;
+
+ deque_base(size_type num_elements, const allocator_type& a)
+ : members_(a)
+ { this->priv_initialize_map(num_elements); }
+
+ explicit deque_base(const allocator_type& a)
+ : members_(a)
+ {}
+
+ deque_base()
+ : members_()
+ {}
+
+ explicit deque_base(BOOST_RV_REF(deque_base) x)
+ : members_( boost::move(x.ptr_alloc())
+ , boost::move(x.alloc()) )
+ {}
+
+ ~deque_base()
+ {
+ if (this->members_.m_map) {
+ this->priv_destroy_nodes(this->members_.m_start.m_node, this->members_.m_finish.m_node + 1);
+ this->priv_deallocate_map(this->members_.m_map, this->members_.m_map_size);
+ }
+ }
+
+ private:
+ deque_base(const deque_base&);
+
+ protected:
+
+ void swap_members(deque_base &x) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ ::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)
+ {
+// if(num_elements){
+ size_type num_nodes = num_elements / s_buffer_size() + 1;
+
+ this->members_.m_map_size = dtl::max_value((size_type) InitialMapSize, num_nodes + 2);
+ this->members_.m_map = this->priv_allocate_map(this->members_.m_map_size);
+
+ ptr_alloc_ptr nstart = this->members_.m_map + (this->members_.m_map_size - num_nodes) / 2;
+ ptr_alloc_ptr nfinish = nstart + num_nodes;
+
+ BOOST_TRY {
+ this->priv_create_nodes(nstart, nfinish);
+ }
+ BOOST_CATCH(...){
+ this->priv_deallocate_map(this->members_.m_map, this->members_.m_map_size);
+ this->members_.m_map = 0;
+ this->members_.m_map_size = 0;
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+
+ this->members_.m_start.priv_set_node(nstart);
+ this->members_.m_finish.priv_set_node(nfinish - 1);
+ this->members_.m_start.m_cur = this->members_.m_start.m_first;
+ this->members_.m_finish.m_cur = this->members_.m_finish.m_first +
+ num_elements % s_buffer_size();
+// }
+ }
+
+ void priv_create_nodes(ptr_alloc_ptr nstart, ptr_alloc_ptr nfinish)
+ {
+ ptr_alloc_ptr cur = nstart;
+ BOOST_TRY {
+ for (; cur < nfinish; ++cur)
+ *cur = this->priv_allocate_node();
+ }
+ BOOST_CATCH(...){
+ this->priv_destroy_nodes(nstart, cur);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ }
+
+ 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_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);
+ this->priv_deallocate_map(this->members_.m_map, this->members_.m_map_size);
+ this->members_.m_map = 0;
+ this->members_.m_map_size = 0;
+ this->members_.m_start = iterator();
+ this->members_.m_finish = this->members_.m_start;
+ }
+ }
+
+ enum { InitialMapSize = 8 };
+
+ protected:
+ struct members_holder
+ : public ptr_alloc_t
+ , public allocator_type
+ {
+ members_holder()
+ : map_allocator_type(), allocator_type()
+ , m_map(0), m_map_size(0)
+ , m_start(), m_finish(m_start)
+ {}
+
+ explicit members_holder(const allocator_type &a)
+ : map_allocator_type(a), allocator_type(a)
+ , m_map(0), m_map_size(0)
+ , m_start(), m_finish(m_start)
+ {}
+
+ template<class ValAllocConvertible, class PtrAllocConvertible>
+ members_holder(BOOST_FWD_REF(PtrAllocConvertible) pa, BOOST_FWD_REF(ValAllocConvertible) va)
+ : map_allocator_type(boost::forward<PtrAllocConvertible>(pa))
+ , allocator_type (boost::forward<ValAllocConvertible>(va))
+ , m_map(0), m_map_size(0)
+ , m_start(), m_finish(m_start)
+ {}
+
+ ptr_alloc_ptr m_map;
+ val_alloc_size m_map_size;
+ iterator m_start;
+ iterator m_finish;
+ } members_;
+
+ ptr_alloc_t &ptr_alloc() BOOST_NOEXCEPT_OR_NOTHROW
+ { return members_; }
+
+ const ptr_alloc_t &ptr_alloc() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return members_; }
+
+ allocator_type &alloc() BOOST_NOEXCEPT_OR_NOTHROW
+ { return members_; }
+
+ const allocator_type &alloc() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return members_; }
+};
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
+//! A double-ended queue is a sequence that supports random access to elements, constant time insertion
+//! and removal of elements at the end of the sequence, and linear time insertion and removal of elements in the middle.
+//!
+//! \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 = new_allocator<T> >
+#else
+template <class T, class Allocator>
+#endif
+class deque : protected deque_base<Allocator>
+{
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ private:
+ typedef deque_base<Allocator> Base;
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ public:
+
+ //////////////////////////////////////////////
+ //
+ // types
+ //
+ //////////////////////////////////////////////
+
+ typedef 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;
+ typedef typename ::boost::container::allocator_traits<Allocator>::const_reference const_reference;
+ typedef typename ::boost::container::allocator_traits<Allocator>::size_type size_type;
+ typedef typename ::boost::container::allocator_traits<Allocator>::difference_type difference_type;
+ typedef Allocator allocator_type;
+ 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(boost::container::reverse_iterator<iterator>) reverse_iterator;
+ typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<const_iterator>) const_reverse_iterator;
+
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ private: // Internal typedefs
+ BOOST_COPYABLE_AND_MOVABLE(deque)
+ typedef typename Base::ptr_alloc_ptr index_pointer;
+ static size_type s_buffer_size()
+ { return Base::s_buffer_size(); }
+ typedef allocator_traits<Allocator> allocator_traits_type;
+
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ public:
+ //////////////////////////////////////////////
+ //
+ // construct/copy/destroy
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Default constructors a deque.
+ //!
+ //! <b>Throws</b>: If allocator_type's default constructor throws.
+ //!
+ //! <b>Complexity</b>: Constant.
+ deque() BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<Allocator>::value)
+ : Base()
+ {}
+
+ //! <b>Effects</b>: Constructs a deque taking the allocator as parameter.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ explicit deque(const allocator_type& a) BOOST_NOEXCEPT_OR_NOTHROW
+ : Base(a)
+ {}
+
+ //! <b>Effects</b>: Constructs a deque
+ //! 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)
+ : Base(n, allocator_type())
+ {
+ dtl::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
+ //! 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)
+ : Base(n, allocator_type())
+ {
+ dtl::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 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)
+ {
+ dtl::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)
+ {
+ dtl::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
+ //! throws or T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to n.
+ deque(size_type n, const value_type& value)
+ : Base(n, allocator_type())
+ { this->priv_fill_initialize(value); }
+
+ //! <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
+ //! throws or T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to n.
+ deque(size_type n, const value_type& value, const allocator_type& a)
+ : Base(n, a)
+ { this->priv_fill_initialize(value); }
+
+ //! <b>Effects</b>: Constructs a deque that will use a copy of allocator a
+ //! and inserts a copy of the range [first, last) in the deque.
+ //!
+ //! <b>Throws</b>: If allocator_type's default constructor
+ //! throws or T's constructor taking a dereferenced InIt throws.
+ //!
+ //! <b>Complexity</b>: Linear to the range [first, last).
+ template <class InIt>
+ deque(InIt first, InIt last
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename dtl::disable_if_convertible
+ <InIt, size_type>::type * = 0
+ #endif
+ )
+ : Base(allocator_type())
+ {
+ this->priv_range_initialize(first, last);
+ }
+
+ //! <b>Effects</b>: Constructs a deque that will use a copy of allocator a
+ //! and inserts a copy of the range [first, last) in the deque.
+ //!
+ //! <b>Throws</b>: If allocator_type's default constructor
+ //! throws or T's constructor taking a dereferenced InIt throws.
+ //!
+ //! <b>Complexity</b>: Linear to the range [first, last).
+ template <class InIt>
+ deque(InIt first, InIt last, const allocator_type& a
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename dtl::disable_if_convertible
+ <InIt, size_type>::type * = 0
+ #endif
+ )
+ : Base(a)
+ {
+ this->priv_range_initialize(first, last);
+ }
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Constructs a deque that will use a copy of allocator a
+ //! and inserts a copy of the range [il.begin(), il.end()) in the deque.
+ //!
+ //! <b>Throws</b>: If allocator_type's default constructor
+ //! throws or T's constructor taking a dereferenced std::initializer_list iterator throws.
+ //!
+ //! <b>Complexity</b>: Linear to the range [il.begin(), il.end()).
+ deque(std::initializer_list<value_type> il, const allocator_type& a = allocator_type())
+ : Base(a)
+ {
+ this->priv_range_initialize(il.begin(), il.end());
+ }
+#endif
+
+ //! <b>Effects</b>: Copy constructs a deque.
+ //!
+ //! <b>Postcondition</b>: x == *this.
+ //!
+ //! <b>Complexity</b>: Linear to the elements x contains.
+ deque(const deque& x)
+ : Base(allocator_traits_type::select_on_container_copy_construction(x.alloc()))
+ {
+ if(x.size()){
+ this->priv_initialize_map(x.size());
+ boost::container::uninitialized_copy_alloc
+ (this->alloc(), x.begin(), x.end(), this->members_.m_start);
+ }
+ }
+
+ //! <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) BOOST_NOEXCEPT_OR_NOTHROW
+ : Base(BOOST_MOVE_BASE(Base, x))
+ { this->swap_members(x); }
+
+ //! <b>Effects</b>: Copy constructs a vector using the specified allocator.
+ //!
+ //! <b>Postcondition</b>: x == *this.
+ //!
+ //! <b>Throws</b>: If allocation
+ //! throws or T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to the elements x contains.
+ deque(const deque& x, const allocator_type &a)
+ : Base(a)
+ {
+ if(x.size()){
+ this->priv_initialize_map(x.size());
+ boost::container::uninitialized_copy_alloc
+ (this->alloc(), x.begin(), x.end(), this->members_.m_start);
+ }
+ }
+
+ //! <b>Effects</b>: Move constructor using the specified allocator.
+ //! 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 == x.get_allocator(), linear otherwise.
+ deque(BOOST_RV_REF(deque) x, const allocator_type &a)
+ : Base(a)
+ {
+ if(x.alloc() == a){
+ this->swap_members(x);
+ }
+ else{
+ if(x.size()){
+ this->priv_initialize_map(x.size());
+ boost::container::uninitialized_copy_alloc
+ ( this->alloc(), boost::make_move_iterator(x.begin())
+ , boost::make_move_iterator(x.end()), this->members_.m_start);
+ }
+ }
+ }
+
+ //! <b>Effects</b>: Destroys the deque. All stored values are destroyed
+ //! and used memory is deallocated.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements.
+ ~deque() BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ this->priv_destroy_range(this->members_.m_start, this->members_.m_finish);
+ }
+
+ //! <b>Effects</b>: Makes *this contain the same elements as x.
+ //!
+ //! <b>Postcondition</b>: this->size() == x.size(). *this contains a copy
+ //! of each of x's elements.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in x.
+ deque& operator= (BOOST_COPY_ASSIGN_REF(deque) x)
+ {
+ if (&x != this){
+ allocator_type &this_alloc = this->alloc();
+ const allocator_type &x_alloc = x.alloc();
+ dtl::bool_<allocator_traits_type::
+ propagate_on_container_copy_assignment::value> flag;
+ if(flag && this_alloc != x_alloc){
+ this->clear();
+ this->shrink_to_fit();
+ }
+ dtl::assign_alloc(this->alloc(), x.alloc(), flag);
+ dtl::assign_alloc(this->ptr_alloc(), x.ptr_alloc(), flag);
+ this->assign(x.cbegin(), x.cend());
+ }
+ return *this;
+ }
+
+ //! <b>Effects</b>: Move assignment. All x's values are transferred to *this.
+ //!
+ //! <b>Throws</b>: If allocator_traits_type::propagate_on_container_move_assignment
+ //! is false and (allocation throws or value_type's move constructor throws)
+ //!
+ //! <b>Complexity</b>: Constant if allocator_traits_type::
+ //! propagate_on_container_move_assignment is true or
+ //! this->get>allocator() == x.get_allocator(). Linear otherwise.
+ deque& operator= (BOOST_RV_REF(deque) x)
+ 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();
+ allocator_type &x_alloc = x.alloc();
+ const bool propagate_alloc = allocator_traits_type::
+ propagate_on_container_move_assignment::value;
+ dtl::bool_<propagate_alloc> flag;
+ const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
+ //Resources can be transferred if both allocators are
+ //going to be equal after this function (either propagated or already equal)
+ if(propagate_alloc || allocators_equal){
+ //Destroy objects but retain memory in case x reuses it in the future
+ this->clear();
+ //Move allocator if needed
+ dtl::move_alloc(this_alloc, x_alloc, flag);
+ dtl::move_alloc(this->ptr_alloc(), x.ptr_alloc(), flag);
+ //Nothrow swap
+ this->swap_members(x);
+ }
+ //Else do a one by one move
+ else{
+ this->assign( boost::make_move_iterator(x.begin())
+ , boost::make_move_iterator(x.end()));
+ }
+ return *this;
+ }
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Makes *this contain the same elements as il.
+ //!
+ //! <b>Postcondition</b>: this->size() == il.size(). *this contains a copy
+ //! of each of x's elements.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in il.
+ deque& operator=(std::initializer_list<value_type> il)
+ {
+ this->assign(il.begin(), il.end());
+ return *this;
+ }
+#endif
+
+ //! <b>Effects</b>: Assigns the n copies of val to *this.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to n.
+ void assign(size_type n, const T& val)
+ {
+ typedef constant_iterator<value_type, difference_type> c_it;
+ this->assign(c_it(val, n), c_it());
+ }
+
+ //! <b>Effects</b>: Assigns the the range [first, last) to *this.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or
+ //! T's constructor from dereferencing InIt throws.
+ //!
+ //! <b>Complexity</b>: Linear to n.
+ template <class InIt>
+ void assign(InIt first, InIt last
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename dtl::disable_if_or
+ < void
+ , dtl::is_convertible<InIt, size_type>
+ , dtl::is_not_input_iterator<InIt>
+ >::type * = 0
+ #endif
+ )
+ {
+ iterator cur = this->begin();
+ for ( ; first != last && cur != end(); ++cur, ++first){
+ *cur = *first;
+ }
+ if (first == last){
+ this->erase(cur, this->cend());
+ }
+ else{
+ this->insert(this->cend(), first, last);
+ }
+ }
+
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ template <class FwdIt>
+ void assign(FwdIt first, FwdIt last
+ , typename dtl::disable_if_or
+ < void
+ , dtl::is_convertible<FwdIt, size_type>
+ , dtl::is_input_iterator<FwdIt>
+ >::type * = 0
+ )
+ {
+ const size_type len = boost::container::iterator_distance(first, last);
+ if (len > size()) {
+ FwdIt mid = first;
+ boost::container::iterator_advance(mid, this->size());
+ boost::container::copy(first, mid, begin());
+ this->insert(this->cend(), mid, last);
+ }
+ else{
+ this->erase(boost::container::copy(first, last, this->begin()), cend());
+ }
+ }
+ #endif
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Assigns the the range [il.begin(), il.end()) to *this.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or
+ //! T's constructor from dereferencing std::initializer_list iterator throws.
+ //!
+ //! <b>Complexity</b>: Linear to il.size().
+ void assign(std::initializer_list<value_type> il)
+ { this->assign(il.begin(), il.end()); }
+#endif
+
+ //! <b>Effects</b>: Returns a copy of the internal allocator.
+ //!
+ //! <b>Throws</b>: If allocator's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Constant.
+ allocator_type get_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return Base::alloc(); }
+
+ //! <b>Effects</b>: Returns a reference to the internal allocator.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return Base::alloc(); }
+
+ //////////////////////////////////////////////
+ //
+ // iterators
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Returns a reference to the internal allocator.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ 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.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ 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.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ 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.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ iterator end() BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->members_.m_finish; }
+
+ //! <b>Effects</b>: Returns a const_iterator to the end of the deque.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->members_.m_finish; }
+
+ //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
+ //! of the reversed deque.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ 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
+ //! of the reversed deque.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ 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
+ //! of the reversed deque.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ 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
+ //! of the reversed deque.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ 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.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ 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.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ 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
+ //! of the reversed deque.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ 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
+ //! of the reversed deque.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return const_reverse_iterator(this->members_.m_start); }
+
+ //////////////////////////////////////////////
+ //
+ // capacity
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Returns true if the deque contains no elements.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ 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.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ 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.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ 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
+ //! the size becomes n. New elements are value initialized.
+ //!
+ //! <b>Throws</b>: If memory allocation throws, or T's constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to the difference between size() and new_size.
+ void resize(size_type new_size)
+ {
+ const size_type len = size();
+ if (new_size < len)
+ this->priv_erase_last_n(len - new_size);
+ else{
+ const size_type n = new_size - this->size();
+ dtl::insert_value_initialized_n_proxy<Allocator, iterator> proxy;
+ priv_insert_back_aux_impl(n, proxy);
+ }
+ }
+
+ //! <b>Effects</b>: Inserts or erases elements at the end such that
+ //! the size becomes n. New elements are default initialized.
+ //!
+ //! <b>Throws</b>: If memory allocation throws, or T's constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to the difference between size() and new_size.
+ //!
+ //! <b>Note</b>: Non-standard extension
+ void resize(size_type new_size, default_init_t)
+ {
+ const size_type len = size();
+ if (new_size < len)
+ this->priv_erase_last_n(len - new_size);
+ else{
+ const size_type n = new_size - this->size();
+ dtl::insert_default_initialized_n_proxy<Allocator, iterator> proxy;
+ priv_insert_back_aux_impl(n, proxy);
+ }
+ }
+
+ //! <b>Effects</b>: Inserts or erases elements at the end such that
+ //! the size becomes n. New elements are copy constructed from x.
+ //!
+ //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to the difference between size() and new_size.
+ void resize(size_type new_size, const value_type& x)
+ {
+ const size_type len = size();
+ if (new_size < len)
+ this->erase(this->members_.m_start + new_size, this->members_.m_finish);
+ else
+ this->insert(this->members_.m_finish, new_size - len, x);
+ }
+
+ //! <b>Effects</b>: Tries to deallocate the excess of memory created
+ //! with previous allocations. The size of the deque is unchanged
+ //!
+ //! <b>Throws</b>: If memory allocation throws.
+ //!
+ //! <b>Complexity</b>: Constant.
+ void shrink_to_fit()
+ {
+ //This deque implementation already
+ //deallocates excess nodes when erasing
+ //so there is nothing to do except for
+ //empty deque
+ if(this->empty()){
+ this->priv_clear_map();
+ }
+ }
+
+ //////////////////////////////////////////////
+ //
+ // element access
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Requires</b>: !empty()
+ //!
+ //! <b>Effects</b>: Returns a reference to the first
+ //! element of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ reference front() BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(!this->empty());
+ return *this->members_.m_start;
+ }
+
+ //! <b>Requires</b>: !empty()
+ //!
+ //! <b>Effects</b>: Returns a const reference to the first element
+ //! from the beginning of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reference front() const BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(!this->empty());
+ return *this->members_.m_start;
+ }
+
+ //! <b>Requires</b>: !empty()
+ //!
+ //! <b>Effects</b>: Returns a reference to the last
+ //! element of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ reference back() BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(!this->empty());
+ return *(end()-1);
+ }
+
+ //! <b>Requires</b>: !empty()
+ //!
+ //! <b>Effects</b>: Returns a const reference to the last
+ //! element of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reference back() const BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(!this->empty());
+ return *(cend()-1);
+ }
+
+ //! <b>Requires</b>: size() > n.
+ //!
+ //! <b>Effects</b>: Returns a reference to the nth element
+ //! from the beginning of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ reference operator[](size_type n) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(this->size() > n);
+ return this->members_.m_start[difference_type(n)];
+ }
+
+ //! <b>Requires</b>: size() > n.
+ //!
+ //! <b>Effects</b>: Returns a const reference to the nth element
+ //! from the beginning of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reference operator[](size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(this->size() > n);
+ 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>: 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(iterator p) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ //Range checked priv_index_of
+ 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
+ {
+ //Range checked priv_index_of
+ return this->priv_index_of(p);
+ }
+
+ //! <b>Requires</b>: size() > n.
+ //!
+ //! <b>Effects</b>: Returns a reference to the nth element
+ //! from the beginning of the container.
+ //!
+ //! <b>Throws</b>: std::range_error if n >= size()
+ //!
+ //! <b>Complexity</b>: Constant.
+ reference at(size_type n)
+ {
+ this->priv_throw_if_out_of_range(n);
+ return (*this)[n];
+ }
+
+ //! <b>Requires</b>: size() > n.
+ //!
+ //! <b>Effects</b>: Returns a const reference to the nth element
+ //! from the beginning of the container.
+ //!
+ //! <b>Throws</b>: std::range_error if n >= size()
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reference at(size_type n) const
+ {
+ this->priv_throw_if_out_of_range(n);
+ return (*this)[n];
+ }
+
+ //////////////////////////////////////////////
+ //
+ // modifiers
+ //
+ //////////////////////////////////////////////
+
+ #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.
+ //!
+ //! <b>Returns</b>: A reference to the created object.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or the in-place constructor throws.
+ //!
+ //! <b>Complexity</b>: Amortized constant time
+ template <class... Args>
+ reference emplace_front(BOOST_FWD_REF(Args)... args)
+ {
+ if(this->priv_push_front_simple_available()){
+ reference r = *this->priv_push_front_simple_pos();
+ allocator_traits_type::construct
+ ( this->alloc()
+ , this->priv_push_front_simple_pos()
+ , boost::forward<Args>(args)...);
+ this->priv_push_front_simple_commit();
+ return r;
+ }
+ else{
+ typedef dtl::insert_nonmovable_emplace_proxy<Allocator, iterator, Args...> type;
+ return *this->priv_insert_front_aux_impl(1, type(boost::forward<Args>(args)...));
+ }
+ }
+
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... in the end of the deque.
+ //!
+ //! <b>Returns</b>: A reference to the created object.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or the in-place constructor throws.
+ //!
+ //! <b>Complexity</b>: Amortized constant time
+ template <class... Args>
+ reference emplace_back(BOOST_FWD_REF(Args)... args)
+ {
+ if(this->priv_push_back_simple_available()){
+ reference r = *this->priv_push_back_simple_pos();
+ allocator_traits_type::construct
+ ( this->alloc()
+ , this->priv_push_back_simple_pos()
+ , boost::forward<Args>(args)...);
+ this->priv_push_back_simple_commit();
+ return r;
+ }
+ else{
+ typedef dtl::insert_nonmovable_emplace_proxy<Allocator, iterator, Args...> type;
+ return *this->priv_insert_back_aux_impl(1, type(boost::forward<Args>(args)...));
+ }
+ }
+
+ //! <b>Requires</b>: p must be a valid iterator of *this.
+ //!
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... before p
+ //!
+ //! <b>Throws</b>: If memory allocation throws or the in-place constructor throws.
+ //!
+ //! <b>Complexity</b>: If p is end(), amortized constant time
+ //! Linear time otherwise.
+ template <class... Args>
+ iterator emplace(const_iterator p, BOOST_FWD_REF(Args)... args)
+ {
+ BOOST_ASSERT(this->priv_in_range_or_end(p));
+ if(p == this->cbegin()){
+ this->emplace_front(boost::forward<Args>(args)...);
+ return this->begin();
+ }
+ else if(p == this->cend()){
+ this->emplace_back(boost::forward<Args>(args)...);
+ return (this->end()-1);
+ }
+ else{
+ typedef dtl::insert_emplace_proxy<Allocator, iterator, Args...> type;
+ return this->priv_insert_aux_impl(p, 1, type(boost::forward<Args>(args)...));
+ }
+ }
+
+ #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\
+ reference emplace_front(BOOST_MOVE_UREF##N)\
+ {\
+ if(priv_push_front_simple_available()){\
+ reference r = *this->priv_push_front_simple_pos();\
+ 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();\
+ return r;\
+ }\
+ else{\
+ typedef dtl::insert_nonmovable_emplace_proxy##N\
+ <Allocator, iterator BOOST_MOVE_I##N BOOST_MOVE_TARG##N> type;\
+ return *priv_insert_front_aux_impl(1, type(BOOST_MOVE_FWD##N));\
+ }\
+ }\
+ \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N\
+ reference emplace_back(BOOST_MOVE_UREF##N)\
+ {\
+ if(priv_push_back_simple_available()){\
+ reference r = *this->priv_push_back_simple_pos();\
+ 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();\
+ return r;\
+ }\
+ else{\
+ typedef dtl::insert_nonmovable_emplace_proxy##N\
+ <Allocator, iterator BOOST_MOVE_I##N BOOST_MOVE_TARG##N> type;\
+ return *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)\
+ {\
+ BOOST_ASSERT(this->priv_in_range_or_end(p));\
+ 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 dtl::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.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or
+ //! T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Amortized constant time.
+ void push_front(const T &x);
+
+ //! <b>Effects</b>: Constructs a new element in the front of the deque
+ //! and moves the resources of x to this new element.
+ //!
+ //! <b>Throws</b>: If memory allocation throws.
+ //!
+ //! <b>Complexity</b>: Amortized constant time.
+ void push_front(T &&x);
+ #else
+ BOOST_MOVE_CONVERSION_AWARE_CATCH(push_front, T, void, priv_push_front)
+ #endif
+
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ //! <b>Effects</b>: Inserts a copy of x at the end of the deque.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or
+ //! T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Amortized constant time.
+ void push_back(const T &x);
+
+ //! <b>Effects</b>: Constructs a new element in the end of the deque
+ //! and moves the resources of x to this new element.
+ //!
+ //! <b>Throws</b>: If memory allocation throws.
+ //!
+ //! <b>Complexity</b>: Amortized constant time.
+ void push_back(T &&x);
+ #else
+ BOOST_MOVE_CONVERSION_AWARE_CATCH(push_back, T, void, priv_push_back)
+ #endif
+
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ //! <b>Requires</b>: p must be a valid iterator of *this.
+ //!
+ //! <b>Effects</b>: Insert a copy of x before p.
+ //!
+ //! <b>Returns</b>: an iterator to the inserted element.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or x's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: If p is end(), amortized constant time
+ //! Linear time otherwise.
+ iterator insert(const_iterator p, const T &x);
+
+ //! <b>Requires</b>: p must be a valid iterator of *this.
+ //!
+ //! <b>Effects</b>: Insert a new element before p with x's resources.
+ //!
+ //! <b>Returns</b>: an iterator to the inserted element.
+ //!
+ //! <b>Throws</b>: If memory allocation throws.
+ //!
+ //! <b>Complexity</b>: If p is end(), amortized constant time
+ //! Linear time otherwise.
+ iterator insert(const_iterator p, T &&x);
+ #else
+ BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator, const_iterator)
+ #endif
+
+ //! <b>Requires</b>: pos must be a valid iterator of *this.
+ //!
+ //! <b>Effects</b>: Insert n copies of x before pos.
+ //!
+ //! <b>Returns</b>: an iterator to the first inserted element or pos if n is 0.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to n.
+ iterator insert(const_iterator pos, size_type n, const value_type& x)
+ {
+ //Range check of p is done by insert()
+ typedef constant_iterator<value_type, difference_type> c_it;
+ return this->insert(pos, c_it(x, n), c_it());
+ }
+
+ //! <b>Requires</b>: pos must be a valid iterator of *this.
+ //!
+ //! <b>Effects</b>: Insert a copy of the [first, last) range before pos.
+ //!
+ //! <b>Returns</b>: an iterator to the first inserted element or pos if first == last.
+ //!
+ //! <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 distance [first, last).
+ template <class InIt>
+ iterator insert(const_iterator pos, InIt first, InIt last
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename dtl::disable_if_or
+ < void
+ , dtl::is_convertible<InIt, size_type>
+ , dtl::is_not_input_iterator<InIt>
+ >::type * = 0
+ #endif
+ )
+ {
+ BOOST_ASSERT(this->priv_in_range_or_end(pos));
+ size_type n = 0;
+ iterator it(pos.unconst());
+ for(;first != last; ++first, ++n){
+ it = this->emplace(it, *first);
+ ++it;
+ }
+ it -= n;
+ return it;
+ }
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Requires</b>: pos must be a valid iterator of *this.
+ //!
+ //! <b>Effects</b>: Insert a copy of the [il.begin(), il.end()) range before pos.
+ //!
+ //! <b>Returns</b>: an iterator to the first inserted element or pos if il.begin() == il.end().
+ //!
+ //! <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 distance [il.begin(), il.end()).
+ iterator insert(const_iterator pos, std::initializer_list<value_type> il)
+ {
+ //Range check os pos is done in insert()
+ return insert(pos, il.begin(), il.end());
+ }
+#endif
+
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ template <class FwdIt>
+ iterator insert(const_iterator p, FwdIt first, FwdIt last
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename dtl::disable_if_or
+ < void
+ , dtl::is_convertible<FwdIt, size_type>
+ , dtl::is_input_iterator<FwdIt>
+ >::type * = 0
+ #endif
+ )
+ {
+ BOOST_ASSERT(this->priv_in_range_or_end(p));
+ dtl::insert_range_proxy<Allocator, FwdIt, iterator> proxy(first);
+ return priv_insert_aux_impl(p, boost::container::iterator_distance(first, last), proxy);
+ }
+ #endif
+
+ //! <b>Effects</b>: Removes the first element from the deque.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant time.
+ void pop_front() BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(!this->empty());
+ if (this->members_.m_start.m_cur != this->members_.m_start.m_last - 1) {
+ allocator_traits_type::destroy
+ ( this->alloc()
+ , boost::movelib::to_raw_pointer(this->members_.m_start.m_cur)
+ );
+ ++this->members_.m_start.m_cur;
+ }
+ else
+ this->priv_pop_front_aux();
+ }
+
+ //! <b>Effects</b>: Removes the last element from the deque.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant time.
+ void pop_back() BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(!this->empty());
+ if (this->members_.m_finish.m_cur != this->members_.m_finish.m_first) {
+ --this->members_.m_finish.m_cur;
+ allocator_traits_type::destroy
+ ( this->alloc()
+ , boost::movelib::to_raw_pointer(this->members_.m_finish.m_cur)
+ );
+ }
+ else
+ this->priv_pop_back_aux();
+ }
+
+ //! <b>Effects</b>: Erases the element at p.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Linear to the elements between pos and the
+ //! 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_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(this->priv_in_range(pos));
+ iterator next = pos.unconst();
+ ++next;
+ size_type index = pos - this->members_.m_start;
+ if (index < (this->size()/2)) {
+ boost::container::move_backward(this->begin(), pos.unconst(), next);
+ pop_front();
+ }
+ else {
+ boost::container::move(next, this->end(), pos.unconst());
+ pop_back();
+ }
+ return this->members_.m_start + index;
+ }
+
+ //! <b>Effects</b>: Erases the elements pointed by [first, last).
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Linear to the distance between first and
+ //! 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_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(first == last ||
+ (first < last && this->priv_in_range(first) && this->priv_in_range_or_end(last)));
+ if (first == this->members_.m_start && last == this->members_.m_finish) {
+ this->clear();
+ return this->members_.m_finish;
+ }
+ else {
+ 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::container::move_backward(begin(), first.unconst(), last.unconst());
+ iterator new_start = this->members_.m_start + n;
+ this->priv_destroy_range(this->members_.m_start, new_start);
+ this->priv_destroy_nodes(this->members_.m_start.m_node, new_start.m_node);
+ this->members_.m_start = new_start;
+ }
+ else {
+ boost::container::move(last.unconst(), end(), first.unconst());
+ iterator new_finish = this->members_.m_finish - n;
+ this->priv_destroy_range(new_finish, this->members_.m_finish);
+ this->priv_destroy_nodes(new_finish.m_node + 1, this->members_.m_finish.m_node + 1);
+ this->members_.m_finish = new_finish;
+ }
+ return this->members_.m_start + elems_before;
+ }
+ }
+
+ //! <b>Effects</b>: Swaps the contents of *this and x.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <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);
+ dtl::bool_<allocator_traits_type::propagate_on_container_swap::value> flag;
+ dtl::swap_alloc(this->alloc(), x.alloc(), flag);
+ dtl::swap_alloc(this->ptr_alloc(), x.ptr_alloc(), flag);
+ }
+
+ //! <b>Effects</b>: Erases all the elements of the deque.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the deque.
+ void clear() BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ for (index_pointer node = this->members_.m_start.m_node + 1;
+ node < this->members_.m_finish.m_node;
+ ++node) {
+ this->priv_destroy_range(*node, *node + this->s_buffer_size());
+ this->priv_deallocate_node(*node);
+ }
+
+ if (this->members_.m_start.m_node != this->members_.m_finish.m_node) {
+ this->priv_destroy_range(this->members_.m_start.m_cur, this->members_.m_start.m_last);
+ this->priv_destroy_range(this->members_.m_finish.m_first, this->members_.m_finish.m_cur);
+ this->priv_deallocate_node(this->members_.m_finish.m_first);
+ }
+ else
+ this->priv_destroy_range(this->members_.m_start.m_cur, this->members_.m_finish.m_cur);
+
+ this->members_.m_finish = this->members_.m_start;
+ }
+
+ //! <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 deque& x, const deque& y)
+ { return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin()); }
+
+ //! <b>Effects</b>: Returns true if x and y are unequal
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator!=(const deque& x, const deque& y)
+ { return !(x == y); }
+
+ //! <b>Effects</b>: Returns true if x is less than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator<(const deque& x, const deque& y)
+ { return ::boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
+
+ //! <b>Effects</b>: Returns true if x is greater than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator>(const deque& x, const deque& y)
+ { return y < x; }
+
+ //! <b>Effects</b>: Returns true if x is equal or less than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator<=(const deque& x, const deque& y)
+ { return !(y < x); }
+
+ //! <b>Effects</b>: Returns true if x is equal or greater than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator>=(const deque& x, const deque& y)
+ { return !(x < y); }
+
+ //! <b>Effects</b>: x.swap(y)
+ //!
+ //! <b>Complexity</b>: Constant.
+ friend void swap(deque& x, deque& y)
+ { x.swap(y); }
+
+ #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()) {
+ this->clear();
+ }
+ else {
+ iterator new_finish = this->members_.m_finish - n;
+ this->priv_destroy_range(new_finish, this->members_.m_finish);
+ this->priv_destroy_nodes(new_finish.m_node + 1, this->members_.m_finish.m_node + 1);
+ this->members_.m_finish = new_finish;
+ }
+ }
+
+ void priv_throw_if_out_of_range(size_type n) const
+ {
+ if (n >= this->size())
+ throw_out_of_range("deque::at out of range");
+ }
+
+ bool priv_in_range(const_iterator pos) const
+ {
+ return (this->begin() <= pos) && (pos < this->end());
+ }
+
+ bool priv_in_range_or_end(const_iterator pos) const
+ {
+ return (this->begin() <= pos) && (pos <= this->end());
+ }
+
+ template <class U>
+ iterator priv_insert(const_iterator p, BOOST_FWD_REF(U) x)
+ {
+ BOOST_ASSERT(this->priv_in_range_or_end(p));
+ if (p == cbegin()){
+ this->push_front(::boost::forward<U>(x));
+ return begin();
+ }
+ else if (p == cend()){
+ this->push_back(::boost::forward<U>(x));
+ return --end();
+ }
+ else {
+ return priv_insert_aux_impl
+ ( p, (size_type)1
+ , dtl::get_insert_value_proxy<iterator, Allocator>(::boost::forward<U>(x)));
+ }
+ }
+
+ template <class U>
+ void priv_push_front(BOOST_FWD_REF(U) x)
+ {
+ if(this->priv_push_front_simple_available()){
+ allocator_traits_type::construct
+ ( this->alloc(), this->priv_push_front_simple_pos(), ::boost::forward<U>(x));
+ this->priv_push_front_simple_commit();
+ }
+ else{
+ priv_insert_aux_impl
+ ( this->cbegin(), (size_type)1
+ , dtl::get_insert_value_proxy<iterator, Allocator>(::boost::forward<U>(x)));
+ }
+ }
+
+ template <class U>
+ void priv_push_back(BOOST_FWD_REF(U) x)
+ {
+ if(this->priv_push_back_simple_available()){
+ allocator_traits_type::construct
+ ( this->alloc(), this->priv_push_back_simple_pos(), ::boost::forward<U>(x));
+ this->priv_push_back_simple_commit();
+ }
+ else{
+ priv_insert_aux_impl
+ ( this->cend(), (size_type)1
+ , dtl::get_insert_value_proxy<iterator, Allocator>(::boost::forward<U>(x)));
+ }
+ }
+
+ bool priv_push_back_simple_available() const
+ {
+ return this->members_.m_map &&
+ (this->members_.m_finish.m_cur != (this->members_.m_finish.m_last - 1));
+ }
+
+ T *priv_push_back_simple_pos() const
+ {
+ return boost::movelib::to_raw_pointer(this->members_.m_finish.m_cur);
+ }
+
+ void priv_push_back_simple_commit()
+ {
+ ++this->members_.m_finish.m_cur;
+ }
+
+ bool priv_push_front_simple_available() const
+ {
+ return this->members_.m_map &&
+ (this->members_.m_start.m_cur != this->members_.m_start.m_first);
+ }
+
+ T *priv_push_front_simple_pos() const
+ { return boost::movelib::to_raw_pointer(this->members_.m_start.m_cur) - 1; }
+
+ void priv_push_front_simple_commit()
+ { --this->members_.m_start.m_cur; }
+
+ void priv_destroy_range(iterator p, iterator p2)
+ {
+ if(!Base::traits_t::trivial_dctr){
+ for(;p != p2; ++p){
+ allocator_traits_type::destroy(this->alloc(), boost::movelib::iterator_to_raw_pointer(p));
+ }
+ }
+ }
+
+ void priv_destroy_range(pointer p, pointer p2)
+ {
+ if(!Base::traits_t::trivial_dctr){
+ for(;p != p2; ++p){
+ allocator_traits_type::destroy(this->alloc(), boost::movelib::iterator_to_raw_pointer(p));
+ }
+ }
+ }
+
+ template<class InsertProxy>
+ iterator priv_insert_aux_impl(const_iterator p, size_type n, InsertProxy proxy)
+ {
+ iterator pos(p.unconst());
+ const size_type pos_n = p - this->cbegin();
+ if(!this->members_.m_map){
+ this->priv_initialize_map(0);
+ pos = this->begin();
+ }
+
+ const size_type elemsbefore = static_cast<size_type>(pos - this->members_.m_start);
+ const size_type length = this->size();
+ if (elemsbefore < length / 2) {
+ const iterator new_start = this->priv_reserve_elements_at_front(n);
+ const iterator old_start = this->members_.m_start;
+ if(!elemsbefore){
+ proxy.uninitialized_copy_n_and_update(this->alloc(), new_start, n);
+ this->members_.m_start = new_start;
+ }
+ else{
+ pos = this->members_.m_start + elemsbefore;
+ if (elemsbefore >= n) {
+ const iterator start_n = this->members_.m_start + n;
+ ::boost::container::uninitialized_move_alloc
+ (this->alloc(), this->members_.m_start, start_n, new_start);
+ this->members_.m_start = new_start;
+ boost::container::move(start_n, pos, old_start);
+ proxy.copy_n_and_update(this->alloc(), pos - n, n);
+ }
+ else {
+ const size_type mid_count = n - elemsbefore;
+ const iterator mid_start = old_start - mid_count;
+ proxy.uninitialized_copy_n_and_update(this->alloc(), mid_start, mid_count);
+ this->members_.m_start = mid_start;
+ ::boost::container::uninitialized_move_alloc
+ (this->alloc(), old_start, pos, new_start);
+ this->members_.m_start = new_start;
+ proxy.copy_n_and_update(this->alloc(), old_start, elemsbefore);
+ }
+ }
+ }
+ else {
+ const iterator new_finish = this->priv_reserve_elements_at_back(n);
+ const iterator old_finish = this->members_.m_finish;
+ const size_type elemsafter = length - elemsbefore;
+ if(!elemsafter){
+ proxy.uninitialized_copy_n_and_update(this->alloc(), old_finish, n);
+ this->members_.m_finish = new_finish;
+ }
+ else{
+ pos = old_finish - elemsafter;
+ if (elemsafter >= n) {
+ iterator finish_n = old_finish - difference_type(n);
+ ::boost::container::uninitialized_move_alloc
+ (this->alloc(), finish_n, old_finish, old_finish);
+ this->members_.m_finish = new_finish;
+ boost::container::move_backward(pos, finish_n, old_finish);
+ proxy.copy_n_and_update(this->alloc(), pos, n);
+ }
+ else {
+ const size_type raw_gap = n - elemsafter;
+ ::boost::container::uninitialized_move_alloc
+ (this->alloc(), pos, old_finish, old_finish + raw_gap);
+ BOOST_TRY{
+ proxy.copy_n_and_update(this->alloc(), pos, elemsafter);
+ proxy.uninitialized_copy_n_and_update(this->alloc(), old_finish, raw_gap);
+ }
+ BOOST_CATCH(...){
+ this->priv_destroy_range(old_finish, old_finish + elemsafter);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ this->members_.m_finish = new_finish;
+ }
+ }
+ }
+ return this->begin() + pos_n;
+ }
+
+ template <class InsertProxy>
+ iterator priv_insert_back_aux_impl(size_type n, InsertProxy proxy)
+ {
+ if(!this->members_.m_map){
+ this->priv_initialize_map(0);
+ }
+
+ iterator new_finish = this->priv_reserve_elements_at_back(n);
+ iterator old_finish = this->members_.m_finish;
+ proxy.uninitialized_copy_n_and_update(this->alloc(), old_finish, n);
+ this->members_.m_finish = new_finish;
+ return iterator(this->members_.m_finish - n);
+ }
+
+ template <class InsertProxy>
+ iterator priv_insert_front_aux_impl(size_type n, InsertProxy proxy)
+ {
+ if(!this->members_.m_map){
+ this->priv_initialize_map(0);
+ }
+
+ iterator new_start = this->priv_reserve_elements_at_front(n);
+ proxy.uninitialized_copy_n_and_update(this->alloc(), new_start, n);
+ this->members_.m_start = new_start;
+ return new_start;
+ }
+
+ iterator priv_fill_insert(const_iterator pos, size_type n, const value_type& x)
+ {
+ typedef constant_iterator<value_type, difference_type> c_it;
+ return this->insert(pos, c_it(x, n), c_it());
+ }
+
+ // Precondition: this->members_.m_start and this->members_.m_finish have already been initialized,
+ // but none of the deque's elements have yet been constructed.
+ void priv_fill_initialize(const value_type& value)
+ {
+ index_pointer cur = this->members_.m_start.m_node;
+ BOOST_TRY {
+ for ( ; cur < this->members_.m_finish.m_node; ++cur){
+ boost::container::uninitialized_fill_alloc
+ (this->alloc(), *cur, *cur + this->s_buffer_size(), value);
+ }
+ boost::container::uninitialized_fill_alloc
+ (this->alloc(), this->members_.m_finish.m_first, this->members_.m_finish.m_cur, value);
+ }
+ BOOST_CATCH(...){
+ this->priv_destroy_range(this->members_.m_start, iterator(*cur, cur));
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ }
+
+ template <class InIt>
+ void priv_range_initialize(InIt first, InIt last, typename iterator_enable_if_tag<InIt, std::input_iterator_tag>::type* =0)
+ {
+ this->priv_initialize_map(0);
+ BOOST_TRY {
+ for ( ; first != last; ++first)
+ this->emplace_back(*first);
+ }
+ BOOST_CATCH(...){
+ this->clear();
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ }
+
+ template <class FwdIt>
+ void priv_range_initialize(FwdIt first, FwdIt last, typename iterator_disable_if_tag<FwdIt, std::input_iterator_tag>::type* =0)
+ {
+ size_type n = 0;
+ n = boost::container::iterator_distance(first, last);
+ this->priv_initialize_map(n);
+
+ index_pointer cur_node = this->members_.m_start.m_node;
+ BOOST_TRY {
+ for (; cur_node < this->members_.m_finish.m_node; ++cur_node) {
+ FwdIt mid = first;
+ boost::container::iterator_advance(mid, this->s_buffer_size());
+ ::boost::container::uninitialized_copy_alloc(this->alloc(), first, mid, *cur_node);
+ first = mid;
+ }
+ ::boost::container::uninitialized_copy_alloc(this->alloc(), first, last, this->members_.m_finish.m_first);
+ }
+ BOOST_CATCH(...){
+ this->priv_destroy_range(this->members_.m_start, iterator(*cur_node, cur_node));
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ }
+
+ // Called only if this->members_.m_finish.m_cur == this->members_.m_finish.m_first.
+ 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);
+ this->members_.m_finish.m_cur = this->members_.m_finish.m_last - 1;
+ allocator_traits_type::destroy
+ ( this->alloc()
+ , boost::movelib::to_raw_pointer(this->members_.m_finish.m_cur)
+ );
+ }
+
+ // Called only if this->members_.m_start.m_cur == this->members_.m_start.m_last - 1. Note that
+ // 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_NOEXCEPT_OR_NOTHROW
+ {
+ allocator_traits_type::destroy
+ ( this->alloc()
+ , boost::movelib::to_raw_pointer(this->members_.m_start.m_cur)
+ );
+ this->priv_deallocate_node(this->members_.m_start.m_first);
+ this->members_.m_start.priv_set_node(this->members_.m_start.m_node + 1);
+ this->members_.m_start.m_cur = this->members_.m_start.m_first;
+ }
+
+ iterator priv_reserve_elements_at_front(size_type n)
+ {
+ size_type vacancies = this->members_.m_start.m_cur - this->members_.m_start.m_first;
+ if (n > vacancies){
+ size_type new_elems = n-vacancies;
+ size_type new_nodes = (new_elems + this->s_buffer_size() - 1) /
+ this->s_buffer_size();
+ size_type s = (size_type)(this->members_.m_start.m_node - this->members_.m_map);
+ if (new_nodes > s){
+ this->priv_reallocate_map(new_nodes, true);
+ }
+ size_type i = 1;
+ BOOST_TRY {
+ for (; i <= new_nodes; ++i)
+ *(this->members_.m_start.m_node - i) = this->priv_allocate_node();
+ }
+ BOOST_CATCH(...) {
+ for (size_type j = 1; j < i; ++j)
+ this->priv_deallocate_node(*(this->members_.m_start.m_node - j));
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ }
+ return this->members_.m_start - difference_type(n);
+ }
+
+ iterator priv_reserve_elements_at_back(size_type n)
+ {
+ size_type vacancies = (this->members_.m_finish.m_last - this->members_.m_finish.m_cur) - 1;
+ if (n > vacancies){
+ size_type new_elems = n - vacancies;
+ size_type new_nodes = (new_elems + this->s_buffer_size() - 1)/s_buffer_size();
+ size_type s = (size_type)(this->members_.m_map_size - (this->members_.m_finish.m_node - this->members_.m_map));
+ if (new_nodes + 1 > s){
+ this->priv_reallocate_map(new_nodes, false);
+ }
+ size_type i = 1;
+ BOOST_TRY {
+ for (; i <= new_nodes; ++i)
+ *(this->members_.m_finish.m_node + i) = this->priv_allocate_node();
+ }
+ BOOST_CATCH(...) {
+ for (size_type j = 1; j < i; ++j)
+ this->priv_deallocate_node(*(this->members_.m_finish.m_node + j));
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ }
+ return this->members_.m_finish + difference_type(n);
+ }
+
+ void priv_reallocate_map(size_type nodes_to_add, bool add_at_front)
+ {
+ size_type old_num_nodes = this->members_.m_finish.m_node - this->members_.m_start.m_node + 1;
+ size_type new_num_nodes = old_num_nodes + nodes_to_add;
+
+ index_pointer new_nstart;
+ if (this->members_.m_map_size > 2 * new_num_nodes) {
+ 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::container::move(this->members_.m_start.m_node, this->members_.m_finish.m_node + 1, new_nstart);
+ else
+ boost::container::move_backward
+ (this->members_.m_start.m_node, this->members_.m_finish.m_node + 1, new_nstart + old_num_nodes);
+ }
+ else {
+ size_type new_map_size =
+ this->members_.m_map_size + dtl::max_value(this->members_.m_map_size, nodes_to_add) + 2;
+
+ 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::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;
+ this->members_.m_map_size = new_map_size;
+ }
+
+ this->members_.m_start.priv_set_node(new_nstart);
+ this->members_.m_finish.priv_set_node(new_nstart + old_num_nodes - 1);
+ }
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+};
+
+#if __cplusplus >= 201703L
+template <typename InputIterator>
+deque(InputIterator, InputIterator) -> deque<typename iterator_traits<InputIterator>::value_type>;
+template <typename InputIterator, typename Allocator>
+deque(InputIterator, InputIterator, Allocator const&) -> deque<typename iterator_traits<InputIterator>::value_type, Allocator>;
+#endif
+
+}}
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+namespace boost {
+
+//!has_trivial_destructor_after_move<> == true_type
+//!specialization for optimizations
+template <class T, class Allocator>
+struct has_trivial_destructor_after_move<boost::container::deque<T, Allocator> >
+{
+ typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer;
+ static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value &&
+ ::boost::has_trivial_destructor_after_move<pointer>::value;
+};
+
+}
+
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif // #ifndef BOOST_CONTAINER_DEQUE_HPP
diff --git a/include/boost/container/detail/adaptive_node_pool.hpp b/include/boost/container/detail/adaptive_node_pool.hpp
new file mode 100644
index 0000000..d14e865
--- /dev/null
+++ b/include/boost/container/detail/adaptive_node_pool.hpp
@@ -0,0 +1,169 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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_ADAPTIVE_NODE_POOL_HPP
+#define BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_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/intrusive/set.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>
+
+
+namespace boost {
+namespace container {
+namespace dtl {
+
+//!Pooled memory allocator using an smart adaptive pool. Includes
+//!a reference count but the class does not delete itself, this is
+//!responsibility of user classes. Node size (NodeSize) and the number of
+//!nodes allocated per block (NodesPerBlock) are known at compile time.
+template< std::size_t NodeSize
+ , std::size_t NodesPerBlock
+ , std::size_t MaxFreeBlocks
+ , std::size_t OverheadPercent
+ >
+class private_adaptive_node_pool
+ : public private_adaptive_node_pool_impl_ct
+ < fake_segment_manager
+ , MaxFreeBlocks
+ , NodeSize
+ , NodesPerBlock
+ , OverheadPercent
+ , unsigned(OverheadPercent == 0)*::boost::container::adaptive_pool_flag::align_only
+ | ::boost::container::adaptive_pool_flag::size_ordered
+ | ::boost::container::adaptive_pool_flag::address_ordered
+ >
+{
+ typedef private_adaptive_node_pool_impl_ct
+ < fake_segment_manager
+ , MaxFreeBlocks
+ , NodeSize
+ , NodesPerBlock
+ , OverheadPercent
+ , unsigned(OverheadPercent == 0)*::boost::container::adaptive_pool_flag::align_only
+ | ::boost::container::adaptive_pool_flag::size_ordered
+ | ::boost::container::adaptive_pool_flag::address_ordered
+ > base_t;
+
+ //Non-copyable
+ private_adaptive_node_pool(const private_adaptive_node_pool &);
+ private_adaptive_node_pool &operator=(const private_adaptive_node_pool &);
+
+ public:
+ static const std::size_t nodes_per_block = NodesPerBlock;
+
+ //!Constructor. Never throws
+ private_adaptive_node_pool()
+ : base_t(0)
+ {}
+};
+
+//!Pooled memory allocator using adaptive pool. Includes
+//!a reference count but the class does not delete itself, this is
+//!responsibility of user classes. Node size (NodeSize) and the number of
+//!nodes allocated per block (NodesPerBlock) are known at compile time
+template< std::size_t NodeSize
+ , std::size_t NodesPerBlock
+ , std::size_t MaxFreeBlocks
+ , std::size_t OverheadPercent
+ >
+class shared_adaptive_node_pool
+ : public private_adaptive_node_pool
+ <NodeSize, NodesPerBlock, MaxFreeBlocks, OverheadPercent>
+{
+ private:
+ typedef private_adaptive_node_pool
+ <NodeSize, NodesPerBlock, MaxFreeBlocks, OverheadPercent> private_node_allocator_t;
+ public:
+ typedef typename private_node_allocator_t::multiallocation_chain multiallocation_chain;
+
+ //!Constructor. Never throws
+ shared_adaptive_node_pool()
+ : private_node_allocator_t(){}
+
+ //!Destructor. Deallocates all allocated blocks. Never throws
+ ~shared_adaptive_node_pool()
+ {}
+
+ //!Allocates array of count elements. Can throw std::bad_alloc
+ void *allocate_node()
+ {
+ //-----------------------
+ scoped_lock<default_mutex> guard(mutex_);
+ //-----------------------
+ return private_node_allocator_t::allocate_node();
+ }
+
+ //!Deallocates an array pointed by ptr. Never throws
+ void deallocate_node(void *ptr)
+ {
+ //-----------------------
+ scoped_lock<default_mutex> guard(mutex_);
+ //-----------------------
+ private_node_allocator_t::deallocate_node(ptr);
+ }
+
+ //!Allocates a singly linked list of n nodes ending in null pointer.
+ //!can throw std::bad_alloc
+ void allocate_nodes(const std::size_t n, multiallocation_chain &chain)
+ {
+ //-----------------------
+ scoped_lock<default_mutex> guard(mutex_);
+ //-----------------------
+ return private_node_allocator_t::allocate_nodes(n, chain);
+ }
+
+ void deallocate_nodes(multiallocation_chain &chain)
+ {
+ //-----------------------
+ scoped_lock<default_mutex> guard(mutex_);
+ //-----------------------
+ private_node_allocator_t::deallocate_nodes(chain);
+ }
+
+ //!Deallocates all the free blocks of memory. Never throws
+ void deallocate_free_blocks()
+ {
+ //-----------------------
+ scoped_lock<default_mutex> guard(mutex_);
+ //-----------------------
+ private_node_allocator_t::deallocate_free_blocks();
+ }
+
+ private:
+ default_mutex mutex_;
+};
+
+} //namespace dtl {
+} //namespace container {
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_HPP
diff --git a/include/boost/container/detail/adaptive_node_pool_impl.hpp b/include/boost/container/detail/adaptive_node_pool_impl.hpp
new file mode 100644
index 0000000..a92ba98
--- /dev/null
+++ b/include/boost/container/detail/adaptive_node_pool_impl.hpp
@@ -0,0 +1,1259 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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_ADAPTIVE_NODE_POOL_IMPL_HPP
+#define BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_IMPL_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+
+// container
+#include <boost/container/container_fwd.hpp>
+#include <boost/container/throw_exception.hpp>
+// container/detail
+#include <boost/container/detail/pool_common.hpp>
+#include <boost/container/detail/iterator.hpp>
+#include <boost/move/detail/iterator_to_raw_pointer.hpp>
+#include <boost/container/detail/math_functions.hpp>
+#include <boost/container/detail/mpl.hpp>
+#include <boost/move/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>
+// other
+#include <boost/assert.hpp>
+#include <boost/core/no_exceptions_support.hpp>
+#include <cstddef>
+
+namespace boost {
+namespace container {
+
+namespace adaptive_pool_flag {
+
+static const unsigned int none = 0u;
+static const unsigned int align_only = 1u << 0u;
+static const unsigned int size_ordered = 1u << 1u;
+static const unsigned int address_ordered = 1u << 2u;
+
+} //namespace adaptive_pool_flag{
+
+namespace dtl {
+
+template<class size_type>
+struct hdr_offset_holder_t
+{
+ hdr_offset_holder_t(size_type offset = 0)
+ : hdr_offset(offset)
+ {}
+ size_type hdr_offset;
+};
+
+template<class SizeType, unsigned int Flags>
+struct less_func;
+
+template<class SizeType>
+struct less_func<SizeType, adaptive_pool_flag::none>
+{
+ static bool less(SizeType, SizeType, const void *, const void *)
+ { return true; }
+};
+
+template<class SizeType>
+struct less_func<SizeType, adaptive_pool_flag::size_ordered>
+{
+ static bool less(SizeType ls, SizeType rs, const void *, const void *)
+ { return ls < rs; }
+};
+
+template<class SizeType>
+struct less_func<SizeType, adaptive_pool_flag::address_ordered>
+{
+ static bool less(SizeType, SizeType, const void *la, const void *ra)
+ { return la < ra; }
+};
+
+template<class SizeType>
+struct less_func<SizeType, adaptive_pool_flag::size_ordered | adaptive_pool_flag::address_ordered>
+{
+ static bool less(SizeType ls, SizeType rs, const void *la, const void *ra)
+ { return (ls < rs) || ((ls == rs) && (la < ra)); }
+};
+
+template<class VoidPointer, class SizeType, unsigned OrderFlags>
+struct block_container_traits
+{
+ typedef typename bi::make_set_base_hook
+ < bi::void_pointer<VoidPointer>
+ , bi::optimize_size<true>
+ , bi::link_mode<bi::normal_link> >::type hook_t;
+
+ template<class T>
+ struct container
+ {
+ typedef typename bi::make_multiset
+ <T, bi::base_hook<hook_t>, bi::size_type<SizeType> >::type type;
+ };
+
+ template<class Container>
+ static void reinsert_was_used(Container &container, typename Container::reference v, bool)
+ {
+ typedef typename Container::const_iterator const_block_iterator;
+ typedef typename Container::iterator block_iterator;
+ typedef typename Container::value_compare value_compare;
+
+ const block_iterator this_block(Container::s_iterator_to(v));
+ const const_block_iterator cendit(container.cend());
+ block_iterator next_block(this_block);
+
+ if(++next_block != cendit && value_compare()(*next_block, v)){
+ const_block_iterator next2_block(next_block);
+ //Test if v should be swapped with next (optimization)
+ if(++next2_block == cendit || !value_compare()(*next2_block, v)){
+ v.swap_nodes(*next_block);
+ BOOST_ASSERT(++next_block == this_block);
+ }
+ else{
+ container.erase(this_block);
+ container.insert(v);
+ }
+ }
+ }
+
+ template<class Container>
+ static void insert_was_empty(Container &container, typename Container::value_type &v, bool)
+ {
+ container.insert(v);
+ }
+
+ template<class Container>
+ static void erase_first(Container &container)
+ {
+ container.erase(container.cbegin());
+ }
+
+ template<class Container>
+ static void erase_last(Container &container)
+ {
+ container.erase(--container.cend());
+ }
+};
+
+template<class VoidPointer, class SizeType>
+struct block_container_traits<VoidPointer, SizeType, 0u>
+{
+ typedef typename bi::make_list_base_hook
+ < bi::void_pointer<VoidPointer>
+ , bi::link_mode<bi::normal_link> >::type hook_t;
+
+ template<class T>
+ struct container
+ {
+ typedef typename bi::make_list
+ <T, bi::base_hook<hook_t>, bi::size_type<SizeType>, bi::constant_time_size<false> >::type type;
+ };
+
+ template<class Container>
+ static void reinsert_was_used(Container &container, typename Container::value_type &v, bool is_full)
+ {
+ if(is_full){
+ container.erase(Container::s_iterator_to(v));
+ container.push_back(v);
+ }
+ }
+
+ template<class Container>
+ static void insert_was_empty(Container &container, typename Container::value_type &v, bool is_full)
+ {
+ if(is_full){
+ container.push_back(v);
+ }
+ else{
+ container.push_front(v);
+ }
+ }
+
+ template<class Container>
+ static void erase_first(Container &container)
+ {
+ container.pop_front();
+ }
+
+ template<class Container>
+ static void erase_last(Container &container)
+ {
+ container.pop_back();
+ }
+};
+
+/////////////////////////////
+//
+// adaptive_pool_types
+//
+/////////////////////////////
+template<class MultiallocationChain, class VoidPointer, class SizeType, unsigned int Flags>
+struct adaptive_pool_types
+{
+ typedef VoidPointer void_pointer;
+ static const unsigned ordered = (Flags & (adaptive_pool_flag::size_ordered | adaptive_pool_flag::address_ordered));
+ typedef block_container_traits<VoidPointer, SizeType, ordered> block_container_traits_t;
+ typedef typename block_container_traits_t::hook_t hook_t;
+ typedef hdr_offset_holder_t<SizeType> hdr_offset_holder;
+ static const unsigned int order_flags = Flags & (adaptive_pool_flag::size_ordered | adaptive_pool_flag::address_ordered);
+ typedef MultiallocationChain free_nodes_t;
+
+ struct block_info_t
+ : public hdr_offset_holder,
+ public hook_t
+ {
+ //An intrusive list of free node from this block
+ free_nodes_t free_nodes;
+ friend bool operator <(const block_info_t &l, const block_info_t &r)
+ {
+ return less_func<SizeType, order_flags>::
+ less(l.free_nodes.size(), r.free_nodes.size(), &l , &r);
+ }
+
+ friend bool operator ==(const block_info_t &l, const block_info_t &r)
+ { return &l == &r; }
+ };
+ typedef typename block_container_traits_t:: template container<block_info_t>::type block_container_t;
+};
+
+
+/////////////////////////////////////////////
+//
+// candidate_power_of_2_ct
+//
+/////////////////////////////////////////////
+template< std::size_t alignment
+ , std::size_t real_node_size
+ , std::size_t payload_per_allocation
+ , std::size_t min_elements_per_block
+ , std::size_t hdr_size
+ , std::size_t hdr_offset_size
+ , std::size_t overhead_percent>
+struct candidate_power_of_2_ct_helper
+{
+ static const std::size_t hdr_subblock_elements_alone = (alignment - hdr_size - payload_per_allocation)/real_node_size;
+ static const std::size_t hdr_subblock_elements_first = (alignment - hdr_size - payload_per_allocation)/real_node_size;
+ static const std::size_t elements_per_b_subblock_mid = (alignment - hdr_offset_size)/real_node_size;
+ static const std::size_t elements_per_b_subblock_end = (alignment - hdr_offset_size - payload_per_allocation)/real_node_size;
+ static const std::size_t num_b_subblock =
+ hdr_subblock_elements_alone >= min_elements_per_block
+ ? 0
+ : ( ((hdr_subblock_elements_first + elements_per_b_subblock_end) >= min_elements_per_block)
+ ? 1
+ : 2 + (min_elements_per_block - hdr_subblock_elements_first - elements_per_b_subblock_end - 1)/elements_per_b_subblock_mid
+ )
+ ;
+
+ static const std::size_t num_b_subblock_mid = (num_b_subblock > 1) ? (num_b_subblock - 1) : 0;
+
+ static const std::size_t total_nodes = (num_b_subblock == 0)
+ ? hdr_subblock_elements_alone
+ : ( (num_b_subblock == 1)
+ ? (hdr_subblock_elements_first + elements_per_b_subblock_end)
+ : (hdr_subblock_elements_first + num_b_subblock_mid*elements_per_b_subblock_mid + elements_per_b_subblock_end)
+ )
+ ;
+ static const std::size_t total_data = total_nodes*real_node_size;
+ static const std::size_t total_size = alignment*(num_b_subblock+1);
+ static const bool overhead_satisfied = (total_size - total_data)*100/total_size < overhead_percent;
+};
+
+template< std::size_t initial_alignment
+ , std::size_t real_node_size
+ , std::size_t payload_per_allocation
+ , std::size_t min_elements_per_block
+ , std::size_t hdr_size
+ , std::size_t hdr_offset_size
+ , std::size_t overhead_percent
+ , bool Loop = true>
+struct candidate_power_of_2_ct
+{
+ typedef candidate_power_of_2_ct_helper
+ < initial_alignment
+ , real_node_size
+ , payload_per_allocation
+ , min_elements_per_block
+ , hdr_size
+ , hdr_offset_size
+ , overhead_percent> helper_t;
+
+ static const std::size_t candidate_power_of_2 = initial_alignment << std::size_t(!helper_t::overhead_satisfied);
+
+ typedef typename candidate_power_of_2_ct
+ < candidate_power_of_2
+ , real_node_size
+ , payload_per_allocation
+ , min_elements_per_block
+ , hdr_size
+ , hdr_offset_size
+ , overhead_percent
+ , !helper_t::overhead_satisfied
+ >::type type;
+
+ static const std::size_t alignment = type::alignment;
+ static const std::size_t num_subblocks = type::num_subblocks;
+ static const std::size_t real_num_node = type::real_num_node;
+};
+
+template< std::size_t initial_alignment
+ , std::size_t real_node_size
+ , std::size_t payload_per_allocation
+ , std::size_t min_elements_per_block
+ , std::size_t hdr_size
+ , std::size_t hdr_offset_size
+ , std::size_t overhead_percent
+ >
+struct candidate_power_of_2_ct
+ < initial_alignment
+ , real_node_size
+ , payload_per_allocation
+ , min_elements_per_block
+ , hdr_size
+ , hdr_offset_size
+ , overhead_percent
+ , false>
+{
+ typedef candidate_power_of_2_ct
+ < initial_alignment
+ , real_node_size
+ , payload_per_allocation
+ , min_elements_per_block
+ , hdr_size
+ , hdr_offset_size
+ , overhead_percent
+ , false> type;
+
+ typedef candidate_power_of_2_ct_helper
+ < initial_alignment
+ , real_node_size
+ , payload_per_allocation
+ , min_elements_per_block
+ , hdr_size
+ , hdr_offset_size
+ , overhead_percent> helper_t;
+
+ static const std::size_t alignment = initial_alignment;
+ static const std::size_t num_subblocks = helper_t::num_b_subblock+1;
+ static const std::size_t real_num_node = helper_t::total_nodes;
+};
+
+/////////////////////////////////////////////
+//
+// candidate_power_of_2_rt
+//
+/////////////////////////////////////////////
+void candidate_power_of_2_rt ( std::size_t initial_alignment
+ , std::size_t real_node_size
+ , std::size_t payload_per_allocation
+ , std::size_t min_elements_per_block
+ , std::size_t hdr_size
+ , std::size_t hdr_offset_size
+ , std::size_t overhead_percent
+ , std::size_t &alignment
+ , std::size_t &num_subblocks
+ , std::size_t &real_num_node)
+{
+ bool overhead_satisfied = false;
+ std::size_t num_b_subblock = 0;
+ std::size_t total_nodes = 0;
+
+ while(!overhead_satisfied)
+ {
+ std::size_t hdr_subblock_elements_alone = (initial_alignment - hdr_size - payload_per_allocation)/real_node_size;
+ std::size_t hdr_subblock_elements_first = (initial_alignment - hdr_size - payload_per_allocation)/real_node_size;
+ std::size_t elements_per_b_subblock_mid = (initial_alignment - hdr_offset_size)/real_node_size;
+ std::size_t elements_per_b_subblock_end = (initial_alignment - hdr_offset_size - payload_per_allocation)/real_node_size;
+
+ num_b_subblock =
+ hdr_subblock_elements_alone >= min_elements_per_block
+ ? 0
+ : ( ((hdr_subblock_elements_first + elements_per_b_subblock_end) >= min_elements_per_block)
+ ? 1
+ : 2 + (min_elements_per_block - hdr_subblock_elements_first - elements_per_b_subblock_end - 1)/elements_per_b_subblock_mid
+ )
+ ;
+
+ std::size_t num_b_subblock_mid = (num_b_subblock > 1) ? (num_b_subblock - 1) : 0;
+
+ total_nodes = (num_b_subblock == 0)
+ ? hdr_subblock_elements_alone
+ : ( (num_b_subblock == 1)
+ ? (hdr_subblock_elements_first + elements_per_b_subblock_end)
+ : (hdr_subblock_elements_first + num_b_subblock_mid*elements_per_b_subblock_mid + elements_per_b_subblock_end)
+ )
+ ;
+ std::size_t total_data = total_nodes*real_node_size;
+ std::size_t total_size = initial_alignment*(num_b_subblock+1);
+ overhead_satisfied = (total_size - total_data)*100/total_size < overhead_percent;
+ initial_alignment = initial_alignment << std::size_t(!overhead_satisfied);
+ }
+ alignment = initial_alignment;
+ num_subblocks = num_b_subblock+1;
+ real_num_node = total_nodes;
+}
+
+/////////////////////////////////////////////
+//
+// private_adaptive_node_pool_impl_common
+//
+/////////////////////////////////////////////
+template< class SegmentManagerBase, unsigned int Flags>
+class private_adaptive_node_pool_impl_common
+{
+ public:
+ //!Segment manager typedef
+ typedef SegmentManagerBase segment_manager_base_type;
+ typedef typename SegmentManagerBase::multiallocation_chain multiallocation_chain;
+ typedef typename SegmentManagerBase::size_type size_type;
+ //Flags
+ //align_only
+ static const bool AlignOnly = (Flags & adaptive_pool_flag::align_only) != 0;
+ typedef bool_<AlignOnly> IsAlignOnly;
+ typedef true_ AlignOnlyTrue;
+ typedef false_ AlignOnlyFalse;
+
+ typedef typename SegmentManagerBase::void_pointer void_pointer;
+ static const typename SegmentManagerBase::
+ size_type PayloadPerAllocation = SegmentManagerBase::PayloadPerAllocation;
+
+ typedef typename boost::intrusive::pointer_traits
+ <void_pointer>::template rebind_pointer<segment_manager_base_type>::type segment_mngr_base_ptr_t;
+
+ protected:
+ typedef adaptive_pool_types
+ <multiallocation_chain, void_pointer, size_type, Flags> adaptive_pool_types_t;
+ typedef typename adaptive_pool_types_t::free_nodes_t free_nodes_t;
+ typedef typename adaptive_pool_types_t::block_info_t block_info_t;
+ typedef typename adaptive_pool_types_t::block_container_t block_container_t;
+ typedef typename adaptive_pool_types_t::block_container_traits_t block_container_traits_t;
+ typedef typename block_container_t::iterator block_iterator;
+ typedef typename block_container_t::const_iterator const_block_iterator;
+ typedef typename adaptive_pool_types_t::hdr_offset_holder hdr_offset_holder;
+ typedef private_adaptive_node_pool_impl_common this_type;
+
+ static const size_type MaxAlign = alignment_of<void_pointer>::value;
+ static const size_type HdrSize = ((sizeof(block_info_t)-1)/MaxAlign+1)*MaxAlign;
+ static const size_type HdrOffsetSize = ((sizeof(hdr_offset_holder)-1)/MaxAlign+1)*MaxAlign;
+
+ segment_mngr_base_ptr_t mp_segment_mngr_base; //Segment manager
+ block_container_t m_block_container; //Intrusive block list
+ size_type m_totally_free_blocks; //Free blocks
+
+ class block_destroyer;
+ friend class block_destroyer;
+
+ class block_destroyer
+ {
+ public:
+ block_destroyer(const this_type *impl, multiallocation_chain &chain, const size_type num_subblocks, const size_type real_block_alignment, const size_type real_num_node)
+ : mp_impl(impl), m_chain(chain), m_num_subblocks(num_subblocks), m_real_block_alignment(real_block_alignment), m_real_num_node(real_num_node)
+ {}
+
+ void operator()(typename block_container_t::pointer to_deallocate)
+ { return this->do_destroy(to_deallocate, IsAlignOnly()); }
+
+ private:
+ void do_destroy(typename block_container_t::pointer to_deallocate, AlignOnlyTrue)
+ {
+ BOOST_ASSERT(to_deallocate->free_nodes.size() == m_real_num_node);
+ m_chain.push_back(to_deallocate);
+ }
+
+ void do_destroy(typename block_container_t::pointer to_deallocate, AlignOnlyFalse)
+ {
+ BOOST_ASSERT(to_deallocate->free_nodes.size() == m_real_num_node);
+ BOOST_ASSERT(0 == to_deallocate->hdr_offset);
+ hdr_offset_holder *hdr_off_holder =
+ mp_impl->priv_first_subblock_from_block(boost::movelib::to_raw_pointer(to_deallocate), m_num_subblocks, m_real_block_alignment);
+ m_chain.push_back(hdr_off_holder);
+ }
+
+ const this_type *mp_impl;
+ multiallocation_chain &m_chain;
+ const size_type m_num_subblocks;
+ const size_type m_real_block_alignment;
+ const size_type m_real_num_node;
+ };
+
+ //This macro will activate invariant checking. Slow, but helpful for debugging the code.
+ //#define BOOST_CONTAINER_ADAPTIVE_NODE_POOL_CHECK_INVARIANTS
+ void priv_invariants(const size_type real_num_node, const size_type num_subblocks, const size_type real_block_alignment) const
+ {
+ (void)real_num_node; (void)num_subblocks; (void)real_block_alignment;
+ #ifdef BOOST_CONTAINER_ADAPTIVE_NODE_POOL_CHECK_INVARIANTS
+ //Check that the total totally free blocks are correct
+ BOOST_ASSERT(m_block_container.size() >= m_totally_free_blocks);
+
+ const const_block_iterator itend(m_block_container.cend());
+ const const_block_iterator itbeg(m_block_container.cbegin());
+
+ { //Try to do checks in a single iteration
+ const_block_iterator it(itbeg);
+ size_type total_free_nodes = 0;
+ size_type total_free_blocks = 0u;
+ for(; it != itend; ++it){
+ if(it != itbeg){
+ //Check order invariant
+ const_block_iterator prev(it);
+ --prev;
+ BOOST_ASSERT(!(m_block_container.key_comp()(*it, *prev)));
+ (void)prev; (void)it;
+ }
+
+ //free_nodes invariant
+ const size_type free_nodes = it->free_nodes.size();
+ BOOST_ASSERT(free_nodes <= real_num_node);
+ BOOST_ASSERT(free_nodes != 0);
+
+ //Acummulate total_free_nodes and total_free_blocks
+ total_free_nodes += free_nodes;
+ total_free_blocks += it->free_nodes.size() == real_num_node;
+
+ if (!AlignOnly) {
+ //Check that header offsets are correct
+ hdr_offset_holder *hdr_off_holder = this->priv_first_subblock_from_block(const_cast<block_info_t *>(&*it), num_subblocks, real_block_alignment);
+ for (size_type i = 0, max = num_subblocks; i < max; ++i) {
+ const size_type offset = reinterpret_cast<char*>(const_cast<block_info_t *>(&*it)) - reinterpret_cast<char*>(hdr_off_holder);
+ (void)offset;
+ BOOST_ASSERT(hdr_off_holder->hdr_offset == offset);
+ BOOST_ASSERT(0 == (reinterpret_cast<std::size_t>(hdr_off_holder) & (real_block_alignment - 1)));
+ BOOST_ASSERT(0 == (hdr_off_holder->hdr_offset & (real_block_alignment - 1)));
+ hdr_off_holder = reinterpret_cast<hdr_offset_holder *>(reinterpret_cast<char*>(hdr_off_holder) + real_block_alignment);
+ }
+ }
+ }
+ BOOST_ASSERT(total_free_blocks == m_totally_free_blocks);
+ BOOST_ASSERT(total_free_nodes >= m_totally_free_blocks*real_num_node);
+ }
+ #endif
+ }
+
+ void priv_deallocate_free_blocks( const size_type max_free_blocks, const size_type real_num_node
+ , const size_type num_subblocks, const size_type real_block_alignment)
+ { //Trampoline function to ease inlining
+ if(m_totally_free_blocks > max_free_blocks){
+ this->priv_deallocate_free_blocks_impl(max_free_blocks, real_num_node, num_subblocks, real_block_alignment);
+ }
+ }
+
+ hdr_offset_holder *priv_first_subblock_from_block(block_info_t *block, const size_type num_subblocks, const size_type real_block_alignment) const
+ { return this->priv_first_subblock_from_block(block, num_subblocks, real_block_alignment, IsAlignOnly()); }
+
+ hdr_offset_holder *priv_first_subblock_from_block(block_info_t *block, const size_type num_subblocks, const size_type real_block_alignment, AlignOnlyFalse) const
+ {
+ hdr_offset_holder *const hdr_off_holder = reinterpret_cast<hdr_offset_holder*>
+ (reinterpret_cast<char*>(block) - (num_subblocks-1)*real_block_alignment);
+ BOOST_ASSERT(hdr_off_holder->hdr_offset == size_type(reinterpret_cast<char*>(block) - reinterpret_cast<char*>(hdr_off_holder)));
+ BOOST_ASSERT(0 == ((std::size_t)hdr_off_holder & (real_block_alignment - 1)));
+ BOOST_ASSERT(0 == (hdr_off_holder->hdr_offset & (real_block_alignment - 1)));
+ return hdr_off_holder;
+ }
+
+ hdr_offset_holder *priv_first_subblock_from_block(block_info_t *block, const size_type num_subblocks, const size_type real_block_alignment, AlignOnlyTrue) const
+ {
+ (void)num_subblocks; (void)real_block_alignment;
+ return reinterpret_cast<hdr_offset_holder*>(block);
+ }
+
+ void priv_deallocate_free_blocks_impl( const size_type max_free_blocks, const size_type real_num_node
+ , const size_type num_subblocks, const size_type real_block_alignment)
+ {
+ this->priv_invariants(real_num_node, num_subblocks, real_block_alignment);
+ //Now check if we've reached the free nodes limit
+ //and check if we have free blocks. If so, deallocate as much
+ //as we can to stay below the limit
+ multiallocation_chain chain;
+ {
+ if(Flags & adaptive_pool_flag::size_ordered){
+ const_block_iterator it = m_block_container.cend();
+ --it;
+ size_type totally_free_blocks = m_totally_free_blocks;
+
+ for( ; totally_free_blocks > max_free_blocks; --totally_free_blocks){
+ BOOST_ASSERT(it->free_nodes.size() == real_num_node);
+ void *addr = priv_first_subblock_from_block(const_cast<block_info_t*>(&*it), num_subblocks, real_block_alignment);
+ --it;
+ block_container_traits_t::erase_last(m_block_container);
+ chain.push_front(void_pointer(addr));
+ }
+ }
+ else{
+ const_block_iterator it = m_block_container.cend();
+ size_type totally_free_blocks = m_totally_free_blocks;
+
+ while(totally_free_blocks > max_free_blocks){
+ --it;
+ if(it->free_nodes.size() == real_num_node){
+ void *addr = priv_first_subblock_from_block(const_cast<block_info_t*>(&*it), num_subblocks, real_block_alignment);
+ it = m_block_container.erase(it);
+ chain.push_front(void_pointer(addr));
+ --totally_free_blocks;
+ }
+ }
+ }
+ BOOST_ASSERT((m_totally_free_blocks - max_free_blocks) == chain.size());
+ m_totally_free_blocks = max_free_blocks;
+ }
+ this->mp_segment_mngr_base->deallocate_many(chain);
+ this->priv_invariants(real_num_node, num_subblocks, real_block_alignment);
+ }
+
+ void priv_fill_chain_remaining_to_block
+ ( multiallocation_chain &chain, size_type target_elem_in_chain, block_info_t &c_info
+ , char *mem_address, size_type max_node_in_mem
+ , const size_type real_node_size)
+ {
+ BOOST_ASSERT(chain.size() <= target_elem_in_chain);
+
+ //First add all possible nodes to the chain
+ const size_type left = target_elem_in_chain - chain.size();
+ const size_type add_to_chain = (max_node_in_mem < left) ? max_node_in_mem : left;
+ char *free_mem_address = static_cast<char *>(boost::movelib::to_raw_pointer
+ (chain.incorporate_after(chain.last(), void_pointer(mem_address), real_node_size, add_to_chain)));
+ //Now store remaining nodes in the free list
+ if(const size_type free = max_node_in_mem - add_to_chain){
+ free_nodes_t & free_nodes = c_info.free_nodes;
+ free_nodes.incorporate_after(free_nodes.last(), void_pointer(free_mem_address), real_node_size, free);
+ }
+ }
+
+ //!Allocates a several blocks of nodes. Can throw
+ void priv_append_from_new_blocks( size_type min_elements, multiallocation_chain &chain
+ , const size_type max_free_blocks
+ , const size_type real_block_alignment, const size_type real_node_size
+ , const size_type real_num_node, const size_type num_subblocks
+ , AlignOnlyTrue)
+ {
+ (void)num_subblocks;
+ BOOST_ASSERT(m_block_container.empty());
+ BOOST_ASSERT(min_elements > 0);
+ const size_type n = (min_elements - 1)/real_num_node + 1;
+ const size_type real_block_size = real_block_alignment - PayloadPerAllocation;
+ const size_type target_elem_in_chain = chain.size() + min_elements;
+ for(size_type i = 0; i != n; ++i){
+ //We allocate a new NodeBlock and put it the last
+ //element of the tree
+ char *mem_address = static_cast<char*>
+ (mp_segment_mngr_base->allocate_aligned(real_block_size, real_block_alignment));
+ if(!mem_address){
+ //In case of error, free memory deallocating all nodes (the new ones allocated
+ //in this function plus previously stored nodes in chain).
+ this->priv_deallocate_nodes(chain, max_free_blocks, real_num_node, num_subblocks, real_block_alignment);
+ throw_bad_alloc();
+ }
+ block_info_t &c_info = *new(mem_address)block_info_t();
+ mem_address += HdrSize;
+ this->priv_fill_chain_remaining_to_block(chain, target_elem_in_chain, c_info, mem_address, real_num_node, real_node_size);
+ const size_type free_nodes = c_info.free_nodes.size();
+ if(free_nodes){
+ const bool is_full = free_nodes == real_num_node;
+ BOOST_ASSERT(free_nodes < real_num_node);
+ m_totally_free_blocks += static_cast<size_type>(is_full);
+ block_container_traits_t::insert_was_empty(m_block_container, c_info, is_full);
+ }
+ }
+ }
+
+ void priv_append_from_new_blocks( size_type min_elements, multiallocation_chain &chain
+ , const size_type max_free_blocks
+ , const size_type real_block_alignment, const size_type real_node_size
+ , const size_type real_num_node, const size_type num_subblocks
+ , AlignOnlyFalse)
+ {
+ BOOST_ASSERT(m_block_container.empty());
+ BOOST_ASSERT(min_elements > 0);
+ const size_type n = (min_elements - 1)/real_num_node + 1;
+ const size_type real_block_size = real_block_alignment*num_subblocks - PayloadPerAllocation;
+ const size_type elements_per_subblock_mid = (real_block_alignment - HdrOffsetSize)/real_node_size;
+ const size_type elements_per_subblock_end = (real_block_alignment - HdrOffsetSize - PayloadPerAllocation) / real_node_size;
+ const size_type hdr_subblock_elements = (real_block_alignment - HdrSize - PayloadPerAllocation)/real_node_size;
+ const size_type target_elem_in_chain = chain.size() + min_elements;
+
+ for(size_type i = 0; i != n; ++i){
+ //We allocate a new NodeBlock and put it the last
+ //element of the tree
+ char *mem_address = static_cast<char*>
+ (mp_segment_mngr_base->allocate_aligned(real_block_size, real_block_alignment));
+ if(!mem_address){
+ //In case of error, free memory deallocating all nodes (the new ones allocated
+ //in this function plus previously stored nodes in chain).
+ this->priv_deallocate_nodes(chain, max_free_blocks, real_num_node, num_subblocks, real_block_alignment);
+ throw_bad_alloc();
+ }
+ //First initialize header information on the last subblock
+ char *hdr_addr = mem_address + real_block_alignment*(num_subblocks-1);
+ block_info_t &c_info = *new(hdr_addr)block_info_t();
+ //Some structural checks
+ BOOST_ASSERT(static_cast<void*>(&static_cast<hdr_offset_holder&>(c_info).hdr_offset) ==
+ static_cast<void*>(&c_info)); (void)c_info;
+ for( size_type subblock = 0, maxsubblock = num_subblocks - 1
+ ; subblock < maxsubblock
+ ; ++subblock, mem_address += real_block_alignment){
+ //Initialize header offset mark
+ new(mem_address) hdr_offset_holder(size_type(hdr_addr - mem_address));
+ const size_type elements_per_subblock = (subblock != (maxsubblock - 1)) ? elements_per_subblock_mid : elements_per_subblock_end;
+ this->priv_fill_chain_remaining_to_block
+ (chain, target_elem_in_chain, c_info, mem_address + HdrOffsetSize, elements_per_subblock, real_node_size);
+ }
+ this->priv_fill_chain_remaining_to_block
+ (chain, target_elem_in_chain, c_info, hdr_addr + HdrSize, hdr_subblock_elements, real_node_size);
+ m_totally_free_blocks += static_cast<size_type>(c_info.free_nodes.size() == real_num_node);
+ if (c_info.free_nodes.size())
+ m_block_container.push_front(c_info);
+ }
+ }
+
+ //!Allocates array of count elements. Can throw
+ void *priv_allocate_node( const size_type max_free_blocks, const size_type real_block_alignment, const size_type real_node_size
+ , const size_type real_num_node, const size_type num_subblocks)
+ {
+ this->priv_invariants(real_num_node, num_subblocks, real_block_alignment);
+ //If there are no free nodes we allocate a new block
+ if(!m_block_container.empty()){
+ //We take the first free node the multiset can't be empty
+ free_nodes_t &free_nodes = m_block_container.begin()->free_nodes;
+ BOOST_ASSERT(!free_nodes.empty());
+ const size_type free_nodes_count = free_nodes.size();
+ void *first_node = boost::movelib::to_raw_pointer(free_nodes.pop_front());
+ if(free_nodes.empty()){
+ block_container_traits_t::erase_first(m_block_container);
+ }
+ m_totally_free_blocks -= static_cast<size_type>(free_nodes_count == real_num_node);
+ this->priv_invariants(real_num_node, num_subblocks, real_block_alignment);
+ return first_node;
+ }
+ else{
+ multiallocation_chain chain;
+ this->priv_append_from_new_blocks
+ (1, chain, max_free_blocks, real_block_alignment, real_node_size, real_num_node, num_subblocks, IsAlignOnly());
+ void *node = boost::movelib::to_raw_pointer(chain.pop_front());
+ this->priv_invariants(real_num_node, num_subblocks, real_block_alignment);
+ return node;
+ }
+ }
+
+ void priv_allocate_nodes( const size_type n, multiallocation_chain &chain
+ , const size_type max_free_blocks, const size_type real_block_alignment, const size_type real_node_size
+ , const size_type real_num_node, const size_type num_subblocks)
+ {
+ size_type i = 0;
+ BOOST_TRY{
+ this->priv_invariants(real_num_node, num_subblocks, real_block_alignment);
+ while(i != n){
+ //If there are no free nodes we allocate all needed blocks
+ if (m_block_container.empty()){
+ this->priv_append_from_new_blocks
+ (n - i, chain, max_free_blocks, real_block_alignment, real_node_size, real_num_node, num_subblocks, IsAlignOnly());
+ BOOST_ASSERT(m_block_container.empty() || (++m_block_container.cbegin() == m_block_container.cend()));
+ BOOST_ASSERT(chain.size() == n);
+ break;
+ }
+ free_nodes_t &free_nodes = m_block_container.begin()->free_nodes;
+ const size_type free_nodes_count_before = free_nodes.size();
+ m_totally_free_blocks -= static_cast<size_type>(free_nodes_count_before == real_num_node);
+ const size_type num_left = n-i;
+ const size_type num_elems = (num_left < free_nodes_count_before) ? num_left : free_nodes_count_before;
+ typedef typename free_nodes_t::iterator free_nodes_iterator;
+
+ if(num_left < free_nodes_count_before){
+ const free_nodes_iterator it_bbeg(free_nodes.before_begin());
+ free_nodes_iterator it_bend(it_bbeg);
+ for(size_type j = 0; j != num_elems; ++j){
+ ++it_bend;
+ }
+ free_nodes_iterator it_end = it_bend; ++it_end;
+ free_nodes_iterator it_beg = it_bbeg; ++it_beg;
+ free_nodes.erase_after(it_bbeg, it_end, num_elems);
+ chain.incorporate_after(chain.last(), &*it_beg, &*it_bend, num_elems);
+ //chain.splice_after(chain.last(), free_nodes, it_bbeg, it_bend, num_elems);
+ BOOST_ASSERT(!free_nodes.empty());
+ }
+ else{
+ const free_nodes_iterator it_beg(free_nodes.begin()), it_bend(free_nodes.last());
+ free_nodes.clear();
+ chain.incorporate_after(chain.last(), &*it_beg, &*it_bend, num_elems);
+ block_container_traits_t::erase_first(m_block_container);
+ }
+ i += num_elems;
+ }
+ }
+ BOOST_CATCH(...){
+ this->priv_deallocate_nodes(chain, max_free_blocks, real_num_node, num_subblocks, real_block_alignment);
+ this->priv_invariants(real_num_node, num_subblocks, real_block_alignment);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ this->priv_invariants(real_num_node, num_subblocks, real_block_alignment);
+ }
+
+ //!Deallocates an array pointed by ptr. Never throws
+ void priv_deallocate_node( void *pElem
+ , const size_type max_free_blocks, const size_type real_num_node
+ , const size_type num_subblocks, const size_type real_block_alignment)
+ {
+ this->priv_invariants(real_num_node, num_subblocks, real_block_alignment);
+ block_info_t &block_info = *this->priv_block_from_node(pElem, real_block_alignment);
+ const size_type prev_free_nodes = block_info.free_nodes.size();
+ BOOST_ASSERT(block_info.free_nodes.size() < real_num_node);
+
+ //We put the node at the beginning of the free node list
+ block_info.free_nodes.push_back(void_pointer(pElem));
+
+ //The loop reinserts all blocks except the last one
+ this->priv_reinsert_block(block_info, prev_free_nodes == 0, real_num_node);
+ this->priv_deallocate_free_blocks(max_free_blocks, real_num_node, num_subblocks, real_block_alignment);
+ this->priv_invariants(real_num_node, num_subblocks, real_block_alignment);
+ }
+
+ void priv_deallocate_nodes( multiallocation_chain &nodes
+ , const size_type max_free_blocks, const size_type real_num_node
+ , const size_type num_subblocks, const size_type real_block_alignment)
+ {
+ this->priv_invariants(real_num_node, num_subblocks, real_block_alignment);
+ //To take advantage of node locality, wait until two
+ //nodes belong to different blocks. Only then reinsert
+ //the block of the first node in the block tree.
+ //Cache of the previous block
+ block_info_t *prev_block_info = 0;
+
+ //If block was empty before this call, it's not already
+ //inserted in the block tree.
+ bool prev_block_was_empty = false;
+ typedef typename free_nodes_t::iterator free_nodes_iterator;
+ {
+ const free_nodes_iterator itbb(nodes.before_begin()), ite(nodes.end());
+ free_nodes_iterator itf(nodes.begin()), itbf(itbb);
+ size_type splice_node_count = size_type(-1);
+ while(itf != ite){
+ void *pElem = boost::movelib::to_raw_pointer(boost::movelib::iterator_to_raw_pointer(itf));
+ block_info_t &block_info = *this->priv_block_from_node(pElem, real_block_alignment);
+ BOOST_ASSERT(block_info.free_nodes.size() < real_num_node);
+ ++splice_node_count;
+
+ //If block change is detected calculate the cached block position in the tree
+ if(&block_info != prev_block_info){
+ if(prev_block_info){ //Make sure we skip the initial "dummy" cache
+ free_nodes_iterator it(itbb); ++it;
+ nodes.erase_after(itbb, itf, splice_node_count);
+ prev_block_info->free_nodes.incorporate_after(prev_block_info->free_nodes.last(), &*it, &*itbf, splice_node_count);
+ this->priv_reinsert_block(*prev_block_info, prev_block_was_empty, real_num_node);
+ splice_node_count = 0;
+ }
+ //Update cache with new data
+ prev_block_was_empty = block_info.free_nodes.empty();
+ prev_block_info = &block_info;
+ }
+ itbf = itf;
+ ++itf;
+ }
+ }
+ if(prev_block_info){
+ //The loop reinserts all blocks except the last one
+ const free_nodes_iterator itfirst(nodes.begin()), itlast(nodes.last());
+ const size_type splice_node_count = nodes.size();
+ nodes.clear();
+ prev_block_info->free_nodes.incorporate_after(prev_block_info->free_nodes.last(), &*itfirst, &*itlast, splice_node_count);
+ this->priv_reinsert_block(*prev_block_info, prev_block_was_empty, real_num_node);
+ this->priv_deallocate_free_blocks(max_free_blocks, real_num_node, num_subblocks, real_block_alignment);
+ }
+ this->priv_invariants(real_num_node, num_subblocks, real_block_alignment);
+ }
+
+ void priv_reinsert_block(block_info_t &prev_block_info, const bool prev_block_was_empty, const size_type real_num_node)
+ {
+ //Cache the free nodes from the block
+ const size_type this_block_free_nodes = prev_block_info.free_nodes.size();
+ const bool is_full = this_block_free_nodes == real_num_node;
+
+ //Update free block count
+ m_totally_free_blocks += static_cast<size_type>(is_full);
+ if(prev_block_was_empty){
+ block_container_traits_t::insert_was_empty(m_block_container, prev_block_info, is_full);
+ }
+ else{
+ block_container_traits_t::reinsert_was_used(m_block_container, prev_block_info, is_full);
+ }
+ }
+
+ block_info_t *priv_block_from_node(void *node, const size_type real_block_alignment, AlignOnlyFalse) const
+ {
+ hdr_offset_holder *hdr_off_holder =
+ reinterpret_cast<hdr_offset_holder*>((std::size_t)node & size_type(~(real_block_alignment - 1)));
+ BOOST_ASSERT(0 == ((std::size_t)hdr_off_holder & (real_block_alignment - 1)));
+ BOOST_ASSERT(0 == (hdr_off_holder->hdr_offset & (real_block_alignment - 1)));
+ block_info_t *block = reinterpret_cast<block_info_t *>
+ (reinterpret_cast<char*>(hdr_off_holder) + hdr_off_holder->hdr_offset);
+ BOOST_ASSERT(block->hdr_offset == 0);
+ return block;
+ }
+
+ block_info_t *priv_block_from_node(void *node, const size_type real_block_alignment, AlignOnlyTrue) const
+ {
+ return (block_info_t *)((std::size_t)node & std::size_t(~(real_block_alignment - 1)));
+ }
+
+ block_info_t *priv_block_from_node(void *node, const size_type real_block_alignment) const
+ { return this->priv_block_from_node(node, real_block_alignment, IsAlignOnly()); }
+
+ //!Deallocates all used memory. Never throws
+ void priv_clear(const size_type num_subblocks, const size_type real_block_alignment, const size_type real_num_node)
+ {
+ #ifndef NDEBUG
+ block_iterator it = m_block_container.begin();
+ block_iterator itend = m_block_container.end();
+ size_type n_free_nodes = 0;
+ for(; it != itend; ++it){
+ //Check for memory leak
+ BOOST_ASSERT(it->free_nodes.size() == real_num_node);
+ ++n_free_nodes;
+ }
+ BOOST_ASSERT(n_free_nodes == m_totally_free_blocks);
+ #endif
+ //Check for memory leaks
+ this->priv_invariants(real_num_node, num_subblocks, real_block_alignment);
+ multiallocation_chain chain;
+ m_block_container.clear_and_dispose(block_destroyer(this, chain, num_subblocks, real_block_alignment, real_num_node));
+ this->mp_segment_mngr_base->deallocate_many(chain);
+ m_totally_free_blocks = 0;
+ this->priv_invariants(real_num_node, num_subblocks, real_block_alignment);
+ }
+
+ public:
+ private_adaptive_node_pool_impl_common(segment_manager_base_type *segment_mngr_base)
+ //General purpose allocator
+ : mp_segment_mngr_base(segment_mngr_base)
+ , m_block_container()
+ , m_totally_free_blocks(0)
+ {}
+
+ size_type num_free_nodes()
+ {
+ typedef typename block_container_t::const_iterator citerator;
+ size_type count = 0;
+ citerator it (m_block_container.begin()), itend(m_block_container.end());
+ for(; it != itend; ++it){
+ count += it->free_nodes.size();
+ }
+ return count;
+ }
+
+ void swap(private_adaptive_node_pool_impl_common &other)
+ {
+ std::swap(mp_segment_mngr_base, other.mp_segment_mngr_base);
+ std::swap(m_totally_free_blocks, other.m_totally_free_blocks);
+ m_block_container.swap(other.m_block_container);
+ }
+
+ //!Returns the segment manager. Never throws
+ segment_manager_base_type* get_segment_manager_base()const
+ { return boost::movelib::to_raw_pointer(mp_segment_mngr_base); }
+};
+
+template< class SizeType
+ , std::size_t HdrSize
+ , std::size_t PayloadPerAllocation
+ , std::size_t RealNodeSize
+ , std::size_t NodesPerBlock
+ , std::size_t HdrOffsetSize
+ , std::size_t OverheadPercent
+ , bool AlignOnly>
+struct calculate_alignment_ct
+{
+ static const std::size_t alignment = upper_power_of_2_ct<SizeType, HdrSize + RealNodeSize*NodesPerBlock>::value;
+ static const std::size_t num_subblocks = 0;
+ static const std::size_t real_num_node = (alignment - PayloadPerAllocation - HdrSize)/RealNodeSize;
+};
+
+template< class SizeType
+ , std::size_t HdrSize
+ , std::size_t PayloadPerAllocation
+ , std::size_t RealNodeSize
+ , std::size_t NodesPerBlock
+ , std::size_t HdrOffsetSize
+ , std::size_t OverheadPercent>
+struct calculate_alignment_ct
+ < SizeType
+ , HdrSize
+ , PayloadPerAllocation
+ , RealNodeSize
+ , NodesPerBlock
+ , HdrOffsetSize
+ , OverheadPercent
+ , false>
+{
+ typedef typename candidate_power_of_2_ct
+ < upper_power_of_2_ct<SizeType, HdrSize + PayloadPerAllocation + RealNodeSize>::value
+ , RealNodeSize
+ , PayloadPerAllocation
+ , NodesPerBlock
+ , HdrSize
+ , HdrOffsetSize
+ , OverheadPercent
+ >::type type;
+
+ static const std::size_t alignment = type::alignment;
+ static const std::size_t num_subblocks = type::num_subblocks;
+ static const std::size_t real_num_node = type::real_num_node;
+};
+
+
+/////////////////////////////////////////////
+//
+// private_adaptive_node_pool_impl_ct
+//
+/////////////////////////////////////////////
+template< class SegmentManagerBase
+ , std::size_t MaxFreeBlocks
+ , std::size_t NodeSize
+ , std::size_t NodesPerBlock
+ , std::size_t OverheadPercent
+ , unsigned int Flags>
+class private_adaptive_node_pool_impl_ct
+ : public private_adaptive_node_pool_impl_common<SegmentManagerBase, Flags>
+{
+ typedef private_adaptive_node_pool_impl_common<SegmentManagerBase, Flags> base_t;
+
+ //Non-copyable
+ private_adaptive_node_pool_impl_ct();
+ private_adaptive_node_pool_impl_ct(const private_adaptive_node_pool_impl_ct &);
+ private_adaptive_node_pool_impl_ct &operator=(const private_adaptive_node_pool_impl_ct &);
+
+ public:
+ typedef typename base_t::void_pointer void_pointer;
+ typedef typename base_t::size_type size_type;
+ typedef typename base_t::multiallocation_chain multiallocation_chain;
+ typedef typename base_t::segment_manager_base_type segment_manager_base_type;
+
+ static const typename base_t::size_type PayloadPerAllocation = base_t::PayloadPerAllocation;
+
+ //align_only
+ static const bool AlignOnly = base_t::AlignOnly;
+
+ private:
+ static const size_type MaxAlign = base_t::MaxAlign;
+ static const size_type HdrSize = base_t::HdrSize;
+ static const size_type HdrOffsetSize = base_t::HdrOffsetSize;
+
+ static const size_type RealNodeSize = lcm_ct<NodeSize, alignment_of<void_pointer>::value>::value;
+
+ typedef calculate_alignment_ct
+ < size_type, HdrSize, PayloadPerAllocation
+ , RealNodeSize, NodesPerBlock, HdrOffsetSize, OverheadPercent, AlignOnly> data_t;
+
+ //Round the size to a power of two value.
+ //This is the total memory size (including payload) that we want to
+ //allocate from the general-purpose allocator
+ static const size_type NumSubBlocks = data_t::num_subblocks;
+ static const size_type RealNumNode = data_t::real_num_node;
+ static const size_type RealBlockAlignment = data_t::alignment;
+
+ public:
+
+ //!Constructor from a segment manager. Never throws
+ private_adaptive_node_pool_impl_ct(typename base_t::segment_manager_base_type *segment_mngr_base)
+ //General purpose allocator
+ : base_t(segment_mngr_base)
+ {}
+
+ //!Destructor. Deallocates all allocated blocks. Never throws
+ ~private_adaptive_node_pool_impl_ct()
+ { this->priv_clear(NumSubBlocks, data_t::alignment, RealNumNode); }
+
+ size_type get_real_num_node() const
+ { return RealNumNode; }
+
+ //!Allocates array of count elements. Can throw
+ void *allocate_node()
+ {
+ return this->priv_allocate_node
+ (MaxFreeBlocks, data_t::alignment, RealNodeSize, RealNumNode, NumSubBlocks);
+ }
+
+ //!Allocates n nodes.
+ //!Can throw
+ void allocate_nodes(const size_type n, multiallocation_chain &chain)
+ {
+ this->priv_allocate_nodes
+ (n, chain, MaxFreeBlocks, data_t::alignment, RealNodeSize, RealNumNode, NumSubBlocks);
+ }
+
+ //!Deallocates an array pointed by ptr. Never throws
+ void deallocate_node(void *pElem)
+ {
+ this->priv_deallocate_node(pElem, MaxFreeBlocks, RealNumNode, NumSubBlocks, RealBlockAlignment);
+ }
+
+ //!Deallocates a linked list of nodes. Never throws
+ void deallocate_nodes(multiallocation_chain &nodes)
+ {
+ this->priv_deallocate_nodes(nodes, MaxFreeBlocks, RealNumNode, NumSubBlocks, data_t::alignment);
+ }
+
+ void deallocate_free_blocks()
+ { this->priv_deallocate_free_blocks(0, RealNumNode, NumSubBlocks, data_t::alignment); }
+
+ //Deprecated, use deallocate_free_blocks
+ void deallocate_free_chunks()
+ { this->priv_deallocate_free_blocks(0, RealNumNode, NumSubBlocks, data_t::alignment); }
+};
+
+/////////////////////////////////////////////
+//
+// private_adaptive_node_pool_impl_rt
+//
+/////////////////////////////////////////////
+template<class SizeType>
+struct private_adaptive_node_pool_impl_rt_data
+{
+ typedef SizeType size_type;
+
+ private_adaptive_node_pool_impl_rt_data(size_type max_free_blocks, size_type real_node_size)
+ : m_max_free_blocks(max_free_blocks), m_real_node_size(real_node_size)
+ , m_real_block_alignment(), m_num_subblocks(), m_real_num_node()
+ {}
+
+ const size_type m_max_free_blocks;
+ const size_type m_real_node_size;
+ //Round the size to a power of two value.
+ //This is the total memory size (including payload) that we want to
+ //allocate from the general-purpose allocator
+ size_type m_real_block_alignment;
+ size_type m_num_subblocks;
+ //This is the real number of nodes per block
+ size_type m_real_num_node;
+};
+
+
+template<class SegmentManagerBase, unsigned int Flags>
+class private_adaptive_node_pool_impl_rt
+ : private private_adaptive_node_pool_impl_rt_data<typename SegmentManagerBase::size_type>
+ , public private_adaptive_node_pool_impl_common<SegmentManagerBase, Flags>
+{
+ typedef private_adaptive_node_pool_impl_common<SegmentManagerBase, Flags> impl_t;
+ typedef private_adaptive_node_pool_impl_rt_data<typename SegmentManagerBase::size_type> data_t;
+
+ //Non-copyable
+ private_adaptive_node_pool_impl_rt();
+ private_adaptive_node_pool_impl_rt(const private_adaptive_node_pool_impl_rt &);
+ private_adaptive_node_pool_impl_rt &operator=(const private_adaptive_node_pool_impl_rt &);
+
+ protected:
+
+ typedef typename impl_t::void_pointer void_pointer;
+ typedef typename impl_t::size_type size_type;
+ typedef typename impl_t::multiallocation_chain multiallocation_chain;
+
+ static const typename impl_t::size_type PayloadPerAllocation = impl_t::PayloadPerAllocation;
+
+ //Flags
+ //align_only
+ static const bool AlignOnly = impl_t::AlignOnly;
+
+ static const size_type HdrSize = impl_t::HdrSize;
+ static const size_type HdrOffsetSize = impl_t::HdrOffsetSize;
+
+ public:
+
+ //!Segment manager typedef
+ typedef SegmentManagerBase segment_manager_base_type;
+
+ //!Constructor from a segment manager. Never throws
+ private_adaptive_node_pool_impl_rt
+ ( segment_manager_base_type *segment_mngr_base
+ , size_type node_size
+ , size_type nodes_per_block
+ , size_type max_free_blocks
+ , unsigned char overhead_percent
+ )
+ : data_t(max_free_blocks, lcm(node_size, size_type(alignment_of<void_pointer>::value)))
+ , impl_t(segment_mngr_base)
+ {
+ if(AlignOnly){
+ this->m_real_block_alignment = upper_power_of_2(HdrSize + this->m_real_node_size*nodes_per_block);
+ this->m_real_num_node = (this->m_real_block_alignment - PayloadPerAllocation - HdrSize)/this->m_real_node_size;
+ }
+ else{
+ candidate_power_of_2_rt ( upper_power_of_2(HdrSize + PayloadPerAllocation + this->m_real_node_size)
+ , this->m_real_node_size
+ , PayloadPerAllocation
+ , nodes_per_block
+ , HdrSize
+ , HdrOffsetSize
+ , overhead_percent
+ , this->m_real_block_alignment
+ , this->m_num_subblocks
+ , this->m_real_num_node);
+ }
+ }
+
+ //!Destructor. Deallocates all allocated blocks. Never throws
+ ~private_adaptive_node_pool_impl_rt()
+ { this->priv_clear(this->m_num_subblocks, this->m_real_block_alignment, this->m_real_num_node); }
+
+ size_type get_real_num_node() const
+ { return this->m_real_num_node; }
+
+ //!Allocates array of count elements. Can throw
+ void *allocate_node()
+ {
+ return this->priv_allocate_node
+ (this->m_max_free_blocks, this->m_real_block_alignment, this->m_real_node_size, this->m_real_num_node, this->m_num_subblocks);
+ }
+
+ //!Allocates n nodes.
+ //!Can throw
+ void allocate_nodes(const size_type n, multiallocation_chain &chain)
+ {
+
+ this->priv_allocate_nodes
+ (n, chain, this->m_max_free_blocks, this->m_real_block_alignment, this->m_real_node_size, this->m_real_num_node, this->m_num_subblocks);
+ }
+
+ //!Deallocates an array pointed by ptr. Never throws
+ void deallocate_node(void *pElem)
+ {
+ this->priv_deallocate_node(pElem, this->m_max_free_blocks, this->m_real_num_node, this->m_num_subblocks, this->m_real_block_alignment);
+ }
+
+ //!Deallocates a linked list of nodes. Never throws
+ void deallocate_nodes(multiallocation_chain &nodes)
+ {
+ this->priv_deallocate_nodes(nodes, this->m_max_free_blocks, this->m_real_num_node, this->m_num_subblocks, this->m_real_block_alignment);
+ }
+
+ void deallocate_free_blocks()
+ { this->priv_deallocate_free_blocks(0, this->m_real_num_node, this->m_num_subblocks, this->m_real_block_alignment); }
+
+ //Deprecated, use deallocate_free_blocks
+ void deallocate_free_chunks()
+ { this->priv_deallocate_free_blocks(0, this->m_real_num_node, this->m_num_subblocks, this->m_real_block_alignment); }
+};
+
+} //namespace dtl {
+} //namespace container {
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_IMPL_HPP
diff --git a/include/boost/container/detail/addressof.hpp b/include/boost/container/detail/addressof.hpp
new file mode 100644
index 0000000..b3b8a4d
--- /dev/null
+++ b/include/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 dtl {
+
+template <typename T>
+BOOST_CONTAINER_FORCEINLINE T* addressof(T& obj)
+{
+ return static_cast<T*>(
+ static_cast<void*>(
+ const_cast<char*>(
+ &reinterpret_cast<const volatile char&>(obj)
+ )));
+}
+
+} //namespace dtl {
+} //namespace container {
+} //namespace boost {
+
+#endif //#ifndef BOOST_CONTAINER_DETAIL_ADDRESSOF_HPP
diff --git a/include/boost/container/detail/advanced_insert_int.hpp b/include/boost/container/detail/advanced_insert_int.hpp
new file mode 100644
index 0000000..fc8a33a
--- /dev/null
+++ b/include/boost/container/detail/advanced_insert_int.hpp
@@ -0,0 +1,495 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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_ADVANCED_INSERT_INT_HPP
+#define BOOST_CONTAINER_ADVANCED_INSERT_INT_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+
+// container
+#include <boost/container/allocator_traits.hpp>
+// container/detail
+#include <boost/container/detail/copy_move_algo.hpp>
+#include <boost/container/detail/destroyers.hpp>
+#include <boost/container/detail/mpl.hpp>
+#include <boost/container/detail/type_traits.hpp>
+#include <boost/container/detail/iterator.hpp>
+#include <boost/container/detail/iterators.hpp>
+#include <boost/move/detail/iterator_to_raw_pointer.hpp>
+#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+#include <boost/move/detail/fwd_macros.hpp>
+#endif
+// move
+#include <boost/move/utility_core.hpp>
+// other
+#include <boost/assert.hpp>
+#include <boost/core/no_exceptions_support.hpp>
+
+namespace boost { namespace container { namespace dtl {
+
+template<class Allocator, class FwdIt, class Iterator>
+struct move_insert_range_proxy
+{
+ 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(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(Allocator &, Iterator p, size_type n)
+ {
+ this->first_ = ::boost::container::move_n_source(this->first_, n, p);
+ }
+
+ FwdIt first_;
+};
+
+
+template<class Allocator, class FwdIt, class Iterator>
+struct insert_range_proxy
+{
+ 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(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(Allocator &, Iterator p, size_type n)
+ {
+ this->first_ = ::boost::container::copy_n_source(this->first_, n, p);
+ }
+
+ FwdIt first_;
+};
+
+
+template<class Allocator, class Iterator>
+struct insert_n_copies_proxy
+{
+ 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(Allocator &a, Iterator p, size_type n) const
+ { boost::container::uninitialized_fill_alloc_n(a, v_, n, p); }
+
+ void copy_n_and_update(Allocator &, Iterator p, size_type n) const
+ {
+ for (; 0 < n; --n, ++p){
+ *p = v_;
+ }
+ }
+
+ const value_type &v_;
+};
+
+template<class Allocator, class Iterator>
+struct insert_value_initialized_n_proxy
+{
+ 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(Allocator &a, Iterator p, size_type n) const
+ { boost::container::uninitialized_value_init_alloc_n(a, n, p); }
+
+ void copy_n_and_update(Allocator &a, Iterator p, size_type n) const
+ {
+ for (; 0 < n; --n, ++p){
+ typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type stor;
+ value_type &v = *static_cast<value_type *>(static_cast<void *>(stor.data));
+ alloc_traits::construct(a, &v);
+ value_destructor<Allocator> on_exit(a, v); (void)on_exit;
+ *p = ::boost::move(v);
+ }
+ }
+};
+
+template<class Allocator, class Iterator>
+struct insert_default_initialized_n_proxy
+{
+ 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(Allocator &a, Iterator p, size_type n) const
+ { boost::container::uninitialized_default_init_alloc_n(a, n, p); }
+
+ void copy_n_and_update(Allocator &a, Iterator p, size_type n) const
+ {
+ if(!is_pod<value_type>::value){
+ for (; 0 < n; --n, ++p){
+ typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type stor;
+ value_type &v = *static_cast<value_type *>(static_cast<void *>(stor.data));
+ alloc_traits::construct(a, &v, default_init);
+ value_destructor<Allocator> on_exit(a, v); (void)on_exit;
+ *p = ::boost::move(v);
+ }
+ }
+ }
+};
+
+template<class Allocator, class Iterator>
+struct insert_copy_proxy
+{
+ 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_copy_proxy(const value_type &v)
+ : v_(v)
+ {}
+
+ void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const
+ {
+ BOOST_ASSERT(n == 1); (void)n;
+ alloc_traits::construct( a, boost::movelib::iterator_to_raw_pointer(p), v_);
+ }
+
+ void copy_n_and_update(Allocator &, Iterator p, size_type n) const
+ {
+ BOOST_ASSERT(n == 1); (void)n;
+ *p = v_;
+ }
+
+ const value_type &v_;
+};
+
+
+template<class Allocator, class Iterator>
+struct insert_move_proxy
+{
+ 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_move_proxy(value_type &v)
+ : v_(v)
+ {}
+
+ void uninitialized_copy_n_and_update(Allocator &a, Iterator p, size_type n) const
+ {
+ BOOST_ASSERT(n == 1); (void)n;
+ alloc_traits::construct( a, boost::movelib::iterator_to_raw_pointer(p), ::boost::move(v_) );
+ }
+
+ void copy_n_and_update(Allocator &, Iterator p, size_type n) const
+ {
+ BOOST_ASSERT(n == 1); (void)n;
+ *p = ::boost::move(v_);
+ }
+
+ 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<Allocator, It>(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<Allocator, It>(v);
+}
+
+}}} //namespace boost { namespace container { namespace dtl {
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+#include <boost/container/detail/variadic_templates_tools.hpp>
+#include <boost/move/utility_core.hpp>
+
+namespace boost {
+namespace container {
+namespace dtl {
+
+template<class Allocator, class Iterator, class ...Args>
+struct insert_nonmovable_emplace_proxy
+{
+ 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_nonmovable_emplace_proxy(BOOST_FWD_REF(Args)... args)
+ : args_(args...)
+ {}
+
+ 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<std::size_t ...IdxPack>
+ 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, boost::movelib::iterator_to_raw_pointer(p), ::boost::forward<Args>(get<IdxPack>(this->args_))... );
+ }
+
+ protected:
+ tuple<Args&...> args_;
+};
+
+template<class Allocator, class Iterator, class ...Args>
+struct insert_emplace_proxy
+ : public insert_nonmovable_emplace_proxy<Allocator, Iterator, Args...>
+{
+ 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(BOOST_FWD_REF(Args)... args)
+ : base_t(::boost::forward<Args>(args)...)
+ {}
+
+ 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<std::size_t ...IdxPack>
+ void priv_copy_some_and_update(Allocator &a, const index_tuple<IdxPack...>&, Iterator p, size_type n)
+ {
+ BOOST_ASSERT(n ==1); (void)n;
+ typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v;
+ value_type *vp = static_cast<value_type *>(static_cast<void *>(v.data));
+ alloc_traits::construct(a, vp,
+ ::boost::forward<Args>(get<IdxPack>(this->args_))...);
+ BOOST_TRY{
+ *p = ::boost::move(*vp);
+ }
+ BOOST_CATCH(...){
+ alloc_traits::destroy(a, vp);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ alloc_traits::destroy(a, vp);
+ }
+};
+
+//Specializations to avoid an unneeded temporary when emplacing from a single argument o type value_type
+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<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").
+//Any problem is solvable with an extra layer of indirection? ;-)
+template<class Allocator, class Iterator>
+struct insert_emplace_proxy<Allocator, Iterator
+ , typename boost::container::dtl::add_const<typename boost::container::allocator_traits<Allocator>::value_type>::type
+ >
+ : public insert_copy_proxy<Allocator, Iterator>
+{
+ explicit insert_emplace_proxy(const typename boost::container::allocator_traits<Allocator>::value_type &v)
+ : insert_copy_proxy<Allocator, Iterator>(v)
+ {}
+};
+
+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<Allocator>::value_type &v)
+ : insert_copy_proxy<Allocator, Iterator>(v)
+ {}
+};
+
+template<class Allocator, class Iterator>
+struct insert_emplace_proxy<Allocator, Iterator
+ , typename boost::container::dtl::add_const<typename boost::container::allocator_traits<Allocator>::value_type>::type &
+ >
+ : public insert_copy_proxy<Allocator, Iterator>
+{
+ 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 dtl {
+
+#else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+#include <boost/container/detail/value_init.hpp>
+
+namespace boost {
+namespace container {
+namespace dtl {
+
+#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, boost::movelib::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.data));\
+ 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 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<Allocator>::value_type &v)
+ : insert_move_proxy<Allocator, Iterator>(v)
+ {}
+};
+
+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<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 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<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").
+//Any problem is solvable with an extra layer of indirection? ;-)
+template<class Allocator, class Iterator>
+struct insert_emplace_proxy_arg1<Allocator, Iterator
+ , typename boost::container::dtl::add_const<typename boost::container::allocator_traits<Allocator>::value_type>::type
+ >
+ : public insert_copy_proxy<Allocator, Iterator>
+{
+ explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<Allocator>::value_type &v)
+ : insert_copy_proxy<Allocator, Iterator>(v)
+ {}
+};
+
+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<Allocator>::value_type &v)
+ : insert_copy_proxy<Allocator, Iterator>(v)
+ {}
+};
+
+template<class Allocator, class Iterator>
+struct insert_emplace_proxy_arg1<Allocator, Iterator
+ , typename boost::container::dtl::add_const<typename boost::container::allocator_traits<Allocator>::value_type>::type &
+ >
+ : public insert_copy_proxy<Allocator, Iterator>
+{
+ explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<Allocator>::value_type &v)
+ : insert_copy_proxy<Allocator, Iterator>(v)
+ {}
+};
+
+#endif
+
+}}} //namespace boost { namespace container { namespace dtl {
+
+#endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_CONTAINER_ADVANCED_INSERT_INT_HPP
diff --git a/include/boost/container/detail/algorithm.hpp b/include/boost/container/detail/algorithm.hpp
new file mode 100644
index 0000000..1184422
--- /dev/null
+++ b/include/boost/container/detail/algorithm.hpp
@@ -0,0 +1,157 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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;
+
+template<class Func>
+class binder1st
+{
+ public:
+ typedef typename Func::second_argument_type argument_type;
+ typedef typename Func::result_type result_type;
+
+ binder1st(const Func& func, const typename Func::first_argument_type& arg)
+ : op(func), value(arg)
+ {}
+
+ result_type operator()(const argument_type& arg) const
+ { return op(value, arg); }
+
+ result_type operator()(argument_type& arg) const
+ { return op(value, arg); }
+
+ private:
+ Func op;
+ typename Func::first_argument_type value;
+};
+
+template<class Func, class T>
+inline binder1st<Func> bind1st(const Func& func, const T& arg)
+{ return boost::container::binder1st<Func>(func, arg); }
+
+template<class Func>
+class binder2nd
+{
+ public:
+ typedef typename Func::first_argument_type argument_type;
+ typedef typename Func::result_type result_type;
+
+ binder2nd(const Func& func, const typename Func::second_argument_type& arg)
+ : op(func), value(arg)
+ {}
+
+ result_type operator()(const argument_type& arg) const
+ { return op(arg, value); }
+
+ result_type operator()(argument_type& arg) const
+ { return op(arg, value); }
+
+ private:
+ Func op;
+ typename Func::second_argument_type value;
+};
+
+template<class Func, class T>
+inline binder2nd<Func> bind2nd(const Func& func, const T& arg)
+{
+ return (boost::container::binder2nd<Func>(func, arg));
+}
+
+template<class Func>
+class unary_negate
+{
+ public:
+ typedef typename Func::argument_type argument_type;
+ typedef typename Func::result_type result_type;
+
+ explicit unary_negate(const Func& func)
+ : m_func(func)
+ {}
+
+ bool operator()(const typename Func::argument_type& arg) const
+ { return !m_func(arg); }
+
+ private:
+ Func m_func;
+};
+
+template<class Func> inline
+unary_negate<Func> not1(const Func& func)
+{
+ return boost::container::unary_negate<Func>(func);
+}
+
+template<class InputIt, class UnaryPredicate>
+InputIt find_if(InputIt first, InputIt last, UnaryPredicate p)
+{
+ for (; first != last; ++first) {
+ if (p(*first)) {
+ return first;
+ }
+ }
+ return last;
+}
+
+template<class InputIt, class ForwardIt, class BinaryPredicate>
+InputIt find_first_of(InputIt first1, InputIt last1, ForwardIt first2, ForwardIt last2, BinaryPredicate p)
+{
+ for (; first1 != last1; ++first1) {
+ for (ForwardIt it = first2; it != last2; ++it) {
+ if (p(*first1, *it)) {
+ return first1;
+ }
+ }
+ }
+ return last1;
+}
+
+template<class ForwardIt1, class ForwardIt2, class BinaryPredicate>
+ForwardIt1 search(ForwardIt1 first1, ForwardIt1 last1,
+ ForwardIt2 first2, ForwardIt2 last2, BinaryPredicate p)
+{
+ for (; ; ++first1) {
+ ForwardIt1 it = first1;
+ for (ForwardIt2 it2 = first2; ; ++it, ++it2) {
+ if (it2 == last2) {
+ return first1;
+ }
+ if (it == last1) {
+ return last1;
+ }
+ if (!p(*it, *it2)) {
+ break;
+ }
+ }
+ }
+}
+
+} //namespace container {
+} //namespace boost {
+
+#endif //#ifndef BOOST_CONTAINER_DETAIL_ALGORITHM_HPP
diff --git a/include/boost/container/detail/alloc_helpers.hpp b/include/boost/container/detail/alloc_helpers.hpp
new file mode 100644
index 0000000..57c59e4
--- /dev/null
+++ b/include/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 dtl {
+
+template<class AllocatorType>
+inline void swap_alloc(AllocatorType &, AllocatorType &, dtl::false_type)
+ BOOST_NOEXCEPT_OR_NOTHROW
+{}
+
+template<class AllocatorType>
+inline void swap_alloc(AllocatorType &l, AllocatorType &r, dtl::true_type)
+{ boost::adl_move_swap(l, r); }
+
+template<class AllocatorType>
+inline void assign_alloc(AllocatorType &, const AllocatorType &, dtl::false_type)
+ BOOST_NOEXCEPT_OR_NOTHROW
+{}
+
+template<class AllocatorType>
+inline void assign_alloc(AllocatorType &l, const AllocatorType &r, dtl::true_type)
+{ l = r; }
+
+template<class AllocatorType>
+inline void move_alloc(AllocatorType &, AllocatorType &, dtl::false_type)
+ BOOST_NOEXCEPT_OR_NOTHROW
+{}
+
+template<class AllocatorType>
+inline void move_alloc(AllocatorType &l, AllocatorType &r, dtl::true_type)
+{ l = ::boost::move(r); }
+
+} //namespace dtl {
+} //namespace container {
+} //namespace boost {
+
+#endif //#ifndef BOOST_CONTAINER_DETAIL_ALLOC_TRAITS_HPP
diff --git a/include/boost/container/detail/alloc_lib.h b/include/boost/container/detail/alloc_lib.h
new file mode 100644
index 0000000..950ff72
--- /dev/null
+++ b/include/boost/container/detail/alloc_lib.h
@@ -0,0 +1,314 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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_ALLOC_LIB_EXT_H
+#define BOOST_CONTAINER_ALLOC_LIB_EXT_H
+
+#include <stddef.h>
+
+#ifdef _MSC_VER
+#pragma warning (push)
+#pragma warning (disable : 4127)
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*!An forward iterator to traverse the elements of a memory chain container.*/
+typedef struct multialloc_node_impl
+{
+ struct multialloc_node_impl *next_node_ptr;
+} boost_cont_memchain_node;
+
+
+/*!An forward iterator to traverse the elements of a memory chain container.*/
+typedef struct multialloc_it_impl
+{
+ boost_cont_memchain_node *node_ptr;
+} boost_cont_memchain_it;
+
+/*!Memory chain: A container holding memory portions allocated by boost_cont_multialloc_nodes
+ and boost_cont_multialloc_arrays functions.*/
+typedef struct boost_cont_memchain_impl
+{
+ size_t num_mem;
+ boost_cont_memchain_node root_node;
+ boost_cont_memchain_node *last_node_ptr;
+} boost_cont_memchain;
+
+/*!Advances the iterator one position so that it points to the next element in the memory chain*/
+#define BOOST_CONTAINER_MEMIT_NEXT(IT) (IT.node_ptr = IT.node_ptr->next_node_ptr)
+
+/*!Returns the address of the memory chain currently pointed by the iterator*/
+#define BOOST_CONTAINER_MEMIT_ADDR(IT) ((void*)IT.node_ptr)
+
+/*!Initializer for an iterator pointing to the position before the first element*/
+#define BOOST_CONTAINER_MEMCHAIN_BEFORE_BEGIN_IT(PMEMCHAIN) { &((PMEMCHAIN)->root_node) }
+
+/*!Initializer for an iterator pointing to the first element*/
+#define BOOST_CONTAINER_MEMCHAIN_BEGIN_IT(PMEMCHAIN) {(PMEMCHAIN)->root_node.next_node_ptr }
+
+/*!Initializer for an iterator pointing to the last element*/
+#define BOOST_CONTAINER_MEMCHAIN_LAST_IT(PMEMCHAIN) {(PMEMCHAIN)->last_node_ptr }
+
+/*!Initializer for an iterator pointing to one past the last element (end iterator)*/
+#define BOOST_CONTAINER_MEMCHAIN_END_IT(PMEMCHAIN) {(boost_cont_memchain_node *)0 }
+
+/*!True if IT is the end iterator, false otherwise*/
+#define BOOST_CONTAINER_MEMCHAIN_IS_END_IT(PMEMCHAIN, IT) (!(IT).node_ptr)
+
+/*!The address of the first memory portion hold by the memory chain*/
+#define BOOST_CONTAINER_MEMCHAIN_FIRSTMEM(PMEMCHAIN)((void*)((PMEMCHAIN)->root_node.next_node_ptr))
+
+/*!The address of the last memory portion hold by the memory chain*/
+#define BOOST_CONTAINER_MEMCHAIN_LASTMEM(PMEMCHAIN) ((void*)((PMEMCHAIN)->last_node_ptr))
+
+/*!The number of memory portions hold by the memory chain*/
+#define BOOST_CONTAINER_MEMCHAIN_SIZE(PMEMCHAIN) ((PMEMCHAIN)->num_mem)
+
+/*!Initializes the memory chain from the first memory portion, the last memory
+ portion and number of portions obtained from another memory chain*/
+#define BOOST_CONTAINER_MEMCHAIN_INIT_FROM(PMEMCHAIN, FIRST, LAST, NUM)\
+ (PMEMCHAIN)->last_node_ptr = (boost_cont_memchain_node *)(LAST), \
+ (PMEMCHAIN)->root_node.next_node_ptr = (boost_cont_memchain_node *)(FIRST), \
+ (PMEMCHAIN)->num_mem = (NUM);\
+/**/
+
+/*!Default initializes a memory chain. Postconditions: begin iterator is end iterator,
+ the number of portions is zero.*/
+#define BOOST_CONTAINER_MEMCHAIN_INIT(PMEMCHAIN)\
+ ((PMEMCHAIN)->root_node.next_node_ptr = 0, (PMEMCHAIN)->last_node_ptr = &((PMEMCHAIN)->root_node), (PMEMCHAIN)->num_mem = 0)\
+/**/
+
+/*!True if the memory chain is empty (holds no memory portions*/
+#define BOOST_CONTAINER_MEMCHAIN_EMPTY(PMEMCHAIN)\
+ ((PMEMCHAIN)->num_mem == 0)\
+/**/
+
+/*!Inserts a new memory portions in the front of the chain*/
+#define BOOST_CONTAINER_MEMCHAIN_PUSH_BACK(PMEMCHAIN, MEM)\
+ do{\
+ boost_cont_memchain *____chain____ = (PMEMCHAIN);\
+ boost_cont_memchain_node *____tmp_mem____ = (boost_cont_memchain_node *)(MEM);\
+ ____chain____->last_node_ptr->next_node_ptr = ____tmp_mem____;\
+ ____tmp_mem____->next_node_ptr = 0;\
+ ____chain____->last_node_ptr = ____tmp_mem____;\
+ ++____chain____->num_mem;\
+ }while(0)\
+/**/
+
+/*!Inserts a new memory portions in the back of the chain*/
+#define BOOST_CONTAINER_MEMCHAIN_PUSH_FRONT(PMEMCHAIN, MEM)\
+ do{\
+ boost_cont_memchain *____chain____ = (PMEMCHAIN);\
+ boost_cont_memchain_node *____tmp_mem____ = (boost_cont_memchain_node *)(MEM);\
+ boost_cont_memchain *____root____ = &((PMEMCHAIN)->root_node);\
+ if(!____chain____->root_node.next_node_ptr){\
+ ____chain____->last_node_ptr = ____tmp_mem____;\
+ }\
+ boost_cont_memchain_node *____old_first____ = ____root____->next_node_ptr;\
+ ____tmp_mem____->next_node_ptr = ____old_first____;\
+ ____root____->next_node_ptr = ____tmp_mem____;\
+ ++____chain____->num_mem;\
+ }while(0)\
+/**/
+
+/*!Erases the memory portion after the portion pointed by BEFORE_IT from the memory chain*/
+/*!Precondition: BEFORE_IT must be a valid iterator of the memory chain and it can't be the end iterator*/
+#define BOOST_CONTAINER_MEMCHAIN_ERASE_AFTER(PMEMCHAIN, BEFORE_IT)\
+ do{\
+ boost_cont_memchain *____chain____ = (PMEMCHAIN);\
+ boost_cont_memchain_node *____prev_node____ = (BEFORE_IT).node_ptr;\
+ boost_cont_memchain_node *____erase_node____ = ____prev_node____->next_node_ptr;\
+ if(____chain____->last_node_ptr == ____erase_node____){\
+ ____chain____->last_node_ptr = &____chain____->root_node;\
+ }\
+ ____prev_node____->next_node_ptr = ____erase_node____->next_node_ptr;\
+ --____chain____->num_mem;\
+ }while(0)\
+/**/
+
+/*!Erases the first portion from the memory chain.
+ Precondition: the memory chain must not be empty*/
+#define BOOST_CONTAINER_MEMCHAIN_POP_FRONT(PMEMCHAIN)\
+ do{\
+ boost_cont_memchain *____chain____ = (PMEMCHAIN);\
+ boost_cont_memchain_node *____prev_node____ = &____chain____->root_node;\
+ boost_cont_memchain_node *____erase_node____ = ____prev_node____->next_node_ptr;\
+ if(____chain____->last_node_ptr == ____erase_node____){\
+ ____chain____->last_node_ptr = &____chain____->root_node;\
+ }\
+ ____prev_node____->next_node_ptr = ____erase_node____->next_node_ptr;\
+ --____chain____->num_mem;\
+ }while(0)\
+/**/
+
+/*!Joins two memory chains inserting the portions of the second chain at the back of the first chain*/
+/*
+#define BOOST_CONTAINER_MEMCHAIN_SPLICE_BACK(PMEMCHAIN, PMEMCHAIN2)\
+ do{\
+ boost_cont_memchain *____chain____ = (PMEMCHAIN);\
+ boost_cont_memchain *____chain2____ = (PMEMCHAIN2);\
+ if(!____chain2____->root_node.next_node_ptr){\
+ break;\
+ }\
+ else if(!____chain____->first_mem){\
+ ____chain____->first_mem = ____chain2____->first_mem;\
+ ____chain____->last_node_ptr = ____chain2____->last_node_ptr;\
+ ____chain____->num_mem = ____chain2____->num_mem;\
+ BOOST_CONTAINER_MEMCHAIN_INIT(*____chain2____);\
+ }\
+ else{\
+ ____chain____->last_node_ptr->next_node_ptr = ____chain2____->first_mem;\
+ ____chain____->last_node_ptr = ____chain2____->last_node_ptr;\
+ ____chain____->num_mem += ____chain2____->num_mem;\
+ }\
+ }while(0)\*/
+/**/
+
+/*!Joins two memory chains inserting the portions of the second chain at the back of the first chain*/
+#define BOOST_CONTAINER_MEMCHAIN_INCORPORATE_AFTER(PMEMCHAIN, BEFORE_IT, FIRST, BEFORELAST, NUM)\
+ do{\
+ boost_cont_memchain *____chain____ = (PMEMCHAIN);\
+ boost_cont_memchain_node *____pnode____ = (BEFORE_IT).node_ptr;\
+ boost_cont_memchain_node *____next____ = ____pnode____->next_node_ptr;\
+ boost_cont_memchain_node *____first____ = (boost_cont_memchain_node *)(FIRST);\
+ boost_cont_memchain_node *____blast____ = (boost_cont_memchain_node *)(BEFORELAST);\
+ size_t ____num____ = (NUM);\
+ if(!____num____){\
+ break;\
+ }\
+ if(____pnode____ == ____chain____->last_node_ptr){\
+ ____chain____->last_node_ptr = ____blast____;\
+ }\
+ ____pnode____->next_node_ptr = ____first____;\
+ ____blast____->next_node_ptr = ____next____;\
+ ____chain____->num_mem += ____num____;\
+ }while(0)\
+/**/
+
+/*!Indicates the all elements allocated by boost_cont_multialloc_nodes or boost_cont_multialloc_arrays
+ must be contiguous.*/
+#define DL_MULTIALLOC_ALL_CONTIGUOUS ((size_t)(-1))
+
+/*!Indicates the number of contiguous elements allocated by boost_cont_multialloc_nodes or boost_cont_multialloc_arrays
+ should be selected by those functions.*/
+#define DL_MULTIALLOC_DEFAULT_CONTIGUOUS ((size_t)(0))
+
+typedef struct boost_cont_malloc_stats_impl
+{
+ size_t max_system_bytes;
+ size_t system_bytes;
+ size_t in_use_bytes;
+} boost_cont_malloc_stats_t;
+
+typedef unsigned int allocation_type;
+
+enum
+{
+ // constants for allocation commands
+ BOOST_CONTAINER_ALLOCATE_NEW = 0X01,
+ BOOST_CONTAINER_EXPAND_FWD = 0X02,
+ BOOST_CONTAINER_EXPAND_BWD = 0X04,
+ BOOST_CONTAINER_SHRINK_IN_PLACE = 0X08,
+ BOOST_CONTAINER_NOTHROW_ALLOCATION = 0X10,
+// BOOST_CONTAINER_ZERO_MEMORY = 0X20,
+ BOOST_CONTAINER_TRY_SHRINK_IN_PLACE = 0X40,
+ BOOST_CONTAINER_EXPAND_BOTH = BOOST_CONTAINER_EXPAND_FWD | BOOST_CONTAINER_EXPAND_BWD,
+ BOOST_CONTAINER_EXPAND_OR_NEW = BOOST_CONTAINER_ALLOCATE_NEW | BOOST_CONTAINER_EXPAND_BOTH
+};
+
+//#define BOOST_CONTAINERDLMALLOC__FOOTERS
+#ifndef BOOST_CONTAINERDLMALLOC__FOOTERS
+enum { BOOST_CONTAINER_ALLOCATION_PAYLOAD = sizeof(size_t) };
+#else
+enum { BOOST_CONTAINER_ALLOCATION_PAYLOAD = sizeof(size_t)*2 };
+#endif
+
+typedef struct boost_cont_command_ret_impl
+{
+ void *first;
+ int second;
+}boost_cont_command_ret_t;
+
+size_t boost_cont_size(const void *p);
+
+void* boost_cont_malloc(size_t bytes);
+
+void boost_cont_free(void* mem);
+
+void* boost_cont_memalign(size_t bytes, size_t alignment);
+
+int boost_cont_multialloc_nodes
+ (size_t n_elements, size_t elem_size, size_t contiguous_elements, boost_cont_memchain *pchain);
+
+int boost_cont_multialloc_arrays
+ (size_t n_elements, const size_t *sizes, size_t sizeof_element, size_t contiguous_elements, boost_cont_memchain *pchain);
+
+void boost_cont_multidealloc(boost_cont_memchain *pchain);
+
+size_t boost_cont_footprint();
+
+size_t boost_cont_allocated_memory();
+
+size_t boost_cont_chunksize(const void *p);
+
+int boost_cont_all_deallocated();
+
+boost_cont_malloc_stats_t boost_cont_malloc_stats();
+
+size_t boost_cont_in_use_memory();
+
+int boost_cont_trim(size_t pad);
+
+int boost_cont_mallopt(int parameter_number, int parameter_value);
+
+int boost_cont_grow
+ (void* oldmem, size_t minbytes, size_t maxbytes, size_t *received);
+
+int boost_cont_shrink
+ (void* oldmem, size_t minbytes, size_t maxbytes, size_t *received, int do_commit);
+
+void* boost_cont_alloc
+ (size_t minbytes, size_t preferred_bytes, size_t *received_bytes);
+
+int boost_cont_malloc_check();
+
+boost_cont_command_ret_t boost_cont_allocation_command
+ ( allocation_type command
+ , size_t sizeof_object
+ , size_t limit_objects
+ , size_t preferred_objects
+ , size_t *received_objects
+ , void *reuse_ptr
+ );
+
+void *boost_cont_sync_create();
+
+void boost_cont_sync_destroy(void *sync);
+
+int boost_cont_sync_lock(void *sync);
+
+void boost_cont_sync_unlock(void *sync);
+
+int boost_cont_global_sync_lock();
+
+void boost_cont_global_sync_unlock();
+
+#ifdef __cplusplus
+} //extern "C" {
+#endif
+
+#ifdef _MSC_VER
+#pragma warning (pop)
+#endif
+
+
+#endif //#define BOOST_CONTAINERDLMALLOC__EXT_H
diff --git a/include/boost/container/detail/allocation_type.hpp b/include/boost/container/detail/allocation_type.hpp
new file mode 100644
index 0000000..1e8aa67
--- /dev/null
+++ b/include/boost/container/detail/allocation_type.hpp
@@ -0,0 +1,58 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// (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_ALLOCATION_TYPE_HPP
+#define BOOST_CONTAINER_ALLOCATION_TYPE_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+
+namespace boost {
+namespace container {
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+enum allocation_type_v
+{
+ // constants for allocation commands
+ allocate_new_v = 0x01,
+ expand_fwd_v = 0x02,
+ expand_bwd_v = 0x04,
+// expand_both = expand_fwd | expand_bwd,
+// expand_or_new = allocate_new | expand_both,
+ shrink_in_place_v = 0x08,
+ nothrow_allocation_v = 0x10,
+ zero_memory_v = 0x20,
+ try_shrink_in_place_v = 0x40
+};
+
+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;
+static const allocation_type expand_bwd = (allocation_type)expand_bwd_v;
+static const allocation_type shrink_in_place = (allocation_type)shrink_in_place_v;
+static const allocation_type try_shrink_in_place= (allocation_type)try_shrink_in_place_v;
+static const allocation_type nothrow_allocation = (allocation_type)nothrow_allocation_v;
+static const allocation_type zero_memory = (allocation_type)zero_memory_v;
+
+} //namespace container {
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //BOOST_CONTAINER_ALLOCATION_TYPE_HPP
diff --git a/include/boost/container/detail/allocator_version_traits.hpp b/include/boost/container/detail/allocator_version_traits.hpp
new file mode 100644
index 0000000..18460bd
--- /dev/null
+++ b/include/boost/container/detail/allocator_version_traits.hpp
@@ -0,0 +1,162 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2012-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_ALLOCATOR_VERSION_TRAITS_HPP
+#define BOOST_CONTAINER_DETAIL_ALLOCATOR_VERSION_TRAITS_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/allocator_traits.hpp> //allocator_traits
+#include <boost/container/throw_exception.hpp>
+#include <boost/container/detail/multiallocation_chain.hpp> //multiallocation_chain
+#include <boost/container/detail/version_type.hpp> //version_type
+#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 <boost/core/no_exceptions_support.hpp> //BOOST_TRY
+
+namespace boost {
+namespace container {
+namespace dtl {
+
+template<class Allocator, unsigned Version = boost::container::dtl::version<Allocator>::value>
+struct allocator_version_traits
+{
+ typedef ::boost::container::dtl::integral_constant
+ <unsigned, Version> alloc_version;
+
+ typedef typename Allocator::multiallocation_chain multiallocation_chain;
+
+ typedef typename boost::container::allocator_traits<Allocator>::pointer pointer;
+ typedef typename boost::container::allocator_traits<Allocator>::size_type size_type;
+
+ //Node allocation interface
+ static pointer allocate_one(Allocator &a)
+ { return a.allocate_one(); }
+
+ static void deallocate_one(Allocator &a, const pointer &p)
+ { a.deallocate_one(p); }
+
+ static void allocate_individual(Allocator &a, size_type n, multiallocation_chain &m)
+ { return a.allocate_individual(n, m); }
+
+ static void deallocate_individual(Allocator &a, multiallocation_chain &holder)
+ { a.deallocate_individual(holder); }
+
+ 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>
+struct allocator_version_traits<Allocator, 1>
+{
+ typedef ::boost::container::dtl::integral_constant
+ <unsigned, 1> alloc_version;
+
+ typedef typename boost::container::allocator_traits<Allocator>::pointer pointer;
+ typedef typename boost::container::allocator_traits<Allocator>::size_type size_type;
+ typedef typename boost::container::allocator_traits<Allocator>::value_type value_type;
+
+ typedef typename boost::intrusive::pointer_traits<pointer>::
+ template rebind_pointer<void>::type void_ptr;
+ typedef dtl::basic_multiallocation_chain
+ <void_ptr> multialloc_cached_counted;
+ typedef boost::container::dtl::
+ transform_multiallocation_chain
+ < multialloc_cached_counted, value_type> multiallocation_chain;
+
+ //Node allocation interface
+ static pointer allocate_one(Allocator &a)
+ { return a.allocate(1); }
+
+ static void deallocate_one(Allocator &a, const pointer &p)
+ { a.deallocate(p, 1); }
+
+ static void deallocate_individual(Allocator &a, multiallocation_chain &holder)
+ {
+ size_type n = holder.size();
+ typename multiallocation_chain::iterator it = holder.begin();
+ while(n--){
+ pointer p = boost::intrusive::pointer_traits<pointer>::pointer_to(*it);
+ ++it;
+ a.deallocate(p, 1);
+ }
+ }
+
+ struct allocate_individual_rollback
+ {
+ allocate_individual_rollback(Allocator &a, multiallocation_chain &chain)
+ : mr_a(a), mp_chain(&chain)
+ {}
+
+ ~allocate_individual_rollback()
+ {
+ if(mp_chain)
+ allocator_version_traits::deallocate_individual(mr_a, *mp_chain);
+ }
+
+ void release()
+ {
+ mp_chain = 0;
+ }
+
+ Allocator &mr_a;
+ multiallocation_chain * mp_chain;
+ };
+
+ static void allocate_individual(Allocator &a, size_type n, multiallocation_chain &m)
+ {
+ allocate_individual_rollback rollback(a, m);
+ while(n--){
+ m.push_front(a.allocate(1));
+ }
+ rollback.release();
+ }
+
+ static pointer allocation_command(Allocator &a, allocation_type command,
+ size_type, size_type &prefer_in_recvd_out_size, pointer &reuse)
+ {
+ pointer ret = pointer();
+ if(BOOST_UNLIKELY(!(command & allocate_new) && !(command & nothrow_allocation))){
+ throw_logic_error("version 1 allocator without allocate_new flag");
+ }
+ else{
+ BOOST_TRY{
+ ret = a.allocate(prefer_in_recvd_out_size);
+ }
+ BOOST_CATCH(...){
+ if(!(command & nothrow_allocation)){
+ BOOST_RETHROW
+ }
+ }
+ BOOST_CATCH_END
+ reuse = pointer();
+ }
+ return ret;
+ }
+};
+
+} //namespace dtl {
+} //namespace container {
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif // ! defined(BOOST_CONTAINER_DETAIL_ALLOCATOR_VERSION_TRAITS_HPP)
diff --git a/include/boost/container/detail/auto_link.hpp b/include/boost/container/detail/auto_link.hpp
new file mode 100644
index 0000000..264b1ba
--- /dev/null
+++ b/include/boost/container/detail/auto_link.hpp
@@ -0,0 +1,51 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2007-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_AUTO_LINK_HPP_INCLUDED
+#define BOOST_CONTAINER_DETAIL_AUTO_LINK_HPP_INCLUDED
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+//Define BOOST_CONTAINER_DYNAMIC_LINKING which is independent from BOOST_*_NO_LIB
+//and is needed is some tests that need to disable some checks (like operator new replacements)
+//that don't work across DLL boundaries
+#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_CONTAINER_DYN_LINK)
+# define BOOST_CONTAINER_DYNAMIC_LINKING
+#endif
+
+//
+// Automatically link to the correct build variant where possible.
+//
+#if !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_CONTAINER_NO_LIB) && !defined(BOOST_CONTAINER_SOURCE)
+//
+// Set the name of our library, this will get undef'ed by auto_link.hpp
+// once it's done with it:
+//
+#define BOOST_LIB_NAME boost_container
+
+//
+// If we're importing code from a dll, then tell auto_link.hpp about it:
+//
+#if defined(BOOST_CONTAINER_DYNAMIC_LINKING)
+# define BOOST_DYN_LINK
+#endif
+
+//
+// And include the header that does the work:
+//
+#include <boost/config/auto_link.hpp>
+#endif // auto-linking disabled
+
+#endif //#ifndef BOOST_CONTAINER_DETAIL_AUTO_LINK_HPP_INCLUDED
diff --git a/include/boost/container/detail/block_list.hpp b/include/boost/container/detail/block_list.hpp
new file mode 100644
index 0000000..1a6057c
--- /dev/null
+++ b/include/boost/container/detail/block_list.hpp
@@ -0,0 +1,139 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_DETAIL_BLOCK_LIST_HEADER
+#define BOOST_CONTAINER_DETAIL_BLOCK_LIST_HEADER
+
+#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/pmr/memory_resource.hpp>
+#include <boost/container/throw_exception.hpp>
+#include <boost/intrusive/circular_list_algorithms.hpp>
+#include <boost/move/detail/type_traits.hpp>
+#include <boost/assert.hpp>
+
+#include <cstddef>
+
+namespace boost {
+namespace container {
+namespace pmr {
+
+struct list_node
+{
+ list_node *next;
+ list_node *previous;
+};
+
+struct list_node_traits
+{
+ typedef list_node node;
+ typedef list_node* node_ptr;
+ typedef const list_node* const_node_ptr;
+
+ static node_ptr get_next(const_node_ptr n)
+ { return n->next; }
+
+ static node_ptr get_previous(const_node_ptr n)
+ { return n->previous; }
+
+ static void set_next(const node_ptr & n, const node_ptr & next)
+ { n->next = next; }
+
+ static void set_previous(const node_ptr & n, const node_ptr & previous)
+ { n->previous = previous; }
+};
+
+struct block_list_header
+ : public list_node
+{
+ std::size_t size;
+};
+
+typedef bi::circular_list_algorithms<list_node_traits> list_algo;
+
+
+template<class DerivedFromBlockListHeader = block_list_header>
+class block_list_base
+{
+ list_node m_list;
+
+ static const std::size_t MaxAlignMinus1 = memory_resource::max_align-1u;
+
+ public:
+
+ static const std::size_t header_size = std::size_t(sizeof(DerivedFromBlockListHeader) + MaxAlignMinus1) & std::size_t(~MaxAlignMinus1);
+
+ explicit block_list_base()
+ { list_algo::init_header(&m_list); }
+
+ #if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ block_list_base(const block_list_base&) = delete;
+ block_list_base operator=(const block_list_base&) = delete;
+ #else
+ private:
+ block_list_base (const block_list_base&);
+ block_list_base operator=(const block_list_base&);
+ public:
+ #endif
+
+ ~block_list_base()
+ {}
+
+ void *allocate(std::size_t size, memory_resource &mr)
+ {
+ if((size_t(-1) - header_size) < size)
+ throw_bad_alloc();
+ void *p = mr.allocate(size+header_size);
+ block_list_header &mb = *::new((void*)p) DerivedFromBlockListHeader;
+ mb.size = size+header_size;
+ list_algo::link_after(&m_list, &mb);
+ return (char *)p + header_size;
+ }
+
+ void deallocate(void *p, memory_resource &mr) BOOST_NOEXCEPT
+ {
+ DerivedFromBlockListHeader *pheader = static_cast<DerivedFromBlockListHeader*>
+ (static_cast<void*>((char*)p - header_size));
+ list_algo::unlink(pheader);
+ const std::size_t size = pheader->size;
+ static_cast<DerivedFromBlockListHeader*>(pheader)->~DerivedFromBlockListHeader();
+ mr.deallocate(pheader, size, memory_resource::max_align);
+ }
+
+ void release(memory_resource &mr) BOOST_NOEXCEPT
+ {
+ list_node *n = list_algo::node_traits::get_next(&m_list);
+ while(n != &m_list){
+ DerivedFromBlockListHeader &d = static_cast<DerivedFromBlockListHeader&>(*n);
+ n = list_algo::node_traits::get_next(n);
+ std::size_t size = d.size;
+ d.~DerivedFromBlockListHeader();
+ mr.deallocate(reinterpret_cast<char*>(&d), size, memory_resource::max_align);
+ }
+ list_algo::init_header(&m_list);
+ }
+};
+
+} //namespace pmr {
+} //namespace container {
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //BOOST_CONTAINER_DETAIL_BLOCK_LIST_HEADER
diff --git a/include/boost/container/detail/block_slist.hpp b/include/boost/container/detail/block_slist.hpp
new file mode 100644
index 0000000..278e641
--- /dev/null
+++ b/include/boost/container/detail/block_slist.hpp
@@ -0,0 +1,157 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_DETAIL_BLOCK_SLIST_HEADER
+#define BOOST_CONTAINER_DETAIL_BLOCK_SLIST_HEADER
+
+#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/pmr/memory_resource.hpp>
+#include <boost/container/throw_exception.hpp>
+
+#include <boost/move/detail/type_traits.hpp>
+#include <boost/intrusive/linear_slist_algorithms.hpp>
+#include <boost/assert.hpp>
+
+#include <cstddef>
+
+namespace boost {
+namespace container {
+namespace pmr {
+
+struct slist_node
+{
+ slist_node *next;
+};
+
+struct slist_node_traits
+{
+ typedef slist_node node;
+ typedef slist_node* node_ptr;
+ typedef const slist_node* const_node_ptr;
+
+ static node_ptr get_next(const_node_ptr n)
+ { return n->next; }
+
+ static void set_next(const node_ptr & n, const node_ptr & next)
+ { n->next = next; }
+};
+
+struct block_slist_header
+ : public slist_node
+{
+ std::size_t size;
+};
+
+typedef bi::linear_slist_algorithms<slist_node_traits> slist_algo;
+
+template<class DerivedFromBlockSlistHeader = block_slist_header>
+class block_slist_base
+{
+ slist_node m_slist;
+
+ static const std::size_t MaxAlignMinus1 = memory_resource::max_align-1u;
+
+ public:
+
+ static const std::size_t header_size = std::size_t(sizeof(DerivedFromBlockSlistHeader) + MaxAlignMinus1) & std::size_t(~MaxAlignMinus1);
+
+ explicit block_slist_base()
+ { slist_algo::init_header(&m_slist); }
+
+ #if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ block_slist_base(const block_slist_base&) = delete;
+ block_slist_base operator=(const block_slist_base&) = delete;
+ #else
+ private:
+ block_slist_base (const block_slist_base&);
+ block_slist_base operator=(const block_slist_base&);
+ public:
+ #endif
+
+ ~block_slist_base()
+ {}
+
+ void *allocate(std::size_t size, memory_resource &mr)
+ {
+ if((size_t(-1) - header_size) < size)
+ throw_bad_alloc();
+ void *p = mr.allocate(size+header_size);
+ block_slist_header &mb = *::new((void*)p) DerivedFromBlockSlistHeader;
+ mb.size = size+header_size;
+ slist_algo::link_after(&m_slist, &mb);
+ return (char *)p + header_size;
+ }
+
+ void release(memory_resource &mr) BOOST_NOEXCEPT
+ {
+ slist_node *n = slist_algo::node_traits::get_next(&m_slist);
+ while(n){
+ DerivedFromBlockSlistHeader &d = static_cast<DerivedFromBlockSlistHeader&>(*n);
+ n = slist_algo::node_traits::get_next(n);
+ std::size_t size = d.block_slist_header::size;
+ d.~DerivedFromBlockSlistHeader();
+ mr.deallocate(reinterpret_cast<char*>(&d), size, memory_resource::max_align);
+ }
+ slist_algo::init_header(&m_slist);
+ }
+};
+
+class block_slist
+ : public block_slist_base<>
+{
+ memory_resource &m_upstream_rsrc;
+
+ public:
+
+ explicit block_slist(memory_resource &upstream_rsrc)
+ : block_slist_base<>(), m_upstream_rsrc(upstream_rsrc)
+ {}
+
+ #if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ block_slist(const block_slist&) = delete;
+ block_slist operator=(const block_slist&) = delete;
+ #else
+ private:
+ block_slist (const block_slist&);
+ block_slist operator=(const block_slist&);
+ public:
+ #endif
+
+ ~block_slist()
+ { this->release(); }
+
+ void *allocate(std::size_t size)
+ { return this->block_slist_base<>::allocate(size, m_upstream_rsrc); }
+
+ void release() BOOST_NOEXCEPT
+ { return this->block_slist_base<>::release(m_upstream_rsrc); }
+
+ memory_resource& upstream_resource() const BOOST_NOEXCEPT
+ { return m_upstream_rsrc; }
+};
+
+} //namespace pmr {
+} //namespace container {
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //BOOST_CONTAINER_DETAIL_BLOCK_SLIST_HEADER
diff --git a/include/boost/container/detail/compare_functors.hpp b/include/boost/container/detail/compare_functors.hpp
new file mode 100644
index 0000000..28f9093
--- /dev/null
+++ b/include/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.get_data(), b.get_data()); }
+
+ bool operator()(const Node &a) const
+ { return static_cast<const Pred&>(*this)(a.get_data()); }
+
+ bool operator()(const Node &a, const Node &b)
+ { return static_cast<Pred&>(*this)(a.get_data(), b.get_data()); }
+
+ bool operator()(const Node &a)
+ { return static_cast<Pred&>(*this)(a.get_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/include/boost/container/detail/config_begin.hpp b/include/boost/container/detail/config_begin.hpp
new file mode 100644
index 0000000..4df9e35
--- /dev/null
+++ b/include/boost/container/detail/config_begin.hpp
@@ -0,0 +1,53 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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_CONTAINER_DETAIL_CONFIG_INCLUDED
+#define BOOST_CONTAINER_CONTAINER_DETAIL_CONFIG_INCLUDED
+#ifndef BOOST_CONFIG_HPP
+#include <boost/config.hpp>
+#endif
+
+#endif //BOOST_CONTAINER_CONTAINER_DETAIL_CONFIG_INCLUDED
+
+#ifdef BOOST_MSVC
+ #pragma warning (push)
+ #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 : 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 : 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow)
+ #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 : 4714) // "function": marked as __forceinline 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
+
+#endif //BOOST_MSVC
diff --git a/include/boost/container/detail/config_end.hpp b/include/boost/container/detail/config_end.hpp
new file mode 100644
index 0000000..f93c8f6
--- /dev/null
+++ b/include/boost/container/detail/config_end.hpp
@@ -0,0 +1,13 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+#if defined BOOST_MSVC
+ #pragma warning (pop)
+#endif
+
diff --git a/include/boost/container/detail/construct_in_place.hpp b/include/boost/container/detail/construct_in_place.hpp
new file mode 100644
index 0000000..b131f06
--- /dev/null
+++ b/include/boost/container/detail/construct_in_place.hpp
@@ -0,0 +1,96 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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>
+#include <boost/container/detail/value_init.hpp>
+
+namespace boost {
+namespace container {
+
+//In place construction
+
+template<class Allocator, class T, class InpIt>
+BOOST_CONTAINER_FORCEINLINE 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>
+BOOST_CONTAINER_FORCEINLINE 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>
+BOOST_CONTAINER_FORCEINLINE 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>
+BOOST_CONTAINER_FORCEINLINE void construct_in_place(Allocator &a, T *dest, emplace_iterator<U, EF, D> ei)
+{
+ ei.construct_in_place(a, dest);
+}
+
+//Assignment
+
+template<class DstIt, class InpIt>
+BOOST_CONTAINER_FORCEINLINE void assign_in_place(DstIt dest, InpIt source)
+{ *dest = *source; }
+
+template<class DstIt, class U, class D>
+BOOST_CONTAINER_FORCEINLINE void assign_in_place(DstIt dest, value_init_construct_iterator<U, D>)
+{
+ dtl::value_init<U> val;
+ *dest = boost::move(val.get());
+}
+
+template <class DstIt, class Difference>
+class default_init_construct_iterator;
+
+template<class DstIt, class U, class D>
+BOOST_CONTAINER_FORCEINLINE void assign_in_place(DstIt dest, default_init_construct_iterator<U, D>)
+{
+ U u;
+ *dest = boost::move(u);
+}
+
+template <class T, class EmplaceFunctor, class Difference>
+class emplace_iterator;
+
+template<class DstIt, class U, class EF, class D>
+BOOST_CONTAINER_FORCEINLINE void assign_in_place(DstIt dest, emplace_iterator<U, EF, D> ei)
+{
+ ei.assign_in_place(dest);
+}
+
+} //namespace container {
+} //namespace boost {
+
+#endif //#ifndef BOOST_CONTAINER_DETAIL_CONSTRUCT_IN_PLACE_HPP
diff --git a/include/boost/container/detail/container_or_allocator_rebind.hpp b/include/boost/container/detail/container_or_allocator_rebind.hpp
new file mode 100644
index 0000000..d74df6c
--- /dev/null
+++ b/include/boost/container/detail/container_or_allocator_rebind.hpp
@@ -0,0 +1,49 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2017-2017. 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_CONTAINER_OR_ALLOCATOR_REBIND_HPP
+#define BOOST_CONTAINER_DETAIL_CONTAINER_OR_ALLOCATOR_REBIND_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/container_rebind.hpp>
+#include <boost/container/detail/is_container.hpp>
+
+namespace boost {
+namespace container {
+namespace dtl {
+
+template<class AllocatorOrContainer, class ToType, bool = is_container<AllocatorOrContainer>::value>
+struct container_or_allocator_rebind_impl
+ : container_rebind<AllocatorOrContainer, ToType>
+{};
+
+template<class AllocatorOrContainer, class ToType>
+struct container_or_allocator_rebind_impl<AllocatorOrContainer, ToType, false>
+ : allocator_traits<AllocatorOrContainer>::template portable_rebind_alloc<ToType>
+
+{};
+
+template<class AllocatorOrContainer, class ToType>
+struct container_or_allocator_rebind
+ : container_or_allocator_rebind_impl<AllocatorOrContainer, ToType>
+{};
+
+} //namespace dtl {
+} //namespace container {
+} //namespace boost {
+
+#endif //#ifndef BOOST_CONTAINER_DETAIL_CONTAINER_OR_ALLOCATOR_REBIND_HPP
diff --git a/include/boost/container/detail/container_rebind.hpp b/include/boost/container/detail/container_rebind.hpp
new file mode 100644
index 0000000..0ebb478
--- /dev/null
+++ b/include/boost/container/detail/container_rebind.hpp
@@ -0,0 +1,258 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2017-2017. 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_CONTAINER_REBIND_HPP
+#define BOOST_CONTAINER_DETAIL_CONTAINER_REBIND_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>
+
+
+namespace boost {
+namespace container {
+namespace dtl {
+
+ template <class Cont, class U>
+ struct container_rebind;
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ template <template <class, class, class...> class Cont, typename V, typename A, class... An, class U>
+ struct container_rebind<Cont<V, A, An...>, U>
+ {
+ typedef Cont<U, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, An...> type;
+ };
+
+ //Needed for non-conforming compilers like GCC 4.3
+ template <template <class, class> class Cont, typename V, typename A, class U>
+ struct container_rebind<Cont<V, A>, U>
+ {
+ typedef Cont<U, typename allocator_traits<A>::template portable_rebind_alloc<U>::type> type;
+ };
+
+ template <template <class> class Cont, typename V, class U>
+ struct container_rebind<Cont<V>, U>
+ {
+ typedef Cont<U> type;
+ };
+
+ //for small_vector,static_vector
+
+ template <template <class, std::size_t, class, class...> class Cont, typename V, std::size_t N, typename A, class... An, class U>
+ struct container_rebind<Cont<V, N, A, An...>, U>
+ {
+ typedef Cont<U, N, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, An...> type;
+ };
+
+ //Needed for non-conforming compilers like GCC 4.3
+ template <template <class, std::size_t, class> class Cont, typename V, std::size_t N, typename A, class U>
+ struct container_rebind<Cont<V, N, A>, U>
+ {
+ typedef Cont<U, N, typename allocator_traits<A>::template portable_rebind_alloc<U>::type> type;
+ };
+
+ template <template <class, std::size_t> class Cont, typename V, std::size_t N, class U>
+ struct container_rebind<Cont<V, N>, U>
+ {
+ typedef Cont<U, N> type;
+ };
+
+#else //C++03 compilers
+
+ template <template <class> class Cont //0arg
+ , typename V
+ , class U>
+ struct container_rebind<Cont<V>, U>
+ {
+ typedef Cont<U> type;
+ };
+
+ template <template <class, class> class Cont //0arg
+ , typename V, typename A
+ , class U>
+ struct container_rebind<Cont<V, A>, U>
+ {
+ typedef Cont<U, typename allocator_traits<A>::template portable_rebind_alloc<U>::type> type;
+ };
+
+ template <template <class, class, class> class Cont //1arg
+ , typename V, typename A, class P0
+ , class U>
+ struct container_rebind<Cont<V, A, P0>, U>
+ {
+ typedef Cont<U, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0> type;
+ };
+
+ template <template <class, class, class, class> class Cont //2arg
+ , typename V, typename A, class P0, class P1
+ , class U>
+ struct container_rebind<Cont<V, A, P0, P1>, U>
+ {
+ typedef Cont<U, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1> type;
+ };
+
+ template <template <class, class, class, class, class> class Cont //3arg
+ , typename V, typename A, class P0, class P1, class P2
+ , class U>
+ struct container_rebind<Cont<V, A, P0, P1, P2>, U>
+ {
+ typedef Cont<U, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1, P2> type;
+ };
+
+ template <template <class, class, class, class, class, class> class Cont //4arg
+ , typename V, typename A, class P0, class P1, class P2, class P3
+ , class U>
+ struct container_rebind<Cont<V, A, P0, P1, P2, P3>, U>
+ {
+ typedef Cont<U, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3> type;
+ };
+
+ template <template <class, class, class, class, class, class, class> class Cont //5arg
+ , typename V, typename A, class P0, class P1, class P2, class P3, class P4
+ , class U>
+ struct container_rebind<Cont<V, A, P0, P1, P2, P3, P4>, U>
+ {
+ typedef Cont<U, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4> type;
+ };
+
+ template <template <class, class, class, class, class, class, class, class> class Cont //6arg
+ , typename V, typename A, class P0, class P1, class P2, class P3, class P4, class P5
+ , class U>
+ struct container_rebind<Cont<V, A, P0, P1, P2, P3, P4, P5>, U>
+ {
+ typedef Cont<U, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4, P5> type;
+ };
+
+ template <template <class, class, class, class, class, class, class, class, class> class Cont //7arg
+ , typename V, typename A, class P0, class P1, class P2, class P3, class P4, class P5, class P6
+ , class U>
+ struct container_rebind<Cont<V, A, P0, P1, P2, P3, P4, P5, P6>, U>
+ {
+ typedef Cont<U, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4, P5, P6> type;
+ };
+
+ template <template <class, class, class, class, class, class, class, class, class, class> class Cont //8arg
+ , typename V, typename A, class P0, class P1, class P2, class P3, class P4, class P5, class P6, class P7
+ , class U>
+ struct container_rebind<Cont<V, A, P0, P1, P2, P3, P4, P5, P6, P7>, U>
+ {
+ typedef Cont<U, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4, P5, P6, P7> type;
+ };
+
+ template <template <class, class, class, class, class, class, class, class, class, class, class> class Cont //9arg
+ , typename V, typename A, class P0, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8
+ , class U>
+ struct container_rebind<Cont<V, A, P0, P1, P2, P3, P4, P5, P6, P7, P8>, U>
+ {
+ typedef Cont<U, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4, P5, P6, P7, P8> type;
+ };
+
+ //For small_vector/static_vector
+ template <template <class, std::size_t> class Cont //0arg
+ , typename V, std::size_t N
+ , class U>
+ struct container_rebind<Cont<V, N>, U>
+ {
+ typedef Cont<U, N> type;
+ };
+
+ template <template <class, std::size_t, class> class Cont //0arg
+ , typename V, std::size_t N, typename A
+ , class U>
+ struct container_rebind<Cont<V, N, A>, U>
+ {
+ typedef Cont<U, N, typename allocator_traits<A>::template portable_rebind_alloc<U>::type> type;
+ };
+
+ template <template <class, std::size_t, class, class> class Cont //1arg
+ , typename V, std::size_t N, typename A, class P0
+ , class U>
+ struct container_rebind<Cont<V, N, A, P0>, U>
+ {
+ typedef Cont<U, N, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0> type;
+ };
+
+ template <template <class, std::size_t, class, class, class> class Cont //2arg
+ , typename V, std::size_t N, typename A, class P0, class P1
+ , class U>
+ struct container_rebind<Cont<V, N, A, P0, P1>, U>
+ {
+ typedef Cont<U, N, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1> type;
+ };
+
+ template <template <class, std::size_t, class, class, class, class> class Cont //3arg
+ , typename V, std::size_t N, typename A, class P0, class P1, class P2
+ , class U>
+ struct container_rebind<Cont<V, N, A, P0, P1, P2>, U>
+ {
+ typedef Cont<U, N, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1, P2> type;
+ };
+
+ template <template <class, std::size_t, class, class, class, class, class> class Cont //4arg
+ , typename V, std::size_t N, typename A, class P0, class P1, class P2, class P3
+ , class U>
+ struct container_rebind<Cont<V, N, A, P0, P1, P2, P3>, U>
+ {
+ typedef Cont<U, N, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3> type;
+ };
+
+ template <template <class, std::size_t, class, class, class, class, class, class> class Cont //5arg
+ , typename V, std::size_t N, typename A, class P0, class P1, class P2, class P3, class P4
+ , class U>
+ struct container_rebind<Cont<V, N, A, P0, P1, P2, P3, P4>, U>
+ {
+ typedef Cont<U, N, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4> type;
+ };
+
+ template <template <class, std::size_t, class, class, class, class, class, class, class> class Cont //6arg
+ , typename V, std::size_t N, typename A, class P0, class P1, class P2, class P3, class P4, class P5
+ , class U>
+ struct container_rebind<Cont<V, N, A, P0, P1, P2, P3, P4, P5>, U>
+ {
+ typedef Cont<U, N, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4, P5> type;
+ };
+
+ template <template <class, std::size_t, class, class, class, class, class, class, class, class> class Cont //7arg
+ , typename V, std::size_t N, typename A, class P0, class P1, class P2, class P3, class P4, class P5, class P6
+ , class U>
+ struct container_rebind<Cont<V, N, A, P0, P1, P2, P3, P4, P5, P6>, U>
+ {
+ typedef Cont<U, N, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4, P5, P6> type;
+ };
+
+ template <template <class, std::size_t, class, class, class, class, class, class, class, class, class> class Cont //8arg
+ , typename V, std::size_t N, typename A, class P0, class P1, class P2, class P3, class P4, class P5, class P6, class P7
+ , class U>
+ struct container_rebind<Cont<V, N, A, P0, P1, P2, P3, P4, P5, P6, P7>, U>
+ {
+ typedef Cont<U, N, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4, P5, P6, P7> type;
+ };
+
+ template <template <class, std::size_t, class, class, class, class, class, class, class, class, class, class> class Cont //9arg
+ , typename V, std::size_t N, typename A, class P0, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8
+ , class U>
+ struct container_rebind<Cont<V, N, A, P0, P1, P2, P3, P4, P5, P6, P7, P8>, U>
+ {
+ typedef Cont<U, N, typename allocator_traits<A>::template portable_rebind_alloc<U>::type, P0, P1, P2, P3, P4, P5, P6, P7, P8> type;
+ };
+
+#endif //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+} //namespace dtl {
+} //namespace container {
+} //namespace boost {
+
+#endif //#ifndef BOOST_CONTAINER_DETAIL_CONTAINER_REBIND_HPP
diff --git a/include/boost/container/detail/copy_move_algo.hpp b/include/boost/container/detail/copy_move_algo.hpp
new file mode 100644
index 0000000..f03800a
--- /dev/null
+++ b/include/boost/container/detail/copy_move_algo.hpp
@@ -0,0 +1,1154 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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_COPY_MOVE_ALGO_HPP
+#define BOOST_CONTAINER_DETAIL_COPY_MOVE_ALGO_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+// container
+#include <boost/container/allocator_traits.hpp>
+// container/detail
+#include <boost/container/detail/iterator.hpp>
+#include <boost/move/detail/iterator_to_raw_pointer.hpp>
+#include <boost/container/detail/mpl.hpp>
+#include <boost/container/detail/type_traits.hpp>
+#include <boost/container/detail/construct_in_place.hpp>
+
+// 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>
+// std
+#include <cstring> //for memmove/memcpy
+
+#if defined(BOOST_GCC) && (BOOST_GCC >= 80000)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wclass-memaccess"
+#endif
+
+namespace boost {
+namespace container {
+namespace dtl {
+
+template<class I>
+struct are_elements_contiguous
+{
+ static const bool value = false;
+};
+
+/////////////////////////
+// raw pointers
+/////////////////////////
+
+template<class T>
+struct are_elements_contiguous<T*>
+{
+ static const bool value = true;
+};
+
+/////////////////////////
+// move iterators
+/////////////////////////
+
+template<class It>
+struct are_elements_contiguous< ::boost::move_iterator<It> >
+ : are_elements_contiguous<It>
+{};
+
+} //namespace dtl {
+
+/////////////////////////
+// predeclarations
+/////////////////////////
+
+template <class Pointer, bool IsConst>
+class vec_iterator;
+
+} //namespace container {
+
+namespace interprocess {
+
+template <class PointedType, class DifferenceType, class OffsetType, std::size_t OffsetAlignment>
+class offset_ptr;
+
+} //namespace interprocess {
+
+namespace container {
+
+namespace dtl {
+
+/////////////////////////
+//vector_[const_]iterator
+/////////////////////////
+
+template <class Pointer, bool IsConst>
+struct are_elements_contiguous<boost::container::vec_iterator<Pointer, IsConst> >
+{
+ static const bool value = true;
+};
+
+/////////////////////////
+// offset_ptr
+/////////////////////////
+
+template <class PointedType, class DifferenceType, class OffsetType, std::size_t OffsetAlignment>
+struct are_elements_contiguous< ::boost::interprocess::offset_ptr<PointedType, DifferenceType, OffsetType, OffsetAlignment> >
+{
+ static const bool value = true;
+};
+
+template <typename I, typename O>
+struct are_contiguous_and_same
+ : boost::move_detail::and_
+ < are_elements_contiguous<I>
+ , are_elements_contiguous<O>
+ , is_same< typename remove_const< typename ::boost::container::iterator_traits<I>::value_type >::type
+ , typename ::boost::container::iterator_traits<O>::value_type
+ >
+ >
+{};
+
+template <typename I, typename O>
+struct is_memtransfer_copy_assignable
+ : boost::move_detail::and_
+ < are_contiguous_and_same<I, O>
+ , dtl::is_trivially_copy_assignable< typename ::boost::container::iterator_traits<I>::value_type >
+ >
+{};
+
+template <typename I, typename O>
+struct is_memtransfer_copy_constructible
+ : boost::move_detail::and_
+ < are_contiguous_and_same<I, O>
+ , dtl::is_trivially_copy_constructible< typename ::boost::container::iterator_traits<I>::value_type >
+ >
+{};
+
+template <typename I, typename O, typename R>
+struct enable_if_memtransfer_copy_constructible
+ : enable_if<dtl::is_memtransfer_copy_constructible<I, O>, R>
+{};
+
+template <typename I, typename O, typename R>
+struct disable_if_memtransfer_copy_constructible
+ : disable_if<dtl::is_memtransfer_copy_constructible<I, O>, R>
+{};
+
+template <typename I, typename O, typename R>
+struct enable_if_memtransfer_copy_assignable
+ : enable_if<dtl::is_memtransfer_copy_assignable<I, O>, R>
+{};
+
+template <typename I, typename O, typename R>
+struct disable_if_memtransfer_copy_assignable
+ : disable_if<dtl::is_memtransfer_copy_assignable<I, O>, R>
+{};
+
+template
+ <typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+inline F memmove(I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW
+{
+ typedef typename boost::container::iterator_traits<I>::value_type value_type;
+ typename boost::container::iterator_traits<I>::difference_type n = boost::container::iterator_distance(f, l);
+ if(n){
+ std::memmove(boost::movelib::iterator_to_raw_pointer(r), boost::movelib::iterator_to_raw_pointer(f), sizeof(value_type)*n);
+ boost::container::iterator_advance(r, n);
+ }
+ return r;
+}
+
+template
+ <typename I, // I models InputIterator
+ typename U, // U models unsigned integral constant
+ typename F> // F models ForwardIterator
+F memmove_n(I f, U n, F r) BOOST_NOEXCEPT_OR_NOTHROW
+{
+ typedef typename boost::container::iterator_traits<I>::value_type value_type;
+ if(n){
+ std::memmove(boost::movelib::iterator_to_raw_pointer(r), boost::movelib::iterator_to_raw_pointer(f), sizeof(value_type)*n);
+ boost::container::iterator_advance(r, n);
+ }
+ return r;
+}
+
+template
+ <typename I, // I models InputIterator
+ typename U, // U models unsigned integral constant
+ typename F> // F models ForwardIterator
+I memmove_n_source(I f, U n, F r) BOOST_NOEXCEPT_OR_NOTHROW
+{
+ if(n){
+ typedef typename boost::container::iterator_traits<I>::value_type value_type;
+ std::memmove(boost::movelib::iterator_to_raw_pointer(r), boost::movelib::iterator_to_raw_pointer(f), sizeof(value_type)*n);
+ boost::container::iterator_advance(f, n);
+ }
+ return f;
+}
+
+template
+ <typename I, // I models InputIterator
+ typename U, // U models unsigned integral constant
+ typename F> // F models ForwardIterator
+I memmove_n_source_dest(I f, U n, F &r) BOOST_NOEXCEPT_OR_NOTHROW
+{
+ typedef typename boost::container::iterator_traits<I>::value_type value_type;
+ if(n){
+ std::memmove(boost::movelib::iterator_to_raw_pointer(r), boost::movelib::iterator_to_raw_pointer(f), sizeof(value_type)*n);
+ boost::container::iterator_advance(f, n);
+ boost::container::iterator_advance(r, n);
+ }
+ return f;
+}
+
+template <typename O>
+struct is_memzero_initializable
+{
+ typedef typename ::boost::container::iterator_traits<O>::value_type value_type;
+ static const bool value = are_elements_contiguous<O>::value &&
+ ( dtl::is_integral<value_type>::value || dtl::is_enum<value_type>::value
+ #if defined(BOOST_CONTAINER_MEMZEROED_POINTER_IS_NULL)
+ || dtl::is_pointer<value_type>::value
+ #endif
+ #if defined(BOOST_CONTAINER_MEMZEROED_FLOATING_POINT_IS_ZERO)
+ || dtl::is_floating_point<value_type>::value
+ #endif
+ #if defined(BOOST_CONTAINER_MEMZEROED_FLOATING_POINT_IS_ZERO) && defined(BOOST_CONTAINER_MEMZEROED_POINTER_IS_NULL)
+ || dtl::is_pod<value_type>::value
+ #endif
+ );
+};
+
+template <typename O, typename R>
+struct enable_if_memzero_initializable
+ : enable_if_c<dtl::is_memzero_initializable<O>::value, R>
+{};
+
+template <typename O, typename R>
+struct disable_if_memzero_initializable
+ : enable_if_c<!dtl::is_memzero_initializable<O>::value, R>
+{};
+
+template <typename I, typename R>
+struct enable_if_trivially_destructible
+ : enable_if_c < dtl::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 <!dtl::is_trivially_destructible
+ <typename boost::container::iterator_traits<I>::value_type>::value
+ , R>
+{};
+
+} //namespace dtl {
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// uninitialized_move_alloc
+//
+//////////////////////////////////////////////////////////////////////////////
+
+
+//! <b>Effects</b>:
+//! \code
+//! for (; f != l; ++r, ++f)
+//! allocator_traits::construct(a, &*r, boost::move(*f));
+//! \endcode
+//!
+//! <b>Returns</b>: r
+template
+ <typename Allocator,
+ typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+inline typename dtl::disable_if_memtransfer_copy_constructible<I, F, F>::type
+ uninitialized_move_alloc(Allocator &a, I f, I l, F r)
+{
+ F back = r;
+ BOOST_TRY{
+ while (f != l) {
+ allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r), boost::move(*f));
+ ++f; ++r;
+ }
+ }
+ BOOST_CATCH(...){
+ for (; back != r; ++back){
+ allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
+ }
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ return r;
+}
+
+template
+ <typename Allocator,
+ typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+inline typename dtl::enable_if_memtransfer_copy_constructible<I, F, F>::type
+ uninitialized_move_alloc(Allocator &, I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW
+{ return dtl::memmove(f, l, r); }
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// uninitialized_move_alloc_n
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! <b>Effects</b>:
+//! \code
+//! for (; n--; ++r, ++f)
+//! allocator_traits::construct(a, &*r, boost::move(*f));
+//! \endcode
+//!
+//! <b>Returns</b>: r
+template
+ <typename Allocator,
+ typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+inline typename dtl::disable_if_memtransfer_copy_constructible<I, F, F>::type
+ uninitialized_move_alloc_n(Allocator &a, I f, typename boost::container::allocator_traits<Allocator>::size_type n, F r)
+{
+ F back = r;
+ BOOST_TRY{
+ while (n--) {
+ allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r), boost::move(*f));
+ ++f; ++r;
+ }
+ }
+ BOOST_CATCH(...){
+ for (; back != r; ++back){
+ allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
+ }
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ return r;
+}
+
+template
+ <typename Allocator,
+ typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+inline typename dtl::enable_if_memtransfer_copy_constructible<I, F, F>::type
+ uninitialized_move_alloc_n(Allocator &, I f, typename boost::container::allocator_traits<Allocator>::size_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW
+{ return dtl::memmove_n(f, n, r); }
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// uninitialized_move_alloc_n_source
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! <b>Effects</b>:
+//! \code
+//! for (; n--; ++r, ++f)
+//! allocator_traits::construct(a, &*r, boost::move(*f));
+//! \endcode
+//!
+//! <b>Returns</b>: f (after incremented)
+template
+ <typename Allocator,
+ typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+inline typename dtl::disable_if_memtransfer_copy_constructible<I, F, I>::type
+ uninitialized_move_alloc_n_source(Allocator &a, I f, typename boost::container::allocator_traits<Allocator>::size_type n, F r)
+{
+ F back = r;
+ BOOST_TRY{
+ while (n--) {
+ allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r), boost::move(*f));
+ ++f; ++r;
+ }
+ }
+ BOOST_CATCH(...){
+ for (; back != r; ++back){
+ allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
+ }
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ return f;
+}
+
+template
+ <typename Allocator,
+ typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+inline typename dtl::enable_if_memtransfer_copy_constructible<I, F, I>::type
+ uninitialized_move_alloc_n_source(Allocator &, I f, typename boost::container::allocator_traits<Allocator>::size_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW
+{ return dtl::memmove_n_source(f, n, r); }
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// uninitialized_copy_alloc
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! <b>Effects</b>:
+//! \code
+//! for (; f != l; ++r, ++f)
+//! allocator_traits::construct(a, &*r, *f);
+//! \endcode
+//!
+//! <b>Returns</b>: r
+template
+ <typename Allocator,
+ typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+inline typename dtl::disable_if_memtransfer_copy_constructible<I, F, F>::type
+ uninitialized_copy_alloc(Allocator &a, I f, I l, F r)
+{
+ F back = r;
+ BOOST_TRY{
+ while (f != l) {
+ allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r), *f);
+ ++f; ++r;
+ }
+ }
+ BOOST_CATCH(...){
+ for (; back != r; ++back){
+ allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
+ }
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ return r;
+}
+
+template
+ <typename Allocator,
+ typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+inline typename dtl::enable_if_memtransfer_copy_constructible<I, F, F>::type
+ uninitialized_copy_alloc(Allocator &, I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW
+{ return dtl::memmove(f, l, r); }
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// uninitialized_copy_alloc_n
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! <b>Effects</b>:
+//! \code
+//! for (; n--; ++r, ++f)
+//! allocator_traits::construct(a, &*r, *f);
+//! \endcode
+//!
+//! <b>Returns</b>: r
+template
+ <typename Allocator,
+ typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+inline typename dtl::disable_if_memtransfer_copy_constructible<I, F, F>::type
+ uninitialized_copy_alloc_n(Allocator &a, I f, typename boost::container::allocator_traits<Allocator>::size_type n, F r)
+{
+ F back = r;
+ BOOST_TRY{
+ while (n--) {
+ allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r), *f);
+ ++f; ++r;
+ }
+ }
+ BOOST_CATCH(...){
+ for (; back != r; ++back){
+ allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
+ }
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ return r;
+}
+
+template
+ <typename Allocator,
+ typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+inline typename dtl::enable_if_memtransfer_copy_constructible<I, F, F>::type
+ uninitialized_copy_alloc_n(Allocator &, I f, typename boost::container::allocator_traits<Allocator>::size_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW
+{ return dtl::memmove_n(f, n, r); }
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// uninitialized_copy_alloc_n_source
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! <b>Effects</b>:
+//! \code
+//! for (; n--; ++r, ++f)
+//! allocator_traits::construct(a, &*r, *f);
+//! \endcode
+//!
+//! <b>Returns</b>: f (after incremented)
+template
+ <typename Allocator,
+ typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+inline typename dtl::disable_if_memtransfer_copy_constructible<I, F, I>::type
+ uninitialized_copy_alloc_n_source(Allocator &a, I f, typename boost::container::allocator_traits<Allocator>::size_type n, F r)
+{
+ F back = r;
+ BOOST_TRY{
+ while (n--) {
+ boost::container::construct_in_place(a, boost::movelib::iterator_to_raw_pointer(r), f);
+ ++f; ++r;
+ }
+ }
+ BOOST_CATCH(...){
+ for (; back != r; ++back){
+ allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
+ }
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ return f;
+}
+
+template
+ <typename Allocator,
+ typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+inline typename dtl::enable_if_memtransfer_copy_constructible<I, F, I>::type
+ uninitialized_copy_alloc_n_source(Allocator &, I f, typename boost::container::allocator_traits<Allocator>::size_type n, F r) BOOST_NOEXCEPT_OR_NOTHROW
+{ return dtl::memmove_n_source(f, n, r); }
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// uninitialized_value_init_alloc_n
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! <b>Effects</b>:
+//! \code
+//! for (; n--; ++r, ++f)
+//! allocator_traits::construct(a, &*r);
+//! \endcode
+//!
+//! <b>Returns</b>: r
+template
+ <typename Allocator,
+ typename F> // F models ForwardIterator
+inline typename dtl::disable_if_memzero_initializable<F, F>::type
+ uninitialized_value_init_alloc_n(Allocator &a, typename boost::container::allocator_traits<Allocator>::size_type n, F r)
+{
+ F back = r;
+ BOOST_TRY{
+ while (n--) {
+ allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r));
+ ++r;
+ }
+ }
+ BOOST_CATCH(...){
+ for (; back != r; ++back){
+ allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
+ }
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ return r;
+}
+
+template
+ <typename Allocator,
+ typename F> // F models ForwardIterator
+inline typename dtl::enable_if_memzero_initializable<F, F>::type
+ uninitialized_value_init_alloc_n(Allocator &, typename boost::container::allocator_traits<Allocator>::size_type n, F r)
+{
+ typedef typename boost::container::iterator_traits<F>::value_type value_type;
+ std::memset((void*)boost::movelib::iterator_to_raw_pointer(r), 0, sizeof(value_type)*n);
+ boost::container::iterator_advance(r, n);
+ return r;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// uninitialized_default_init_alloc_n
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! <b>Effects</b>:
+//! \code
+//! for (; n--; ++r, ++f)
+//! allocator_traits::construct(a, &*r);
+//! \endcode
+//!
+//! <b>Returns</b>: r
+template
+ <typename Allocator,
+ typename F> // F models ForwardIterator
+inline F uninitialized_default_init_alloc_n(Allocator &a, typename boost::container::allocator_traits<Allocator>::size_type n, F r)
+{
+ F back = r;
+ BOOST_TRY{
+ while (n--) {
+ allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r), default_init);
+ ++r;
+ }
+ }
+ BOOST_CATCH(...){
+ for (; back != r; ++back){
+ allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
+ }
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ return r;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// uninitialized_fill_alloc
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! <b>Effects</b>:
+//! \code
+//! for (; f != l; ++r, ++f)
+//! allocator_traits::construct(a, &*r, *f);
+//! \endcode
+//!
+//! <b>Returns</b>: r
+template
+ <typename Allocator,
+ typename F, // F models ForwardIterator
+ typename 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<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(f), t);
+ ++f;
+ }
+ }
+ BOOST_CATCH(...){
+ for (; back != l; ++back){
+ allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
+ }
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// uninitialized_fill_alloc_n
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//! <b>Effects</b>:
+//! \code
+//! for (; n--; ++r, ++f)
+//! allocator_traits::construct(a, &*r, v);
+//! \endcode
+//!
+//! <b>Returns</b>: r
+template
+ <typename Allocator,
+ typename T,
+ typename F> // F models ForwardIterator
+inline F uninitialized_fill_alloc_n(Allocator &a, const T &v, typename boost::container::allocator_traits<Allocator>::size_type n, F r)
+{
+ F back = r;
+ BOOST_TRY{
+ while (n--) {
+ allocator_traits<Allocator>::construct(a, boost::movelib::iterator_to_raw_pointer(r), v);
+ ++r;
+ }
+ }
+ BOOST_CATCH(...){
+ for (; back != r; ++back){
+ allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(back));
+ }
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ return r;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// copy
+//
+//////////////////////////////////////////////////////////////////////////////
+
+template
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline typename dtl::disable_if_memtransfer_copy_assignable<I, F, F>::type
+ copy(I f, I l, F r)
+{
+ while (f != l) {
+ *r = *f;
+ ++f; ++r;
+ }
+ return r;
+}
+
+template
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline typename dtl::enable_if_memtransfer_copy_assignable<I, F, F>::type
+ copy(I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW
+{ return dtl::memmove(f, l, r); }
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// copy_n
+//
+//////////////////////////////////////////////////////////////////////////////
+
+template
+<typename I, // I models InputIterator
+typename U, // U models unsigned integral constant
+typename F> // F models ForwardIterator
+inline typename dtl::disable_if_memtransfer_copy_assignable<I, F, F>::type
+ copy_n(I f, U n, F r)
+{
+ while (n--) {
+ *r = *f;
+ ++f; ++r;
+ }
+ return r;
+}
+
+template
+<typename I, // I models InputIterator
+typename U, // U models unsigned integral constant
+typename F> // F models ForwardIterator
+inline typename dtl::enable_if_memtransfer_copy_assignable<I, F, F>::type
+ copy_n(I f, U n, F r) BOOST_NOEXCEPT_OR_NOTHROW
+{ return dtl::memmove_n(f, n, r); }
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// copy_n_source
+//
+//////////////////////////////////////////////////////////////////////////////
+
+template
+<typename I, // I models InputIterator
+typename U, // U models unsigned integral constant
+typename F> // F models ForwardIterator
+inline typename dtl::disable_if_memtransfer_copy_assignable<I, F, I>::type
+ copy_n_source(I f, U n, F r)
+{
+ while (n--) {
+ boost::container::assign_in_place(r, f);
+ ++f; ++r;
+ }
+ return f;
+}
+
+template
+<typename I, // I models InputIterator
+typename U, // U models unsigned integral constant
+typename F> // F models ForwardIterator
+inline typename dtl::enable_if_memtransfer_copy_assignable<I, F, I>::type
+ copy_n_source(I f, U n, F r) BOOST_NOEXCEPT_OR_NOTHROW
+{ return dtl::memmove_n_source(f, n, r); }
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// copy_n_source_dest
+//
+//////////////////////////////////////////////////////////////////////////////
+
+template
+<typename I, // I models InputIterator
+typename U, // U models unsigned integral constant
+typename F> // F models ForwardIterator
+inline typename dtl::disable_if_memtransfer_copy_assignable<I, F, I>::type
+ copy_n_source_dest(I f, U n, F &r)
+{
+ while (n--) {
+ *r = *f;
+ ++f; ++r;
+ }
+ return f;
+}
+
+template
+<typename I, // I models InputIterator
+typename U, // U models unsigned integral constant
+typename F> // F models ForwardIterator
+inline typename dtl::enable_if_memtransfer_copy_assignable<I, F, I>::type
+ copy_n_source_dest(I f, U n, F &r) BOOST_NOEXCEPT_OR_NOTHROW
+{ return dtl::memmove_n_source_dest(f, n, r); }
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// move
+//
+//////////////////////////////////////////////////////////////////////////////
+
+template
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline typename dtl::disable_if_memtransfer_copy_assignable<I, F, F>::type
+ move(I f, I l, F r)
+{
+ while (f != l) {
+ *r = ::boost::move(*f);
+ ++f; ++r;
+ }
+ return r;
+}
+
+template
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline typename dtl::enable_if_memtransfer_copy_assignable<I, F, F>::type
+ move(I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW
+{ return dtl::memmove(f, l, r); }
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// move_n
+//
+//////////////////////////////////////////////////////////////////////////////
+
+template
+<typename I, // I models InputIterator
+typename U, // U models unsigned integral constant
+typename F> // F models ForwardIterator
+inline typename dtl::disable_if_memtransfer_copy_assignable<I, F, F>::type
+ move_n(I f, U n, F r)
+{
+ while (n--) {
+ *r = ::boost::move(*f);
+ ++f; ++r;
+ }
+ return r;
+}
+
+template
+<typename I, // I models InputIterator
+typename U, // U models unsigned integral constant
+typename F> // F models ForwardIterator
+inline typename dtl::enable_if_memtransfer_copy_assignable<I, F, F>::type
+ move_n(I f, U n, F r) BOOST_NOEXCEPT_OR_NOTHROW
+{ return dtl::memmove_n(f, n, r); }
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// move_backward
+//
+//////////////////////////////////////////////////////////////////////////////
+
+template
+<typename I, // I models BidirectionalIterator
+typename F> // F models ForwardIterator
+inline typename dtl::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 dtl::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((boost::movelib::iterator_to_raw_pointer)(r), (boost::movelib::iterator_to_raw_pointer)(f), sizeof(value_type)*n);
+ return r;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// move_n_source_dest
+//
+//////////////////////////////////////////////////////////////////////////////
+
+template
+<typename I // I models InputIterator
+,typename U // U models unsigned integral constant
+,typename F> // F models ForwardIterator
+inline typename dtl::disable_if_memtransfer_copy_assignable<I, F, I>::type
+ move_n_source_dest(I f, U n, F &r)
+{
+ while (n--) {
+ *r = ::boost::move(*f);
+ ++f; ++r;
+ }
+ return f;
+}
+
+template
+<typename I // I models InputIterator
+,typename U // U models unsigned integral constant
+,typename F> // F models ForwardIterator
+inline typename dtl::enable_if_memtransfer_copy_assignable<I, F, I>::type
+ move_n_source_dest(I f, U n, F &r) BOOST_NOEXCEPT_OR_NOTHROW
+{ return dtl::memmove_n_source_dest(f, n, r); }
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// move_n_source
+//
+//////////////////////////////////////////////////////////////////////////////
+
+template
+<typename I // I models InputIterator
+,typename U // U models unsigned integral constant
+,typename F> // F models ForwardIterator
+inline typename dtl::disable_if_memtransfer_copy_assignable<I, F, I>::type
+ move_n_source(I f, U n, F r)
+{
+ while (n--) {
+ *r = ::boost::move(*f);
+ ++f; ++r;
+ }
+ return f;
+}
+
+template
+<typename I // I models InputIterator
+,typename U // U models unsigned integral constant
+,typename F> // F models ForwardIterator
+inline typename dtl::enable_if_memtransfer_copy_assignable<I, F, I>::type
+ move_n_source(I f, U n, F r) BOOST_NOEXCEPT_OR_NOTHROW
+{ return dtl::memmove_n_source(f, n, r); }
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// destroy_alloc_n
+//
+//////////////////////////////////////////////////////////////////////////////
+
+template
+ <typename Allocator
+ ,typename I // I models InputIterator
+ ,typename U> // U models unsigned integral constant
+inline typename dtl::disable_if_trivially_destructible<I, void>::type
+ destroy_alloc_n(Allocator &a, I f, U n)
+{
+ while(n){
+ --n;
+ allocator_traits<Allocator>::destroy(a, boost::movelib::iterator_to_raw_pointer(f));
+ ++f;
+ }
+}
+
+template
+ <typename Allocator
+ ,typename I // I models InputIterator
+ ,typename U> // U models unsigned integral constant
+inline typename dtl::enable_if_trivially_destructible<I, void>::type
+ destroy_alloc_n(Allocator &, I, U)
+{}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// deep_swap_alloc_n
+//
+//////////////////////////////////////////////////////////////////////////////
+
+template
+ <std::size_t MaxTmpBytes
+ ,typename Allocator
+ ,typename F // F models ForwardIterator
+ ,typename G // G models ForwardIterator
+ >
+inline typename dtl::disable_if_memtransfer_copy_assignable<F, G, void>::type
+ 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<Allocator>::size_type n = 0;
+ for (; n != n_i ; ++short_range_f, ++large_range_f, ++n){
+ 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);
+}
+
+static const std::size_t DeepSwapAllocNMaxStorage = std::size_t(1) << std::size_t(11); //2K bytes
+
+template
+ <std::size_t MaxTmpBytes
+ ,typename Allocator
+ ,typename F // F models ForwardIterator
+ ,typename G // G models ForwardIterator
+ >
+inline typename dtl::enable_if_c
+ < dtl::is_memtransfer_copy_assignable<F, G>::value && (MaxTmpBytes <= DeepSwapAllocNMaxStorage) && false
+ , void>::type
+ 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<Allocator>::value_type value_type;
+ typedef typename dtl::aligned_storage
+ <MaxTmpBytes, dtl::alignment_of<value_type>::value>::type storage_type;
+ storage_type storage;
+
+ const std::size_t n_i_bytes = sizeof(value_type)*n_i;
+ void *const large_ptr = static_cast<void*>(boost::movelib::iterator_to_raw_pointer(large_range_f));
+ void *const short_ptr = static_cast<void*>(boost::movelib::iterator_to_raw_pointer(short_range_f));
+ void *const stora_ptr = static_cast<void*>(boost::movelib::iterator_to_raw_pointer(storage.data));
+ 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 Allocator
+ ,typename F // F models ForwardIterator
+ ,typename G // G models ForwardIterator
+ >
+inline typename dtl::enable_if_c
+ < dtl::is_memtransfer_copy_assignable<F, G>::value && true//(MaxTmpBytes > DeepSwapAllocNMaxStorage)
+ , void>::type
+ 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<Allocator>::value_type value_type;
+ typedef typename dtl::aligned_storage
+ <DeepSwapAllocNMaxStorage, dtl::alignment_of<value_type>::value>::type storage_type;
+ storage_type storage;
+ const std::size_t sizeof_storage = sizeof(storage);
+
+ std::size_t n_i_bytes = sizeof(value_type)*n_i;
+ char *large_ptr = static_cast<char*>(static_cast<void*>(boost::movelib::iterator_to_raw_pointer(large_range_f)));
+ char *short_ptr = static_cast<char*>(static_cast<void*>(boost::movelib::iterator_to_raw_pointer(short_range_f)));
+ char *stora_ptr = static_cast<char*>(static_cast<void*>(storage.data));
+
+ std::size_t szt_times = n_i_bytes/sizeof_storage;
+ const std::size_t szt_rem = n_i_bytes%sizeof_storage;
+
+ //Loop unrolling using Duff's device, as it seems it helps on some architectures
+ const std::size_t Unroll = 4;
+ std::size_t n = (szt_times + (Unroll-1))/Unroll;
+ const std::size_t branch_number = (!szt_times)*Unroll + (szt_times % Unroll);
+ switch(branch_number){
+ case 4:
+ break;
+ case 0: do{
+ 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_FALLTHROUGH;
+ case 3:
+ 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_FALLTHROUGH;
+ case 2:
+ 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_FALLTHROUGH;
+ case 1:
+ 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);
+ }
+ 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);
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// copy_assign_range_alloc_n
+//
+//////////////////////////////////////////////////////////////////////////////
+
+template
+ <typename Allocator
+ ,typename I // F models InputIterator
+ ,typename O // G models OutputIterator
+ >
+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
+ boost::container::uninitialized_copy_alloc_n(a, inp_start, n_i - n_o, out_start);// may throw
+ }
+ else{
+ out_start = boost::container::copy_n(inp_start, n_i, out_start); // may throw
+ boost::container::destroy_alloc_n(a, out_start, n_o - n_i);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// move_assign_range_alloc_n
+//
+//////////////////////////////////////////////////////////////////////////////
+
+template
+ <typename Allocator
+ ,typename I // F models InputIterator
+ ,typename O // G models OutputIterator
+ >
+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
+ boost::container::uninitialized_move_alloc_n(a, inp_start, n_i - n_o, out_start); // may throw
+ }
+ else{
+ out_start = boost::container::move_n(inp_start, n_i, out_start); // may throw
+ boost::container::destroy_alloc_n(a, out_start, n_o - n_i);
+ }
+}
+
+} //namespace container {
+} //namespace boost {
+
+#if defined(BOOST_GCC) && (BOOST_GCC >= 80000)
+#pragma GCC diagnostic pop
+#endif
+
+
+#endif //#ifndef BOOST_CONTAINER_DETAIL_COPY_MOVE_ALGO_HPP
diff --git a/include/boost/container/detail/destroyers.hpp b/include/boost/container/detail/destroyers.hpp
new file mode 100644
index 0000000..9b0be44
--- /dev/null
+++ b/include/boost/container/detail/destroyers.hpp
@@ -0,0 +1,378 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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_DESTROYERS_HPP
+#define BOOST_CONTAINER_DESTROYERS_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/allocator_traits.hpp>
+#include <boost/move/detail/to_raw_pointer.hpp>
+#include <boost/container/detail/version_type.hpp>
+
+namespace boost {
+namespace container {
+namespace dtl {
+
+//!A deleter for scoped_ptr that deallocates the memory
+//!allocated for an object using a STL allocator.
+template <class Allocator>
+struct scoped_deallocator
+{
+ typedef allocator_traits<Allocator> allocator_traits_type;
+ typedef typename allocator_traits_type::pointer pointer;
+ typedef dtl::integral_constant<unsigned,
+ boost::container::dtl::
+ version<Allocator>::value> alloc_version;
+
+ private:
+ void priv_deallocate(version_1)
+ { m_alloc.deallocate(m_ptr, 1); }
+
+ void priv_deallocate(version_2)
+ { m_alloc.deallocate_one(m_ptr); }
+
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(scoped_deallocator)
+
+ public:
+
+ pointer m_ptr;
+ Allocator& m_alloc;
+
+ scoped_deallocator(pointer p, Allocator& a)
+ : m_ptr(p), m_alloc(a)
+ {}
+
+ ~scoped_deallocator()
+ { if (m_ptr)priv_deallocate(alloc_version()); }
+
+ scoped_deallocator(BOOST_RV_REF(scoped_deallocator) o)
+ : m_ptr(o.m_ptr), m_alloc(o.m_alloc)
+ { o.release(); }
+
+ pointer get() const
+ { return m_ptr; }
+
+ void set(const pointer &p)
+ { m_ptr = p; }
+
+ void release()
+ { m_ptr = 0; }
+};
+
+template <class Allocator>
+struct null_scoped_deallocator
+{
+ typedef boost::container::allocator_traits<Allocator> AllocTraits;
+ typedef typename AllocTraits::pointer pointer;
+ typedef typename AllocTraits::size_type size_type;
+
+ null_scoped_deallocator(pointer, Allocator&, size_type)
+ {}
+
+ void release()
+ {}
+
+ pointer get() const
+ { return pointer(); }
+
+ void set(const pointer &)
+ {}
+};
+
+//!A deleter for scoped_ptr that deallocates the memory
+//!allocated for an array of objects using a STL allocator.
+template <class Allocator>
+struct scoped_array_deallocator
+{
+ typedef boost::container::allocator_traits<Allocator> AllocTraits;
+ typedef typename AllocTraits::pointer pointer;
+ typedef typename AllocTraits::size_type size_type;
+
+ scoped_array_deallocator(pointer p, Allocator& a, size_type length)
+ : m_ptr(p), m_alloc(a), m_length(length) {}
+
+ ~scoped_array_deallocator()
+ { if (m_ptr) m_alloc.deallocate(m_ptr, m_length); }
+
+ void release()
+ { m_ptr = 0; }
+
+ private:
+ pointer m_ptr;
+ Allocator& m_alloc;
+ size_type m_length;
+};
+
+template <class Allocator>
+struct null_scoped_array_deallocator
+{
+ typedef boost::container::allocator_traits<Allocator> AllocTraits;
+ typedef typename AllocTraits::pointer pointer;
+ typedef typename AllocTraits::size_type size_type;
+
+ null_scoped_array_deallocator(pointer, Allocator&, size_type)
+ {}
+
+ void release()
+ {}
+};
+
+template <class Allocator>
+struct scoped_destroy_deallocator
+{
+ typedef boost::container::allocator_traits<Allocator> AllocTraits;
+ typedef typename AllocTraits::pointer pointer;
+ typedef typename AllocTraits::size_type size_type;
+ typedef dtl::integral_constant<unsigned,
+ boost::container::dtl::
+ version<Allocator>::value> alloc_version;
+
+ scoped_destroy_deallocator(pointer p, Allocator& a)
+ : m_ptr(p), m_alloc(a) {}
+
+ ~scoped_destroy_deallocator()
+ {
+ if(m_ptr){
+ AllocTraits::destroy(m_alloc, boost::movelib::to_raw_pointer(m_ptr));
+ priv_deallocate(m_ptr, alloc_version());
+ }
+ }
+
+ void release()
+ { m_ptr = 0; }
+
+ private:
+
+ void priv_deallocate(const pointer &p, version_1)
+ { AllocTraits::deallocate(m_alloc, p, 1); }
+
+ void priv_deallocate(const pointer &p, version_2)
+ { m_alloc.deallocate_one(p); }
+
+ pointer m_ptr;
+ Allocator& m_alloc;
+};
+
+
+//!A deleter for scoped_ptr that destroys
+//!an object using a STL allocator.
+template <class Allocator>
+struct scoped_destructor_n
+{
+ typedef boost::container::allocator_traits<Allocator> AllocTraits;
+ typedef typename AllocTraits::pointer pointer;
+ typedef typename AllocTraits::value_type value_type;
+ typedef typename AllocTraits::size_type size_type;
+
+ scoped_destructor_n(pointer p, Allocator& a, size_type n)
+ : m_p(p), m_a(a), m_n(n)
+ {}
+
+ void release()
+ { m_p = 0; }
+
+ void increment_size(size_type inc)
+ { m_n += inc; }
+
+ void increment_size_backwards(size_type inc)
+ { m_n += inc; m_p -= inc; }
+
+ void shrink_forward(size_type inc)
+ { m_n -= inc; m_p += inc; }
+
+ ~scoped_destructor_n()
+ {
+ if(!m_p) return;
+ value_type *raw_ptr = boost::movelib::to_raw_pointer(m_p);
+ while(m_n--){
+ AllocTraits::destroy(m_a, raw_ptr++);
+ }
+ }
+
+ private:
+ pointer m_p;
+ Allocator & m_a;
+ size_type m_n;
+};
+
+//!A deleter for scoped_ptr that destroys
+//!an object using a STL allocator.
+template <class Allocator>
+struct null_scoped_destructor_n
+{
+ typedef boost::container::allocator_traits<Allocator> AllocTraits;
+ typedef typename AllocTraits::pointer pointer;
+ typedef typename AllocTraits::size_type size_type;
+
+ null_scoped_destructor_n(pointer, Allocator&, size_type)
+ {}
+
+ void increment_size(size_type)
+ {}
+
+ void increment_size_backwards(size_type)
+ {}
+
+ void shrink_forward(size_type)
+ {}
+
+ void release()
+ {}
+};
+
+template<class Allocator>
+class scoped_destructor
+{
+ typedef boost::container::allocator_traits<Allocator> AllocTraits;
+ public:
+ typedef typename Allocator::value_type value_type;
+ scoped_destructor(Allocator &a, value_type *pv)
+ : pv_(pv), a_(a)
+ {}
+
+ ~scoped_destructor()
+ {
+ if(pv_){
+ AllocTraits::destroy(a_, pv_);
+ }
+ }
+
+ void release()
+ { pv_ = 0; }
+
+
+ void set(value_type *ptr) { pv_ = ptr; }
+
+ value_type *get() const { return pv_; }
+
+ private:
+ value_type *pv_;
+ Allocator &a_;
+};
+
+
+template<class Allocator, class Value = typename Allocator::value_type>
+class value_destructor
+{
+ typedef boost::container::allocator_traits<Allocator> AllocTraits;
+ public:
+ typedef Value value_type;
+ value_destructor(Allocator &a, value_type &rv)
+ : rv_(rv), a_(a)
+ {}
+
+ ~value_destructor()
+ {
+ AllocTraits::destroy(a_, &rv_);
+ }
+
+ private:
+ value_type &rv_;
+ Allocator &a_;
+};
+
+template <class Allocator>
+class allocator_destroyer
+{
+ typedef boost::container::allocator_traits<Allocator> AllocTraits;
+ typedef typename AllocTraits::value_type value_type;
+ typedef typename AllocTraits::pointer pointer;
+ typedef dtl::integral_constant<unsigned,
+ boost::container::dtl::
+ version<Allocator>::value> alloc_version;
+
+ private:
+ Allocator & a_;
+
+ private:
+ void priv_deallocate(const pointer &p, version_1)
+ { AllocTraits::deallocate(a_,p, 1); }
+
+ void priv_deallocate(const pointer &p, version_2)
+ { a_.deallocate_one(p); }
+
+ public:
+ explicit allocator_destroyer(Allocator &a)
+ : a_(a)
+ {}
+
+ void operator()(const pointer &p)
+ {
+ AllocTraits::destroy(a_, boost::movelib::to_raw_pointer(p));
+ this->priv_deallocate(p, alloc_version());
+ }
+};
+
+template <class Allocator>
+class allocator_destroyer_and_chain_builder
+{
+ typedef allocator_traits<Allocator> allocator_traits_type;
+ typedef typename allocator_traits_type::value_type value_type;
+ typedef typename Allocator::multiallocation_chain multiallocation_chain;
+
+ Allocator & a_;
+ multiallocation_chain &c_;
+
+ public:
+ allocator_destroyer_and_chain_builder(Allocator &a, multiallocation_chain &c)
+ : a_(a), c_(c)
+ {}
+
+ void operator()(const typename Allocator::pointer &p)
+ {
+ allocator_traits<Allocator>::destroy(a_, boost::movelib::to_raw_pointer(p));
+ c_.push_back(p);
+ }
+};
+
+template <class Allocator>
+class allocator_multialloc_chain_node_deallocator
+{
+ typedef allocator_traits<Allocator> allocator_traits_type;
+ typedef typename allocator_traits_type::value_type value_type;
+ typedef typename Allocator::multiallocation_chain multiallocation_chain;
+ typedef allocator_destroyer_and_chain_builder<Allocator> chain_builder;
+
+ Allocator & a_;
+ multiallocation_chain c_;
+
+ public:
+ allocator_multialloc_chain_node_deallocator(Allocator &a)
+ : a_(a), c_()
+ {}
+
+ chain_builder get_chain_builder()
+ { return chain_builder(a_, c_); }
+
+ ~allocator_multialloc_chain_node_deallocator()
+ {
+ a_.deallocate_individual(c_);
+ }
+};
+
+} //namespace dtl {
+} //namespace container {
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_CONTAINER_DESTROYERS_HPP
diff --git a/include/boost/container/detail/dispatch_uses_allocator.hpp b/include/boost/container/detail/dispatch_uses_allocator.hpp
new file mode 100644
index 0000000..0b8cfea
--- /dev/null
+++ b/include/boost/container/detail/dispatch_uses_allocator.hpp
@@ -0,0 +1,461 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_DISPATCH_USES_ALLOCATOR_HPP
+#define BOOST_CONTAINER_DISPATCH_USES_ALLOCATOR_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/uses_allocator.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>
+
+#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 {
+
+namespace dtl {
+
+
+// Check if we can detect is_convertible using advanced SFINAE expressions
+#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
+ template<class T, class ...Args>
+ struct is_constructible
+ {
+ typedef char yes_type;
+ struct no_type
+ { char padding[2]; };
+
+ template<std::size_t N>
+ struct dummy;
+
+ template<class X>
+ static decltype(X(boost::move_detail::declval<Args>()...), true_type()) test(int);
+
+ template<class X>
+ static no_type test(...);
+
+ static const bool value = sizeof(test<T>(0)) == sizeof(yes_type);
+ };
+
+ 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_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>
+ struct is_constructible_with_allocator_prefix
+ : constructible_with_allocator_prefix<T>
+ {};
+
+ 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_MOVE_CLASSDFLT9>
+ struct is_constructible_with_allocator_prefix
+ : constructible_with_allocator_prefix<T>
+ {};
+
+ 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)
+
+#endif // #if !defined(BOOST_NO_SFINAE_EXPR)
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+template < typename ConstructAlloc
+ , typename ArgAlloc
+ , typename T
+ , class ...Args
+ >
+inline typename dtl::enable_if_and
+ < void
+ , dtl::is_not_pair<T>
+ , dtl::not_< uses_allocator<T, ArgAlloc> >
+ >::type dispatch_uses_allocator
+ ( ConstructAlloc & construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, T* p, BOOST_FWD_REF(Args)...args)
+{
+ (void)arg_alloc;
+ allocator_traits<ConstructAlloc>::construct(construct_alloc, p, ::boost::forward<Args>(args)...);
+}
+
+// allocator_arg_t
+template < typename ConstructAlloc
+ , typename ArgAlloc
+ , typename T
+ , class ...Args
+ >
+inline typename dtl::enable_if_and
+ < void
+ , dtl::is_not_pair<T>
+ , uses_allocator<T, ArgAlloc>
+ , is_constructible_with_allocator_prefix<T, ArgAlloc, Args...>
+ >::type dispatch_uses_allocator
+ ( ConstructAlloc& construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, T* p, BOOST_FWD_REF(Args) ...args)
+{
+ allocator_traits<ConstructAlloc>::construct
+ ( construct_alloc, p, allocator_arg
+ , ::boost::forward<ArgAlloc>(arg_alloc), ::boost::forward<Args>(args)...);
+}
+
+// allocator suffix
+template < typename ConstructAlloc
+ , typename ArgAlloc
+ , typename T
+ , class ...Args
+ >
+inline typename dtl::enable_if_and
+ < void
+ , dtl::is_not_pair<T>
+ , uses_allocator<T, ArgAlloc>
+ , dtl::not_<is_constructible_with_allocator_prefix<T, ArgAlloc, Args...> >
+ >::type dispatch_uses_allocator
+ ( ConstructAlloc& construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, T* p, BOOST_FWD_REF(Args)...args)
+{
+ allocator_traits<ConstructAlloc>::construct
+ (construct_alloc, p, ::boost::forward<Args>(args)..., ::boost::forward<ArgAlloc>(arg_alloc));
+}
+
+#else //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+#define BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE(N) \
+ template <typename ConstructAlloc, typename ArgAlloc, typename T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
+ inline typename dtl::enable_if_and\
+ < void\
+ , dtl::is_not_pair<T>\
+ , dtl::not_<uses_allocator<T, ArgAlloc> >\
+ >::type\
+ dispatch_uses_allocator\
+ (ConstructAlloc &construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, T* p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ {\
+ (void)arg_alloc;\
+ allocator_traits<ConstructAlloc>::construct(construct_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
+
+#define BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE(N) \
+ template < typename ConstructAlloc, typename ArgAlloc, typename T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
+ inline typename dtl::enable_if_and\
+ < void\
+ , dtl::is_not_pair<T>\
+ , uses_allocator<T, ArgAlloc>\
+ , is_constructible_with_allocator_prefix<T, ArgAlloc BOOST_MOVE_I##N BOOST_MOVE_TARG##N>\
+ >::type\
+ dispatch_uses_allocator\
+ (ConstructAlloc& construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, T* p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ {\
+ allocator_traits<ConstructAlloc>::construct\
+ (construct_alloc, p, allocator_arg, ::boost::forward<ArgAlloc>(arg_alloc) 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
+
+#define BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE(N) \
+ template < typename ConstructAlloc, typename ArgAlloc, typename T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
+ inline typename dtl::enable_if_and\
+ < void\
+ , dtl::is_not_pair<T>\
+ , uses_allocator<T, ArgAlloc>\
+ , dtl::not_<is_constructible_with_allocator_prefix<T, ArgAlloc BOOST_MOVE_I##N BOOST_MOVE_TARG##N> >\
+ >::type\
+ dispatch_uses_allocator\
+ (ConstructAlloc& construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, T* p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ {\
+ allocator_traits<ConstructAlloc>::construct\
+ (construct_alloc, p BOOST_MOVE_I##N BOOST_MOVE_FWD##N, ::boost::forward<ArgAlloc>(arg_alloc));\
+ }\
+//
+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)
+
+template < typename ConstructAlloc
+ , typename ArgAlloc
+ , typename Pair
+ > inline
+BOOST_CONTAINER_DOC1ST(void, typename dtl::enable_if<dtl::is_pair<Pair> >::type)
+ dispatch_uses_allocator
+ ( ConstructAlloc & construct_alloc
+ , BOOST_FWD_REF(ArgAlloc) arg_alloc
+ , Pair* p)
+{
+ (dispatch_uses_allocator)(construct_alloc, arg_alloc, dtl::addressof(p->first));
+ BOOST_TRY{
+ (dispatch_uses_allocator)(construct_alloc, arg_alloc, dtl::addressof(p->second));
+ }
+ BOOST_CATCH(...) {
+ allocator_traits<ConstructAlloc>::destroy(construct_alloc, dtl::addressof(p->first));
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+}
+
+
+template < typename ConstructAlloc
+ , typename ArgAlloc
+ , class Pair, class U, class V>
+BOOST_CONTAINER_DOC1ST(void, typename dtl::enable_if<dtl::is_pair<Pair> >::type)
+ dispatch_uses_allocator
+ ( ConstructAlloc & construct_alloc
+ , BOOST_FWD_REF(ArgAlloc) arg_alloc
+ , Pair* p, BOOST_FWD_REF(U) x, BOOST_FWD_REF(V) y)
+{
+ (dispatch_uses_allocator)(construct_alloc, arg_alloc, dtl::addressof(p->first), ::boost::forward<U>(x));
+ BOOST_TRY{
+ (dispatch_uses_allocator)(construct_alloc, arg_alloc, dtl::addressof(p->second), ::boost::forward<V>(y));
+ }
+ BOOST_CATCH(...){
+ allocator_traits<ConstructAlloc>::destroy(construct_alloc, dtl::addressof(p->first));
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+}
+
+template < typename ConstructAlloc
+ , typename ArgAlloc
+ , class Pair, class Pair2>
+BOOST_CONTAINER_DOC1ST(void, typename dtl::enable_if< dtl::is_pair<Pair> >::type)
+ dispatch_uses_allocator
+ (ConstructAlloc & construct_alloc
+ , BOOST_FWD_REF(ArgAlloc) arg_alloc
+ , Pair* p, Pair2& x)
+{ (dispatch_uses_allocator)(construct_alloc, arg_alloc, p, x.first, x.second); }
+
+template < typename ConstructAlloc
+ , typename ArgAlloc
+ , class Pair, class Pair2>
+typename dtl::enable_if_and
+ < void
+ , dtl::is_pair<Pair>
+ , dtl::not_<boost::move_detail::is_reference<Pair2> > >::type //This is needed for MSVC10 and ambiguous overloads
+ dispatch_uses_allocator
+ (ConstructAlloc & construct_alloc
+ , BOOST_FWD_REF(ArgAlloc) arg_alloc
+ , Pair* p, BOOST_RV_REF_BEG Pair2 BOOST_RV_REF_END x)
+{ (dispatch_uses_allocator)(construct_alloc, arg_alloc, p, ::boost::move(x.first), ::boost::move(x.second)); }
+
+
+//piecewise construction from boost::tuple
+#define BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_BOOST_TUPLE_CODE(N,M)\
+template< typename ConstructAlloc, typename ArgAlloc, class Pair \
+ , template<class, class, class, class, class, class, class, class, class, class> class BoostTuple \
+ BOOST_MOVE_I_IF(BOOST_MOVE_OR(N,M)) BOOST_MOVE_CLASS##N BOOST_MOVE_I_IF(BOOST_MOVE_AND(N,M)) BOOST_MOVE_CLASSQ##M > \
+typename dtl::enable_if< dtl::is_pair<Pair> >::type\
+ dispatch_uses_allocator( ConstructAlloc & construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, Pair* pair, piecewise_construct_t\
+ , BoostTuple<BOOST_MOVE_TARG##N BOOST_MOVE_I##N BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,N),::boost::tuples::null_type)> p\
+ , BoostTuple<BOOST_MOVE_TARGQ##M BOOST_MOVE_I##M BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,M),::boost::tuples::null_type)> q)\
+{\
+ (void)p; (void)q;\
+ (dispatch_uses_allocator)\
+ (construct_alloc, arg_alloc, dtl::addressof(pair->first) BOOST_MOVE_I_IF(N) BOOST_MOVE_TMPL_GET##N);\
+ BOOST_TRY{\
+ (dispatch_uses_allocator)\
+ (construct_alloc, arg_alloc, dtl::addressof(pair->second) BOOST_MOVE_I_IF(M) BOOST_MOVE_TMPL_GETQ##M);\
+ }\
+ BOOST_CATCH(...) {\
+ allocator_traits<ConstructAlloc>::destroy(construct_alloc, dtl::addressof(pair->first));\
+ BOOST_RETHROW\
+ }\
+ BOOST_CATCH_END\
+}\
+//
+BOOST_MOVE_ITER2D_0TOMAX(9, BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_BOOST_TUPLE_CODE)
+#undef BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_BOOST_TUPLE_CODE
+
+//piecewise construction from Std Tuple
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ template< typename ConstructAlloc, typename ArgAlloc, class Pair
+ , template<class ...> class Tuple, class... Args1, class... Args2, size_t... Indexes1, size_t... Indexes2>
+ void dispatch_uses_allocator_index( ConstructAlloc & construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, Pair* pair
+ , Tuple<Args1...>& t1, Tuple<Args2...>& t2, index_tuple<Indexes1...>, index_tuple<Indexes2...>)
+ {
+ (void)t1; (void)t2;
+ (dispatch_uses_allocator)(construct_alloc, arg_alloc, dtl::addressof(pair->first), ::boost::forward<Args1>(get<Indexes1>(t1))...);
+ BOOST_TRY{
+ (dispatch_uses_allocator)(construct_alloc, arg_alloc, dtl::addressof(pair->second), ::boost::forward<Args2>(get<Indexes2>(t2))...);
+ }
+ BOOST_CATCH(...){
+ allocator_traits<ConstructAlloc>::destroy(construct_alloc, dtl::addressof(pair->first));
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ }
+
+ template< typename ConstructAlloc, typename ArgAlloc, class Pair
+ , template<class ...> class Tuple, class... Args1, class... Args2>
+ typename dtl::enable_if< dtl::is_pair<Pair> >::type
+ dispatch_uses_allocator( ConstructAlloc & construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, Pair* pair, piecewise_construct_t
+ , Tuple<Args1...> t1, Tuple<Args2...> t2)
+ {
+ (dispatch_uses_allocator_index)( construct_alloc, arg_alloc, pair, t1, t2
+ , typename build_number_seq<sizeof...(Args1)>::type()
+ , typename build_number_seq<sizeof...(Args2)>::type());
+ }
+
+#elif defined(BOOST_MSVC) && (_CPPLIB_VER == 520)
+
+ //MSVC 2010 tuple implementation
+ #define BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE(N,M)\
+ template< typename ConstructAlloc, typename ArgAlloc, class Pair\
+ , template<class, class, class, class, class, class, class, class, class, class> class StdTuple\
+ BOOST_MOVE_I_IF(BOOST_MOVE_OR(N,M)) BOOST_MOVE_CLASS##N BOOST_MOVE_I_IF(BOOST_MOVE_AND(N,M)) BOOST_MOVE_CLASSQ##M > \
+ typename dtl::enable_if< dtl::is_pair<Pair> >::type\
+ dispatch_uses_allocator(ConstructAlloc & construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, Pair* pair, piecewise_construct_t\
+ , StdTuple<BOOST_MOVE_TARG##N BOOST_MOVE_I##N BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,N),::std::tr1::_Nil)> p\
+ , StdTuple<BOOST_MOVE_TARGQ##M BOOST_MOVE_I##M BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,M),::std::tr1::_Nil)> q)\
+ {\
+ (void)p; (void)q;\
+ (dispatch_uses_allocator)\
+ (construct_alloc, arg_alloc, dtl::addressof(pair->first) BOOST_MOVE_I_IF(N) BOOST_MOVE_GET_IDX##N);\
+ BOOST_TRY{\
+ (dispatch_uses_allocator)\
+ (construct_alloc, arg_alloc, dtl::addressof(pair->second) BOOST_MOVE_I_IF(M) BOOST_MOVE_GET_IDXQ##M);\
+ }\
+ BOOST_CATCH(...) {\
+ allocator_traits<ConstructAlloc>::destroy(construct_alloc, dtl::addressof(pair->first));\
+ BOOST_RETHROW\
+ }\
+ BOOST_CATCH_END\
+ }\
+ //
+ BOOST_MOVE_ITER2D_0TOMAX(9, BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE)
+ #undef BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE
+
+#elif defined(BOOST_MSVC) && (_CPPLIB_VER == 540)
+ #if _VARIADIC_MAX >= 9
+ #define BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT 9
+ #else
+ #define BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT BOOST_MOVE_ADD(_VARIADIC_MAX, 1)
+ #endif
+
+ //MSVC 2012 tuple implementation
+ #define BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_CODE(N,M)\
+ template< typename ConstructAlloc, typename ArgAlloc, class Pair\
+ , template<BOOST_MOVE_REPEAT(_VARIADIC_MAX, class), class, class, class> class StdTuple \
+ BOOST_MOVE_I_IF(BOOST_MOVE_OR(N,M)) BOOST_MOVE_CLASS##N BOOST_MOVE_I_IF(BOOST_MOVE_AND(N,M)) BOOST_MOVE_CLASSQ##M > \
+ typename dtl::enable_if< dtl::is_pair<Pair> >::type\
+ dispatch_uses_allocator\
+ ( ConstructAlloc & construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, Pair* pair, piecewise_construct_t\
+ , StdTuple<BOOST_MOVE_TARG##N BOOST_MOVE_I##N BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(BOOST_MOVE_ADD(_VARIADIC_MAX, 3),N),::std::_Nil) > p\
+ , StdTuple<BOOST_MOVE_TARGQ##M BOOST_MOVE_I##M BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(BOOST_MOVE_ADD(_VARIADIC_MAX, 3),M),::std::_Nil) > q)\
+ {\
+ (void)p; (void)q;\
+ (dispatch_uses_allocator)\
+ (construct_alloc, arg_alloc, dtl::addressof(pair->first) BOOST_MOVE_I_IF(N) BOOST_MOVE_GET_IDX##N);\
+ BOOST_TRY{\
+ (dispatch_uses_allocator)\
+ (construct_alloc, arg_alloc, dtl::addressof(pair->second) BOOST_MOVE_I_IF(M) BOOST_MOVE_GET_IDXQ##M);\
+ }\
+ BOOST_CATCH(...) {\
+ allocator_traits<ConstructAlloc>::destroy(construct_alloc, dtl::addressof(pair->first));\
+ BOOST_RETHROW\
+ }\
+ BOOST_CATCH_END\
+ }\
+ //
+ BOOST_MOVE_ITER2D_0TOMAX(BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT, BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_CODE)
+ #undef BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE
+ #undef BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT
+
+#endif //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+template < typename ConstructAlloc
+ , typename ArgAlloc
+ , class Pair, class KeyType, class ... Args>
+typename dtl::enable_if< dtl::is_pair<Pair>, void >::type
+ dispatch_uses_allocator
+ (ConstructAlloc & construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, Pair* p, try_emplace_t, BOOST_FWD_REF(KeyType) k, BOOST_FWD_REF(Args) ...args)
+{
+ (dispatch_uses_allocator)(construct_alloc, arg_alloc, dtl::addressof(p->first), ::boost::forward<KeyType>(k));
+ BOOST_TRY{
+ (dispatch_uses_allocator)(construct_alloc, arg_alloc, dtl::addressof(p->second), ::boost::forward<Args>(args)...);
+ }
+ BOOST_CATCH(...) {
+ allocator_traits<ConstructAlloc>::destroy(construct_alloc, dtl::addressof(p->first));
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+}
+
+#else
+
+#define BOOST_CONTAINER_DISPATCH_USES_ALLOCATOR_PAIR_TRY_EMPLACE_CODE(N) \
+ template <typename ConstructAlloc, typename ArgAlloc, class Pair, class KeyType BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
+ inline typename dtl::enable_if\
+ < dtl::is_pair<Pair>, void >::type\
+ dispatch_uses_allocator\
+ (ConstructAlloc &construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, Pair* p, try_emplace_t, \
+ BOOST_FWD_REF(KeyType) k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ {\
+ (dispatch_uses_allocator)(construct_alloc, arg_alloc, dtl::addressof(p->first), ::boost::forward<KeyType>(k));\
+ BOOST_TRY{\
+ (dispatch_uses_allocator)(construct_alloc, arg_alloc, dtl::addressof(p->second) BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
+ }\
+ BOOST_CATCH(...) {\
+ allocator_traits<ConstructAlloc>::destroy(construct_alloc, dtl::addressof(p->first));\
+ BOOST_RETHROW\
+ }\
+ BOOST_CATCH_END\
+ }\
+//
+BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_DISPATCH_USES_ALLOCATOR_PAIR_TRY_EMPLACE_CODE)
+#undef BOOST_CONTAINER_DISPATCH_USES_ALLOCATOR_PAIR_TRY_EMPLACE_CODE
+
+#endif //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+} //namespace dtl
+
+}} // namespace boost { namespace container {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif // BOOST_CONTAINER_DISPATCH_USES_ALLOCATOR_HPP
diff --git a/include/boost/container/detail/dlmalloc.hpp b/include/boost/container/detail/dlmalloc.hpp
new file mode 100644
index 0000000..15086c3
--- /dev/null
+++ b/include/boost/container/detail/dlmalloc.hpp
@@ -0,0 +1,103 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#ifndef BOOST_CONTAINER_DETAIL_ALLOC_LIB_HPP
+#define BOOST_CONTAINER_DETAIL_ALLOC_LIB_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/detail/auto_link.hpp>
+
+#include <boost/container/detail/alloc_lib.h>
+
+namespace boost{
+namespace container{
+
+typedef boost_cont_command_ret_t dlmalloc_command_ret_t;
+typedef boost_cont_memchain dlmalloc_memchain;
+typedef boost_cont_memchain_it dlmalloc_memchain_it;
+typedef boost_cont_malloc_stats_t dlmalloc_malloc_stats_t;
+
+BOOST_CONTAINER_DECL size_t dlmalloc_size(const void *p);
+
+BOOST_CONTAINER_DECL void* dlmalloc_malloc(size_t bytes);
+
+BOOST_CONTAINER_DECL void dlmalloc_free(void* mem);
+
+BOOST_CONTAINER_DECL void* dlmalloc_memalign(size_t bytes, size_t alignment);
+
+BOOST_CONTAINER_DECL int dlmalloc_multialloc_nodes
+ (size_t n_elements, size_t elem_size, size_t contiguous_elements, boost_cont_memchain *pchain);
+
+BOOST_CONTAINER_DECL int dlmalloc_multialloc_arrays
+ (size_t n_elements, const size_t *sizes, size_t sizeof_element, size_t contiguous_elements, boost_cont_memchain *pchain);
+
+BOOST_CONTAINER_DECL void dlmalloc_multidealloc(boost_cont_memchain *pchain);
+
+BOOST_CONTAINER_DECL size_t dlmalloc_footprint();
+
+BOOST_CONTAINER_DECL size_t dlmalloc_allocated_memory();
+
+BOOST_CONTAINER_DECL size_t dlmalloc_chunksize(const void *p);
+
+BOOST_CONTAINER_DECL int dlmalloc_all_deallocated();
+
+BOOST_CONTAINER_DECL boost_cont_malloc_stats_t dlmalloc_malloc_stats();
+
+BOOST_CONTAINER_DECL size_t dlmalloc_in_use_memory();
+
+BOOST_CONTAINER_DECL int dlmalloc_trim(size_t pad);
+
+BOOST_CONTAINER_DECL int dlmalloc_mallopt(int parameter_number, int parameter_value);
+
+BOOST_CONTAINER_DECL int dlmalloc_grow(void* oldmem, size_t minbytes, size_t maxbytes, size_t *received);
+
+BOOST_CONTAINER_DECL int dlmalloc_shrink(void* oldmem, size_t minbytes, size_t maxbytes, size_t *received, int do_commit);
+
+BOOST_CONTAINER_DECL void* dlmalloc_alloc(size_t minbytes, size_t preferred_bytes, size_t *received_bytes);
+
+BOOST_CONTAINER_DECL int dlmalloc_malloc_check();
+
+BOOST_CONTAINER_DECL boost_cont_command_ret_t dlmalloc_allocation_command
+ ( allocation_type command
+ , size_t sizeof_object
+ , size_t limit_objects
+ , size_t preferred_objects
+ , size_t *received_objects
+ , void *reuse_ptr
+ );
+
+BOOST_CONTAINER_DECL int dlmalloc_mallopt(int param_number, int value);
+
+BOOST_CONTAINER_DECL void *dlmalloc_sync_create();
+
+BOOST_CONTAINER_DECL void dlmalloc_sync_destroy(void *sync);
+
+BOOST_CONTAINER_DECL bool dlmalloc_sync_lock(void *sync);
+
+BOOST_CONTAINER_DECL void dlmalloc_sync_unlock(void *sync);
+
+BOOST_CONTAINER_DECL bool dlmalloc_global_sync_lock();
+
+BOOST_CONTAINER_DECL void dlmalloc_global_sync_unlock();
+
+} //namespace container{
+} //namespace boost{
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //BOOST_CONTAINER_DETAIL_ALLOC_LIB_HPP
diff --git a/include/boost/container/detail/flat_tree.hpp b/include/boost/container/detail/flat_tree.hpp
new file mode 100644
index 0000000..e9cbe38
--- /dev/null
+++ b/include/boost/container/detail/flat_tree.hpp
@@ -0,0 +1,1621 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// (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 http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_FLAT_TREE_HPP
+#define BOOST_CONTAINER_FLAT_TREE_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/container_fwd.hpp>
+
+#include <boost/move/utility_core.hpp>
+
+#include <boost/container/detail/pair.hpp>
+#include <boost/container/vector.hpp>
+#include <boost/container/allocator_traits.hpp>
+
+#include <boost/container/detail/value_init.hpp>
+#include <boost/container/detail/destroyers.hpp>
+#include <boost/container/detail/algorithm.hpp> //algo_equal(), algo_lexicographical_compare
+#include <boost/container/detail/iterator.hpp>
+#include <boost/container/detail/is_sorted.hpp>
+#include <boost/container/detail/type_traits.hpp>
+#include <boost/container/detail/iterators.hpp>
+#include <boost/container/detail/mpl.hpp>
+#include <boost/container/detail/is_contiguous_container.hpp>
+#include <boost/container/detail/is_container.hpp>
+
+#include <boost/intrusive/detail/minimal_pair_header.hpp> //pair
+
+#include <boost/move/make_unique.hpp>
+#include <boost/move/iterator.hpp>
+#include <boost/move/adl_move_swap.hpp>
+#include <boost/move/algo/adaptive_sort.hpp>
+#include <boost/move/algo/detail/pdqsort.hpp>
+
+#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+#include <boost/move/detail/fwd_macros.hpp>
+#endif
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+//merge_unique
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME merge_unique
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace dtl {
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 3
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 3
+#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
+
+//merge_equal
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME merge
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace dtl {
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 3
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 3
+#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
+
+//index_of
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME index_of
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace dtl {
+#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>
+
+//nth
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME nth
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace dtl {
+#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>
+
+//reserve
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME reserve
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace dtl {
+#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>
+
+//capacity
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME capacity
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace dtl {
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 0
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 0
+#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
+
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+namespace boost {
+namespace container {
+namespace dtl {
+
+///////////////////////////////////////
+//
+// Helper functions to merge elements
+//
+///////////////////////////////////////
+
+BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(stored_allocator_type)
+
+///////////////////////////////////////
+//
+// flat_tree_container_inplace_merge
+//
+///////////////////////////////////////
+template<class SequenceContainer, class Compare>
+void flat_tree_container_inplace_merge //is_contiguous_container == true
+ (SequenceContainer& dest, typename SequenceContainer::iterator it, Compare comp , dtl::true_)
+{
+ typedef typename SequenceContainer::value_type value_type;
+ value_type *const braw = boost::movelib::iterator_to_raw_pointer(dest.begin());
+ value_type *const iraw = boost::movelib::iterator_to_raw_pointer(it);
+ value_type *const eraw = boost::movelib::iterator_to_raw_pointer(dest.end());
+ boost::movelib::adaptive_merge(braw, iraw, eraw, comp, eraw, dest.capacity()- dest.size());
+}
+
+template<class SequenceContainer, class Compare>
+void flat_tree_container_inplace_merge //is_contiguous_container == false
+ (SequenceContainer& dest, typename SequenceContainer::iterator it, Compare comp, dtl::false_)
+{
+ boost::movelib::adaptive_merge(dest.begin(), it, dest.end(), comp);
+}
+
+///////////////////////////////////////
+//
+// flat_tree_container_inplace_sort_ending
+//
+///////////////////////////////////////
+template<class SequenceContainer, class Compare>
+void flat_tree_container_inplace_sort_ending //is_contiguous_container == true
+ (SequenceContainer& dest, typename SequenceContainer::iterator it, Compare comp, dtl::true_)
+{
+ typedef typename SequenceContainer::value_type value_type;
+ value_type *const iraw = boost::movelib::iterator_to_raw_pointer(it);
+ value_type *const eraw = boost::movelib::iterator_to_raw_pointer(dest.end());
+ boost::movelib::adaptive_sort(iraw, eraw, comp, eraw, dest.capacity()- dest.size());
+}
+
+template<class SequenceContainer, class Compare>
+void flat_tree_container_inplace_sort_ending //is_contiguous_container == false
+ (SequenceContainer& dest, typename SequenceContainer::iterator it, Compare comp , dtl::false_)
+{
+ boost::movelib::adaptive_sort(it, dest.end(), comp);
+}
+
+///////////////////////////////////////
+//
+// flat_tree_merge
+//
+///////////////////////////////////////
+template<class SequenceContainer, class Iterator, class Compare>
+BOOST_CONTAINER_FORCEINLINE void flat_tree_merge_equal
+ (SequenceContainer& dest, Iterator first, Iterator last, Compare comp, dtl::true_)
+{
+ dest.merge(first, last, comp);
+}
+
+template<class SequenceContainer, class Iterator, class Compare>
+BOOST_CONTAINER_FORCEINLINE void flat_tree_merge_equal //has_merge_unique == false
+ (SequenceContainer& dest, Iterator first, Iterator last, Compare comp, dtl::false_)
+{
+ typedef typename SequenceContainer::iterator iterator;
+ iterator const it = dest.insert( dest.end(), first, last );
+ dtl::bool_<is_contiguous_container<SequenceContainer>::value> contiguous_tag;
+ (flat_tree_container_inplace_merge)(dest, it, comp, contiguous_tag);
+}
+
+///////////////////////////////////////
+//
+// flat_tree_merge_unique
+//
+///////////////////////////////////////
+template<class SequenceContainer, class Iterator, class Compare>
+BOOST_CONTAINER_FORCEINLINE void flat_tree_merge_unique //has_merge_unique == true
+ (SequenceContainer& dest, Iterator first, Iterator last, Compare comp, dtl::true_)
+{
+ dest.merge_unique(first, last, comp);
+}
+
+template<class SequenceContainer, class Iterator, class Compare>
+BOOST_CONTAINER_FORCEINLINE void flat_tree_merge_unique //has_merge_unique == false
+ (SequenceContainer& dest, Iterator first, Iterator last, Compare comp, dtl::false_)
+{
+ typedef typename SequenceContainer::iterator iterator;
+ typedef typename SequenceContainer::size_type size_type;
+
+ size_type const old_sz = dest.size();
+ iterator const first_new = dest.insert(dest.cend(), first, last );
+ iterator e = boost::movelib::inplace_set_difference(first_new, dest.end(), dest.begin(), first_new, comp);
+ dest.erase(e, dest.end());
+ dtl::bool_<is_contiguous_container<SequenceContainer>::value> contiguous_tag;
+ (flat_tree_container_inplace_merge)(dest, dest.begin()+old_sz, comp, contiguous_tag);
+}
+
+///////////////////////////////////////
+//
+// flat_tree_index_of
+//
+///////////////////////////////////////
+template<class SequenceContainer, class Iterator>
+BOOST_CONTAINER_FORCEINLINE typename SequenceContainer::size_type
+ flat_tree_index_of // has_index_of == true
+ (SequenceContainer& cont, Iterator p, dtl::true_)
+{
+ return cont.index_of(p);
+}
+
+template<class SequenceContainer, class Iterator>
+BOOST_CONTAINER_FORCEINLINE typename SequenceContainer::size_type
+ flat_tree_index_of // has_index_of == false
+ (SequenceContainer& cont, Iterator p, dtl::false_)
+{
+ typedef typename SequenceContainer::size_type size_type;
+ return static_cast<size_type>(p - cont.begin());
+}
+
+///////////////////////////////////////
+//
+// flat_tree_nth
+//
+///////////////////////////////////////
+template<class Iterator, class SequenceContainer>
+BOOST_CONTAINER_FORCEINLINE Iterator
+ flat_tree_nth // has_nth == true
+ (SequenceContainer& cont, typename SequenceContainer::size_type n, dtl::true_)
+{
+ return cont.nth(n);
+}
+
+template<class Iterator, class SequenceContainer>
+BOOST_CONTAINER_FORCEINLINE Iterator
+ flat_tree_nth // has_nth == false
+ (SequenceContainer& cont, typename SequenceContainer::size_type n, dtl::false_)
+{
+ return cont.begin()+ n;
+}
+
+///////////////////////////////////////
+//
+// flat_tree_get_stored_allocator
+//
+///////////////////////////////////////
+template<class SequenceContainer>
+BOOST_CONTAINER_FORCEINLINE typename SequenceContainer::stored_allocator_type &
+ flat_tree_get_stored_allocator // has_get_stored_allocator == true
+ (SequenceContainer& cont, dtl::true_)
+{
+ return cont.get_stored_allocator();
+}
+
+template<class SequenceContainer>
+BOOST_CONTAINER_FORCEINLINE const typename SequenceContainer::stored_allocator_type &
+ flat_tree_get_stored_allocator // has_get_stored_allocator == true
+ (const SequenceContainer& cont, dtl::true_)
+{
+ return cont.get_stored_allocator();
+}
+
+template<class SequenceContainer>
+BOOST_CONTAINER_FORCEINLINE typename SequenceContainer::allocator_type
+ flat_tree_get_stored_allocator // has_get_stored_allocator == false
+ (SequenceContainer& cont, dtl::false_)
+{
+ return cont.get_allocator();
+}
+
+///////////////////////////////////////
+//
+// flat_tree_adopt_sequence_equal
+//
+///////////////////////////////////////
+template<class SequenceContainer, class Compare>
+void flat_tree_sort_contiguous_to_adopt // is_contiguous_container == true
+ (SequenceContainer &tseq, BOOST_RV_REF(SequenceContainer) seq, Compare comp)
+{
+ if(tseq.capacity() >= (seq.capacity() - seq.size())) {
+ tseq.clear();
+ boost::movelib::adaptive_sort
+ (boost::movelib::iterator_to_raw_pointer(seq.begin())
+ , boost::movelib::iterator_to_raw_pointer(seq.end())
+ , comp
+ , boost::movelib::iterator_to_raw_pointer(tseq.begin())
+ , tseq.capacity());
+ }
+ else{
+ boost::movelib::adaptive_sort
+ (boost::movelib::iterator_to_raw_pointer(seq.begin())
+ , boost::movelib::iterator_to_raw_pointer(seq.end())
+ , comp
+ , boost::movelib::iterator_to_raw_pointer(seq.end())
+ , seq.capacity() - seq.size());
+ }
+}
+
+template<class SequenceContainer, class Compare>
+void flat_tree_adopt_sequence_equal // is_contiguous_container == true
+ (SequenceContainer &tseq, BOOST_RV_REF(SequenceContainer) seq, Compare comp, dtl::true_)
+{
+ flat_tree_sort_contiguous_to_adopt(tseq, boost::move(seq), comp);
+ tseq = boost::move(seq);
+}
+
+template<class SequenceContainer, class Compare>
+void flat_tree_adopt_sequence_equal // is_contiguous_container == false
+ (SequenceContainer &tseq, BOOST_RV_REF(SequenceContainer) seq, Compare comp, dtl::false_)
+{
+ boost::movelib::adaptive_sort(seq.begin(), seq.end(), comp);
+ tseq = boost::move(seq);
+}
+
+///////////////////////////////////////
+//
+// flat_tree_adopt_sequence_unique
+//
+///////////////////////////////////////
+template<class SequenceContainer, class Compare>
+void flat_tree_adopt_sequence_unique// is_contiguous_container == true
+ (SequenceContainer &tseq, BOOST_RV_REF(SequenceContainer) seq, Compare comp, dtl::true_)
+{
+ boost::movelib::pdqsort
+ ( boost::movelib::iterator_to_raw_pointer(seq.begin())
+ , boost::movelib::iterator_to_raw_pointer(seq.end())
+ , comp);
+ seq.erase(boost::movelib::unique
+ (seq.begin(), seq.end(), boost::movelib::negate<Compare>(comp)), seq.cend());
+ tseq = boost::move(seq);
+}
+
+template<class SequenceContainer, class Compare>
+void flat_tree_adopt_sequence_unique// is_contiguous_container == false
+ (SequenceContainer &tseq, BOOST_RV_REF(SequenceContainer) seq, Compare comp, dtl::false_)
+{
+ boost::movelib::pdqsort(seq.begin(), seq.end(), comp);
+ seq.erase(boost::movelib::unique
+ (seq.begin(), seq.end(), boost::movelib::negate<Compare>(comp)), seq.cend());
+ tseq = boost::move(seq);
+}
+
+///////////////////////////////////////
+//
+// flat_tree_reserve
+//
+///////////////////////////////////////
+template<class SequenceContainer>
+BOOST_CONTAINER_FORCEINLINE void // has_reserve == true
+ flat_tree_reserve(SequenceContainer &tseq, typename SequenceContainer::size_type cap, dtl::true_)
+{
+ tseq.reserve(cap);
+}
+
+template<class SequenceContainer>
+BOOST_CONTAINER_FORCEINLINE void // has_reserve == false
+ flat_tree_reserve(SequenceContainer &, typename SequenceContainer::size_type, dtl::false_)
+{
+}
+
+///////////////////////////////////////
+//
+// flat_tree_capacity
+//
+///////////////////////////////////////
+template<class SequenceContainer> // has_capacity == true
+BOOST_CONTAINER_FORCEINLINE typename SequenceContainer::size_type
+ flat_tree_capacity(const SequenceContainer &tseq, dtl::true_)
+{
+ return tseq.capacity();
+}
+
+template<class SequenceContainer> // has_capacity == false
+BOOST_CONTAINER_FORCEINLINE typename SequenceContainer::size_type
+ flat_tree_capacity(const SequenceContainer &tseq, dtl::false_)
+{
+ return tseq.size();
+}
+
+///////////////////////////////////////
+//
+// flat_tree_value_compare
+//
+///////////////////////////////////////
+
+template<class Compare, class Value, class KeyOfValue>
+class flat_tree_value_compare
+ : private Compare
+{
+ typedef Value first_argument_type;
+ typedef Value second_argument_type;
+ typedef bool return_type;
+ public:
+ flat_tree_value_compare()
+ : Compare()
+ {}
+
+ flat_tree_value_compare(const Compare &pred)
+ : Compare(pred)
+ {}
+
+ bool operator()(const Value& lhs, const Value& rhs) const
+ {
+ KeyOfValue key_extract;
+ return Compare::operator()(key_extract(lhs), key_extract(rhs));
+ }
+
+ const Compare &get_comp() const
+ { return *this; }
+
+ Compare &get_comp()
+ { return *this; }
+};
+
+///////////////////////////////////////
+//
+// select_container_type
+//
+///////////////////////////////////////
+template < class Value, class AllocatorOrContainer
+ , bool = boost::container::dtl::is_container<AllocatorOrContainer>::value >
+struct select_container_type
+{
+ typedef AllocatorOrContainer type;
+};
+
+template <class Value, class AllocatorOrContainer>
+struct select_container_type<Value, AllocatorOrContainer, false>
+{
+ typedef boost::container::vector<Value, AllocatorOrContainer> type;
+};
+
+
+///////////////////////////////////////
+//
+// flat_tree
+//
+///////////////////////////////////////
+template <class Value, class KeyOfValue,
+ class Compare, class AllocatorOrContainer>
+class flat_tree
+{
+ public:
+ typedef typename select_container_type<Value, AllocatorOrContainer>::type container_type;
+ typedef container_type sequence_type; //For backwards compatibility
+
+ private:
+ typedef typename container_type::allocator_type allocator_t;
+ typedef allocator_traits<allocator_t> allocator_traits_type;
+
+ public:
+ typedef flat_tree_value_compare<Compare, Value, KeyOfValue> value_compare;
+
+ private:
+
+ struct Data
+ //Inherit from value_compare to do EBO
+ : public value_compare
+ {
+ BOOST_COPYABLE_AND_MOVABLE(Data)
+
+ public:
+ Data()
+ : value_compare(), m_seq()
+ {}
+
+ explicit Data(const allocator_t &alloc)
+ : value_compare(), m_seq(alloc)
+ {}
+
+ explicit Data(const Compare &comp)
+ : value_compare(comp), m_seq()
+ {}
+
+ Data(const Compare &comp, const allocator_t &alloc)
+ : value_compare(comp), m_seq(alloc)
+ {}
+
+ explicit Data(const Data &d)
+ : value_compare(static_cast<const value_compare&>(d)), m_seq(d.m_seq)
+ {}
+
+ Data(BOOST_RV_REF(Data) d)
+ : value_compare(boost::move(static_cast<value_compare&>(d))), m_seq(boost::move(d.m_seq))
+ {}
+
+ Data(const Data &d, const allocator_t &a)
+ : value_compare(static_cast<const value_compare&>(d)), m_seq(d.m_seq, a)
+ {}
+
+ Data(BOOST_RV_REF(Data) d, const allocator_t &a)
+ : value_compare(boost::move(static_cast<value_compare&>(d))), m_seq(boost::move(d.m_seq), a)
+ {}
+
+ Data& operator=(BOOST_COPY_ASSIGN_REF(Data) d)
+ {
+ this->value_compare::operator=(d);
+ m_seq = d.m_seq;
+ return *this;
+ }
+
+ Data& operator=(BOOST_RV_REF(Data) d)
+ {
+ this->value_compare::operator=(boost::move(static_cast<value_compare &>(d)));
+ m_seq = boost::move(d.m_seq);
+ return *this;
+ }
+
+ void swap(Data &d)
+ {
+ value_compare& mycomp = *this, & othercomp = d;
+ boost::adl_move_swap(mycomp, othercomp);
+ this->m_seq.swap(d.m_seq);
+ }
+
+ container_type m_seq;
+ };
+
+ Data m_data;
+ BOOST_COPYABLE_AND_MOVABLE(flat_tree)
+
+ public:
+
+ typedef typename container_type::value_type value_type;
+ typedef typename container_type::pointer pointer;
+ typedef typename container_type::const_pointer const_pointer;
+ typedef typename container_type::reference reference;
+ typedef typename container_type::const_reference const_reference;
+ typedef typename KeyOfValue::type key_type;
+ typedef Compare key_compare;
+ typedef typename container_type::allocator_type allocator_type;
+ typedef typename container_type::size_type size_type;
+ typedef typename container_type::difference_type difference_type;
+ typedef typename container_type::iterator iterator;
+ typedef typename container_type::const_iterator const_iterator;
+ typedef typename container_type::reverse_iterator reverse_iterator;
+ typedef typename container_type::const_reverse_iterator const_reverse_iterator;
+
+ //!Standard extension
+ typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
+ (boost::container::dtl::, container_type
+ ,stored_allocator_type, allocator_type) stored_allocator_type;
+
+ static const bool has_stored_allocator_type =
+ BOOST_INTRUSIVE_HAS_TYPE(boost::container::dtl::, container_type, stored_allocator_type);
+
+ private:
+ typedef allocator_traits<stored_allocator_type> stored_allocator_traits;
+
+ public:
+ typedef typename dtl::if_c
+ <has_stored_allocator_type, const stored_allocator_type &, allocator_type>::type get_stored_allocator_const_return_t;
+
+ typedef typename dtl::if_c
+ <has_stored_allocator_type, stored_allocator_type &, allocator_type>::type get_stored_allocator_noconst_return_t;
+
+ BOOST_CONTAINER_FORCEINLINE flat_tree()
+ : m_data()
+ { }
+
+ BOOST_CONTAINER_FORCEINLINE explicit flat_tree(const Compare& comp)
+ : m_data(comp)
+ { }
+
+ BOOST_CONTAINER_FORCEINLINE explicit flat_tree(const allocator_type& a)
+ : m_data(a)
+ { }
+
+ BOOST_CONTAINER_FORCEINLINE flat_tree(const Compare& comp, const allocator_type& a)
+ : m_data(comp, a)
+ { }
+
+ BOOST_CONTAINER_FORCEINLINE flat_tree(const flat_tree& x)
+ : m_data(x.m_data)
+ { }
+
+ BOOST_CONTAINER_FORCEINLINE flat_tree(BOOST_RV_REF(flat_tree) x)
+ BOOST_NOEXCEPT_IF(boost::container::dtl::is_nothrow_move_constructible<Compare>::value)
+ : m_data(boost::move(x.m_data))
+ { }
+
+ BOOST_CONTAINER_FORCEINLINE flat_tree(const flat_tree& x, const allocator_type &a)
+ : m_data(x.m_data, a)
+ { }
+
+ BOOST_CONTAINER_FORCEINLINE flat_tree(BOOST_RV_REF(flat_tree) x, const allocator_type &a)
+ : m_data(boost::move(x.m_data), a)
+ { }
+
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_tree( ordered_range_t, InputIterator first, InputIterator last)
+ : m_data()
+ {
+ this->m_data.m_seq.insert(this->m_data.m_seq.end(), first, last);
+ BOOST_ASSERT((is_sorted)(this->m_data.m_seq.cbegin(), this->m_data.m_seq.cend(), this->priv_value_comp()));
+ }
+
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_tree( ordered_range_t, InputIterator first, InputIterator last, const Compare& comp)
+ : m_data(comp)
+ {
+ this->m_data.m_seq.insert(this->m_data.m_seq.end(), first, last);
+ BOOST_ASSERT((is_sorted)(this->m_data.m_seq.cbegin(), this->m_data.m_seq.cend(), this->priv_value_comp()));
+ }
+
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_tree( ordered_range_t, InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
+ : m_data(comp, a)
+ {
+ this->m_data.m_seq.insert(this->m_data.m_seq.end(), first, last);
+ BOOST_ASSERT((is_sorted)(this->m_data.m_seq.cbegin(), this->m_data.m_seq.cend(), this->priv_value_comp()));
+ }
+
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_tree( ordered_unique_range_t, InputIterator first, InputIterator last)
+ : m_data()
+ {
+ this->m_data.m_seq.insert(this->m_data.m_seq.end(), first, last);
+ BOOST_ASSERT((is_sorted_and_unique)(this->m_data.m_seq.cbegin(), this->m_data.m_seq.cend(), this->priv_value_comp()));
+ }
+
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_tree( ordered_unique_range_t, InputIterator first, InputIterator last, const Compare& comp)
+ : m_data(comp)
+ {
+ this->m_data.m_seq.insert(this->m_data.m_seq.end(), first, last);
+ BOOST_ASSERT((is_sorted_and_unique)(this->m_data.m_seq.cbegin(), this->m_data.m_seq.cend(), this->priv_value_comp()));
+ }
+
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_tree( ordered_unique_range_t, InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
+ : m_data(comp, a)
+ {
+ this->m_data.m_seq.insert(this->m_data.m_seq.end(), first, last);
+ BOOST_ASSERT((is_sorted_and_unique)(this->m_data.m_seq.cbegin(), this->m_data.m_seq.cend(), this->priv_value_comp()));
+ }
+
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_tree( bool unique_insertion, InputIterator first, InputIterator last)
+ : m_data()
+ {
+ this->priv_range_insertion_construct(unique_insertion, first, last);
+ }
+
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_tree( bool unique_insertion, InputIterator first, InputIterator last
+ , const Compare& comp)
+ : m_data(comp)
+ {
+ this->priv_range_insertion_construct(unique_insertion, first, last);
+ }
+
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_tree( bool unique_insertion, InputIterator first, InputIterator last
+ , const allocator_type& a)
+ : m_data(a)
+ {
+ this->priv_range_insertion_construct(unique_insertion, first, last);
+ }
+
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_tree( bool unique_insertion, InputIterator first, InputIterator last
+ , const Compare& comp, const allocator_type& a)
+ : m_data(comp, a)
+ {
+ this->priv_range_insertion_construct(unique_insertion, first, last);
+ }
+
+ BOOST_CONTAINER_FORCEINLINE ~flat_tree()
+ {}
+
+ BOOST_CONTAINER_FORCEINLINE flat_tree& operator=(BOOST_COPY_ASSIGN_REF(flat_tree) x)
+ { m_data = x.m_data; return *this; }
+
+ BOOST_CONTAINER_FORCEINLINE flat_tree& operator=(BOOST_RV_REF(flat_tree) x)
+ BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value ||
+ allocator_traits_type::is_always_equal::value) &&
+ boost::container::dtl::is_nothrow_move_assignable<Compare>::value)
+ { m_data = boost::move(x.m_data); return *this; }
+
+ BOOST_CONTAINER_FORCEINLINE const value_compare &priv_value_comp() const
+ { return static_cast<const value_compare &>(this->m_data); }
+
+ BOOST_CONTAINER_FORCEINLINE value_compare &priv_value_comp()
+ { return static_cast<value_compare &>(this->m_data); }
+
+ BOOST_CONTAINER_FORCEINLINE const key_compare &priv_key_comp() const
+ { return this->priv_value_comp().get_comp(); }
+
+ BOOST_CONTAINER_FORCEINLINE key_compare &priv_key_comp()
+ { return this->priv_value_comp().get_comp(); }
+
+ struct insert_commit_data
+ {
+ const_iterator position;
+ };
+
+ public:
+ // accessors:
+ BOOST_CONTAINER_FORCEINLINE Compare key_comp() const
+ { return this->m_data.get_comp(); }
+
+ BOOST_CONTAINER_FORCEINLINE value_compare value_comp() const
+ { return this->m_data; }
+
+ BOOST_CONTAINER_FORCEINLINE allocator_type get_allocator() const
+ { return this->m_data.m_seq.get_allocator(); }
+
+ BOOST_CONTAINER_FORCEINLINE get_stored_allocator_const_return_t get_stored_allocator() const
+ {
+ return flat_tree_get_stored_allocator(this->m_data.m_seq, dtl::bool_<has_stored_allocator_type>());
+ }
+
+ BOOST_CONTAINER_FORCEINLINE get_stored_allocator_noconst_return_t get_stored_allocator()
+ {
+ return flat_tree_get_stored_allocator(this->m_data.m_seq, dtl::bool_<has_stored_allocator_type>());
+ }
+
+ BOOST_CONTAINER_FORCEINLINE iterator begin()
+ { return this->m_data.m_seq.begin(); }
+
+ BOOST_CONTAINER_FORCEINLINE const_iterator begin() const
+ { return this->cbegin(); }
+
+ BOOST_CONTAINER_FORCEINLINE const_iterator cbegin() const
+ { return this->m_data.m_seq.begin(); }
+
+ BOOST_CONTAINER_FORCEINLINE iterator end()
+ { return this->m_data.m_seq.end(); }
+
+ BOOST_CONTAINER_FORCEINLINE const_iterator end() const
+ { return this->cend(); }
+
+ BOOST_CONTAINER_FORCEINLINE const_iterator cend() const
+ { return this->m_data.m_seq.end(); }
+
+ BOOST_CONTAINER_FORCEINLINE reverse_iterator rbegin()
+ { return reverse_iterator(this->end()); }
+
+ BOOST_CONTAINER_FORCEINLINE const_reverse_iterator rbegin() const
+ { return this->crbegin(); }
+
+ BOOST_CONTAINER_FORCEINLINE const_reverse_iterator crbegin() const
+ { return const_reverse_iterator(this->cend()); }
+
+ BOOST_CONTAINER_FORCEINLINE reverse_iterator rend()
+ { return reverse_iterator(this->begin()); }
+
+ BOOST_CONTAINER_FORCEINLINE const_reverse_iterator rend() const
+ { return this->crend(); }
+
+ BOOST_CONTAINER_FORCEINLINE const_reverse_iterator crend() const
+ { return const_reverse_iterator(this->cbegin()); }
+
+ BOOST_CONTAINER_FORCEINLINE bool empty() const
+ { return this->m_data.m_seq.empty(); }
+
+ BOOST_CONTAINER_FORCEINLINE size_type size() const
+ { return this->m_data.m_seq.size(); }
+
+ BOOST_CONTAINER_FORCEINLINE size_type max_size() const
+ { return this->m_data.m_seq.max_size(); }
+
+ BOOST_CONTAINER_FORCEINLINE void swap(flat_tree& other)
+ BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value
+ && boost::container::dtl::is_nothrow_swappable<Compare>::value )
+ { this->m_data.swap(other.m_data); }
+
+ public:
+ // insert/erase
+ std::pair<iterator,bool> insert_unique(const value_type& val)
+ {
+ std::pair<iterator,bool> ret;
+ insert_commit_data data;
+ ret.second = this->priv_insert_unique_prepare(KeyOfValue()(val), data);
+ ret.first = ret.second ? this->priv_insert_commit(data, val)
+ : this->begin() + (data.position - this->cbegin());
+ //: iterator(vector_iterator_get_ptr(data.position));
+ return ret;
+ }
+
+ std::pair<iterator,bool> insert_unique(BOOST_RV_REF(value_type) val)
+ {
+ std::pair<iterator,bool> ret;
+ insert_commit_data data;
+ ret.second = this->priv_insert_unique_prepare(KeyOfValue()(val), data);
+ ret.first = ret.second ? this->priv_insert_commit(data, boost::move(val))
+ : this->begin() + (data.position - this->cbegin());
+ //: iterator(vector_iterator_get_ptr(data.position));
+ return ret;
+ }
+
+ iterator insert_equal(const value_type& val)
+ {
+ iterator i = this->upper_bound(KeyOfValue()(val));
+ i = this->m_data.m_seq.insert(i, val);
+ return i;
+ }
+
+ iterator insert_equal(BOOST_RV_REF(value_type) mval)
+ {
+ iterator i = this->upper_bound(KeyOfValue()(mval));
+ i = this->m_data.m_seq.insert(i, boost::move(mval));
+ return i;
+ }
+
+ iterator insert_unique(const_iterator hint, const value_type& val)
+ {
+ BOOST_ASSERT(this->priv_in_range_or_end(hint));
+ insert_commit_data data;
+ return this->priv_insert_unique_prepare(hint, KeyOfValue()(val), data)
+ ? this->priv_insert_commit(data, val)
+ : this->begin() + (data.position - this->cbegin());
+ //: iterator(vector_iterator_get_ptr(data.position));
+ }
+
+ iterator insert_unique(const_iterator hint, BOOST_RV_REF(value_type) val)
+ {
+ BOOST_ASSERT(this->priv_in_range_or_end(hint));
+ insert_commit_data data;
+ return this->priv_insert_unique_prepare(hint, KeyOfValue()(val), data)
+ ? this->priv_insert_commit(data, boost::move(val))
+ : this->begin() + (data.position - this->cbegin());
+ //: iterator(vector_iterator_get_ptr(data.position));
+ }
+
+ iterator insert_equal(const_iterator hint, const value_type& val)
+ {
+ BOOST_ASSERT(this->priv_in_range_or_end(hint));
+ insert_commit_data data;
+ this->priv_insert_equal_prepare(hint, val, data);
+ return this->priv_insert_commit(data, val);
+ }
+
+ iterator insert_equal(const_iterator hint, BOOST_RV_REF(value_type) mval)
+ {
+ BOOST_ASSERT(this->priv_in_range_or_end(hint));
+ insert_commit_data data;
+ this->priv_insert_equal_prepare(hint, mval, data);
+ return this->priv_insert_commit(data, boost::move(mval));
+ }
+
+ template <class InIt>
+ void insert_unique(InIt first, InIt last)
+ {
+ dtl::bool_<is_contiguous_container<container_type>::value> contiguous_tag;
+ container_type &seq = this->m_data.m_seq;
+ value_compare &val_cmp = this->priv_value_comp();
+
+ //Step 1: put new elements in the back
+ typename container_type::iterator const it = seq.insert(seq.cend(), first, last);
+
+ //Step 2: sort them
+ boost::movelib::pdqsort(it, seq.end(), val_cmp);
+
+ //Step 3: only left unique values from the back not already present in the original range
+ typename container_type::iterator const e = boost::movelib::inplace_set_unique_difference
+ (it, seq.end(), seq.begin(), it, val_cmp);
+ seq.erase(e, seq.cend());
+
+ //Step 4: merge both ranges
+ (flat_tree_container_inplace_merge)(seq, it, this->priv_value_comp(), contiguous_tag);
+ }
+
+ template <class InIt>
+ void insert_equal(InIt first, InIt last)
+ {
+ dtl::bool_<is_contiguous_container<container_type>::value> contiguous_tag;
+ container_type &seq = this->m_data.m_seq;
+ typename container_type::iterator const it = seq.insert(seq.cend(), first, last);
+ (flat_tree_container_inplace_sort_ending)(seq, it, this->priv_value_comp(), contiguous_tag);
+ (flat_tree_container_inplace_merge) (seq, it, this->priv_value_comp(), contiguous_tag);
+ }
+
+ //Ordered
+
+ template <class InIt>
+ void insert_equal(ordered_range_t, InIt first, InIt last)
+ {
+ const bool value = boost::container::dtl::
+ has_member_function_callable_with_merge_unique<container_type, InIt, InIt, value_compare>::value;
+ (flat_tree_merge_equal)(this->m_data.m_seq, first, last, this->priv_value_comp(), dtl::bool_<value>());
+ }
+
+ template <class InIt>
+ void insert_unique(ordered_unique_range_t, InIt first, InIt last)
+ {
+ const bool value = boost::container::dtl::
+ has_member_function_callable_with_merge_unique<container_type, InIt, InIt, value_compare>::value;
+ (flat_tree_merge_unique)(this->m_data.m_seq, first, last, this->priv_value_comp(), dtl::bool_<value>());
+ }
+
+ #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ template <class... Args>
+ std::pair<iterator, bool> emplace_unique(BOOST_FWD_REF(Args)... args)
+ {
+ typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v;
+ value_type &val = *static_cast<value_type *>(static_cast<void *>(v.data));
+ get_stored_allocator_noconst_return_t a = this->get_stored_allocator();
+ stored_allocator_traits::construct(a, &val, ::boost::forward<Args>(args)... );
+ value_destructor<stored_allocator_type, value_type> d(a, val);
+ return this->insert_unique(::boost::move(val));
+ }
+
+ template <class... Args>
+ iterator emplace_hint_unique(const_iterator hint, BOOST_FWD_REF(Args)... args)
+ {
+ //hint checked in insert_unique
+ typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v;
+ value_type &val = *static_cast<value_type *>(static_cast<void *>(v.data));
+ get_stored_allocator_noconst_return_t a = this->get_stored_allocator();
+ stored_allocator_traits::construct(a, &val, ::boost::forward<Args>(args)... );
+ value_destructor<stored_allocator_type, value_type> d(a, val);
+ return this->insert_unique(hint, ::boost::move(val));
+ }
+
+ template <class... Args>
+ iterator emplace_equal(BOOST_FWD_REF(Args)... args)
+ {
+ typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v;
+ value_type &val = *static_cast<value_type *>(static_cast<void *>(v.data));
+ get_stored_allocator_noconst_return_t a = this->get_stored_allocator();
+ stored_allocator_traits::construct(a, &val, ::boost::forward<Args>(args)... );
+ value_destructor<stored_allocator_type, value_type> d(a, val);
+ return this->insert_equal(::boost::move(val));
+ }
+
+ template <class... Args>
+ iterator emplace_hint_equal(const_iterator hint, BOOST_FWD_REF(Args)... args)
+ {
+ //hint checked in insert_equal
+ typename aligned_storage<sizeof(value_type), alignment_of<value_type>::value>::type v;
+ value_type &val = *static_cast<value_type *>(static_cast<void *>(v.data));
+ get_stored_allocator_noconst_return_t a = this->get_stored_allocator();
+ stored_allocator_traits::construct(a, &val, ::boost::forward<Args>(args)... );
+ value_destructor<stored_allocator_type, value_type> d(a, val);
+ return this->insert_equal(hint, ::boost::move(val));
+ }
+
+ template <class KeyType, class... Args>
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> try_emplace
+ (const_iterator hint, BOOST_FWD_REF(KeyType) key, BOOST_FWD_REF(Args)... args)
+ {
+ std::pair<iterator,bool> ret;
+ insert_commit_data data;
+ const key_type & k = key;
+ ret.second = hint == const_iterator()
+ ? this->priv_insert_unique_prepare(k, data)
+ : this->priv_insert_unique_prepare(hint, k, data);
+
+ if(!ret.second){
+ ret.first = this->nth(data.position - this->cbegin());
+ }
+ else{
+ typedef typename emplace_functor_type<try_emplace_t, KeyType, Args...>::type func_t;
+ typedef emplace_iterator<value_type, func_t, difference_type> it_t;
+ func_t func(try_emplace_t(), ::boost::forward<KeyType>(key), ::boost::forward<Args>(args)...);
+ ret.first = this->m_data.m_seq.insert(data.position, it_t(func), it_t());
+ }
+ return ret;
+ }
+
+ #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.data));\
+ get_stored_allocator_noconst_return_t a = this->get_stored_allocator();\
+ stored_allocator_traits::construct(a, &val BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
+ value_destructor<stored_allocator_type, value_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.data));\
+ get_stored_allocator_noconst_return_t a = this->get_stored_allocator();\
+ stored_allocator_traits::construct(a, &val BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
+ value_destructor<stored_allocator_type, value_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.data));\
+ get_stored_allocator_noconst_return_t a = this->get_stored_allocator();\
+ stored_allocator_traits::construct(a, &val BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
+ value_destructor<stored_allocator_type, value_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.data));\
+ get_stored_allocator_noconst_return_t a = this->get_stored_allocator();\
+ stored_allocator_traits::construct(a, &val BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
+ value_destructor<stored_allocator_type, value_type> d(a, val);\
+ return this->insert_equal(hint, ::boost::move(val));\
+ }\
+ template <class KeyType BOOST_MOVE_I##N BOOST_MOVE_CLASS##N>\
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool>\
+ try_emplace(const_iterator hint, BOOST_FWD_REF(KeyType) key BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ {\
+ std::pair<iterator,bool> ret;\
+ insert_commit_data data;\
+ const key_type & k = key;\
+ ret.second = hint == const_iterator()\
+ ? this->priv_insert_unique_prepare(k, data)\
+ : this->priv_insert_unique_prepare(hint, k, data);\
+ \
+ if(!ret.second){\
+ ret.first = this->nth(data.position - this->cbegin());\
+ }\
+ else{\
+ typedef typename emplace_functor_type<try_emplace_t, KeyType BOOST_MOVE_I##N BOOST_MOVE_TARG##N>::type func_t;\
+ typedef emplace_iterator<value_type, func_t, difference_type> it_t;\
+ func_t func(try_emplace_t(), ::boost::forward<KeyType>(key) BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
+ ret.first = this->m_data.m_seq.insert(data.position, it_t(func), it_t());\
+ }\
+ return ret;\
+ }\
+ //
+ BOOST_MOVE_ITERATE_0TO7(BOOST_CONTAINER_FLAT_TREE_EMPLACE_CODE)
+ #undef BOOST_CONTAINER_FLAT_TREE_EMPLACE_CODE
+
+ #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ template<class KeyType, class M>
+ std::pair<iterator, bool> insert_or_assign(const_iterator hint, BOOST_FWD_REF(KeyType) key, BOOST_FWD_REF(M) obj)
+ {
+ const key_type& k = key;
+ std::pair<iterator,bool> ret;
+ insert_commit_data data;
+ ret.second = hint == const_iterator()
+ ? this->priv_insert_unique_prepare(k, data)
+ : this->priv_insert_unique_prepare(hint, k, data);
+ if(!ret.second){
+ ret.first = this->nth(data.position - this->cbegin());
+ ret.first->second = boost::forward<M>(obj);
+ }
+ else{
+ typedef typename emplace_functor_type<KeyType, M>::type func_t;
+ typedef emplace_iterator<value_type, func_t, difference_type> it_t;
+ func_t func(boost::forward<KeyType>(key), boost::forward<M>(obj));
+ ret.first = this->m_data.m_seq.insert(data.position, it_t(func), it_t());
+ }
+ return ret;
+ }
+
+ BOOST_CONTAINER_FORCEINLINE iterator erase(const_iterator position)
+ { return this->m_data.m_seq.erase(position); }
+
+ size_type erase(const key_type& k)
+ {
+ std::pair<iterator,iterator > itp = this->equal_range(k);
+ size_type ret = static_cast<size_type>(itp.second-itp.first);
+ if (ret){
+ this->m_data.m_seq.erase(itp.first, itp.second);
+ }
+ return ret;
+ }
+
+ BOOST_CONTAINER_FORCEINLINE iterator erase(const_iterator first, const_iterator last)
+ { return this->m_data.m_seq.erase(first, last); }
+
+ BOOST_CONTAINER_FORCEINLINE void clear()
+ { this->m_data.m_seq.clear(); }
+
+ //! <b>Effects</b>: Tries to deallocate the excess of memory created
+ // with previous allocations. The size of the vector is unchanged
+ //!
+ //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to size().
+ BOOST_CONTAINER_FORCEINLINE void shrink_to_fit()
+ { this->m_data.m_seq.shrink_to_fit(); }
+
+ BOOST_CONTAINER_FORCEINLINE iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ const bool value = boost::container::dtl::
+ has_member_function_callable_with_nth<container_type, size_type>::value;
+ return flat_tree_nth<iterator>(this->m_data.m_seq, n, dtl::bool_<value>());
+ }
+
+ BOOST_CONTAINER_FORCEINLINE const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ const bool value = boost::container::dtl::
+ has_member_function_callable_with_nth<container_type, size_type>::value;
+ return flat_tree_nth<const_iterator>(this->m_data.m_seq, n, dtl::bool_<value>());
+ }
+
+ BOOST_CONTAINER_FORCEINLINE size_type index_of(iterator p) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ const bool value = boost::container::dtl::
+ has_member_function_callable_with_index_of<container_type, iterator>::value;
+ return flat_tree_index_of(this->m_data.m_seq, p, dtl::bool_<value>());
+ }
+
+ BOOST_CONTAINER_FORCEINLINE size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ const bool value = boost::container::dtl::
+ has_member_function_callable_with_index_of<container_type, const_iterator>::value;
+ return flat_tree_index_of(this->m_data.m_seq, p, dtl::bool_<value>());
+ }
+
+ // set operations:
+ iterator find(const key_type& k)
+ {
+ iterator i = this->lower_bound(k);
+ iterator end_it = this->end();
+ if (i != end_it && this->m_data.get_comp()(k, KeyOfValue()(*i))){
+ i = end_it;
+ }
+ return i;
+ }
+
+ const_iterator find(const key_type& k) const
+ {
+ const_iterator i = this->lower_bound(k);
+
+ const_iterator end_it = this->cend();
+ if (i != end_it && this->m_data.get_comp()(k, KeyOfValue()(*i))){
+ i = end_it;
+ }
+ return i;
+ }
+
+ template<class K>
+ typename dtl::enable_if_transparent<key_compare, K, iterator>::type
+ find(const K& k)
+ {
+ iterator i = this->lower_bound(k);
+ iterator end_it = this->end();
+ if (i != end_it && this->m_data.get_comp()(k, KeyOfValue()(*i))){
+ i = end_it;
+ }
+ return i;
+ }
+
+ template<class K>
+ typename dtl::enable_if_transparent<key_compare, K, const_iterator>::type
+ find(const K& k) const
+ {
+ const_iterator i = this->lower_bound(k);
+
+ const_iterator end_it = this->cend();
+ if (i != end_it && this->m_data.get_comp()(k, KeyOfValue()(*i))){
+ i = end_it;
+ }
+ return i;
+ }
+
+ size_type count(const key_type& k) const
+ {
+ std::pair<const_iterator, const_iterator> p = this->equal_range(k);
+ size_type n = p.second - p.first;
+ return n;
+ }
+
+ template<class K>
+ typename dtl::enable_if_transparent<key_compare, K, size_type>::type
+ count(const K& k) const
+ {
+ std::pair<const_iterator, const_iterator> p = this->equal_range(k);
+ size_type n = p.second - p.first;
+ return n;
+ }
+
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge_unique(flat_tree<Value, KeyOfValue, C2, AllocatorOrContainer>& source)
+ {
+ this->insert( boost::make_move_iterator(source.begin())
+ , boost::make_move_iterator(source.end()));
+ }
+
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge_equal(flat_tree<Value, KeyOfValue, C2, AllocatorOrContainer>& source)
+ {
+ this->insert( boost::make_move_iterator(source.begin())
+ , boost::make_move_iterator(source.end()));
+ }
+
+ BOOST_CONTAINER_FORCEINLINE void merge_unique(flat_tree& source)
+ {
+ const bool value = boost::container::dtl::
+ has_member_function_callable_with_merge_unique<container_type, iterator, iterator, value_compare>::value;
+ (flat_tree_merge_unique)
+ ( this->m_data.m_seq
+ , boost::make_move_iterator(source.m_data.m_seq.begin())
+ , boost::make_move_iterator(source.m_data.m_seq.end())
+ , this->priv_value_comp()
+ , dtl::bool_<value>());
+ }
+
+ BOOST_CONTAINER_FORCEINLINE void merge_equal(flat_tree& source)
+ {
+ const bool value = boost::container::dtl::
+ has_member_function_callable_with_merge<container_type, iterator, iterator, value_compare>::value;
+ (flat_tree_merge_equal)
+ ( this->m_data.m_seq
+ , boost::make_move_iterator(source.m_data.m_seq.begin())
+ , boost::make_move_iterator(source.m_data.m_seq.end())
+ , this->priv_value_comp()
+ , dtl::bool_<value>());
+ }
+
+ BOOST_CONTAINER_FORCEINLINE iterator lower_bound(const key_type& k)
+ { return this->priv_lower_bound(this->begin(), this->end(), k); }
+
+ BOOST_CONTAINER_FORCEINLINE const_iterator lower_bound(const key_type& k) const
+ { return this->priv_lower_bound(this->cbegin(), this->cend(), k); }
+
+ template<class K>
+ BOOST_CONTAINER_FORCEINLINE
+ typename dtl::enable_if_transparent<key_compare, K, iterator>::type
+ lower_bound(const K& k)
+ { return this->priv_lower_bound(this->begin(), this->end(), k); }
+
+ template<class K>
+ BOOST_CONTAINER_FORCEINLINE
+ typename dtl::enable_if_transparent<key_compare, K, const_iterator>::type
+ lower_bound(const K& k) const
+ { return this->priv_lower_bound(this->cbegin(), this->cend(), k); }
+
+ BOOST_CONTAINER_FORCEINLINE iterator upper_bound(const key_type& k)
+ { return this->priv_upper_bound(this->begin(), this->end(), k); }
+
+ BOOST_CONTAINER_FORCEINLINE const_iterator upper_bound(const key_type& k) const
+ { return this->priv_upper_bound(this->cbegin(), this->cend(), k); }
+
+ template<class K>
+ BOOST_CONTAINER_FORCEINLINE
+ typename dtl::enable_if_transparent<key_compare, K,iterator>::type
+ upper_bound(const K& k)
+ { return this->priv_upper_bound(this->begin(), this->end(), k); }
+
+ template<class K>
+ BOOST_CONTAINER_FORCEINLINE
+ typename dtl::enable_if_transparent<key_compare, K,const_iterator>::type
+ upper_bound(const K& k) const
+ { return this->priv_upper_bound(this->cbegin(), this->cend(), k); }
+
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator,iterator> equal_range(const key_type& k)
+ { return this->priv_equal_range(this->begin(), this->end(), k); }
+
+ BOOST_CONTAINER_FORCEINLINE std::pair<const_iterator, const_iterator> equal_range(const key_type& k) const
+ { return this->priv_equal_range(this->cbegin(), this->cend(), k); }
+
+ template<class K>
+ BOOST_CONTAINER_FORCEINLINE
+ typename dtl::enable_if_transparent<key_compare, K,std::pair<iterator,iterator> >::type
+ equal_range(const K& k)
+ { return this->priv_equal_range(this->begin(), this->end(), k); }
+
+ template<class K>
+ BOOST_CONTAINER_FORCEINLINE
+ typename dtl::enable_if_transparent<key_compare, K,std::pair<const_iterator,const_iterator> >::type
+ equal_range(const K& k) const
+ { return this->priv_equal_range(this->cbegin(), this->cend(), k); }
+
+
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator, iterator> lower_bound_range(const key_type& k)
+ { return this->priv_lower_bound_range(this->begin(), this->end(), k); }
+
+ BOOST_CONTAINER_FORCEINLINE std::pair<const_iterator, const_iterator> lower_bound_range(const key_type& k) const
+ { return this->priv_lower_bound_range(this->cbegin(), this->cend(), k); }
+
+ template<class K>
+ BOOST_CONTAINER_FORCEINLINE
+ typename dtl::enable_if_transparent<key_compare, K,std::pair<iterator,iterator> >::type
+ lower_bound_range(const K& k)
+ { return this->priv_lower_bound_range(this->begin(), this->end(), k); }
+
+ template<class K>
+ BOOST_CONTAINER_FORCEINLINE
+ typename dtl::enable_if_transparent<key_compare, K,std::pair<const_iterator,const_iterator> >::type
+ lower_bound_range(const K& k) const
+ { return this->priv_lower_bound_range(this->cbegin(), this->cend(), k); }
+
+ BOOST_CONTAINER_FORCEINLINE size_type capacity() const
+ {
+ const bool value = boost::container::dtl::
+ has_member_function_callable_with_capacity<container_type>::value;
+ return (flat_tree_capacity)(this->m_data.m_seq, dtl::bool_<value>());
+ }
+
+ BOOST_CONTAINER_FORCEINLINE void reserve(size_type cnt)
+ {
+ const bool value = boost::container::dtl::
+ has_member_function_callable_with_reserve<container_type, size_type>::value;
+ (flat_tree_reserve)(this->m_data.m_seq, cnt, dtl::bool_<value>());
+ }
+
+ BOOST_CONTAINER_FORCEINLINE container_type extract_sequence()
+ {
+ return boost::move(m_data.m_seq);
+ }
+
+ BOOST_CONTAINER_FORCEINLINE container_type &get_sequence_ref()
+ {
+ return m_data.m_seq;
+ }
+
+ BOOST_CONTAINER_FORCEINLINE void adopt_sequence_equal(BOOST_RV_REF(container_type) seq)
+ {
+ (flat_tree_adopt_sequence_equal)( m_data.m_seq, boost::move(seq), this->priv_value_comp()
+ , dtl::bool_<is_contiguous_container<container_type>::value>());
+ }
+
+ BOOST_CONTAINER_FORCEINLINE void adopt_sequence_unique(BOOST_RV_REF(container_type) seq)
+ {
+ (flat_tree_adopt_sequence_unique)(m_data.m_seq, boost::move(seq), this->priv_value_comp()
+ , dtl::bool_<is_contiguous_container<container_type>::value>());
+ }
+
+ void adopt_sequence_equal(ordered_range_t, BOOST_RV_REF(container_type) seq)
+ {
+ BOOST_ASSERT((is_sorted)(seq.cbegin(), seq.cend(), this->priv_value_comp()));
+ m_data.m_seq = boost::move(seq);
+ }
+
+ void adopt_sequence_unique(ordered_unique_range_t, BOOST_RV_REF(container_type) seq)
+ {
+ BOOST_ASSERT((is_sorted_and_unique)(seq.cbegin(), seq.cend(), this->priv_value_comp()));
+ m_data.m_seq = boost::move(seq);
+ }
+
+ BOOST_CONTAINER_FORCEINLINE friend bool operator==(const flat_tree& x, const flat_tree& y)
+ {
+ return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin());
+ }
+
+ BOOST_CONTAINER_FORCEINLINE friend bool operator<(const flat_tree& x, const flat_tree& y)
+ {
+ return ::boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
+ }
+
+ BOOST_CONTAINER_FORCEINLINE friend bool operator!=(const flat_tree& x, const flat_tree& y)
+ { return !(x == y); }
+
+ BOOST_CONTAINER_FORCEINLINE friend bool operator>(const flat_tree& x, const flat_tree& y)
+ { return y < x; }
+
+ BOOST_CONTAINER_FORCEINLINE friend bool operator<=(const flat_tree& x, const flat_tree& y)
+ { return !(y < x); }
+
+ BOOST_CONTAINER_FORCEINLINE friend bool operator>=(const flat_tree& x, const flat_tree& y)
+ { return !(x < y); }
+
+ BOOST_CONTAINER_FORCEINLINE friend void swap(flat_tree& x, flat_tree& y)
+ { x.swap(y); }
+
+ private:
+
+ template <class InputIterator>
+ void priv_range_insertion_construct( bool unique_insertion, InputIterator first, InputIterator last)
+ {
+ //Use cend() as hint to achieve linear time for
+ //ordered ranges as required by the standard
+ //for the constructor
+ //Call end() every iteration as reallocation might have invalidated iterators
+ if(unique_insertion){
+ this->insert_unique(first, last);
+ }
+ else{
+ this->insert_equal (first, last);
+ }
+ }
+
+ BOOST_CONTAINER_FORCEINLINE bool priv_in_range_or_end(const_iterator pos) const
+ {
+ return (this->begin() <= pos) && (pos <= this->end());
+ }
+
+ // insert/erase
+ void priv_insert_equal_prepare
+ (const_iterator pos, const value_type& val, insert_commit_data &data)
+ {
+ // N1780
+ // To insert val at pos:
+ // if pos == end || val <= *pos
+ // if pos == begin || val >= *(pos-1)
+ // insert val before pos
+ // else
+ // insert val before upper_bound(val)
+ // else
+ // insert val before lower_bound(val)
+ const value_compare &val_cmp = this->m_data;
+
+ if(pos == this->cend() || !val_cmp(*pos, val)){
+ if (pos == this->cbegin() || !val_cmp(val, pos[-1])){
+ data.position = pos;
+ }
+ else{
+ data.position =
+ this->priv_upper_bound(this->cbegin(), pos, KeyOfValue()(val));
+ }
+ }
+ else{
+ data.position =
+ this->priv_lower_bound(pos, this->cend(), KeyOfValue()(val));
+ }
+ }
+
+ bool priv_insert_unique_prepare
+ (const_iterator b, const_iterator e, const key_type& k, insert_commit_data &commit_data)
+ {
+ const key_compare &key_cmp = this->priv_key_comp();
+ commit_data.position = this->priv_lower_bound(b, e, k);
+ return commit_data.position == e || key_cmp(k, KeyOfValue()(*commit_data.position));
+ }
+
+ BOOST_CONTAINER_FORCEINLINE bool priv_insert_unique_prepare
+ (const key_type& k, insert_commit_data &commit_data)
+ { return this->priv_insert_unique_prepare(this->cbegin(), this->cend(), k, commit_data); }
+
+ bool priv_insert_unique_prepare
+ (const_iterator pos, const key_type& k, insert_commit_data &commit_data)
+ {
+ //N1780. Props to Howard Hinnant!
+ //To insert k at pos:
+ //if pos == end || k <= *pos
+ // if pos == begin || k >= *(pos-1)
+ // insert k before pos
+ // else
+ // insert k before upper_bound(k)
+ //else if pos+1 == end || k <= *(pos+1)
+ // insert k after pos
+ //else
+ // insert k before lower_bound(k)
+ const key_compare &key_cmp = this->priv_key_comp();
+ const const_iterator cend_it = this->cend();
+ if(pos == cend_it || key_cmp(k, KeyOfValue()(*pos))){ //Check if k should go before end
+ const const_iterator cbeg = this->cbegin();
+ commit_data.position = pos;
+ if(pos == cbeg){ //If container is empty then insert it in the beginning
+ return true;
+ }
+ const_iterator prev(pos);
+ --prev;
+ if(key_cmp(KeyOfValue()(*prev), k)){ //If previous element was less, then it should go between prev and pos
+ return true;
+ }
+ else if(!key_cmp(k, KeyOfValue()(*prev))){ //If previous was equal then insertion should fail
+ commit_data.position = prev;
+ return false;
+ }
+ else{ //Previous was bigger so insertion hint was pointless, dispatch to hintless insertion
+ //but reduce the search between beg and prev as prev is bigger than k
+ return this->priv_insert_unique_prepare(cbeg, prev, k, commit_data);
+ }
+ }
+ else{
+ //The hint is before the insertion position, so insert it
+ //in the remaining range [pos, end)
+ return this->priv_insert_unique_prepare(pos, cend_it, k, commit_data);
+ }
+ }
+
+ template<class Convertible>
+ BOOST_CONTAINER_FORCEINLINE iterator priv_insert_commit
+ (insert_commit_data &commit_data, BOOST_FWD_REF(Convertible) convertible)
+ {
+ return this->m_data.m_seq.insert
+ ( commit_data.position
+ , boost::forward<Convertible>(convertible));
+ }
+
+ template <class RanIt, class K>
+ RanIt priv_lower_bound(RanIt first, const RanIt last,
+ const K & key) const
+ {
+ const Compare &key_cmp = this->m_data.get_comp();
+ KeyOfValue key_extract;
+ size_type len = static_cast<size_type>(last - first);
+ RanIt middle;
+
+ while (len) {
+ size_type step = len >> 1;
+ middle = first;
+ middle += step;
+
+ if (key_cmp(key_extract(*middle), key)) {
+ first = ++middle;
+ len -= step + 1;
+ }
+ else{
+ len = step;
+ }
+ }
+ return first;
+ }
+
+ template <class RanIt, class K>
+ RanIt priv_upper_bound
+ (RanIt first, const RanIt last,const K & key) const
+ {
+ const Compare &key_cmp = this->m_data.get_comp();
+ KeyOfValue key_extract;
+ size_type len = static_cast<size_type>(last - first);
+ RanIt middle;
+
+ while (len) {
+ size_type step = len >> 1;
+ middle = first;
+ middle += step;
+
+ if (key_cmp(key, key_extract(*middle))) {
+ len = step;
+ }
+ else{
+ first = ++middle;
+ len -= step + 1;
+ }
+ }
+ return first;
+ }
+
+ template <class RanIt, class K>
+ std::pair<RanIt, RanIt>
+ priv_equal_range(RanIt first, RanIt last, const K& key) const
+ {
+ const Compare &key_cmp = this->m_data.get_comp();
+ KeyOfValue key_extract;
+ size_type len = static_cast<size_type>(last - first);
+ RanIt middle;
+
+ while (len) {
+ size_type step = len >> 1;
+ middle = first;
+ middle += step;
+
+ if (key_cmp(key_extract(*middle), key)){
+ first = ++middle;
+ len -= step + 1;
+ }
+ else if (key_cmp(key, key_extract(*middle))){
+ len = step;
+ }
+ else {
+ //Middle is equal to key
+ last = first;
+ last += len;
+ RanIt const first_ret = this->priv_lower_bound(first, middle, key);
+ return std::pair<RanIt, RanIt>
+ ( first_ret, this->priv_upper_bound(++middle, last, key));
+ }
+ }
+ return std::pair<RanIt, RanIt>(first, first);
+ }
+
+ template<class RanIt, class K>
+ std::pair<RanIt, RanIt> priv_lower_bound_range(RanIt first, RanIt last, const K& k) const
+ {
+ const Compare &key_cmp = this->m_data.get_comp();
+ KeyOfValue key_extract;
+ RanIt lb(this->priv_lower_bound(first, last, k)), ub(lb);
+ if(lb != last && static_cast<difference_type>(!key_cmp(k, key_extract(*lb)))){
+ ++ub;
+ }
+ return std::pair<RanIt, RanIt>(lb, ub);
+ }
+};
+
+} //namespace dtl {
+
+} //namespace container {
+
+//!has_trivial_destructor_after_move<> == true_type
+//!specialization for optimizations
+template <class T, class KeyOfValue,
+class Compare, class AllocatorOrContainer>
+struct has_trivial_destructor_after_move<boost::container::dtl::flat_tree<T, KeyOfValue, Compare, AllocatorOrContainer> >
+{
+ typedef typename boost::container::dtl::select_container_type<T, AllocatorOrContainer>::type container_type;
+ typedef typename container_type::allocator_type allocator_t;
+ typedef typename ::boost::container::allocator_traits<allocator_t>::pointer pointer;
+ static const bool value = ::boost::has_trivial_destructor_after_move<allocator_t>::value &&
+ ::boost::has_trivial_destructor_after_move<pointer>::value;
+};
+
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif // BOOST_CONTAINER_FLAT_TREE_HPP
diff --git a/include/boost/container/detail/function_detector.hpp b/include/boost/container/detail/function_detector.hpp
new file mode 100644
index 0000000..00caced
--- /dev/null
+++ b/include/boost/container/detail/function_detector.hpp
@@ -0,0 +1,96 @@
+/////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2009-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.
+//
+/////////////////////////////////////////////////////////////////////////////
+// This code was modified from the code posted by Alexandre Courpron in his
+// article "Interface Detection" in The Code Project:
+// http://www.codeproject.com/KB/architecture/Detector.aspx
+///////////////////////////////////////////////////////////////////////////////
+// Copyright 2007 Alexandre Courpron
+//
+// Permission to use, copy, modify, redistribute and sell this software,
+// provided that this copyright notice appears on all copies of the software.
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_DETAIL_FUNCTION_DETECTOR_HPP
+#define BOOST_CONTAINER_DETAIL_FUNCTION_DETECTOR_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>
+
+namespace boost {
+namespace container {
+namespace function_detector {
+
+ typedef char NotFoundType;
+ struct StaticFunctionType { NotFoundType x [2]; };
+ struct NonStaticFunctionType { NotFoundType x [3]; };
+
+ enum
+ { NotFound = 0,
+ StaticFunction = sizeof( StaticFunctionType ) - sizeof( NotFoundType ),
+ NonStaticFunction = sizeof( NonStaticFunctionType ) - sizeof( NotFoundType )
+ };
+
+} //namespace boost {
+} //namespace container {
+} //namespace function_detector {
+
+#define BOOST_CONTAINER_CREATE_FUNCTION_DETECTOR(Identifier, InstantiationKey) \
+ namespace boost { \
+ namespace container { \
+ namespace function_detector { \
+ template < class T, \
+ class NonStaticType, \
+ class NonStaticConstType, \
+ class StaticType > \
+ class DetectMember_##InstantiationKey_##Identifier { \
+ template < NonStaticType > \
+ struct TestNonStaticNonConst ; \
+ \
+ template < NonStaticConstType > \
+ struct TestNonStaticConst ; \
+ \
+ template < StaticType > \
+ struct TestStatic ; \
+ \
+ template <class U > \
+ static NonStaticFunctionType Test( TestNonStaticNonConst<&U::Identifier>*, int ); \
+ \
+ template <class U > \
+ static NonStaticFunctionType Test( TestNonStaticConst<&U::Identifier>*, int ); \
+ \
+ template <class U> \
+ static StaticFunctionType Test( TestStatic<&U::Identifier>*, int ); \
+ \
+ template <class U> \
+ static NotFoundType Test( ... ); \
+ public : \
+ static const int check = NotFound + (sizeof(Test<T>(0, 0)) - sizeof(NotFoundType));\
+ };\
+}}} //namespace boost::container::function_detector {
+
+#define BOOST_CONTAINER_DETECT_FUNCTION(Class, InstantiationKey, ReturnType, Identifier, Params) \
+ ::boost::container::function_detector::DetectMember_##InstantiationKey_##Identifier< Class,\
+ ReturnType (Class::*)Params,\
+ ReturnType (Class::*)Params const,\
+ ReturnType (*)Params \
+ >::check
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //@ifndef BOOST_CONTAINER_DETAIL_FUNCTION_DETECTOR_HPP
diff --git a/include/boost/container/detail/is_container.hpp b/include/boost/container/detail/is_container.hpp
new file mode 100644
index 0000000..feab702
--- /dev/null
+++ b/include/boost/container/detail/is_container.hpp
@@ -0,0 +1,55 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2017-2017. 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_IS_CONTAINER_HPP
+#define BOOST_CONTAINER_DETAIL_IS_CONTAINER_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+//empty
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME empty
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace is_container_detail {
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 0
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 0
+#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
+
+//size
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME size
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace is_container_detail {
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 0
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 0
+#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
+
+namespace boost {
+namespace container {
+namespace dtl {
+
+template <class Container>
+struct is_container
+{
+ static const bool value =
+ boost::container::is_container_detail::
+ has_member_function_callable_with_size <const Container>::value &&
+ boost::container::is_container_detail::
+ has_member_function_callable_with_empty<const Container>::value;
+};
+
+} //namespace dtl {
+} //namespace container {
+} //namespace boost {
+
+#endif //#ifndef BOOST_CONTAINER_DETAIL_IS_CONTAINER_HPP
diff --git a/include/boost/container/detail/is_contiguous_container.hpp b/include/boost/container/detail/is_contiguous_container.hpp
new file mode 100644
index 0000000..528aeee
--- /dev/null
+++ b/include/boost/container/detail/is_contiguous_container.hpp
@@ -0,0 +1,47 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2017-2017. 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_IS_CONTIGUOUS_CONTAINER_HPP
+#define BOOST_CONTAINER_DETAIL_IS_CONTIGUOUS_CONTAINER_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+//data
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME data
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace is_contiguous_container_detail {
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 0
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 0
+#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
+
+namespace boost {
+namespace container {
+namespace dtl {
+
+template <class Container>
+struct is_contiguous_container
+{
+ static const bool value =
+ boost::container::is_contiguous_container_detail::
+ has_member_function_callable_with_data<Container>::value &&
+ boost::container::is_contiguous_container_detail::
+ has_member_function_callable_with_data<const Container>::value;
+};
+
+} //namespace dtl {
+} //namespace container {
+} //namespace boost {
+
+#endif //#ifndef BOOST_CONTAINER_DETAIL_IS_CONTIGUOUS_CONTAINER_HPP
diff --git a/include/boost/container/detail/is_sorted.hpp b/include/boost/container/detail/is_sorted.hpp
new file mode 100644
index 0000000..315bab5
--- /dev/null
+++ b/include/boost/container/detail/is_sorted.hpp
@@ -0,0 +1,57 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2016-2016. 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_IS_SORTED_HPP
+#define BOOST_CONTAINER_DETAIL_IS_SORTED_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+namespace boost {
+namespace container {
+namespace dtl {
+
+template <class ForwardIterator, class Pred>
+bool is_sorted (ForwardIterator first, ForwardIterator last, Pred pred)
+{
+ if(first != last){
+ ForwardIterator next = first;
+ while (++next != last){
+ if(pred(*next, *first))
+ return false;
+ ++first;
+ }
+ }
+ return true;
+}
+
+template <class ForwardIterator, class Pred>
+bool is_sorted_and_unique (ForwardIterator first, ForwardIterator last, Pred pred)
+{
+ if(first != last){
+ ForwardIterator next = first;
+ while (++next != last){
+ if(!pred(*first, *next))
+ return false;
+ ++first;
+ }
+ }
+ return true;
+}
+
+} //namespace dtl {
+} //namespace container {
+} //namespace boost {
+
+#endif //#ifndef BOOST_CONTAINER_DETAIL_IS_SORTED_HPP
diff --git a/include/boost/container/detail/iterator.hpp b/include/boost/container/detail/iterator.hpp
new file mode 100644
index 0000000..2ceaf26
--- /dev/null
+++ b/include/boost/container/detail/iterator.hpp
@@ -0,0 +1,70 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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>
+#include <boost/move/utility_core.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;
+using ::boost::intrusive::iterator_arrow_result;
+
+template <class Container>
+class back_emplacer
+{
+ private:
+ Container& container;
+
+ public:
+ typedef std::output_iterator_tag iterator_category;
+ typedef void value_type;
+ typedef void difference_type;
+ typedef void pointer;
+ typedef void reference;
+
+ back_emplacer(Container& x)
+ : container(x)
+ {}
+
+ template<class U>
+ back_emplacer& operator=(BOOST_FWD_REF(U) value)
+ {
+ container.emplace_back(boost::forward<U>(value));
+ return *this;
+ }
+ back_emplacer& operator*() { return *this; }
+ back_emplacer& operator++() { return *this; }
+ back_emplacer& operator++(int){ return *this; }
+};
+
+
+} //namespace container {
+} //namespace boost {
+
+#endif //#ifndef BOOST_CONTAINER_DETAIL_ITERATORS_HPP
diff --git a/include/boost/container/detail/iterator_to_raw_pointer.hpp b/include/boost/container/detail/iterator_to_raw_pointer.hpp
new file mode 100644
index 0000000..49f1d43
--- /dev/null
+++ b/include/boost/container/detail/iterator_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_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/move/detail/iterator_to_raw_pointer.hpp>
+
+namespace boost {
+namespace container {
+namespace dtl {
+
+using ::boost::movelib::iterator_to_raw_pointer;
+
+} //namespace dtl {
+} //namespace container {
+} //namespace boost {
+
+#endif //#ifndef BOOST_CONTAINER_DETAIL_ITERATOR_TO_RAW_POINTER_HPP
diff --git a/include/boost/container/detail/iterators.hpp b/include/boost/container/detail/iterators.hpp
new file mode 100644
index 0000000..7ccdac9
--- /dev/null
+++ b/include/boost/container/detail/iterators.hpp
@@ -0,0 +1,875 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2013.
+// (C) Copyright Gennaro Prota 2003 - 2004.
+//
+// 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_ITERATORS_HPP
+#define BOOST_CONTAINER_DETAIL_ITERATORS_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/allocator_traits.hpp>
+#include <boost/container/detail/type_traits.hpp>
+#include <boost/container/detail/value_init.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/move/utility_core.hpp>
+#include <boost/intrusive/detail/reverse_iterator.hpp>
+
+#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+#include <boost/move/detail/fwd_macros.hpp>
+#else
+#include <boost/container/detail/variadic_templates_tools.hpp>
+#endif
+#include <boost/container/detail/iterator.hpp>
+
+namespace boost {
+namespace container {
+
+template <class T, class Difference = std::ptrdiff_t>
+class constant_iterator
+ : public ::boost::container::iterator
+ <std::random_access_iterator_tag, T, Difference, const T*, const T &>
+{
+ typedef constant_iterator<T, Difference> this_type;
+
+ public:
+ explicit constant_iterator(const T &ref, Difference range_size)
+ : m_ptr(&ref), m_num(range_size){}
+
+ //Constructors
+ constant_iterator()
+ : m_ptr(0), m_num(0){}
+
+ constant_iterator& operator++()
+ { increment(); return *this; }
+
+ constant_iterator operator++(int)
+ {
+ constant_iterator result (*this);
+ increment();
+ return result;
+ }
+
+ constant_iterator& operator--()
+ { decrement(); return *this; }
+
+ constant_iterator operator--(int)
+ {
+ constant_iterator result (*this);
+ decrement();
+ return result;
+ }
+
+ friend bool operator== (const constant_iterator& i, const constant_iterator& i2)
+ { return i.equal(i2); }
+
+ friend bool operator!= (const constant_iterator& i, const constant_iterator& i2)
+ { return !(i == i2); }
+
+ friend bool operator< (const constant_iterator& i, const constant_iterator& i2)
+ { return i.less(i2); }
+
+ friend bool operator> (const constant_iterator& i, const constant_iterator& i2)
+ { return i2 < i; }
+
+ friend bool operator<= (const constant_iterator& i, const constant_iterator& i2)
+ { return !(i > i2); }
+
+ friend bool operator>= (const constant_iterator& i, const constant_iterator& i2)
+ { return !(i < i2); }
+
+ friend Difference operator- (const constant_iterator& i, const constant_iterator& i2)
+ { return i2.distance_to(i); }
+
+ //Arithmetic
+ constant_iterator& operator+=(Difference off)
+ { this->advance(off); return *this; }
+
+ constant_iterator operator+(Difference off) const
+ {
+ constant_iterator other(*this);
+ other.advance(off);
+ return other;
+ }
+
+ friend constant_iterator operator+(Difference off, const constant_iterator& right)
+ { return right + off; }
+
+ constant_iterator& operator-=(Difference off)
+ { this->advance(-off); return *this; }
+
+ constant_iterator operator-(Difference off) const
+ { return *this + (-off); }
+
+ const T& operator*() const
+ { return dereference(); }
+
+ const T& operator[] (Difference ) const
+ { return dereference(); }
+
+ const T* operator->() const
+ { return &(dereference()); }
+
+ private:
+ const T * m_ptr;
+ Difference m_num;
+
+ void increment()
+ { --m_num; }
+
+ void decrement()
+ { ++m_num; }
+
+ bool equal(const this_type &other) const
+ { return m_num == other.m_num; }
+
+ bool less(const this_type &other) const
+ { return other.m_num < m_num; }
+
+ const T & dereference() const
+ { return *m_ptr; }
+
+ void advance(Difference n)
+ { m_num -= n; }
+
+ Difference distance_to(const this_type &other)const
+ { return m_num - other.m_num; }
+};
+
+template <class T, class Difference>
+class value_init_construct_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;
+
+ public:
+ explicit value_init_construct_iterator(Difference range_size)
+ : m_num(range_size){}
+
+ //Constructors
+ value_init_construct_iterator()
+ : m_num(0){}
+
+ value_init_construct_iterator& operator++()
+ { increment(); return *this; }
+
+ value_init_construct_iterator operator++(int)
+ {
+ value_init_construct_iterator result (*this);
+ increment();
+ return result;
+ }
+
+ value_init_construct_iterator& operator--()
+ { decrement(); return *this; }
+
+ value_init_construct_iterator operator--(int)
+ {
+ value_init_construct_iterator result (*this);
+ decrement();
+ return result;
+ }
+
+ friend bool operator== (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
+ { return i.equal(i2); }
+
+ friend bool operator!= (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
+ { return !(i == i2); }
+
+ friend bool operator< (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
+ { return i.less(i2); }
+
+ friend bool operator> (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
+ { return i2 < i; }
+
+ friend bool operator<= (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
+ { return !(i > i2); }
+
+ friend bool operator>= (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
+ { return !(i < i2); }
+
+ friend Difference operator- (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
+ { return i2.distance_to(i); }
+
+ //Arithmetic
+ value_init_construct_iterator& operator+=(Difference off)
+ { this->advance(off); return *this; }
+
+ value_init_construct_iterator operator+(Difference off) const
+ {
+ value_init_construct_iterator other(*this);
+ other.advance(off);
+ return other;
+ }
+
+ friend value_init_construct_iterator operator+(Difference off, const value_init_construct_iterator& right)
+ { return right + off; }
+
+ value_init_construct_iterator& operator-=(Difference off)
+ { this->advance(-off); return *this; }
+
+ value_init_construct_iterator operator-(Difference off) const
+ { return *this + (-off); }
+
+ //This pseudo-iterator's dereference operations have no sense since value is not
+ //constructed until ::boost::container::construct_in_place is called.
+ //So comment them to catch bad uses
+ //const T& operator*() const;
+ //const T& operator[](difference_type) const;
+ //const T* operator->() const;
+
+ private:
+ Difference m_num;
+
+ void increment()
+ { --m_num; }
+
+ void decrement()
+ { ++m_num; }
+
+ bool equal(const this_type &other) const
+ { return m_num == other.m_num; }
+
+ bool less(const this_type &other) const
+ { return other.m_num < m_num; }
+
+ const T & dereference() const
+ {
+ static T dummy;
+ return dummy;
+ }
+
+ void advance(Difference n)
+ { m_num -= n; }
+
+ Difference distance_to(const this_type &other)const
+ { return m_num - other.m_num; }
+};
+
+template <class T, class Difference>
+class default_init_construct_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;
+
+ public:
+ explicit default_init_construct_iterator(Difference range_size)
+ : m_num(range_size){}
+
+ //Constructors
+ default_init_construct_iterator()
+ : m_num(0){}
+
+ default_init_construct_iterator& operator++()
+ { increment(); return *this; }
+
+ default_init_construct_iterator operator++(int)
+ {
+ default_init_construct_iterator result (*this);
+ increment();
+ return result;
+ }
+
+ default_init_construct_iterator& operator--()
+ { decrement(); return *this; }
+
+ default_init_construct_iterator operator--(int)
+ {
+ default_init_construct_iterator result (*this);
+ decrement();
+ return result;
+ }
+
+ friend bool operator== (const default_init_construct_iterator& i, const default_init_construct_iterator& i2)
+ { return i.equal(i2); }
+
+ friend bool operator!= (const default_init_construct_iterator& i, const default_init_construct_iterator& i2)
+ { return !(i == i2); }
+
+ friend bool operator< (const default_init_construct_iterator& i, const default_init_construct_iterator& i2)
+ { return i.less(i2); }
+
+ friend bool operator> (const default_init_construct_iterator& i, const default_init_construct_iterator& i2)
+ { return i2 < i; }
+
+ friend bool operator<= (const default_init_construct_iterator& i, const default_init_construct_iterator& i2)
+ { return !(i > i2); }
+
+ friend bool operator>= (const default_init_construct_iterator& i, const default_init_construct_iterator& i2)
+ { return !(i < i2); }
+
+ friend Difference operator- (const default_init_construct_iterator& i, const default_init_construct_iterator& i2)
+ { return i2.distance_to(i); }
+
+ //Arithmetic
+ default_init_construct_iterator& operator+=(Difference off)
+ { this->advance(off); return *this; }
+
+ default_init_construct_iterator operator+(Difference off) const
+ {
+ default_init_construct_iterator other(*this);
+ other.advance(off);
+ return other;
+ }
+
+ friend default_init_construct_iterator operator+(Difference off, const default_init_construct_iterator& right)
+ { return right + off; }
+
+ default_init_construct_iterator& operator-=(Difference off)
+ { this->advance(-off); return *this; }
+
+ default_init_construct_iterator operator-(Difference off) const
+ { return *this + (-off); }
+
+ //This pseudo-iterator's dereference operations have no sense since value is not
+ //constructed until ::boost::container::construct_in_place is called.
+ //So comment them to catch bad uses
+ //const T& operator*() const;
+ //const T& operator[](difference_type) const;
+ //const T* operator->() const;
+
+ private:
+ Difference m_num;
+
+ void increment()
+ { --m_num; }
+
+ void decrement()
+ { ++m_num; }
+
+ bool equal(const this_type &other) const
+ { return m_num == other.m_num; }
+
+ bool less(const this_type &other) const
+ { return other.m_num < m_num; }
+
+ const T & dereference() const
+ {
+ static T dummy;
+ return dummy;
+ }
+
+ void advance(Difference n)
+ { m_num -= n; }
+
+ Difference distance_to(const this_type &other)const
+ { return m_num - other.m_num; }
+};
+
+
+template <class T, class Difference = std::ptrdiff_t>
+class repeat_iterator
+ : public ::boost::container::iterator
+ <std::random_access_iterator_tag, T, Difference, T*, T&>
+{
+ typedef repeat_iterator<T, Difference> this_type;
+ public:
+ explicit repeat_iterator(T &ref, Difference range_size)
+ : m_ptr(&ref), m_num(range_size){}
+
+ //Constructors
+ repeat_iterator()
+ : m_ptr(0), m_num(0){}
+
+ this_type& operator++()
+ { increment(); return *this; }
+
+ this_type operator++(int)
+ {
+ this_type result (*this);
+ increment();
+ return result;
+ }
+
+ this_type& operator--()
+ { increment(); return *this; }
+
+ this_type operator--(int)
+ {
+ this_type result (*this);
+ increment();
+ return result;
+ }
+
+ friend bool operator== (const this_type& i, const this_type& i2)
+ { return i.equal(i2); }
+
+ friend bool operator!= (const this_type& i, const this_type& i2)
+ { return !(i == i2); }
+
+ friend bool operator< (const this_type& i, const this_type& i2)
+ { return i.less(i2); }
+
+ friend bool operator> (const this_type& i, const this_type& i2)
+ { return i2 < i; }
+
+ friend bool operator<= (const this_type& i, const this_type& i2)
+ { return !(i > i2); }
+
+ friend bool operator>= (const this_type& i, const this_type& i2)
+ { return !(i < i2); }
+
+ friend Difference operator- (const this_type& i, const this_type& i2)
+ { return i2.distance_to(i); }
+
+ //Arithmetic
+ this_type& operator+=(Difference off)
+ { this->advance(off); return *this; }
+
+ this_type operator+(Difference off) const
+ {
+ this_type other(*this);
+ other.advance(off);
+ return other;
+ }
+
+ friend this_type operator+(Difference off, const this_type& right)
+ { return right + off; }
+
+ this_type& operator-=(Difference off)
+ { this->advance(-off); return *this; }
+
+ this_type operator-(Difference off) const
+ { return *this + (-off); }
+
+ T& operator*() const
+ { return dereference(); }
+
+ T& operator[] (Difference ) const
+ { return dereference(); }
+
+ T *operator->() const
+ { return &(dereference()); }
+
+ private:
+ T * m_ptr;
+ Difference m_num;
+
+ void increment()
+ { --m_num; }
+
+ void decrement()
+ { ++m_num; }
+
+ bool equal(const this_type &other) const
+ { return m_num == other.m_num; }
+
+ bool less(const this_type &other) const
+ { return other.m_num < m_num; }
+
+ T & dereference() const
+ { return *m_ptr; }
+
+ void advance(Difference n)
+ { m_num -= n; }
+
+ Difference distance_to(const this_type &other)const
+ { return m_num - other.m_num; }
+};
+
+template <class T, class EmplaceFunctor, class Difference /*= std::ptrdiff_t*/>
+class emplace_iterator
+ : public ::boost::container::iterator
+ <std::random_access_iterator_tag, T, Difference, const T*, const T &>
+{
+ typedef emplace_iterator this_type;
+
+ public:
+ typedef Difference difference_type;
+ BOOST_CONTAINER_FORCEINLINE explicit emplace_iterator(EmplaceFunctor&e)
+ : m_num(1), m_pe(&e){}
+
+ BOOST_CONTAINER_FORCEINLINE emplace_iterator()
+ : m_num(0), m_pe(0){}
+
+ BOOST_CONTAINER_FORCEINLINE this_type& operator++()
+ { increment(); return *this; }
+
+ this_type operator++(int)
+ {
+ this_type result (*this);
+ increment();
+ return result;
+ }
+
+ BOOST_CONTAINER_FORCEINLINE this_type& operator--()
+ { decrement(); return *this; }
+
+ this_type operator--(int)
+ {
+ this_type result (*this);
+ decrement();
+ return result;
+ }
+
+ BOOST_CONTAINER_FORCEINLINE friend bool operator== (const this_type& i, const this_type& i2)
+ { return i.equal(i2); }
+
+ BOOST_CONTAINER_FORCEINLINE friend bool operator!= (const this_type& i, const this_type& i2)
+ { return !(i == i2); }
+
+ BOOST_CONTAINER_FORCEINLINE friend bool operator< (const this_type& i, const this_type& i2)
+ { return i.less(i2); }
+
+ BOOST_CONTAINER_FORCEINLINE friend bool operator> (const this_type& i, const this_type& i2)
+ { return i2 < i; }
+
+ BOOST_CONTAINER_FORCEINLINE friend bool operator<= (const this_type& i, const this_type& i2)
+ { return !(i > i2); }
+
+ BOOST_CONTAINER_FORCEINLINE friend bool operator>= (const this_type& i, const this_type& i2)
+ { return !(i < i2); }
+
+ BOOST_CONTAINER_FORCEINLINE friend difference_type operator- (const this_type& i, const this_type& i2)
+ { return i2.distance_to(i); }
+
+ //Arithmetic
+ BOOST_CONTAINER_FORCEINLINE this_type& operator+=(difference_type off)
+ { this->advance(off); return *this; }
+
+ this_type operator+(difference_type off) const
+ {
+ this_type other(*this);
+ other.advance(off);
+ return other;
+ }
+
+ BOOST_CONTAINER_FORCEINLINE friend this_type operator+(difference_type off, const this_type& right)
+ { return right + off; }
+
+ BOOST_CONTAINER_FORCEINLINE this_type& operator-=(difference_type off)
+ { this->advance(-off); return *this; }
+
+ BOOST_CONTAINER_FORCEINLINE this_type operator-(difference_type off) const
+ { return *this + (-off); }
+
+ private:
+ //This pseudo-iterator's dereference operations have no sense since value is not
+ //constructed until ::boost::container::construct_in_place is called.
+ //So comment them to catch bad uses
+ const T& operator*() const;
+ const T& operator[](difference_type) const;
+ const T* operator->() const;
+
+ public:
+ template<class Allocator>
+ void construct_in_place(Allocator &a, T* ptr)
+ { (*m_pe)(a, ptr); }
+
+ template<class DestIt>
+ void assign_in_place(DestIt dest)
+ { (*m_pe)(dest); }
+
+ private:
+ difference_type m_num;
+ EmplaceFunctor * m_pe;
+
+ BOOST_CONTAINER_FORCEINLINE void increment()
+ { --m_num; }
+
+ BOOST_CONTAINER_FORCEINLINE void decrement()
+ { ++m_num; }
+
+ BOOST_CONTAINER_FORCEINLINE bool equal(const this_type &other) const
+ { return m_num == other.m_num; }
+
+ BOOST_CONTAINER_FORCEINLINE bool less(const this_type &other) const
+ { return other.m_num < m_num; }
+
+ BOOST_CONTAINER_FORCEINLINE const T & dereference() const
+ {
+ static T dummy;
+ return dummy;
+ }
+
+ BOOST_CONTAINER_FORCEINLINE void advance(difference_type n)
+ { m_num -= n; }
+
+ BOOST_CONTAINER_FORCEINLINE difference_type distance_to(const this_type &other)const
+ { return difference_type(m_num - other.m_num); }
+};
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+template<class ...Args>
+struct emplace_functor
+{
+ typedef typename dtl::build_number_seq<sizeof...(Args)>::type index_tuple_t;
+
+ emplace_functor(BOOST_FWD_REF(Args)... args)
+ : args_(args...)
+ {}
+
+ template<class Allocator, class T>
+ BOOST_CONTAINER_FORCEINLINE void operator()(Allocator &a, T *ptr)
+ { emplace_functor::inplace_impl(a, ptr, index_tuple_t()); }
+
+ template<class DestIt>
+ BOOST_CONTAINER_FORCEINLINE void operator()(DestIt dest)
+ { emplace_functor::inplace_impl(dest, index_tuple_t()); }
+
+ private:
+ template<class Allocator, class T, std::size_t ...IdxPack>
+ BOOST_CONTAINER_FORCEINLINE void inplace_impl(Allocator &a, T* ptr, const dtl::index_tuple<IdxPack...>&)
+ {
+ allocator_traits<Allocator>::construct
+ (a, ptr, ::boost::forward<Args>(dtl::get<IdxPack>(args_))...);
+ }
+
+ template<class DestIt, std::size_t ...IdxPack>
+ BOOST_CONTAINER_FORCEINLINE void inplace_impl(DestIt dest, const dtl::index_tuple<IdxPack...>&)
+ {
+ typedef typename boost::container::iterator_traits<DestIt>::value_type value_type;
+ value_type && tmp= value_type(::boost::forward<Args>(dtl::get<IdxPack>(args_))...);
+ *dest = ::boost::move(tmp);
+ }
+
+ dtl::tuple<Args&...> args_;
+};
+
+template<class ...Args>
+struct emplace_functor_type
+{
+ typedef emplace_functor<Args...> type;
+};
+
+#else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+//Partial specializations cannot match argument list for primary template, so add an extra argument
+template <BOOST_MOVE_CLASSDFLT9, class Dummy = void>
+struct emplace_functor_type;
+
+#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); }\
+ \
+ template<class DestIt>\
+ void operator()(DestIt dest)\
+ {\
+ typedef typename boost::container::iterator_traits<DestIt>::value_type value_type;\
+ BOOST_MOVE_IF(N, value_type tmp(BOOST_MOVE_MFWD##N), dtl::value_init<value_type> tmp) ;\
+ *dest = ::boost::move(const_cast<value_type &>(BOOST_MOVE_IF(N, tmp, tmp.get())));\
+ }\
+ \
+ BOOST_MOVE_MREF##N\
+};\
+\
+template <BOOST_MOVE_CLASS##N>\
+struct emplace_functor_type<BOOST_MOVE_TARG##N>\
+{\
+ typedef emplace_functor##N BOOST_MOVE_LT##N BOOST_MOVE_TARG##N BOOST_MOVE_GT##N type;\
+};\
+//
+
+BOOST_MOVE_ITERATE_0TO9(BOOST_MOVE_ITERATOR_EMPLACE_FUNCTOR_CODE)
+
+#undef BOOST_MOVE_ITERATOR_EMPLACE_FUNCTOR_CODE
+
+#endif
+
+namespace dtl {
+
+template<class T>
+struct has_iterator_category
+{
+ struct two { char _[2]; };
+
+ template <typename X>
+ static char test(int, typename X::iterator_category*);
+
+ template <typename X>
+ static two test(int, ...);
+
+ static const bool value = (1 == sizeof(test<T>(0, 0)));
+};
+
+
+template<class T, bool = has_iterator_category<T>::value >
+struct is_input_iterator
+{
+ static const bool value = is_same<typename T::iterator_category, std::input_iterator_tag>::value;
+};
+
+template<class T>
+struct is_input_iterator<T, false>
+{
+ static const bool value = false;
+};
+
+template<class T>
+struct is_not_input_iterator
+{
+ static const bool value = !is_input_iterator<T>::value;
+};
+
+template<class T, bool = has_iterator_category<T>::value >
+struct is_forward_iterator
+{
+ static const bool value = is_same<typename T::iterator_category, std::forward_iterator_tag>::value;
+};
+
+template<class T>
+struct is_forward_iterator<T, false>
+{
+ static const bool value = false;
+};
+
+template<class T, bool = has_iterator_category<T>::value >
+struct is_bidirectional_iterator
+{
+ static const bool value = is_same<typename T::iterator_category, std::bidirectional_iterator_tag>::value;
+};
+
+template<class T>
+struct is_bidirectional_iterator<T, false>
+{
+ static const bool value = false;
+};
+
+template<class IINodeType>
+struct iiterator_node_value_type {
+ typedef typename IINodeType::value_type type;
+};
+
+template<class IIterator>
+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 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>::
+ template rebind_pointer<const value_type>::type const_pointer;
+ typedef typename ::boost::intrusive::
+ pointer_traits<pointer>::reference reference;
+ typedef typename ::boost::intrusive::
+ pointer_traits<const_pointer>::reference const_reference;
+ typedef typename IIterator::iterator_category iterator_category;
+};
+
+template<class IIterator, bool IsConst>
+struct iterator_types
+{
+ typedef typename ::boost::container::iterator
+ < typename iiterator_types<IIterator>::iterator_category
+ , typename iiterator_types<IIterator>::value_type
+ , typename iiterator_types<IIterator>::difference_type
+ , typename iiterator_types<IIterator>::const_pointer
+ , typename iiterator_types<IIterator>::const_reference> type;
+};
+
+template<class IIterator>
+struct iterator_types<IIterator, false>
+{
+ typedef typename ::boost::container::iterator
+ < typename iiterator_types<IIterator>::iterator_category
+ , typename iiterator_types<IIterator>::value_type
+ , typename iiterator_types<IIterator>::difference_type
+ , typename iiterator_types<IIterator>::pointer
+ , typename iiterator_types<IIterator>::reference> type;
+};
+
+template<class IIterator, bool IsConst>
+class iterator_from_iiterator
+{
+ typedef typename iterator_types<IIterator, IsConst>::type types_t;
+
+ public:
+ typedef typename types_t::pointer pointer;
+ typedef typename types_t::reference reference;
+ typedef typename types_t::difference_type difference_type;
+ typedef typename types_t::iterator_category iterator_category;
+ typedef typename types_t::value_type value_type;
+
+ BOOST_CONTAINER_FORCEINLINE iterator_from_iiterator()
+ : m_iit()
+ {}
+
+ BOOST_CONTAINER_FORCEINLINE explicit iterator_from_iiterator(IIterator iit) BOOST_NOEXCEPT_OR_NOTHROW
+ : m_iit(iit)
+ {}
+
+ BOOST_CONTAINER_FORCEINLINE iterator_from_iiterator(iterator_from_iiterator<IIterator, false> const& other) BOOST_NOEXCEPT_OR_NOTHROW
+ : m_iit(other.get())
+ {}
+
+ BOOST_CONTAINER_FORCEINLINE iterator_from_iiterator& operator++() BOOST_NOEXCEPT_OR_NOTHROW
+ { ++this->m_iit; return *this; }
+
+ BOOST_CONTAINER_FORCEINLINE iterator_from_iiterator operator++(int) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ iterator_from_iiterator result (*this);
+ ++this->m_iit;
+ return result;
+ }
+
+ BOOST_CONTAINER_FORCEINLINE iterator_from_iiterator& operator--() BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ //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;
+ }
+
+ BOOST_CONTAINER_FORCEINLINE iterator_from_iiterator operator--(int) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ iterator_from_iiterator result (*this);
+ --this->m_iit;
+ return result;
+ }
+
+ BOOST_CONTAINER_FORCEINLINE friend bool operator== (const iterator_from_iiterator& l, const iterator_from_iiterator& r) BOOST_NOEXCEPT_OR_NOTHROW
+ { return l.m_iit == r.m_iit; }
+
+ BOOST_CONTAINER_FORCEINLINE friend bool operator!= (const iterator_from_iiterator& l, const iterator_from_iiterator& r) BOOST_NOEXCEPT_OR_NOTHROW
+ { return !(l == r); }
+
+ BOOST_CONTAINER_FORCEINLINE reference operator*() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->m_iit->get_data(); }
+
+ BOOST_CONTAINER_FORCEINLINE pointer operator->() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return ::boost::intrusive::pointer_traits<pointer>::pointer_to(this->operator*()); }
+
+ BOOST_CONTAINER_FORCEINLINE const IIterator &get() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->m_iit; }
+
+ private:
+ IIterator m_iit;
+};
+
+} //namespace dtl {
+
+using ::boost::intrusive::reverse_iterator;
+
+} //namespace container {
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_CONTAINER_DETAIL_ITERATORS_HPP
diff --git a/include/boost/container/detail/math_functions.hpp b/include/boost/container/detail/math_functions.hpp
new file mode 100644
index 0000000..8d350a1
--- /dev/null
+++ b/include/boost/container/detail/math_functions.hpp
@@ -0,0 +1,177 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Stephen Cleary 2000.
+// (C) Copyright Ion Gaztanaga 2007-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.
+//
+// This file is a slightly modified file from Boost.Pool
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_DETAIL_MATH_FUNCTIONS_HPP
+#define BOOST_CONTAINER_DETAIL_MATH_FUNCTIONS_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 <climits>
+#include <boost/static_assert.hpp>
+
+namespace boost {
+namespace container {
+namespace dtl {
+
+// Greatest common divisor and least common multiple
+
+//
+// gcd is an algorithm that calculates the greatest common divisor of two
+// integers, using Euclid's algorithm.
+//
+// Pre: A > 0 && B > 0
+// Recommended: A > B
+template <typename Integer>
+inline Integer gcd(Integer A, Integer B)
+{
+ do
+ {
+ const Integer tmp(B);
+ B = A % B;
+ A = tmp;
+ } while (B != 0);
+
+ return A;
+}
+
+//
+// lcm is an algorithm that calculates the least common multiple of two
+// integers.
+//
+// Pre: A > 0 && B > 0
+// Recommended: A > B
+template <typename Integer>
+inline Integer lcm(const Integer & A, const Integer & B)
+{
+ Integer ret = A;
+ ret /= gcd(A, B);
+ ret *= B;
+ return ret;
+}
+
+template <typename Integer>
+inline Integer log2_ceil(const Integer & A)
+{
+ Integer i = 0;
+ Integer power_of_2 = 1;
+
+ while(power_of_2 < A){
+ power_of_2 <<= 1;
+ ++i;
+ }
+ return i;
+}
+
+template <typename Integer>
+inline Integer upper_power_of_2(const Integer & A)
+{
+ Integer power_of_2 = 1;
+
+ while(power_of_2 < A){
+ power_of_2 <<= 1;
+ }
+ return power_of_2;
+}
+
+template <typename Integer, bool Loop = true>
+struct upper_power_of_2_loop_ct
+{
+
+ template <Integer I, Integer P>
+ struct apply
+ {
+ static const Integer value =
+ upper_power_of_2_loop_ct<Integer, (I > P*2)>::template apply<I, P*2>::value;
+ };
+};
+
+template <typename Integer>
+struct upper_power_of_2_loop_ct<Integer, false>
+{
+ template <Integer I, Integer P>
+ struct apply
+ {
+ static const Integer value = P;
+ };
+};
+
+template <typename Integer, Integer I>
+struct upper_power_of_2_ct
+{
+ static const Integer value = upper_power_of_2_loop_ct<Integer, (I > 1)>::template apply<I, 2>::value;
+};
+
+//This function uses binary search to discover the
+//highest set bit of the integer
+inline std::size_t floor_log2 (std::size_t x)
+{
+ const std::size_t Bits = sizeof(std::size_t)*CHAR_BIT;
+ const bool Size_t_Bits_Power_2= !(Bits & (Bits-1));
+ BOOST_STATIC_ASSERT(((Size_t_Bits_Power_2)== true));
+
+ std::size_t n = x;
+ std::size_t log2 = 0;
+
+ for(std::size_t shift = Bits >> 1; shift; shift >>= 1){
+ std::size_t tmp = n >> shift;
+ if (tmp)
+ log2 += shift, n = tmp;
+ }
+
+ return log2;
+}
+
+template<std::size_t I1, std::size_t I2>
+struct gcd_ct
+{
+ static const std::size_t Max = I1 > I2 ? I1 : I2;
+ static const std::size_t Min = I1 < I2 ? I1 : I2;
+ static const std::size_t value = gcd_ct<Min, Max % Min>::value;
+};
+
+template<std::size_t I1>
+struct gcd_ct<I1, 0>
+{
+ static const std::size_t value = I1;
+};
+
+template<std::size_t I1>
+struct gcd_ct<0, I1>
+{
+ static const std::size_t value = I1;
+};
+
+template<std::size_t I1, std::size_t I2>
+struct lcm_ct
+{
+ static const std::size_t value = I1 * I2 / gcd_ct<I1, I2>::value;
+};
+
+} // namespace dtl
+} // namespace container
+} // namespace boost
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif
diff --git a/include/boost/container/detail/min_max.hpp b/include/boost/container/detail/min_max.hpp
new file mode 100644
index 0000000..35cf066
--- /dev/null
+++ b/include/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 dtl {
+
+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 dtl {
+} //namespace container {
+} //namespace boost {
+
+#endif //#ifndef BOOST_CONTAINER_DETAIL_MIN_MAX_HPP
diff --git a/include/boost/container/detail/minimal_char_traits_header.hpp b/include/boost/container/detail/minimal_char_traits_header.hpp
new file mode 100644
index 0000000..a92a31a
--- /dev/null
+++ b/include/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/include/boost/container/detail/mpl.hpp b/include/boost/container/detail/mpl.hpp
new file mode 100644
index 0000000..385f7db
--- /dev/null
+++ b/include/boost/container/detail/mpl.hpp
@@ -0,0 +1,104 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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_CONTAINER_DETAIL_MPL_HPP
+#define BOOST_CONTAINER_CONTAINER_DETAIL_MPL_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/move/detail/type_traits.hpp>
+#include <boost/intrusive/detail/mpl.hpp>
+
+#include <cstddef>
+
+namespace boost {
+namespace container {
+namespace dtl {
+
+using boost::move_detail::integral_constant;
+using boost::move_detail::true_type;
+using boost::move_detail::false_type;
+using boost::move_detail::enable_if_c;
+using boost::move_detail::enable_if;
+using boost::move_detail::enable_if_convertible;
+using boost::move_detail::disable_if_c;
+using boost::move_detail::disable_if;
+using boost::move_detail::disable_if_convertible;
+using boost::move_detail::is_convertible;
+using boost::move_detail::if_c;
+using boost::move_detail::if_;
+using boost::move_detail::identity;
+using boost::move_detail::bool_;
+using boost::move_detail::true_;
+using boost::move_detail::false_;
+using boost::move_detail::yes_type;
+using boost::move_detail::no_type;
+using boost::move_detail::bool_;
+using boost::move_detail::true_;
+using boost::move_detail::false_;
+using boost::move_detail::unvoid_ref;
+using boost::move_detail::and_;
+using boost::move_detail::or_;
+using boost::move_detail::not_;
+using boost::move_detail::enable_if_and;
+using boost::move_detail::disable_if_and;
+using boost::move_detail::enable_if_or;
+using boost::move_detail::disable_if_or;
+
+template <class FirstType>
+struct select1st
+{
+ typedef FirstType type;
+
+ template<class T>
+ const type& operator()(const T& x) const
+ { return x.first; }
+
+ template<class T>
+ type& operator()(T& x)
+ { return const_cast<type&>(x.first); }
+};
+
+template <class T, class=void>
+struct is_transparent
+{
+ static const bool value = false;
+};
+
+template <class T>
+struct is_transparent<T, typename T::is_transparent>
+{
+ static const bool value = true;
+};
+
+template <typename C, typename K, typename R>
+struct enable_if_transparent
+ : boost::move_detail::enable_if_c<dtl::is_transparent<C>::value, R>
+{};
+
+
+} //namespace dtl {
+} //namespace container {
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_CONTAINER_CONTAINER_DETAIL_MPL_HPP
+
diff --git a/include/boost/container/detail/multiallocation_chain.hpp b/include/boost/container/detail/multiallocation_chain.hpp
new file mode 100644
index 0000000..c10f809
--- /dev/null
+++ b/include/boost/container/detail/multiallocation_chain.hpp
@@ -0,0 +1,298 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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_MULTIALLOCATION_CHAIN_HPP
+#define BOOST_CONTAINER_DETAIL_MULTIALLOCATION_CHAIN_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+// container
+#include <boost/container/container_fwd.hpp>
+// container/detail
+#include <boost/move/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>
+// move
+#include <boost/move/utility_core.hpp>
+
+namespace boost {
+namespace container {
+namespace dtl {
+
+template<class VoidPointer>
+class basic_multiallocation_chain
+{
+ private:
+ typedef bi::slist_base_hook<bi::void_pointer<VoidPointer>
+ ,bi::link_mode<bi::normal_link>
+ > node;
+
+ typedef typename boost::intrusive::pointer_traits
+ <VoidPointer>::template rebind_pointer<char>::type char_ptr;
+ typedef typename boost::intrusive::
+ pointer_traits<char_ptr>::difference_type difference_type;
+
+ typedef bi::slist< node
+ , bi::linear<true>
+ , bi::cache_last<true>
+ , bi::size_type<typename boost::container::dtl::make_unsigned<difference_type>::type>
+ > slist_impl_t;
+ slist_impl_t slist_impl_;
+
+ typedef typename boost::intrusive::pointer_traits
+ <VoidPointer>::template rebind_pointer<node>::type node_ptr;
+ typedef typename boost::intrusive::
+ pointer_traits<node_ptr> node_ptr_traits;
+
+ static node & to_node(const VoidPointer &p)
+ { return *static_cast<node*>(static_cast<void*>(boost::movelib::to_raw_pointer(p))); }
+
+ static VoidPointer from_node(node &n)
+ { return node_ptr_traits::pointer_to(n); }
+
+ static node_ptr to_node_ptr(const VoidPointer &p)
+ { return node_ptr_traits::static_cast_from(p); }
+
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_multiallocation_chain)
+
+ public:
+
+ typedef VoidPointer void_pointer;
+ typedef typename slist_impl_t::iterator iterator;
+ typedef typename slist_impl_t::size_type size_type;
+
+ basic_multiallocation_chain()
+ : slist_impl_()
+ {}
+
+ basic_multiallocation_chain(const void_pointer &b, const void_pointer &before_e, size_type n)
+ : slist_impl_(to_node_ptr(b), to_node_ptr(before_e), n)
+ {}
+
+ basic_multiallocation_chain(BOOST_RV_REF(basic_multiallocation_chain) other)
+ : slist_impl_(::boost::move(other.slist_impl_))
+ {}
+
+ basic_multiallocation_chain& operator=(BOOST_RV_REF(basic_multiallocation_chain) other)
+ {
+ slist_impl_ = ::boost::move(other.slist_impl_);
+ return *this;
+ }
+
+ bool empty() const
+ { return slist_impl_.empty(); }
+
+ size_type size() const
+ { return slist_impl_.size(); }
+
+ iterator before_begin()
+ { return slist_impl_.before_begin(); }
+
+ iterator begin()
+ { return slist_impl_.begin(); }
+
+ iterator end()
+ { return slist_impl_.end(); }
+
+ iterator last()
+ { return slist_impl_.last(); }
+
+ void clear()
+ { slist_impl_.clear(); }
+
+ iterator insert_after(iterator it, void_pointer m)
+ { return slist_impl_.insert_after(it, to_node(m)); }
+
+ void push_front(const void_pointer &m)
+ { return slist_impl_.push_front(to_node(m)); }
+
+ void push_back(const void_pointer &m)
+ { return slist_impl_.push_back(to_node(m)); }
+
+ void_pointer pop_front()
+ {
+ node & n = slist_impl_.front();
+ void_pointer ret = from_node(n);
+ slist_impl_.pop_front();
+ return ret;
+ }
+
+ void splice_after(iterator after_this, basic_multiallocation_chain &x, iterator before_b, iterator before_e, size_type n)
+ { slist_impl_.splice_after(after_this, x.slist_impl_, before_b, before_e, n); }
+
+ void splice_after(iterator after_this, basic_multiallocation_chain &x)
+ { slist_impl_.splice_after(after_this, x.slist_impl_); }
+
+ void erase_after(iterator before_b, iterator e, size_type n)
+ { slist_impl_.erase_after(before_b, e, n); }
+
+ void_pointer incorporate_after(iterator after_this, const void_pointer &b, size_type unit_bytes, size_type num_units)
+ {
+ typedef typename boost::intrusive::pointer_traits<char_ptr> char_pointer_traits;
+ char_ptr elem = char_pointer_traits::static_cast_from(b);
+ if(num_units){
+ char_ptr prev_elem = elem;
+ elem += unit_bytes;
+ for(size_type i = 0; i != num_units-1; ++i, elem += unit_bytes){
+ ::new (boost::movelib::to_raw_pointer(prev_elem)) void_pointer(elem);
+ prev_elem = elem;
+ }
+ slist_impl_.incorporate_after(after_this, to_node_ptr(b), to_node_ptr(prev_elem), num_units);
+ }
+ return elem;
+ }
+
+ void incorporate_after(iterator after_this, void_pointer b, void_pointer before_e, size_type n)
+ { slist_impl_.incorporate_after(after_this, to_node_ptr(b), to_node_ptr(before_e), n); }
+
+ void swap(basic_multiallocation_chain &x)
+ { slist_impl_.swap(x.slist_impl_); }
+
+ static iterator iterator_to(const void_pointer &p)
+ { return slist_impl_t::s_iterator_to(to_node(p)); }
+
+ std::pair<void_pointer, void_pointer> extract_data()
+ {
+ std::pair<void_pointer, void_pointer> ret
+ (slist_impl_.begin().operator->()
+ ,slist_impl_.last().operator->());
+ slist_impl_.clear();
+ return ret;
+ }
+};
+
+template<class T>
+struct cast_functor
+{
+ typedef typename dtl::add_reference<T>::type result_type;
+ template<class U>
+ result_type operator()(U &ptr) const
+ { return *static_cast<T*>(static_cast<void*>(&ptr)); }
+};
+
+template<class MultiallocationChain, class T>
+class transform_multiallocation_chain
+ : public MultiallocationChain
+{
+ private:
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(transform_multiallocation_chain)
+ //transform_multiallocation_chain(const transform_multiallocation_chain &);
+ //transform_multiallocation_chain & operator=(const transform_multiallocation_chain &);
+
+ typedef typename MultiallocationChain::void_pointer void_pointer;
+ typedef typename boost::intrusive::pointer_traits
+ <void_pointer> void_pointer_traits;
+ typedef typename void_pointer_traits::template
+ rebind_pointer<T>::type pointer;
+ typedef typename boost::intrusive::pointer_traits
+ <pointer> pointer_traits;
+
+ static pointer cast(const void_pointer &p)
+ { return pointer_traits::static_cast_from(p); }
+
+ public:
+ typedef transform_iterator
+ < typename MultiallocationChain::iterator
+ , dtl::cast_functor <T> > iterator;
+ typedef typename MultiallocationChain::size_type size_type;
+
+ transform_multiallocation_chain()
+ : MultiallocationChain()
+ {}
+
+ transform_multiallocation_chain(BOOST_RV_REF(transform_multiallocation_chain) other)
+ : MultiallocationChain(::boost::move(static_cast<MultiallocationChain&>(other)))
+ {}
+
+ transform_multiallocation_chain(BOOST_RV_REF(MultiallocationChain) other)
+ : MultiallocationChain(::boost::move(static_cast<MultiallocationChain&>(other)))
+ {}
+
+ transform_multiallocation_chain& operator=(BOOST_RV_REF(transform_multiallocation_chain) other)
+ {
+ return static_cast<MultiallocationChain&>
+ (this->MultiallocationChain::operator=(::boost::move(static_cast<MultiallocationChain&>(other))));
+ }
+/*
+ void push_front(const pointer &mem)
+ { holder_.push_front(mem); }
+
+ void push_back(const pointer &mem)
+ { return holder_.push_back(mem); }
+
+ void swap(transform_multiallocation_chain &other_chain)
+ { holder_.swap(other_chain.holder_); }
+
+ void splice_after(iterator after_this, transform_multiallocation_chain &x, iterator before_b, iterator before_e, size_type n)
+ { holder_.splice_after(after_this.base(), x.holder_, before_b.base(), before_e.base(), n); }
+
+ void incorporate_after(iterator after_this, pointer b, pointer before_e, size_type n)
+ { holder_.incorporate_after(after_this.base(), b, before_e, n); }
+*/
+ pointer pop_front()
+ { return cast(this->MultiallocationChain::pop_front()); }
+/*
+ bool empty() const
+ { return holder_.empty(); }
+
+ iterator before_begin()
+ { return iterator(holder_.before_begin()); }
+*/
+ iterator begin()
+ { return iterator(this->MultiallocationChain::begin()); }
+/*
+ iterator end()
+ { return iterator(holder_.end()); }
+
+ iterator last()
+ { return iterator(holder_.last()); }
+
+ size_type size() const
+ { return holder_.size(); }
+
+ void clear()
+ { holder_.clear(); }
+*/
+ iterator insert_after(iterator it, pointer m)
+ { return iterator(this->MultiallocationChain::insert_after(it.base(), m)); }
+
+ static iterator iterator_to(const pointer &p)
+ { return iterator(MultiallocationChain::iterator_to(p)); }
+
+ std::pair<pointer, pointer> extract_data()
+ {
+ std::pair<void_pointer, void_pointer> data(this->MultiallocationChain::extract_data());
+ return std::pair<pointer, pointer>(cast(data.first), cast(data.second));
+ }
+/*
+ MultiallocationChain &extract_multiallocation_chain()
+ { return holder_; }*/
+};
+
+}}}
+
+// namespace dtl {
+// namespace container {
+// namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //BOOST_CONTAINER_DETAIL_MULTIALLOCATION_CHAIN_HPP
diff --git a/include/boost/container/detail/mutex.hpp b/include/boost/container/detail/mutex.hpp
new file mode 100644
index 0000000..56e72a8
--- /dev/null
+++ b/include/boost/container/detail/mutex.hpp
@@ -0,0 +1,283 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Stephen Cleary 2000
+// (C) Copyright Ion Gaztanaga 2015-2017.
+//
+// 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_MUTEX_HPP
+#define BOOST_CONTAINER_MUTEX_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+//#define BOOST_CONTAINER_NO_MT
+//#define BOOST_CONTAINER_NO_SPINLOCKS
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+
+// Extremely Light-Weight wrapper classes for OS thread synchronization
+
+#define BOOST_MUTEX_HELPER_NONE 0
+#define BOOST_MUTEX_HELPER_WIN32 1
+#define BOOST_MUTEX_HELPER_PTHREAD 2
+#define BOOST_MUTEX_HELPER_SPINLOCKS 3
+
+#if !defined(BOOST_HAS_THREADS) && !defined(BOOST_NO_MT)
+# define BOOST_NO_MT
+#endif
+
+#if defined(BOOST_NO_MT) || defined(BOOST_CONTAINER_NO_MT)
+ // No multithreading -> make locks into no-ops
+ #define BOOST_MUTEX_HELPER BOOST_MUTEX_HELPER_NONE
+#else
+ //Taken from dlmalloc
+ #if !defined(BOOST_CONTAINER_NO_SPINLOCKS) && \
+ ((defined(__GNUC__) && \
+ ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) || \
+ defined(__i386__) || defined(__x86_64__))) || \
+ (defined(_MSC_VER) && _MSC_VER>=1310))
+ #define BOOST_MUTEX_HELPER BOOST_MUTEX_HELPER_SPINLOCKS
+ #endif
+
+ #if defined(BOOST_WINDOWS)
+ #include <windows.h>
+ #ifndef BOOST_MUTEX_HELPER
+ #define BOOST_MUTEX_HELPER BOOST_MUTEX_HELPER_WIN32
+ #endif
+ #elif defined(BOOST_HAS_UNISTD_H)
+ #include <unistd.h>
+ #if !defined(BOOST_MUTEX_HELPER) && (defined(_POSIX_THREADS) || defined(BOOST_HAS_PTHREADS))
+ #define BOOST_MUTEX_HELPER BOOST_MUTEX_HELPER_PTHREAD
+ #endif
+ #endif
+#endif
+
+#ifndef BOOST_MUTEX_HELPER
+ #error Unable to determine platform mutex type; #define BOOST_NO_MT to assume single-threaded
+#endif
+
+#if BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_NONE
+ //...
+#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_SPINLOCKS
+ #if defined(_MSC_VER)
+ #ifndef _M_AMD64
+ /* These are already defined on AMD64 builds */
+ #ifdef __cplusplus
+ extern "C" {
+ #endif /* __cplusplus */
+ long __cdecl _InterlockedCompareExchange(long volatile *Dest, long Exchange, long Comp);
+ long __cdecl _InterlockedExchange(long volatile *Target, long Value);
+ #ifdef __cplusplus
+ }
+ #endif /* __cplusplus */
+ #endif /* _M_AMD64 */
+ #pragma intrinsic (_InterlockedCompareExchange)
+ #pragma intrinsic (_InterlockedExchange)
+ #define interlockedcompareexchange _InterlockedCompareExchange
+ #define interlockedexchange _InterlockedExchange
+ #elif defined(WIN32) && defined(__GNUC__)
+ #define interlockedcompareexchange(a, b, c) __sync_val_compare_and_swap(a, c, b)
+ #define interlockedexchange __sync_lock_test_and_set
+ #endif /* Win32 */
+
+ /* First, define CAS_LOCK and CLEAR_LOCK on ints */
+ /* Note CAS_LOCK defined to return 0 on success */
+
+ #if defined(__GNUC__)&& (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1))
+ #define BOOST_CONTAINER_CAS_LOCK(sl) __sync_lock_test_and_set(sl, 1)
+ #define BOOST_CONTAINER_CLEAR_LOCK(sl) __sync_lock_release(sl)
+
+ #elif (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)))
+ /* Custom spin locks for older gcc on x86 */
+ static inline int boost_container_x86_cas_lock(int *sl) {
+ int ret;
+ int val = 1;
+ int cmp = 0;
+ __asm__ __volatile__ ("lock; cmpxchgl %1, %2"
+ : "=a" (ret)
+ : "r" (val), "m" (*(sl)), "0"(cmp)
+ : "memory", "cc");
+ return ret;
+ }
+
+ static inline void boost_container_x86_clear_lock(int* sl) {
+ assert(*sl != 0);
+ int prev = 0;
+ int ret;
+ __asm__ __volatile__ ("lock; xchgl %0, %1"
+ : "=r" (ret)
+ : "m" (*(sl)), "0"(prev)
+ : "memory");
+ }
+
+ #define BOOST_CONTAINER_CAS_LOCK(sl) boost_container_x86_cas_lock(sl)
+ #define BOOST_CONTAINER_CLEAR_LOCK(sl) boost_container_x86_clear_lock(sl)
+
+ #else /* Win32 MSC */
+ #define BOOST_CONTAINER_CAS_LOCK(sl) interlockedexchange((long volatile*)sl, (long)1)
+ #define BOOST_CONTAINER_CLEAR_LOCK(sl) interlockedexchange((long volatile*)sl, (long)0)
+ #endif
+
+ /* How to yield for a spin lock */
+ #define SPINS_PER_YIELD 63
+ #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
+ #define SLEEP_EX_DURATION 50 /* delay for yield/sleep */
+ #define SPIN_LOCK_YIELD SleepEx(SLEEP_EX_DURATION, FALSE)
+ #elif defined (__SVR4) && defined (__sun) /* solaris */
+ #include <thread.h>
+ #define SPIN_LOCK_YIELD thr_yield();
+ #elif !defined(LACKS_SCHED_H)
+ #include <sched.h>
+ #define SPIN_LOCK_YIELD sched_yield();
+ #else
+ #define SPIN_LOCK_YIELD
+ #endif /* ... yield ... */
+
+ #define BOOST_CONTAINER_SPINS_PER_YIELD 63
+ inline int boost_interprocess_spin_acquire_lock(int *sl) {
+ int spins = 0;
+ while (*(volatile int *)sl != 0 ||
+ BOOST_CONTAINER_CAS_LOCK(sl)) {
+ if ((++spins & BOOST_CONTAINER_SPINS_PER_YIELD) == 0) {
+ SPIN_LOCK_YIELD;
+ }
+ }
+ return 0;
+ }
+ #define BOOST_CONTAINER_MLOCK_T int
+ #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_MOVE_INITIAL_LOCK(sl) (*sl = 0)
+ #define BOOST_CONTAINER_DESTROY_LOCK(sl) (0)
+#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_WIN32
+ //
+#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_PTHREAD
+ #include <pthread.h>
+#endif
+
+namespace boost {
+namespace container {
+namespace dtl {
+
+#if BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_NONE
+ class null_mutex
+ {
+ private:
+ null_mutex(const null_mutex &);
+ void operator=(const null_mutex &);
+
+ public:
+ null_mutex() { }
+
+ static void lock() { }
+ static void unlock() { }
+ };
+
+ typedef null_mutex default_mutex;
+#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_SPINLOCKS
+
+ class spin_mutex
+ {
+ private:
+ BOOST_CONTAINER_MLOCK_T sl;
+ spin_mutex(const spin_mutex &);
+ void operator=(const spin_mutex &);
+
+ public:
+ spin_mutex() { BOOST_MOVE_INITIAL_LOCK(&sl); }
+
+ void lock() { BOOST_CONTAINER_ACQUIRE_LOCK(&sl); }
+ void unlock() { BOOST_CONTAINER_RELEASE_LOCK(&sl); }
+ };
+ typedef spin_mutex default_mutex;
+#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_WIN32
+ class mutex
+ {
+ private:
+ CRITICAL_SECTION mtx;
+
+ mutex(const mutex &);
+ void operator=(const mutex &);
+
+ public:
+ mutex()
+ { InitializeCriticalSection(&mtx); }
+
+ ~mutex()
+ { DeleteCriticalSection(&mtx); }
+
+ void lock()
+ { EnterCriticalSection(&mtx); }
+
+ void unlock()
+ { LeaveCriticalSection(&mtx); }
+ };
+
+ typedef mutex default_mutex;
+#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_PTHREAD
+ class mutex
+ {
+ private:
+ pthread_mutex_t mtx;
+
+ mutex(const mutex &);
+ void operator=(const mutex &);
+
+ public:
+ mutex()
+ { pthread_mutex_init(&mtx, 0); }
+
+ ~mutex()
+ { pthread_mutex_destroy(&mtx); }
+
+ void lock()
+ { pthread_mutex_lock(&mtx); }
+
+ void unlock()
+ { pthread_mutex_unlock(&mtx); }
+ };
+
+ typedef mutex default_mutex;
+#endif
+
+template<class Mutex>
+class scoped_lock
+{
+ public:
+ scoped_lock(Mutex &m)
+ : m_(m)
+ { m_.lock(); }
+ ~scoped_lock()
+ { m_.unlock(); }
+
+ private:
+ Mutex &m_;
+};
+
+} // namespace dtl
+} // namespace container
+} // namespace boost
+
+#undef BOOST_MUTEX_HELPER_WIN32
+#undef BOOST_MUTEX_HELPER_PTHREAD
+#undef BOOST_MUTEX_HELPER_NONE
+#undef BOOST_MUTEX_HELPER
+#undef BOOST_MUTEX_HELPER_SPINLOCKS
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif
diff --git a/include/boost/container/detail/next_capacity.hpp b/include/boost/container/detail/next_capacity.hpp
new file mode 100644
index 0000000..7e6554d
--- /dev/null
+++ b/include/boost/container/detail/next_capacity.hpp
@@ -0,0 +1,77 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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>
+
+#include <boost/static_assert.hpp>
+
+namespace boost {
+namespace container {
+namespace dtl {
+
+template<unsigned Minimum, unsigned Numerator, unsigned Denominator>
+struct grow_factor_ratio
+{
+ BOOST_STATIC_ASSERT(Numerator > Denominator);
+ BOOST_STATIC_ASSERT(Numerator < 100);
+ BOOST_STATIC_ASSERT(Denominator < 100);
+ BOOST_STATIC_ASSERT(Denominator == 1 || (0 != Numerator % Denominator));
+
+ template<class SizeType>
+ SizeType operator()(const SizeType cur_cap, const SizeType add_min_cap, const SizeType max_cap) const
+ {
+ const SizeType overflow_limit = ((SizeType)-1) / Numerator;
+
+ SizeType new_cap = 0;
+
+ if(cur_cap <= overflow_limit){
+ new_cap = cur_cap * Numerator / Denominator;
+ }
+ else if(Denominator == 1 || (SizeType(new_cap = cur_cap) / Denominator) > overflow_limit){
+ new_cap = (SizeType)-1;
+ }
+ else{
+ new_cap *= Numerator;
+ }
+ return max_value(SizeType(Minimum), max_value(cur_cap+add_min_cap, min_value(max_cap, new_cap)));
+ }
+};
+
+} //namespace dtl {
+
+struct growth_factor_50
+ : dtl::grow_factor_ratio<0, 3, 2>
+{};
+
+struct growth_factor_60
+ : dtl::grow_factor_ratio<0, 8, 5>
+{};
+
+struct growth_factor_100
+ : dtl::grow_factor_ratio<0, 2, 1>
+{};
+
+} //namespace container {
+} //namespace boost {
+
+#endif //#ifndef BOOST_CONTAINER_DETAIL_NEXT_CAPACITY_HPP
diff --git a/include/boost/container/detail/node_alloc_holder.hpp b/include/boost/container/detail/node_alloc_holder.hpp
new file mode 100644
index 0000000..ad7b713
--- /dev/null
+++ b/include/boost/container/detail/node_alloc_holder.hpp
@@ -0,0 +1,419 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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_NODE_ALLOC_HPP_
+#define BOOST_CONTAINER_DETAIL_NODE_ALLOC_HPP_
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+
+// container
+#include <boost/container/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/construct_in_place.hpp>
+#include <boost/container/detail/destroyers.hpp>
+#include <boost/move/detail/iterator_to_raw_pointer.hpp>
+#include <boost/container/detail/mpl.hpp>
+#include <boost/container/detail/placement_new.hpp>
+#include <boost/move/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
+// other
+#include <boost/core/no_exceptions_support.hpp>
+
+
+namespace boost {
+namespace container {
+namespace dtl {
+
+BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(value_compare)
+BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(predicate_type)
+
+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::dtl::
+ , ICont, value_compare, dtl::nat) intrusive_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::dtl::
+ , intrusive_value_compare
+ , predicate_type, dtl::nat) value_compare;
+
+ 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;
+ typedef typename allocator_traits_type::template
+ portable_rebind_alloc<Node>::type NodeAlloc;
+ typedef allocator_traits<NodeAlloc> node_allocator_traits_type;
+ typedef dtl::allocator_version_traits<NodeAlloc> node_allocator_version_traits_type;
+ typedef Allocator ValAlloc;
+ typedef typename node_allocator_traits_type::pointer NodePtr;
+ typedef dtl::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 dtl::integral_constant<unsigned,
+ boost::container::dtl::
+ version<NodeAlloc>::value> alloc_version;
+ typedef typename ICont::iterator icont_iterator;
+ typedef typename ICont::const_iterator icont_citerator;
+ typedef allocator_destroyer<NodeAlloc> Destroyer;
+ typedef allocator_traits<NodeAlloc> NodeAllocTraits;
+ typedef allocator_version_traits<NodeAlloc> AllocVersionTraits;
+
+ private:
+ BOOST_COPYABLE_AND_MOVABLE(node_alloc_holder)
+
+ public:
+
+ //Constructors for sequence containers
+ node_alloc_holder()
+ : members_()
+ {}
+
+ explicit node_alloc_holder(const ValAlloc &a)
+ : members_(a)
+ {}
+
+ //Constructors for associative containers
+ node_alloc_holder(const value_compare &c, const ValAlloc &a)
+ : members_(a, c)
+ {}
+
+ explicit node_alloc_holder(const node_alloc_holder &x)
+ : members_(NodeAllocTraits::select_on_container_copy_construction(x.node_alloc()))
+ {}
+
+ node_alloc_holder(const node_alloc_holder &x, const value_compare &c)
+ : members_(NodeAllocTraits::select_on_container_copy_construction(x.node_alloc()), c)
+ {}
+
+ explicit node_alloc_holder(BOOST_RV_REF(node_alloc_holder) x)
+ : members_(boost::move(x.node_alloc()))
+ { this->icont().swap(x.icont()); }
+
+ explicit node_alloc_holder(const value_compare &c)
+ : members_(c)
+ {}
+
+ //helpers for move assignments
+ explicit node_alloc_holder(BOOST_RV_REF(node_alloc_holder) x, const value_compare &c)
+ : members_(boost::move(x.node_alloc()), c)
+ { this->icont().swap(x.icont()); }
+
+ void copy_assign_alloc(const node_alloc_holder &x)
+ {
+ dtl::bool_<allocator_traits_type::propagate_on_container_copy_assignment::value> flag;
+ dtl::assign_alloc( static_cast<NodeAlloc &>(this->members_)
+ , static_cast<const NodeAlloc &>(x.members_), flag);
+ }
+
+ void move_assign_alloc( node_alloc_holder &x)
+ {
+ dtl::bool_<allocator_traits_type::propagate_on_container_move_assignment::value> flag;
+ dtl::move_alloc( static_cast<NodeAlloc &>(this->members_)
+ , static_cast<NodeAlloc &>(x.members_), flag);
+ }
+
+ ~node_alloc_holder()
+ { this->clear(alloc_version()); }
+
+ size_type max_size() const
+ { return allocator_traits_type::max_size(this->node_alloc()); }
+
+ NodePtr allocate_one()
+ { return AllocVersionTraits::allocate_one(this->node_alloc()); }
+
+ void deallocate_one(const NodePtr &p)
+ { AllocVersionTraits::deallocate_one(this->node_alloc(), p); }
+
+ #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ template<class ...Args>
+ NodePtr create_node(Args &&...args)
+ {
+ NodePtr p = this->allocate_one();
+ Deallocator node_deallocator(p, this->node_alloc());
+ allocator_traits<NodeAlloc>::construct
+ ( this->node_alloc()
+ , dtl::addressof(p->m_data), boost::forward<Args>(args)...);
+ node_deallocator.release();
+ //This does not throw
+ typedef typename Node::hook_type hook_type;
+ ::new(static_cast<hook_type*>(boost::movelib::to_raw_pointer(p)), boost_container_new_t()) hook_type;
+ return (p);
+ }
+
+ #else //defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ #define BOOST_CONTAINER_NODE_ALLOC_HOLDER_CONSTRUCT_IMPL(N) \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ NodePtr create_node(BOOST_MOVE_UREF##N)\
+ {\
+ NodePtr p = this->allocate_one();\
+ Deallocator node_deallocator(p, this->node_alloc());\
+ allocator_traits<NodeAlloc>::construct\
+ ( this->node_alloc()\
+ , dtl::addressof(p->m_data)\
+ BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
+ node_deallocator.release();\
+ typedef typename Node::hook_type hook_type;\
+ ::new(static_cast<hook_type*>(boost::movelib::to_raw_pointer(p)), boost_container_new_t()) hook_type;\
+ return (p);\
+ }\
+ //
+ BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_NODE_ALLOC_HOLDER_CONSTRUCT_IMPL)
+ #undef BOOST_CONTAINER_NODE_ALLOC_HOLDER_CONSTRUCT_IMPL
+
+ #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ template<class It>
+ NodePtr create_node_from_it(const It &it)
+ {
+ NodePtr p = this->allocate_one();
+ Deallocator node_deallocator(p, this->node_alloc());
+ ::boost::container::construct_in_place(this->node_alloc(), dtl::addressof(p->m_data), it);
+ node_deallocator.release();
+ //This does not throw
+ typedef typename Node::hook_type hook_type;
+ ::new(static_cast<hook_type*>(boost::movelib::to_raw_pointer(p)), boost_container_new_t()) hook_type;
+ return (p);
+ }
+
+ template<class KeyConvertible>
+ NodePtr create_node_from_key(BOOST_FWD_REF(KeyConvertible) key)
+ {
+ NodePtr p = this->allocate_one();
+ NodeAlloc &na = this->node_alloc();
+ Deallocator node_deallocator(p, this->node_alloc());
+ node_allocator_traits_type::construct
+ (na, dtl::addressof(p->m_data.first), boost::forward<KeyConvertible>(key));
+ BOOST_TRY{
+ node_allocator_traits_type::construct(na, dtl::addressof(p->m_data.second));
+ }
+ BOOST_CATCH(...){
+ node_allocator_traits_type::destroy(na, dtl::addressof(p->m_data.first));
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ node_deallocator.release();
+ //This does not throw
+ typedef typename Node::hook_type hook_type;
+ ::new(static_cast<hook_type*>(boost::movelib::to_raw_pointer(p)), boost_container_new_t()) hook_type;
+ return (p);
+ }
+
+ void destroy_node(const NodePtr &nodep)
+ {
+ allocator_traits<NodeAlloc>::destroy(this->node_alloc(), boost::movelib::to_raw_pointer(nodep));
+ this->deallocate_one(nodep);
+ }
+
+ void swap(node_alloc_holder &x)
+ {
+ this->icont().swap(x.icont());
+ dtl::bool_<allocator_traits_type::propagate_on_container_swap::value> flag;
+ dtl::swap_alloc(this->node_alloc(), x.node_alloc(), flag);
+ }
+
+ template<class FwdIterator, class Inserter>
+ void allocate_many_and_construct
+ (FwdIterator beg, difference_type n, Inserter inserter)
+ {
+ if(n){
+ typedef typename node_allocator_version_traits_type::multiallocation_chain multiallocation_chain;
+
+ //Try to allocate memory in a single block
+ typedef typename multiallocation_chain::iterator multialloc_iterator;
+ multiallocation_chain mem;
+ NodeAlloc &nalloc = this->node_alloc();
+ node_allocator_version_traits_type::allocate_individual(nalloc, n, mem);
+ multialloc_iterator itbeg(mem.begin()), itlast(mem.last());
+ mem.clear();
+ Node *p = 0;
+ BOOST_TRY{
+ Deallocator node_deallocator(NodePtr(), nalloc);
+ dtl::scoped_destructor<NodeAlloc> sdestructor(nalloc, 0);
+ while(n--){
+ p = boost::movelib::iterator_to_raw_pointer(itbeg);
+ node_deallocator.set(p);
+ ++itbeg;
+ //This can throw
+ boost::container::construct_in_place(nalloc, dtl::addressof(p->m_data), beg);
+ sdestructor.set(p);
+ ++beg;
+ //This does not throw
+ typedef typename Node::hook_type hook_type;
+ ::new(static_cast<hook_type*>(p), boost_container_new_t()) hook_type;
+ //This can throw in some containers (predicate might throw).
+ //(sdestructor will destruct the node and node_deallocator will deallocate it in case of exception)
+ inserter(*p);
+ sdestructor.set(0);
+ }
+ sdestructor.release();
+ node_deallocator.release();
+ }
+ BOOST_CATCH(...){
+ mem.incorporate_after(mem.last(), &*itbeg, &*itlast, n);
+ node_allocator_version_traits_type::deallocate_individual(this->node_alloc(), mem);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ }
+ }
+
+ void clear(version_1)
+ { this->icont().clear_and_dispose(Destroyer(this->node_alloc())); }
+
+ void clear(version_2)
+ {
+ typename NodeAlloc::multiallocation_chain chain;
+ allocator_destroyer_and_chain_builder<NodeAlloc> builder(this->node_alloc(), chain);
+ this->icont().clear_and_dispose(builder);
+ //BOOST_STATIC_ASSERT((::boost::has_move_emulation_enabled<typename NodeAlloc::multiallocation_chain>::value == true));
+ if(!chain.empty())
+ this->node_alloc().deallocate_individual(chain);
+ }
+
+ 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, version_2)
+ {
+ typedef typename NodeAlloc::multiallocation_chain multiallocation_chain;
+ NodeAlloc & nalloc = this->node_alloc();
+ multiallocation_chain chain;
+ allocator_destroyer_and_chain_builder<NodeAlloc> chain_builder(nalloc, chain);
+ icont_iterator ret_it = this->icont().erase_and_dispose(first, last, chain_builder);
+ nalloc.deallocate_individual(chain);
+ return ret_it;
+ }
+
+ template<class Key, class Comparator>
+ 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, 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());
+ }
+
+ protected:
+ struct cloner
+ {
+ explicit cloner(node_alloc_holder &holder)
+ : m_holder(holder)
+ {}
+
+ NodePtr operator()(const Node &other) const
+ { return m_holder.create_node(other.m_data); }
+
+ node_alloc_holder &m_holder;
+ };
+
+ struct move_cloner
+ {
+ move_cloner(node_alloc_holder &holder)
+ : m_holder(holder)
+ {}
+
+ NodePtr operator()(Node &other)
+ { //Use m_data instead of get_data to allow moving const key in [multi]map
+ return m_holder.create_node(::boost::move(other.m_data));
+ }
+
+ node_alloc_holder &m_holder;
+ };
+
+ struct members_holder
+ : public NodeAlloc
+ {
+ private:
+ members_holder(const members_holder&);
+ members_holder & operator=(const members_holder&);
+
+ public:
+ members_holder()
+ : NodeAlloc(), m_icont()
+ {}
+
+ template<class ConvertibleToAlloc>
+ explicit members_holder(BOOST_FWD_REF(ConvertibleToAlloc) c2alloc)
+ : NodeAlloc(boost::forward<ConvertibleToAlloc>(c2alloc))
+ , m_icont()
+ {}
+
+ template<class ConvertibleToAlloc>
+ members_holder(BOOST_FWD_REF(ConvertibleToAlloc) c2alloc, const value_compare &c)
+ : NodeAlloc(boost::forward<ConvertibleToAlloc>(c2alloc))
+ , m_icont(typename ICont::key_compare(c))
+ {}
+
+ explicit members_holder(const value_compare &c)
+ : NodeAlloc()
+ , m_icont(typename ICont::key_compare(c))
+ {}
+
+ //The intrusive container
+ ICont m_icont;
+ };
+
+ ICont &non_const_icont() const
+ { return const_cast<ICont&>(this->members_.m_icont); }
+
+ NodeAlloc &node_alloc()
+ { return static_cast<NodeAlloc &>(this->members_); }
+
+ const NodeAlloc &node_alloc() const
+ { return static_cast<const NodeAlloc &>(this->members_); }
+
+ members_holder members_;
+
+ public:
+ ICont &icont()
+ { return this->members_.m_icont; }
+
+ const ICont &icont() const
+ { return this->members_.m_icont; }
+};
+
+} //namespace dtl {
+} //namespace container {
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif // BOOST_CONTAINER_DETAIL_NODE_ALLOC_HPP_
diff --git a/include/boost/container/detail/node_pool.hpp b/include/boost/container/detail/node_pool.hpp
new file mode 100644
index 0000000..e43956b
--- /dev/null
+++ b/include/boost/container/detail/node_pool.hpp
@@ -0,0 +1,157 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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_NODE_POOL_HPP
+#define BOOST_CONTAINER_DETAIL_NODE_POOL_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/detail/mutex.hpp>
+#include <boost/container/detail/pool_common_alloc.hpp>
+#include <boost/container/detail/node_pool_impl.hpp>
+#include <boost/container/detail/mutex.hpp>
+#include <boost/move/utility_core.hpp>
+#include <cstddef>
+#include <cassert>
+
+namespace boost {
+namespace container {
+namespace dtl {
+
+//!Pooled memory allocator using single segregated storage. Includes
+//!a reference count but the class does not delete itself, this is
+//!responsibility of user classes. Node size (NodeSize) and the number of
+//!nodes allocated per block (NodesPerBlock) are known at compile time
+template< std::size_t NodeSize, std::size_t NodesPerBlock >
+class private_node_pool
+ //Inherit from the implementation to avoid template bloat
+ : public boost::container::dtl::
+ private_node_pool_impl<fake_segment_manager>
+{
+ typedef boost::container::dtl::
+ private_node_pool_impl<fake_segment_manager> base_t;
+ //Non-copyable
+ private_node_pool(const private_node_pool &);
+ private_node_pool &operator=(const private_node_pool &);
+
+ public:
+ typedef typename base_t::multiallocation_chain multiallocation_chain;
+ static const std::size_t nodes_per_block = NodesPerBlock;
+
+ //!Constructor from a segment manager. Never throws
+ private_node_pool()
+ : base_t(0, NodeSize, NodesPerBlock)
+ {}
+
+};
+
+template< std::size_t NodeSize
+ , std::size_t NodesPerBlock
+ >
+class shared_node_pool
+ : public private_node_pool<NodeSize, NodesPerBlock>
+{
+ private:
+ typedef private_node_pool<NodeSize, NodesPerBlock> private_node_allocator_t;
+
+ public:
+ typedef typename private_node_allocator_t::free_nodes_t free_nodes_t;
+ typedef typename private_node_allocator_t::multiallocation_chain multiallocation_chain;
+
+ //!Constructor from a segment manager. Never throws
+ shared_node_pool()
+ : private_node_allocator_t(){}
+
+ //!Destructor. Deallocates all allocated blocks. Never throws
+ ~shared_node_pool()
+ {}
+
+ //!Allocates array of count elements. Can throw std::bad_alloc
+ void *allocate_node()
+ {
+ //-----------------------
+ scoped_lock<default_mutex> guard(mutex_);
+ //-----------------------
+ return private_node_allocator_t::allocate_node();
+ }
+
+ //!Deallocates an array pointed by ptr. Never throws
+ void deallocate_node(void *ptr)
+ {
+ //-----------------------
+ scoped_lock<default_mutex> guard(mutex_);
+ //-----------------------
+ private_node_allocator_t::deallocate_node(ptr);
+ }
+
+ //!Allocates a singly linked list of n nodes ending in null pointer.
+ //!can throw std::bad_alloc
+ void allocate_nodes(const std::size_t n, multiallocation_chain &chain)
+ {
+ //-----------------------
+ scoped_lock<default_mutex> guard(mutex_);
+ //-----------------------
+ return private_node_allocator_t::allocate_nodes(n, chain);
+ }
+
+ void deallocate_nodes(multiallocation_chain &chain)
+ {
+ //-----------------------
+ scoped_lock<default_mutex> guard(mutex_);
+ //-----------------------
+ private_node_allocator_t::deallocate_nodes(chain);
+ }
+
+ //!Deallocates all the free blocks of memory. Never throws
+ void deallocate_free_blocks()
+ {
+ //-----------------------
+ scoped_lock<default_mutex> guard(mutex_);
+ //-----------------------
+ private_node_allocator_t::deallocate_free_blocks();
+ }
+
+ //!Deallocates all blocks. Never throws
+ void purge_blocks()
+ {
+ //-----------------------
+ scoped_lock<default_mutex> guard(mutex_);
+ //-----------------------
+ private_node_allocator_t::purge_blocks();
+ }
+
+ std::size_t num_free_nodes()
+ {
+ //-----------------------
+ scoped_lock<default_mutex> guard(mutex_);
+ //-----------------------
+ return private_node_allocator_t::num_free_nodes();
+ }
+
+ private:
+ default_mutex mutex_;
+};
+
+} //namespace dtl {
+} //namespace container {
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_CONTAINER_DETAIL_NODE_POOL_HPP
diff --git a/include/boost/container/detail/node_pool_impl.hpp b/include/boost/container/detail/node_pool_impl.hpp
new file mode 100644
index 0000000..97f555b
--- /dev/null
+++ b/include/boost/container/detail/node_pool_impl.hpp
@@ -0,0 +1,375 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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_NODE_POOL_IMPL_HPP
+#define BOOST_CONTAINER_DETAIL_NODE_POOL_IMPL_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/container_fwd.hpp>
+
+#include <boost/container/detail/math_functions.hpp>
+#include <boost/container/detail/mpl.hpp>
+#include <boost/container/detail/pool_common.hpp>
+#include <boost/move/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>
+
+namespace boost {
+namespace container {
+namespace dtl {
+
+template<class SegmentManagerBase>
+class private_node_pool_impl
+{
+ //Non-copyable
+ private_node_pool_impl();
+ private_node_pool_impl(const private_node_pool_impl &);
+ private_node_pool_impl &operator=(const private_node_pool_impl &);
+
+ //A node object will hold node_t when it's not allocated
+ public:
+ typedef typename SegmentManagerBase::void_pointer void_pointer;
+ typedef typename node_slist<void_pointer>::slist_hook_t slist_hook_t;
+ typedef typename node_slist<void_pointer>::node_t node_t;
+ typedef typename node_slist<void_pointer>::node_slist_t free_nodes_t;
+ typedef typename SegmentManagerBase::multiallocation_chain multiallocation_chain;
+ typedef typename SegmentManagerBase::size_type size_type;
+
+ private:
+ typedef typename bi::make_slist
+ < 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
+ typedef SegmentManagerBase segment_manager_base_type;
+
+ //!Constructor from a segment manager. Never throws
+ private_node_pool_impl(segment_manager_base_type *segment_mngr_base, size_type node_size, size_type nodes_per_block)
+ : m_nodes_per_block(nodes_per_block)
+ , m_real_node_size(lcm(node_size, size_type(alignment_of<node_t>::value)))
+ //General purpose allocator
+ , mp_segment_mngr_base(segment_mngr_base)
+ , m_blocklist()
+ , m_freelist()
+ //Debug node count
+ , m_allocated(0)
+ {}
+
+ //!Destructor. Deallocates all allocated blocks. Never throws
+ ~private_node_pool_impl()
+ { this->purge_blocks(); }
+
+ size_type get_real_num_node() const
+ { return m_nodes_per_block; }
+
+ //!Returns the segment manager. Never throws
+ segment_manager_base_type* get_segment_manager_base()const
+ { return boost::movelib::to_raw_pointer(mp_segment_mngr_base); }
+
+ void *allocate_node()
+ { return this->priv_alloc_node(); }
+
+ //!Deallocates an array pointed by ptr. Never throws
+ void deallocate_node(void *ptr)
+ { this->priv_dealloc_node(ptr); }
+
+ //!Allocates a singly linked list of n nodes ending in null pointer.
+ void allocate_nodes(const size_type n, multiallocation_chain &chain)
+ {
+ //Preallocate all needed blocks to fulfill the request
+ size_type cur_nodes = m_freelist.size();
+ if(cur_nodes < n){
+ this->priv_alloc_block(((n - cur_nodes) - 1)/m_nodes_per_block + 1);
+ }
+
+ //We just iterate the needed nodes to get the last we'll erase
+ typedef typename free_nodes_t::iterator free_iterator;
+ free_iterator before_last_new_it = m_freelist.before_begin();
+ for(size_type j = 0; j != n; ++j){
+ ++before_last_new_it;
+ }
+
+ //Cache the first node of the allocated range before erasing
+ free_iterator first_node(m_freelist.begin());
+ free_iterator last_node (before_last_new_it);
+
+ //Erase the range. Since we already have the distance, this is O(1)
+ m_freelist.erase_after( m_freelist.before_begin()
+ , ++free_iterator(before_last_new_it)
+ , n);
+
+ //Now take the last erased node and just splice it in the end
+ //of the intrusive list that will be traversed by the multialloc iterator.
+ chain.incorporate_after(chain.before_begin(), &*first_node, &*last_node, n);
+ m_allocated += n;
+ }
+
+ void deallocate_nodes(multiallocation_chain &chain)
+ {
+ typedef typename multiallocation_chain::iterator iterator;
+ iterator it(chain.begin()), itend(chain.end());
+ while(it != itend){
+ void *pElem = &*it;
+ ++it;
+ this->priv_dealloc_node(pElem);
+ }
+ }
+
+ //!Deallocates all the free blocks of memory. Never throws
+ void deallocate_free_blocks()
+ {
+ typedef typename free_nodes_t::iterator nodelist_iterator;
+ typename blockslist_t::iterator bit(m_blocklist.before_begin()),
+ it(m_blocklist.begin()),
+ itend(m_blocklist.end());
+ free_nodes_t backup_list;
+ 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)
+ (m_real_node_size*m_nodes_per_block, (size_type) alignment_of<node_t>::value);
+
+ while(it != itend){
+ //Collect all the nodes from the block pointed by it
+ //and push them in the list
+ free_nodes_t free_nodes;
+ nodelist_iterator last_it = free_nodes.before_begin();
+ const void *addr = get_block_from_hook(&*it, blocksize);
+
+ m_freelist.remove_and_dispose_if
+ (is_between(addr, blocksize), push_in_list(free_nodes, last_it));
+
+ //If the number of nodes is equal to m_nodes_per_block
+ //this means that the block can be deallocated
+ if(free_nodes.size() == m_nodes_per_block){
+ //Unlink the nodes
+ free_nodes.clear();
+ it = m_blocklist.erase_after(bit);
+ mp_segment_mngr_base->deallocate((void*)addr);
+ }
+ //Otherwise, insert them in the backup list, since the
+ //next "remove_if" does not need to check them again.
+ else{
+ //Assign the iterator to the last value if necessary
+ if(backup_list.empty() && !m_freelist.empty()){
+ backup_list_last = last_it;
+ }
+ //Transfer nodes. This is constant time.
+ backup_list.splice_after
+ ( backup_list.before_begin()
+ , free_nodes
+ , free_nodes.before_begin()
+ , last_it
+ , free_nodes.size());
+ bit = it;
+ ++it;
+ }
+ }
+ //We should have removed all the nodes from the free list
+ BOOST_ASSERT(m_freelist.empty());
+
+ //Now pass all the node to the free list again
+ m_freelist.splice_after
+ ( m_freelist.before_begin()
+ , backup_list
+ , backup_list.before_begin()
+ , backup_list_last
+ , backup_list.size());
+ }
+
+ size_type num_free_nodes()
+ { return m_freelist.size(); }
+
+ //!Deallocates all used memory. Precondition: all nodes allocated from this pool should
+ //!already be deallocated. Otherwise, undefined behaviour. Never throws
+ void purge_blocks()
+ {
+ //check for memory leaks
+ BOOST_ASSERT(m_allocated==0);
+ 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
+ while(!m_blocklist.empty()){
+ void *addr = get_block_from_hook(&m_blocklist.front(), blocksize);
+ m_blocklist.pop_front();
+ mp_segment_mngr_base->deallocate((void*)addr);
+ }
+ //Just clear free node list
+ m_freelist.clear();
+ }
+
+ void swap(private_node_pool_impl &other)
+ {
+ BOOST_ASSERT(m_nodes_per_block == other.m_nodes_per_block);
+ BOOST_ASSERT(m_real_node_size == other.m_real_node_size);
+ std::swap(mp_segment_mngr_base, other.mp_segment_mngr_base);
+ m_blocklist.swap(other.m_blocklist);
+ m_freelist.swap(other.m_freelist);
+ std::swap(m_allocated, other.m_allocated);
+ }
+
+ private:
+
+ struct push_in_list
+ {
+ push_in_list(free_nodes_t &l, typename free_nodes_t::iterator &it)
+ : slist_(l), last_it_(it)
+ {}
+
+ void operator()(typename free_nodes_t::pointer p) const
+ {
+ slist_.push_front(*p);
+ if(slist_.size() == 1){ //Cache last element
+ ++last_it_ = slist_.begin();
+ }
+ }
+
+ private:
+ free_nodes_t &slist_;
+ typename free_nodes_t::iterator &last_it_;
+ };
+
+ struct is_between
+ {
+ typedef typename free_nodes_t::value_type argument_type;
+ typedef bool result_type;
+
+ is_between(const void *addr, std::size_t size)
+ : beg_(static_cast<const char *>(addr)), end_(beg_+size)
+ {}
+
+ bool operator()(typename free_nodes_t::const_reference v) const
+ {
+ return (beg_ <= reinterpret_cast<const char *>(&v) &&
+ end_ > reinterpret_cast<const char *>(&v));
+ }
+ private:
+ const char * beg_;
+ const char * end_;
+ };
+
+ //!Allocates one node, using single segregated storage algorithm.
+ //!Never throws
+ node_t *priv_alloc_node()
+ {
+ //If there are no free nodes we allocate a new block
+ if (m_freelist.empty())
+ this->priv_alloc_block(1);
+ //We take the first free node
+ node_t *n = (node_t*)&m_freelist.front();
+ m_freelist.pop_front();
+ ++m_allocated;
+ return n;
+ }
+
+ //!Deallocates one node, using single segregated storage algorithm.
+ //!Never throws
+ void priv_dealloc_node(void *pElem)
+ {
+ //We put the node at the beginning of the free node list
+ node_t * to_deallocate = static_cast<node_t*>(pElem);
+ m_freelist.push_front(*to_deallocate);
+ BOOST_ASSERT(m_allocated>0);
+ --m_allocated;
+ }
+
+ //!Allocates several blocks of nodes. Can throw
+ void priv_alloc_block(size_type num_blocks)
+ {
+ 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);
+
+ BOOST_TRY{
+ for(size_type i = 0; i != num_blocks; ++i){
+ //We allocate a new NodeBlock and put it as first
+ //element in the free Node list
+ char *pNode = reinterpret_cast<char*>
+ (mp_segment_mngr_base->allocate(blocksize + sizeof(node_t)));
+ char *pBlock = pNode;
+ m_blocklist.push_front(get_block_hook(pBlock, blocksize));
+
+ //We initialize all Nodes in Node Block to insert
+ //them in the free Node list
+ for(size_type j = 0; j < m_nodes_per_block; ++j, pNode += m_real_node_size){
+ m_freelist.push_front(*new (pNode) node_t);
+ }
+ }
+ }
+ BOOST_CATCH(...){
+ //to-do: if possible, an efficient way to deallocate allocated blocks
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ }
+
+ //!Deprecated, use deallocate_free_blocks
+ void deallocate_free_chunks()
+ { this->deallocate_free_blocks(); }
+
+ //!Deprecated, use purge_blocks
+ void purge_chunks()
+ { this->purge_blocks(); }
+
+ private:
+ //!Returns a reference to the block hook placed in the end of the block
+ static node_t & get_block_hook (void *block, size_type blocksize)
+ {
+ return *reinterpret_cast<node_t*>(reinterpret_cast<char*>(block) + blocksize);
+ }
+
+ //!Returns the starting address of the block reference to the block hook placed in the end of the block
+ void *get_block_from_hook (node_t *hook, size_type blocksize)
+ {
+ return (reinterpret_cast<char*>(hook) - blocksize);
+ }
+
+ private:
+ typedef typename boost::intrusive::pointer_traits
+ <void_pointer>::template rebind_pointer<segment_manager_base_type>::type segment_mngr_base_ptr_t;
+
+ const size_type m_nodes_per_block;
+ const size_type m_real_node_size;
+ segment_mngr_base_ptr_t mp_segment_mngr_base; //Segment manager
+ blockslist_t m_blocklist; //Intrusive container of blocks
+ free_nodes_t m_freelist; //Intrusive container of free nods
+ size_type m_allocated; //Used nodes for debugging
+};
+
+
+} //namespace dtl {
+} //namespace container {
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_IMPL_HPP
diff --git a/include/boost/container/detail/pair.hpp b/include/boost/container/detail/pair.hpp
new file mode 100644
index 0000000..9cca9f6
--- /dev/null
+++ b/include/boost/container/detail/pair.hpp
@@ -0,0 +1,614 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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_CONTAINER_DETAIL_PAIR_HPP
+#define BOOST_CONTAINER_CONTAINER_DETAIL_PAIR_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/detail/mpl.hpp>
+#include <boost/container/detail/type_traits.hpp>
+#include <boost/container/detail/mpl.hpp>
+#include <boost/container/detail/std_fwd.hpp>
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+# include <boost/container/detail/variadic_templates_tools.hpp>
+#endif
+#include <boost/move/adl_move_swap.hpp> //swap
+
+#include <boost/intrusive/detail/minimal_pair_header.hpp> //pair
+#include <boost/move/utility_core.hpp>
+#include <boost/move/detail/fwd_macros.hpp>
+
+namespace boost {
+namespace tuples {
+
+struct null_type;
+
+template <
+ class T0, class T1, class T2,
+ class T3, class T4, class T5,
+ class T6, class T7, class T8,
+ class T9>
+class tuple;
+
+} //namespace tuples {
+} //namespace boost {
+
+namespace boost {
+namespace container {
+namespace pair_impl {
+
+template <class TupleClass>
+struct is_boost_tuple
+{
+ static const bool value = false;
+};
+
+template <
+ class T0, class T1, class T2,
+ class T3, class T4, class T5,
+ class T6, class T7, class T8,
+ class T9>
+struct is_boost_tuple< boost::tuples::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >
+{
+ static const bool value = true;
+};
+
+template<class Tuple>
+struct disable_if_boost_tuple
+ : boost::container::dtl::disable_if< is_boost_tuple<Tuple> >
+{};
+
+template<class T>
+struct is_tuple_null
+{
+ static const bool value = false;
+};
+
+template<>
+struct is_tuple_null<boost::tuples::null_type>
+{
+ static const bool value = true;
+};
+
+}}}
+
+#if defined(BOOST_MSVC) && (_CPPLIB_VER == 520)
+//MSVC 2010 tuple marker
+namespace std { namespace tr1 { struct _Nil; }}
+#elif defined(BOOST_MSVC) && (_CPPLIB_VER == 540)
+//MSVC 2012 tuple marker
+namespace std { struct _Nil; }
+#endif
+
+
+namespace boost {
+namespace container {
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ template <int Dummy = 0>
+ struct std_piecewise_construct_holder
+ {
+ static ::std::piecewise_construct_t *dummy;
+ };
+
+ template <int Dummy>
+ ::std::piecewise_construct_t *std_piecewise_construct_holder<Dummy>::dummy =
+ reinterpret_cast< ::std::piecewise_construct_t *>(0x01234); //Avoid sanitizer errors on references to null pointers
+
+typedef const std::piecewise_construct_t & piecewise_construct_t;
+
+struct try_emplace_t{};
+
+#else
+
+//! The piecewise_construct_t struct is an empty structure type used as a unique type to
+//! disambiguate used to disambiguate between different functions that take two tuple arguments.
+typedef unspecified piecewise_construct_t;
+
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+//! A instance of type
+//! piecewise_construct_t
+static piecewise_construct_t piecewise_construct = BOOST_CONTAINER_DOC1ST(unspecified, *std_piecewise_construct_holder<>::dummy);
+
+///@cond
+
+namespace dtl {
+
+struct piecewise_construct_use
+{
+ //Avoid warnings of unused "piecewise_construct"
+ piecewise_construct_use()
+ { (void)&::boost::container::piecewise_construct; }
+};
+
+template <class T1, class T2>
+struct pair;
+
+template <class T>
+struct is_pair
+{
+ static const bool value = false;
+};
+
+template <class T1, class T2>
+struct is_pair< pair<T1, T2> >
+{
+ static const bool value = true;
+};
+
+template <class T1, class T2>
+struct is_pair< std::pair<T1, T2> >
+{
+ static const bool value = true;
+};
+
+template <class T>
+struct is_not_pair
+{
+ static const bool value = !is_pair<T>::value;
+};
+
+template <class T>
+struct is_std_pair
+{
+ static const bool value = false;
+};
+
+template <class T1, class T2>
+struct is_std_pair< std::pair<T1, T2> >
+{
+ static const bool value = true;
+};
+
+struct pair_nat;
+
+template<typename T, typename U, typename V>
+void get(T); //to enable ADL
+
+///@endcond
+
+template <class T1, class T2>
+struct pair
+{
+ private:
+ BOOST_COPYABLE_AND_MOVABLE(pair)
+
+ public:
+ typedef T1 first_type;
+ typedef T2 second_type;
+
+ T1 first;
+ T2 second;
+
+ //Default constructor
+ pair()
+ : first(), second()
+ {}
+
+ //pair copy assignment
+ pair(const pair& x)
+ : first(x.first), second(x.second)
+ {}
+
+ //pair move constructor
+ pair(BOOST_RV_REF(pair) p)
+ : first(::boost::move(p.first)), second(::boost::move(p.second))
+ {}
+
+ template <class D, class S>
+ pair(const pair<D, S> &p)
+ : first(p.first), second(p.second)
+ {}
+
+ template <class D, class S>
+ pair(BOOST_RV_REF_BEG pair<D, S> BOOST_RV_REF_END p)
+ : first(::boost::move(p.first)), second(::boost::move(p.second))
+ {}
+
+ //pair from two values
+ pair(const T1 &t1, const T2 &t2)
+ : first(t1)
+ , second(t2)
+ {}
+
+ template<class U, class V>
+ pair(BOOST_FWD_REF(U) u, BOOST_FWD_REF(V) v)
+ : first(::boost::forward<U>(u))
+ , second(::boost::forward<V>(v))
+ {}
+
+ //And now compatibility with std::pair
+ pair(const std::pair<T1, T2>& x)
+ : first(x.first), second(x.second)
+ {}
+
+ template <class D, class S>
+ pair(const std::pair<D, S>& p)
+ : first(p.first), second(p.second)
+ {}
+
+ pair(BOOST_RV_REF_BEG std::pair<T1, T2> BOOST_RV_REF_END p)
+ : first(::boost::move(p.first)), second(::boost::move(p.second))
+ {}
+
+ template <class D, class S>
+ pair(BOOST_RV_REF_BEG std::pair<D, S> BOOST_RV_REF_END p)
+ : first(::boost::move(p.first)), second(::boost::move(p.second))
+ {}
+
+ #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ template< class KeyType, class ...Args>
+ pair(try_emplace_t, BOOST_FWD_REF(KeyType) k, Args && ...args)
+ : first(boost::forward<KeyType>(k)), second(::boost::forward<Args>(args)...)\
+ {}
+ #else
+
+ //piecewise construction from boost::tuple
+ #define BOOST_PAIR_TRY_EMPLACE_CONSTRUCT_CODE(N)\
+ template< class KeyType BOOST_MOVE_I##N BOOST_MOVE_CLASS##N > \
+ pair( try_emplace_t, BOOST_FWD_REF(KeyType) k BOOST_MOVE_I##N BOOST_MOVE_UREF##N )\
+ : first(boost::forward<KeyType>(k)), second(BOOST_MOVE_FWD##N)\
+ {}\
+ //
+ BOOST_MOVE_ITERATE_0TO9(BOOST_PAIR_TRY_EMPLACE_CONSTRUCT_CODE)
+ #undef BOOST_PAIR_TRY_EMPLACE_CONSTRUCT_CODE
+
+ #endif //BOOST_NO_CXX11_VARIADIC_TEMPLATES
+
+ //piecewise construction from boost::tuple
+ #define BOOST_PAIR_PIECEWISE_CONSTRUCT_BOOST_TUPLE_CODE(N,M)\
+ template< template<class, class, class, class, class, class, class, class, class, class> class BoostTuple \
+ BOOST_MOVE_I_IF(BOOST_MOVE_OR(N,M)) BOOST_MOVE_CLASS##N BOOST_MOVE_I_IF(BOOST_MOVE_AND(N,M)) BOOST_MOVE_CLASSQ##M > \
+ pair( piecewise_construct_t\
+ , BoostTuple<BOOST_MOVE_TARG##N BOOST_MOVE_I##N BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,N),::boost::tuples::null_type)> p\
+ , BoostTuple<BOOST_MOVE_TARGQ##M BOOST_MOVE_I##M BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,M),::boost::tuples::null_type)> q\
+ , typename dtl::enable_if_c\
+ < pair_impl::is_boost_tuple< BoostTuple<BOOST_MOVE_TARG##N BOOST_MOVE_I##N BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,N),::boost::tuples::null_type)> >::value &&\
+ !(pair_impl::is_tuple_null<BOOST_MOVE_LAST_TARG##N>::value || pair_impl::is_tuple_null<BOOST_MOVE_LAST_TARGQ##M>::value) \
+ >::type* = 0\
+ )\
+ : first(BOOST_MOVE_TMPL_GET##N), second(BOOST_MOVE_TMPL_GETQ##M)\
+ { (void)p; (void)q; }\
+ //
+ BOOST_MOVE_ITER2D_0TOMAX(9, BOOST_PAIR_PIECEWISE_CONSTRUCT_BOOST_TUPLE_CODE)
+ #undef BOOST_PAIR_PIECEWISE_CONSTRUCT_BOOST_TUPLE_CODE
+
+ //piecewise construction from variadic tuple (with delegating constructors)
+ #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+ # if !defined(BOOST_CONTAINER_NO_CXX11_DELEGATING_CONSTRUCTORS)
+ private:
+ template<template<class ...> class Tuple, class... Args1, class... Args2, size_t... Indexes1, size_t... Indexes2>
+ pair(Tuple<Args1...>& t1, Tuple<Args2...>& t2, index_tuple<Indexes1...>, index_tuple<Indexes2...>)
+ : first (::boost::forward<Args1>(get<Indexes1>(t1))...)
+ , second(::boost::forward<Args2>(get<Indexes2>(t2))...)
+ { (void) t1; (void)t2; }
+
+ public:
+ template< template<class ...> class Tuple, class... Args1, class... Args2
+ , class = typename pair_impl::disable_if_boost_tuple< Tuple<Args1...> >::type>
+ pair(piecewise_construct_t, Tuple<Args1...> t1, Tuple<Args2...> t2)
+ : pair(t1, t2, typename build_number_seq<sizeof...(Args1)>::type(), typename build_number_seq<sizeof...(Args2)>::type())
+ {}
+ # else
+ //piecewise construction from variadic tuple (suboptimal, without delegating constructors)
+ private:
+ template<typename T, template<class ...> class Tuple, typename... Args>
+ static T build_from_args(Tuple<Args...>&& t)
+ { return do_build_from_args<T>(::boost::move(t), typename build_number_seq<sizeof...(Args)>::type()); }
+
+ template<typename T, template<class ...> class Tuple, typename... Args, std::size_t... Indexes>
+ static T do_build_from_args(Tuple<Args...> && t, const index_tuple<Indexes...>&)
+ { (void)t; return T(::boost::forward<Args>(get<Indexes>(t))...); }
+
+ public:
+ template< template<class ...> class Tuple, class... Args1, class... Args2
+ , class = typename pair_impl::disable_if_boost_tuple< Tuple<Args1...> >::type>
+ pair(piecewise_construct_t, Tuple<Args1...> t1, Tuple<Args2...> t2)
+ : first (build_from_args<first_type> (::boost::move(t1)))
+ , second (build_from_args<second_type>(::boost::move(t2)))
+ {}
+ # endif //BOOST_NO_CXX11_VARIADIC_TEMPLATES
+ #elif defined(BOOST_MSVC) && (_CPPLIB_VER == 520)
+ //MSVC 2010 tuple implementation
+ #define BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE(N,M)\
+ template< template<class, class, class, class, class, class, class, class, class, class> class StdTuple \
+ BOOST_MOVE_I_IF(BOOST_MOVE_OR(N,M)) BOOST_MOVE_CLASS##N BOOST_MOVE_I_IF(BOOST_MOVE_AND(N,M)) BOOST_MOVE_CLASSQ##M > \
+ pair( piecewise_construct_t\
+ , StdTuple<BOOST_MOVE_TARG##N BOOST_MOVE_I##N BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,N),::std::tr1::_Nil)> p\
+ , StdTuple<BOOST_MOVE_TARGQ##M BOOST_MOVE_I##M BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,M),::std::tr1::_Nil)> q)\
+ : first(BOOST_MOVE_GET_IDX##N), second(BOOST_MOVE_GET_IDXQ##M)\
+ { (void)p; (void)q; }\
+ //
+ BOOST_MOVE_ITER2D_0TOMAX(9, BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE)
+ #undef BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE
+ #elif defined(BOOST_MSVC) && (_CPPLIB_VER == 540)
+ #if _VARIADIC_MAX >= 9
+ #define BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT 9
+ #else
+ #define BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT BOOST_MOVE_ADD(_VARIADIC_MAX, 1)
+ #endif
+
+ //MSVC 2012 tuple implementation
+ #define BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_CODE(N,M)\
+ template< template<BOOST_MOVE_REPEAT(_VARIADIC_MAX, class), class, class, class> class StdTuple \
+ BOOST_MOVE_I_IF(BOOST_MOVE_OR(N,M)) BOOST_MOVE_CLASS##N BOOST_MOVE_I_IF(BOOST_MOVE_AND(N,M)) BOOST_MOVE_CLASSQ##M > \
+ pair( piecewise_construct_t\
+ , StdTuple<BOOST_MOVE_TARG##N BOOST_MOVE_I##N BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(BOOST_MOVE_ADD(_VARIADIC_MAX, 3),N),::std::_Nil) > p\
+ , StdTuple<BOOST_MOVE_TARGQ##M BOOST_MOVE_I##M BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(BOOST_MOVE_ADD(_VARIADIC_MAX, 3),M),::std::_Nil) > q)\
+ : first(BOOST_MOVE_GET_IDX##N), second(BOOST_MOVE_GET_IDXQ##M)\
+ { (void)p; (void)q; }\
+ //
+ BOOST_MOVE_ITER2D_0TOMAX(BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT, BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_CODE)
+ #undef BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE
+ #undef BOOST_PAIR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT
+ #endif
+
+ //pair copy assignment
+ pair& operator=(BOOST_COPY_ASSIGN_REF(pair) p)
+ {
+ first = p.first;
+ second = p.second;
+ return *this;
+ }
+
+ //pair move assignment
+ pair& operator=(BOOST_RV_REF(pair) p)
+ {
+ first = ::boost::move(p.first);
+ second = ::boost::move(p.second);
+ return *this;
+ }
+
+ template <class D, class S>
+ typename ::boost::container::dtl::disable_if_or
+ < pair &
+ , ::boost::container::dtl::is_same<T1, D>
+ , ::boost::container::dtl::is_same<T2, S>
+ >::type
+ operator=(const pair<D, S>&p)
+ {
+ first = p.first;
+ second = p.second;
+ return *this;
+ }
+
+ template <class D, class S>
+ typename ::boost::container::dtl::disable_if_or
+ < pair &
+ , ::boost::container::dtl::is_same<T1, D>
+ , ::boost::container::dtl::is_same<T2, S>
+ >::type
+ operator=(BOOST_RV_REF_BEG pair<D, S> BOOST_RV_REF_END p)
+ {
+ first = ::boost::move(p.first);
+ second = ::boost::move(p.second);
+ return *this;
+ }
+//std::pair copy assignment
+ pair& operator=(const std::pair<T1, T2> &p)
+ {
+ first = p.first;
+ second = p.second;
+ return *this;
+ }
+
+ template <class D, class S>
+ pair& operator=(const std::pair<D, S> &p)
+ {
+ first = ::boost::move(p.first);
+ second = ::boost::move(p.second);
+ return *this;
+ }
+
+ //std::pair move assignment
+ pair& operator=(BOOST_RV_REF_BEG std::pair<T1, T2> BOOST_RV_REF_END p)
+ {
+ first = ::boost::move(p.first);
+ second = ::boost::move(p.second);
+ return *this;
+ }
+
+ template <class D, class S>
+ pair& operator=(BOOST_RV_REF_BEG std::pair<D, S> BOOST_RV_REF_END p)
+ {
+ first = ::boost::move(p.first);
+ second = ::boost::move(p.second);
+ return *this;
+ }
+
+ //swap
+ void swap(pair& p)
+ {
+ ::boost::adl_move_swap(this->first, p.first);
+ ::boost::adl_move_swap(this->second, p.second);
+ }
+};
+
+template <class T1, class T2>
+inline bool operator==(const pair<T1,T2>& x, const pair<T1,T2>& y)
+{ return static_cast<bool>(x.first == y.first && x.second == y.second); }
+
+template <class T1, class T2>
+inline bool operator< (const pair<T1,T2>& x, const pair<T1,T2>& y)
+{ return static_cast<bool>(x.first < y.first ||
+ (!(y.first < x.first) && x.second < y.second)); }
+
+template <class T1, class T2>
+inline bool operator!=(const pair<T1,T2>& x, const pair<T1,T2>& y)
+{ return static_cast<bool>(!(x == y)); }
+
+template <class T1, class T2>
+inline bool operator> (const pair<T1,T2>& x, const pair<T1,T2>& y)
+{ return y < x; }
+
+template <class T1, class T2>
+inline bool operator>=(const pair<T1,T2>& x, const pair<T1,T2>& y)
+{ return static_cast<bool>(!(x < y)); }
+
+template <class T1, class T2>
+inline bool operator<=(const pair<T1,T2>& x, const pair<T1,T2>& y)
+{ return static_cast<bool>(!(y < x)); }
+
+template <class T1, class T2>
+inline pair<T1, T2> make_pair(T1 x, T2 y)
+{ return pair<T1, T2>(x, y); }
+
+template <class T1, class T2>
+inline void swap(pair<T1, T2>& x, pair<T1, T2>& y)
+{ x.swap(y); }
+
+} //namespace dtl {
+} //namespace container {
+
+#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
+
+template<class T1, class T2>
+struct has_move_emulation_enabled< ::boost::container::dtl::pair<T1, T2> >
+{
+ static const bool value = true;
+};
+
+#endif
+
+namespace move_detail{
+
+template<class T>
+struct is_class_or_union;
+
+template <class T1, class T2>
+struct is_class_or_union< ::boost::container::dtl::pair<T1, T2> >
+//This specialization is needed to avoid instantiation of pair in
+//is_class, and allow recursive maps.
+{
+ static const bool value = true;
+};
+
+template <class T1, class T2>
+struct is_class_or_union< std::pair<T1, T2> >
+//This specialization is needed to avoid instantiation of pair in
+//is_class, and allow recursive maps.
+{
+ static const bool value = true;
+};
+
+template<class T>
+struct is_union;
+
+template <class T1, class T2>
+struct is_union< ::boost::container::dtl::pair<T1, T2> >
+//This specialization is needed to avoid instantiation of pair in
+//is_class, and allow recursive maps.
+{
+ static const bool value = false;
+};
+
+template <class T1, class T2>
+struct is_union< std::pair<T1, T2> >
+//This specialization is needed to avoid instantiation of pair in
+//is_class, and allow recursive maps.
+{
+ static const bool value = false;
+};
+
+template<class T>
+struct is_class;
+
+template <class T1, class T2>
+struct is_class< ::boost::container::dtl::pair<T1, T2> >
+//This specialization is needed to avoid instantiation of pair in
+//is_class, and allow recursive maps.
+{
+ static const bool value = true;
+};
+
+template <class T1, class T2>
+struct is_class< std::pair<T1, T2> >
+//This specialization is needed to avoid instantiation of pair in
+//is_class, and allow recursive maps.
+{
+ static const bool value = true;
+};
+
+
+//Triviality of pair
+template<class T>
+struct is_trivially_copy_constructible;
+
+template<class A, class B>
+struct is_trivially_copy_assignable
+ <boost::container::dtl::pair<A,B> >
+{
+ static const bool value = boost::move_detail::is_trivially_copy_assignable<A>::value &&
+ boost::move_detail::is_trivially_copy_assignable<B>::value ;
+};
+
+template<class T>
+struct is_trivially_move_constructible;
+
+template<class A, class B>
+struct is_trivially_move_assignable
+ <boost::container::dtl::pair<A,B> >
+{
+ static const bool value = boost::move_detail::is_trivially_move_assignable<A>::value &&
+ boost::move_detail::is_trivially_move_assignable<B>::value ;
+};
+
+template<class T>
+struct is_trivially_copy_assignable;
+
+template<class A, class B>
+struct is_trivially_copy_constructible<boost::container::dtl::pair<A,B> >
+{
+ static const bool value = boost::move_detail::is_trivially_copy_constructible<A>::value &&
+ boost::move_detail::is_trivially_copy_constructible<B>::value ;
+};
+
+template<class T>
+struct is_trivially_move_assignable;
+
+template<class A, class B>
+struct is_trivially_move_constructible<boost::container::dtl::pair<A,B> >
+{
+ static const bool value = boost::move_detail::is_trivially_move_constructible<A>::value &&
+ boost::move_detail::is_trivially_move_constructible<B>::value ;
+};
+
+template<class T>
+struct is_trivially_destructible;
+
+template<class A, class B>
+struct is_trivially_destructible<boost::container::dtl::pair<A,B> >
+{
+ static const bool value = boost::move_detail::is_trivially_destructible<A>::value &&
+ boost::move_detail::is_trivially_destructible<B>::value ;
+};
+
+
+} //namespace move_detail{
+
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_CONTAINER_DETAIL_PAIR_HPP
diff --git a/include/boost/container/detail/pair_key_mapped_of_value.hpp b/include/boost/container/detail/pair_key_mapped_of_value.hpp
new file mode 100644
index 0000000..6112b87
--- /dev/null
+++ b/include/boost/container/detail/pair_key_mapped_of_value.hpp
@@ -0,0 +1,55 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2013. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#ifndef BOOST_CONTAINER_PAIR_KEY_MAPPED_OF_VALUE_HPP
+#define BOOST_CONTAINER_PAIR_KEY_MAPPED_OF_VALUE_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+
+namespace boost {
+namespace container {
+
+template<class Key, class Mapped>
+struct pair_key_mapped_of_value
+{
+ typedef Key key_type;
+ typedef Mapped mapped_type;
+
+ template<class Pair>
+ const key_type & key_of_value(const Pair &p) const
+ { return p.first; }
+
+ template<class Pair>
+ const mapped_type & mapped_of_value(const Pair &p) const
+ { return p.second; }
+
+ template<class Pair>
+ key_type & key_of_value(Pair &p) const
+ { return const_cast<key_type&>(p.first); }
+
+ template<class Pair>
+ mapped_type & mapped_of_value(Pair &p) const
+ { return p.second; }
+
+};
+
+}}
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif // BOOST_CONTAINER_PAIR_KEY_MAPPED_OF_VALUE_HPP
diff --git a/include/boost/container/detail/placement_new.hpp b/include/boost/container/detail/placement_new.hpp
new file mode 100644
index 0000000..c50981f
--- /dev/null
+++ b/include/boost/container/detail/placement_new.hpp
@@ -0,0 +1,30 @@
+#ifndef BOOST_CONTAINER_DETAIL_PLACEMENT_NEW_HPP
+#define BOOST_CONTAINER_DETAIL_PLACEMENT_NEW_HPP
+///////////////////////////////////////////////////////////////////////////////
+//
+// (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_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+struct boost_container_new_t{};
+
+//avoid including <new>
+inline void *operator new(std::size_t, void *p, boost_container_new_t)
+{ return p; }
+
+inline void operator delete(void *, void *, boost_container_new_t)
+{}
+
+#endif //BOOST_CONTAINER_DETAIL_PLACEMENT_NEW_HPP
diff --git a/include/boost/container/detail/pool_common.hpp b/include/boost/container/detail/pool_common.hpp
new file mode 100644
index 0000000..f42c1dd
--- /dev/null
+++ b/include/boost/container/detail/pool_common.hpp
@@ -0,0 +1,57 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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_POOL_COMMON_HPP
+#define BOOST_CONTAINER_DETAIL_POOL_COMMON_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/intrusive/slist.hpp>
+
+namespace boost {
+namespace container {
+namespace dtl {
+
+template<class VoidPointer>
+struct node_slist
+{
+ //This hook will be used to chain the individual nodes
+ typedef typename bi::make_slist_base_hook
+ <bi::void_pointer<VoidPointer>, bi::link_mode<bi::normal_link> >::type slist_hook_t;
+
+ //A node object will hold node_t when it's not allocated
+ typedef slist_hook_t node_t;
+
+ typedef typename bi::make_slist
+ <node_t, bi::linear<true>, bi::cache_last<true>, bi::base_hook<slist_hook_t> >::type node_slist_t;
+};
+
+template<class T>
+struct is_stateless_segment_manager
+{
+ static const bool value = false;
+};
+
+} //namespace dtl {
+} //namespace container {
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_IMPL_HPP
diff --git a/include/boost/container/detail/pool_common_alloc.hpp b/include/boost/container/detail/pool_common_alloc.hpp
new file mode 100644
index 0000000..bfb82f5
--- /dev/null
+++ b/include/boost/container/detail/pool_common_alloc.hpp
@@ -0,0 +1,102 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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_POOL_COMMON_ALLOC_HPP
+#define BOOST_CONTAINER_DETAIL_POOL_COMMON_ALLOC_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 <boost/intrusive/slist.hpp>
+#include <boost/container/detail/pool_common.hpp>
+#include <boost/container/detail/dlmalloc.hpp>
+#include <cstddef>
+
+namespace boost{
+namespace container{
+namespace dtl{
+
+struct node_slist_helper
+ : public boost::container::dtl::node_slist<void*>
+{};
+
+struct fake_segment_manager
+{
+ typedef void * void_pointer;
+ static const std::size_t PayloadPerAllocation = BOOST_CONTAINER_ALLOCATION_PAYLOAD;
+
+ typedef boost::container::dtl::
+ basic_multiallocation_chain<void*> multiallocation_chain;
+ static void deallocate(void_pointer p)
+ { dlmalloc_free(p); }
+
+ static void deallocate_many(multiallocation_chain &chain)
+ {
+ std::size_t size = chain.size();
+ std::pair<void*, void*> ptrs = chain.extract_data();
+ dlmalloc_memchain dlchain;
+ BOOST_CONTAINER_MEMCHAIN_INIT_FROM(&dlchain, ptrs.first, ptrs.second, size);
+ dlmalloc_multidealloc(&dlchain);
+ }
+
+ typedef std::ptrdiff_t difference_type;
+ typedef std::size_t size_type;
+
+ static void *allocate_aligned(std::size_t nbytes, std::size_t alignment)
+ {
+ void *ret = dlmalloc_memalign(nbytes, alignment);
+ if(!ret)
+ boost::container::throw_bad_alloc();
+ return ret;
+ }
+
+ static void *allocate(std::size_t nbytes)
+ {
+ void *ret = dlmalloc_malloc(nbytes);
+ if(!ret)
+ boost::container::throw_bad_alloc();
+ return ret;
+ }
+};
+
+} //namespace boost{
+} //namespace container{
+} //namespace dtl{
+
+namespace boost {
+namespace container {
+namespace dtl {
+
+template<class T>
+struct is_stateless_segment_manager;
+
+template<>
+struct is_stateless_segment_manager
+ <boost::container::dtl::fake_segment_manager>
+{
+ static const bool value = true;
+};
+
+} //namespace dtl {
+} //namespace container {
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //BOOST_CONTAINER_DETAIL_POOL_COMMON_ALLOC_HPP
diff --git a/include/boost/container/detail/pool_resource.hpp b/include/boost/container/detail/pool_resource.hpp
new file mode 100644
index 0000000..e5f59f5
--- /dev/null
+++ b/include/boost/container/detail/pool_resource.hpp
@@ -0,0 +1,191 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_POOL_RESOURCE_HPP
+#define BOOST_CONTAINER_POOL_RESOURCE_HPP
+
+#if defined (_MSC_VER)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+#include <boost/container/pmr/memory_resource.hpp>
+#include <boost/container/detail/block_list.hpp>
+#include <boost/container/pmr/pool_options.hpp>
+
+#include <cstddef>
+
+namespace boost {
+namespace container {
+namespace pmr {
+
+#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+class pool_data_t;
+
+static const std::size_t pool_options_minimum_max_blocks_per_chunk = 1u;
+static const std::size_t pool_options_default_max_blocks_per_chunk = 32u;
+static const std::size_t pool_options_minimum_largest_required_pool_block =
+ memory_resource::max_align > 2*sizeof(void*) ? memory_resource::max_align : 2*sizeof(void*);
+static const std::size_t pool_options_default_largest_required_pool_block =
+ pool_options_minimum_largest_required_pool_block > 4096u
+ ? pool_options_minimum_largest_required_pool_block : 4096u;
+
+#endif //BOOST_CONTAINER_DOXYGEN_INVOKED
+
+class pool_resource
+{
+ typedef block_list_base<> block_list_base_t;
+
+ pool_options m_options;
+ memory_resource& m_upstream;
+ block_list_base_t m_oversized_list;
+ pool_data_t *m_pool_data;
+ std::size_t m_pool_count;
+
+ static void priv_limit_option(std::size_t &val, std::size_t min, std::size_t max);
+ static std::size_t priv_pool_index(std::size_t block_size);
+ static std::size_t priv_pool_block(std::size_t index);
+
+ void priv_fix_options();
+ void priv_init_pools();
+ void priv_constructor_body();
+
+ public:
+
+ //! <b>Requires</b>: `upstream` is the address of a valid memory resource.
+ //!
+ //! <b>Effects</b>: Constructs a pool resource object that will obtain memory
+ //! from upstream whenever the pool resource is unable to satisfy a memory
+ //! request from its own internal data structures. The resulting object will hold
+ //! a copy of upstream, but will not own the resource to which upstream points.
+ //! [ Note: The intention is that calls to upstream->allocate() will be
+ //! substantially fewer than calls to this->allocate() in most cases. - end note
+ //! The behavior of the pooling mechanism is tuned according to the value of
+ //! the opts argument.
+ //!
+ //! <b>Throws</b>: Nothing unless upstream->allocate() throws. It is unspecified if
+ //! or under what conditions this constructor calls upstream->allocate().
+ pool_resource(const pool_options& opts, memory_resource* upstream) BOOST_NOEXCEPT;
+
+ //! <b>Effects</b>: Same as
+ //! `pool_resource(pool_options(), get_default_resource())`.
+ pool_resource() BOOST_NOEXCEPT;
+
+ //! <b>Effects</b>: Same as
+ //! `pool_resource(pool_options(), upstream)`.
+ explicit pool_resource(memory_resource* upstream) BOOST_NOEXCEPT;
+
+ //! <b>Effects</b>: Same as
+ //! `pool_resource(opts, get_default_resource())`.
+ explicit pool_resource(const pool_options& opts) BOOST_NOEXCEPT;
+
+ #if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ pool_resource(const pool_resource&) = delete;
+ pool_resource operator=(const pool_resource&) = delete;
+ #else
+ private:
+ pool_resource (const pool_resource&);
+ pool_resource operator=(const pool_resource&);
+ public:
+ #endif
+
+ //! <b>Effects</b>: Calls
+ //! `this->release()`.
+ virtual ~pool_resource();
+
+ //! <b>Effects</b>: Calls Calls `upstream_resource()->deallocate()` as necessary
+ //! to release all allocated memory. [ Note: memory is released back to
+ //! `upstream_resource()` even if deallocate has not been called for some
+ //! of the allocated blocks. - end note ]
+ void release();
+
+ //! <b>Returns</b>: The value of the upstream argument provided to the
+ //! constructor of this object.
+ memory_resource* upstream_resource() const;
+
+ //! <b>Returns</b>: The options that control the pooling behavior of this resource.
+ //! The values in the returned struct may differ from those supplied to the pool
+ //! resource constructor in that values of zero will be replaced with
+ //! implementation-defined defaults and sizes may be rounded to unspecified granularity.
+ pool_options options() const;
+
+ public: //public so that [un]synchronized_pool_resource can use them
+
+ //! <b>Returns</b>: A pointer to allocated storage with a size of at least `bytes`.
+ //! The size and alignment of the allocated memory shall meet the requirements for
+ //! a class derived from `memory_resource`.
+ //!
+ //! <b>Effects</b>: If the pool selected for a block of size bytes is unable to
+ //! satisfy the memory request from its own internal data structures, it will call
+ //! `upstream_resource()->allocate()` to obtain more memory. If `bytes` is larger
+ //! than that which the largest pool can handle, then memory will be allocated
+ //! using `upstream_resource()->allocate()`.
+ //!
+ //! <b>Throws</b>: Nothing unless `upstream_resource()->allocate()` throws.
+ virtual void* do_allocate(std::size_t bytes, std::size_t alignment);
+
+ //! <b>Effects</b>: Return the memory at p to the pool. It is unspecified if or under
+ //! what circumstances this operation will result in a call to
+ //! `upstream_resource()->deallocate()`.
+ //!
+ //! <b>Throws</b>: Nothing.
+ virtual void do_deallocate(void* p, std::size_t bytes, std::size_t alignment);
+
+ //! <b>Returns</b>:
+ //! `this == dynamic_cast<const pool_resource*>(&other)`.
+ virtual bool do_is_equal(const memory_resource& other) const BOOST_NOEXCEPT;
+
+ //Non-standard observers
+ public:
+ //! <b>Returns</b>: The number of pools that will be used in the pool resource.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ std::size_t pool_count() const;
+
+ //! <b>Returns</b>: The index of the pool that will be used to serve the allocation of `bytes`.
+ //! from the pool specified by `pool_index`. Returns `pool_count()` if `bytes` is bigger
+ //! than `options().largest_required_pool_block` (no pool will be used to serve this).
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ std::size_t pool_index(std::size_t bytes) const;
+
+ //! <b>Requires</b>: `pool_idx < pool_index()`
+ //!
+ //! <b>Returns</b>: The number blocks that will be allocated in the next chunk
+ //! from the pool specified by `pool_idx`.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ std::size_t pool_next_blocks_per_chunk(std::size_t pool_idx) const;
+
+ //! <b>Requires</b>: `pool_idx < pool_index()`
+ //!
+ //! <b>Returns</b>: The number of bytes of the block that the specified `pool_idx` pool manages.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ std::size_t pool_block(std::size_t pool_idx) const;
+
+ //! <b>Requires</b>: `pool_idx < pool_index()`
+ //!
+ //! <b>Returns</b>: The number of blocks that the specified `pool_idx` pool has cached
+ //! and will be served without calling the upstream_allocator.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ std::size_t pool_cached_blocks(std::size_t pool_idx) const;
+};
+
+} //namespace pmr {
+} //namespace container {
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //BOOST_CONTAINER_POOL_RESOURCE_HPP
diff --git a/include/boost/container/detail/singleton.hpp b/include/boost/container/detail/singleton.hpp
new file mode 100644
index 0000000..7601c3c
--- /dev/null
+++ b/include/boost/container/detail/singleton.hpp
@@ -0,0 +1,121 @@
+// Copyright (C) 2000 Stephen Cleary
+// Copyright (C) 2008 Ion Gaztanaga
+//
+// 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 for updates, documentation, and revision history.
+//
+// This file is a modified file from Boost.Pool
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2007-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_SINGLETON_DETAIL_HPP
+#define BOOST_CONTAINER_DETAIL_SINGLETON_DETAIL_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>
+
+//
+// The following helper classes are placeholders for a generic "singleton"
+// class. The classes below support usage of singletons, including use in
+// program startup/shutdown code, AS LONG AS there is only one thread
+// running before main() begins, and only one thread running after main()
+// exits.
+//
+// This class is also limited in that it can only provide singleton usage for
+// classes with default constructors.
+//
+
+// The design of this class is somewhat twisted, but can be followed by the
+// calling inheritance. Let us assume that there is some user code that
+// calls "singleton_default<T>::instance()". The following (convoluted)
+// sequence ensures that the same function will be called before main():
+// instance() contains a call to create_object.do_nothing()
+// Thus, object_creator is implicitly instantiated, and create_object
+// must exist.
+// Since create_object is a static member, its constructor must be
+// called before main().
+// The constructor contains a call to instance(), thus ensuring that
+// instance() will be called before main().
+// The first time instance() is called (i.e., before main()) is the
+// latest point in program execution where the object of type T
+// can be created.
+// Thus, any call to instance() will auto-magically result in a call to
+// instance() before main(), unless already present.
+// Furthermore, since the instance() function contains the object, instead
+// of the singleton_default class containing a static instance of the
+// object, that object is guaranteed to be constructed (at the latest) in
+// the first call to instance(). This permits calls to instance() from
+// static code, even if that code is called before the file-scope objects
+// in this file have been initialized.
+
+namespace boost {
+namespace container {
+namespace dtl {
+
+// T must be: no-throw default constructible and no-throw destructible
+template <typename T>
+struct singleton_default
+{
+ private:
+ struct object_creator
+ {
+ // This constructor does nothing more than ensure that instance()
+ // is called before main() begins, thus creating the static
+ // T object before multithreading race issues can come up.
+ object_creator() { singleton_default<T>::instance(); }
+ inline void do_nothing() const { }
+ };
+ static object_creator create_object;
+
+ singleton_default();
+
+ public:
+ typedef T object_type;
+
+ // If, at any point (in user code), singleton_default<T>::instance()
+ // is called, then the following function is instantiated.
+ static object_type & instance()
+ {
+ // This is the object that we return a reference to.
+ // It is guaranteed to be created before main() begins because of
+ // the next line.
+ static object_type obj;
+
+ // The following line does nothing else than force the instantiation
+ // of singleton_default<T>::create_object, whose constructor is
+ // called before main() begins.
+ create_object.do_nothing();
+
+ return obj;
+ }
+};
+template <typename T>
+typename singleton_default<T>::object_creator
+singleton_default<T>::create_object;
+
+} // namespace dtl
+} // namespace container
+} // namespace boost
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //BOOST_CONTAINER_DETAIL_SINGLETON_DETAIL_HPP
diff --git a/include/boost/container/detail/std_fwd.hpp b/include/boost/container/detail/std_fwd.hpp
new file mode 100644
index 0000000..0967812
--- /dev/null
+++ b/include/boost/container/detail/std_fwd.hpp
@@ -0,0 +1,56 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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_STD_FWD_HPP
+#define BOOST_CONTAINER_DETAIL_STD_FWD_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+// Standard predeclarations
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/move/detail/std_ns_begin.hpp>
+BOOST_MOVE_STD_NS_BEG
+
+template<class T>
+class allocator;
+
+template<class T>
+struct less;
+
+template<class T1, class T2>
+struct pair;
+
+template<class T>
+struct char_traits;
+
+struct input_iterator_tag;
+struct forward_iterator_tag;
+struct bidirectional_iterator_tag;
+struct random_access_iterator_tag;
+
+template<class Container>
+class insert_iterator;
+
+struct allocator_arg_t;
+
+struct piecewise_construct_t;
+
+BOOST_MOVE_STD_NS_END
+#include <boost/move/detail/std_ns_end.hpp>
+
+#endif //#ifndef BOOST_CONTAINER_DETAIL_STD_FWD_HPP
diff --git a/include/boost/container/detail/thread_mutex.hpp b/include/boost/container/detail/thread_mutex.hpp
new file mode 100644
index 0000000..628f28b
--- /dev/null
+++ b/include/boost/container/detail/thread_mutex.hpp
@@ -0,0 +1,179 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2018-2018. 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/interprocess for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+//
+// This code is partially based on the lightweight mutex implemented
+// by Boost.SmartPtr:
+//
+// Copyright (c) 2002, 2003 Peter Dimov
+// Copyright (c) Microsoft Corporation 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)
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+#
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#ifndef BOOST_CONTAINER_DETAIL_THREAD_MUTEX_HPP
+#define BOOST_CONTAINER_DETAIL_THREAD_MUTEX_HPP
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+
+#if defined(BOOST_HAS_PTHREADS)
+
+#include <pthread.h>
+#include <boost/assert.hpp>
+
+namespace boost{
+namespace container {
+namespace dtl {
+
+class thread_mutex
+{
+ public:
+ thread_mutex()
+ {
+ BOOST_VERIFY(pthread_mutex_init(&m_mut, 0) == 0);
+ }
+
+ ~thread_mutex()
+ {
+ BOOST_VERIFY(pthread_mutex_destroy(&m_mut) == 0);
+ }
+
+ void lock()
+ {
+ BOOST_VERIFY(pthread_mutex_lock( &m_mut) == 0);
+ }
+
+ void unlock()
+ {
+ BOOST_VERIFY(pthread_mutex_unlock(&m_mut) == 0);
+ }
+
+ private:
+ thread_mutex(thread_mutex const &);
+ thread_mutex & operator=(thread_mutex const &);
+
+ pthread_mutex_t m_mut;
+};
+
+} // namespace dtl {
+} // namespace container {
+} // namespace boost {
+
+#else //!BOOST_HAS_PTHREADS (Windows implementation)
+
+#ifdef BOOST_USE_WINDOWS_H
+
+#include <windows.h>
+
+namespace boost{
+namespace container {
+namespace dtl {
+
+typedef ::CRITICAL_SECTION win_critical_section;
+
+} // namespace dtl {
+} // namespace container {
+} // namespace boost {
+
+#else //! BOOST_USE_WINDOWS_H
+
+struct _RTL_CRITICAL_SECTION_DEBUG;
+struct _RTL_CRITICAL_SECTION;
+
+namespace boost{
+namespace container {
+namespace dtl {
+
+#ifdef BOOST_PLAT_WINDOWS_UWP
+extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSectionEx(::_RTL_CRITICAL_SECTION *, unsigned long, unsigned long);
+#else
+extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSection(::_RTL_CRITICAL_SECTION *);
+#endif
+extern "C" __declspec(dllimport) void __stdcall EnterCriticalSection(::_RTL_CRITICAL_SECTION *);
+extern "C" __declspec(dllimport) void __stdcall LeaveCriticalSection(::_RTL_CRITICAL_SECTION *);
+extern "C" __declspec(dllimport) void __stdcall DeleteCriticalSection(::_RTL_CRITICAL_SECTION *);
+
+struct win_critical_section
+{
+ struct _RTL_CRITICAL_SECTION_DEBUG * DebugInfo;
+ long LockCount;
+ long RecursionCount;
+ void * OwningThread;
+ void * LockSemaphore;
+ #if defined(_WIN64)
+ unsigned __int64 SpinCount;
+ #else
+ unsigned long SpinCount;
+ #endif
+};
+
+} // namespace dtl {
+} // namespace container {
+} // namespace boost {
+
+#endif //BOOST_USE_WINDOWS_H
+
+namespace boost{
+namespace container {
+namespace dtl {
+
+class thread_mutex
+{
+ public:
+ thread_mutex()
+ {
+ #ifdef BOOST_PLAT_WINDOWS_UWP
+ InitializeCriticalSectionEx(reinterpret_cast< ::_RTL_CRITICAL_SECTION* >(&m_crit_sect), 4000, 0);
+ #else
+ InitializeCriticalSection(reinterpret_cast< ::_RTL_CRITICAL_SECTION* >(&m_crit_sect));
+ #endif
+ }
+
+ void lock()
+ {
+ EnterCriticalSection(reinterpret_cast< ::_RTL_CRITICAL_SECTION* >(&m_crit_sect));
+ }
+
+ void unlock()
+ {
+ LeaveCriticalSection(reinterpret_cast< ::_RTL_CRITICAL_SECTION* >(&m_crit_sect));
+ }
+
+ ~thread_mutex()
+ {
+ DeleteCriticalSection(reinterpret_cast< ::_RTL_CRITICAL_SECTION* >(&m_crit_sect));
+ }
+
+ private:
+ thread_mutex(thread_mutex const &);
+ thread_mutex & operator=(thread_mutex const &);
+
+ win_critical_section m_crit_sect;
+};
+
+} // namespace dtl {
+} // namespace container {
+} // namespace boost {
+
+#endif //BOOST_HAS_PTHREADS
+
+#endif // #ifndef BOOST_CONTAINER_DETAIL_THREAD_MUTEX_HPP
diff --git a/include/boost/container/detail/transform_iterator.hpp b/include/boost/container/detail/transform_iterator.hpp
new file mode 100644
index 0000000..ce81813
--- /dev/null
+++ b/include/boost/container/detail/transform_iterator.hpp
@@ -0,0 +1,180 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2013.
+// (C) Copyright Gennaro Prota 2003 - 2004.
+//
+// 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_TRANSFORM_ITERATORS_HPP
+#define BOOST_CONTAINER_DETAIL_TRANSFORM_ITERATORS_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/detail/type_traits.hpp>
+#include <boost/container/detail/iterator.hpp>
+
+namespace boost {
+namespace container {
+
+template <class PseudoReference>
+struct operator_arrow_proxy
+{
+ operator_arrow_proxy(const PseudoReference &px)
+ : m_value(px)
+ {}
+
+ typedef PseudoReference element_type;
+
+ PseudoReference* operator->() const { return &m_value; }
+
+ mutable PseudoReference m_value;
+};
+
+template <class T>
+struct operator_arrow_proxy<T&>
+{
+ operator_arrow_proxy(T &px)
+ : m_value(px)
+ {}
+
+ typedef T element_type;
+
+ T* operator->() const { return const_cast<T*>(&m_value); }
+
+ T &m_value;
+};
+
+template <class Iterator, class UnaryFunction>
+class transform_iterator
+ : public UnaryFunction
+ , public boost::container::iterator
+ < typename Iterator::iterator_category
+ , typename dtl::remove_reference<typename UnaryFunction::result_type>::type
+ , typename Iterator::difference_type
+ , operator_arrow_proxy<typename UnaryFunction::result_type>
+ , typename UnaryFunction::result_type>
+{
+ public:
+ explicit transform_iterator(const Iterator &it, const UnaryFunction &f = UnaryFunction())
+ : UnaryFunction(f), m_it(it)
+ {}
+
+ explicit transform_iterator()
+ : UnaryFunction(), m_it()
+ {}
+
+ //Constructors
+ transform_iterator& operator++()
+ { increment(); return *this; }
+
+ transform_iterator operator++(int)
+ {
+ transform_iterator result (*this);
+ increment();
+ return result;
+ }
+
+ friend bool operator== (const transform_iterator& i, const transform_iterator& i2)
+ { return i.equal(i2); }
+
+ friend bool operator!= (const transform_iterator& i, const transform_iterator& i2)
+ { return !(i == i2); }
+
+/*
+ friend bool operator> (const transform_iterator& i, const transform_iterator& i2)
+ { return i2 < i; }
+
+ friend bool operator<= (const transform_iterator& i, const transform_iterator& i2)
+ { return !(i > i2); }
+
+ friend bool operator>= (const transform_iterator& i, const transform_iterator& i2)
+ { return !(i < i2); }
+*/
+ friend typename Iterator::difference_type operator- (const transform_iterator& i, const transform_iterator& i2)
+ { return i2.distance_to(i); }
+
+ //Arithmetic
+ transform_iterator& operator+=(typename Iterator::difference_type off)
+ { this->advance(off); return *this; }
+
+ transform_iterator operator+(typename Iterator::difference_type off) const
+ {
+ transform_iterator other(*this);
+ other.advance(off);
+ return other;
+ }
+
+ friend transform_iterator operator+(typename Iterator::difference_type off, const transform_iterator& right)
+ { return right + off; }
+
+ transform_iterator& operator-=(typename Iterator::difference_type off)
+ { this->advance(-off); return *this; }
+
+ transform_iterator operator-(typename Iterator::difference_type off) const
+ { return *this + (-off); }
+
+ typename UnaryFunction::result_type operator*() const
+ { return dereference(); }
+
+ operator_arrow_proxy<typename UnaryFunction::result_type>
+ operator->() const
+ { return operator_arrow_proxy<typename UnaryFunction::result_type>(dereference()); }
+
+ Iterator & base()
+ { return m_it; }
+
+ const Iterator & base() const
+ { return m_it; }
+
+ private:
+ Iterator m_it;
+
+ void increment()
+ { ++m_it; }
+
+ void decrement()
+ { --m_it; }
+
+ bool equal(const transform_iterator &other) const
+ { return m_it == other.m_it; }
+
+ bool less(const transform_iterator &other) const
+ { return other.m_it < m_it; }
+
+ typename UnaryFunction::result_type dereference() const
+ { return UnaryFunction::operator()(*m_it); }
+
+ void advance(typename Iterator::difference_type n)
+ { boost::container::iterator_advance(m_it, n); }
+
+ typename Iterator::difference_type distance_to(const transform_iterator &other)const
+ { return boost::container::iterator_distance(other.m_it, m_it); }
+};
+
+template <class Iterator, class UnaryFunc>
+transform_iterator<Iterator, UnaryFunc>
+make_transform_iterator(Iterator it, UnaryFunc fun)
+{
+ return transform_iterator<Iterator, UnaryFunc>(it, fun);
+}
+
+} //namespace container {
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_CONTAINER_DETAIL_TRANSFORM_ITERATORS_HPP
diff --git a/include/boost/container/detail/tree.hpp b/include/boost/container/detail/tree.hpp
new file mode 100644
index 0000000..c32e992
--- /dev/null
+++ b/include/boost/container/detail/tree.hpp
@@ -0,0 +1,1458 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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 http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_TREE_HPP
+#define BOOST_CONTAINER_TREE_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+// container
+#include <boost/container/allocator_traits.hpp>
+#include <boost/container/container_fwd.hpp>
+#include <boost/container/options.hpp>
+#include <boost/container/node_handle.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/node_alloc_holder.hpp>
+#include <boost/container/detail/pair.hpp>
+#include <boost/container/detail/type_traits.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
+#include <boost/intrusive/detail/tree_value_compare.hpp> //tree_value_compare
+// move
+#include <boost/move/utility_core.hpp>
+// move/detail
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+#include <boost/move/detail/fwd_macros.hpp>
+#endif
+#include <boost/move/detail/move_helpers.hpp>
+// other
+#include <boost/core/no_exceptions_support.hpp>
+
+
+
+#include <boost/container/detail/std_fwd.hpp>
+
+namespace boost {
+namespace container {
+namespace dtl {
+
+using boost::intrusive::tree_value_compare;
+
+template<class VoidPointer, boost::container::tree_type_enum tree_type_value, bool OptimizeSize>
+struct intrusive_tree_hook;
+
+template<class VoidPointer, bool OptimizeSize>
+struct intrusive_tree_hook<VoidPointer, boost::container::red_black_tree, OptimizeSize>
+{
+ typedef typename dtl::bi::make_set_base_hook
+ < dtl::bi::void_pointer<VoidPointer>
+ , dtl::bi::link_mode<dtl::bi::normal_link>
+ , dtl::bi::optimize_size<OptimizeSize>
+ >::type type;
+};
+
+template<class VoidPointer, bool OptimizeSize>
+struct intrusive_tree_hook<VoidPointer, boost::container::avl_tree, OptimizeSize>
+{
+ typedef typename dtl::bi::make_avl_set_base_hook
+ < dtl::bi::void_pointer<VoidPointer>
+ , dtl::bi::link_mode<dtl::bi::normal_link>
+ , dtl::bi::optimize_size<OptimizeSize>
+ >::type type;
+};
+
+template<class VoidPointer, bool OptimizeSize>
+struct intrusive_tree_hook<VoidPointer, boost::container::scapegoat_tree, OptimizeSize>
+{
+ typedef typename dtl::bi::make_bs_set_base_hook
+ < dtl::bi::void_pointer<VoidPointer>
+ , dtl::bi::link_mode<dtl::bi::normal_link>
+ >::type type;
+};
+
+template<class VoidPointer, bool OptimizeSize>
+struct intrusive_tree_hook<VoidPointer, boost::container::splay_tree, OptimizeSize>
+{
+ typedef typename dtl::bi::make_bs_set_base_hook
+ < dtl::bi::void_pointer<VoidPointer>
+ , dtl::bi::link_mode<dtl::bi::normal_link>
+ >::type type;
+};
+
+//This trait is used to type-pun std::pair because in C++03
+//compilers std::pair is useless for C++11 features
+template<class T>
+struct tree_internal_data_type
+{
+ typedef T type;
+};
+
+template<class T1, class T2>
+struct tree_internal_data_type< std::pair<T1, T2> >
+{
+ typedef pair<typename boost::move_detail::remove_const<T1>::type, T2> type;
+};
+
+//The node to be store in the tree
+template <class T, class VoidPointer, boost::container::tree_type_enum tree_type_value, bool OptimizeSize>
+struct tree_node
+ : public intrusive_tree_hook<VoidPointer, tree_type_value, OptimizeSize>::type
+{
+ private:
+ //BOOST_COPYABLE_AND_MOVABLE(tree_node)
+ tree_node();
+
+ public:
+ typedef typename intrusive_tree_hook
+ <VoidPointer, tree_type_value, OptimizeSize>::type hook_type;
+ typedef T value_type;
+ typedef typename tree_internal_data_type<T>::type internal_type;
+
+ typedef tree_node< T, VoidPointer
+ , tree_type_value, OptimizeSize> node_t;
+
+ BOOST_CONTAINER_FORCEINLINE T &get_data()
+ {
+ T* ptr = reinterpret_cast<T*>(&this->m_data);
+ return *ptr;
+ }
+
+ BOOST_CONTAINER_FORCEINLINE const T &get_data() const
+ {
+ const T* ptr = reinterpret_cast<const T*>(&this->m_data);
+ return *ptr;
+ }
+
+ internal_type m_data;
+
+ template<class T1, class T2>
+ BOOST_CONTAINER_FORCEINLINE void do_assign(const std::pair<const T1, T2> &p)
+ {
+ const_cast<T1&>(m_data.first) = p.first;
+ m_data.second = p.second;
+ }
+
+ template<class T1, class T2>
+ BOOST_CONTAINER_FORCEINLINE void do_assign(const pair<const T1, T2> &p)
+ {
+ const_cast<T1&>(m_data.first) = p.first;
+ m_data.second = p.second;
+ }
+
+ template<class V>
+ BOOST_CONTAINER_FORCEINLINE void do_assign(const V &v)
+ { m_data = v; }
+
+ template<class T1, class T2>
+ BOOST_CONTAINER_FORCEINLINE void do_move_assign(std::pair<const T1, T2> &p)
+ {
+ const_cast<T1&>(m_data.first) = ::boost::move(p.first);
+ m_data.second = ::boost::move(p.second);
+ }
+
+ template<class T1, class T2>
+ BOOST_CONTAINER_FORCEINLINE void do_move_assign(pair<const T1, T2> &p)
+ {
+ const_cast<T1&>(m_data.first) = ::boost::move(p.first);
+ m_data.second = ::boost::move(p.second);
+ }
+
+ template<class V>
+ BOOST_CONTAINER_FORCEINLINE void do_move_assign(V &v)
+ { m_data = ::boost::move(v); }
+};
+
+template <class T, class VoidPointer, boost::container::tree_type_enum tree_type_value, bool OptimizeSize>
+struct iiterator_node_value_type< tree_node<T, VoidPointer, tree_type_value, OptimizeSize> > {
+ typedef T type;
+};
+
+template<class Node, class Icont>
+class insert_equal_end_hint_functor
+{
+ Icont &icont_;
+
+ public:
+ BOOST_CONTAINER_FORCEINLINE insert_equal_end_hint_functor(Icont &icont)
+ : icont_(icont)
+ {}
+
+ BOOST_CONTAINER_FORCEINLINE void operator()(Node &n)
+ { this->icont_.insert_equal(this->icont_.cend(), n); }
+};
+
+template<class Node, class Icont>
+class push_back_functor
+{
+ Icont &icont_;
+
+ public:
+ BOOST_CONTAINER_FORCEINLINE push_back_functor(Icont &icont)
+ : icont_(icont)
+ {}
+
+ BOOST_CONTAINER_FORCEINLINE void operator()(Node &n)
+ { this->icont_.push_back(n); }
+};
+
+}//namespace dtl {
+
+namespace dtl {
+
+template< class NodeType, class NodeCompareType
+ , class SizeType, class HookType
+ , boost::container::tree_type_enum tree_type_value>
+struct intrusive_tree_dispatch;
+
+template<class NodeType, class NodeCompareType, class SizeType, class HookType>
+struct intrusive_tree_dispatch
+ <NodeType, NodeCompareType, SizeType, HookType, boost::container::red_black_tree>
+{
+ typedef typename dtl::bi::make_rbtree
+ <NodeType
+ ,dtl::bi::compare<NodeCompareType>
+ ,dtl::bi::base_hook<HookType>
+ ,dtl::bi::constant_time_size<true>
+ ,dtl::bi::size_type<SizeType>
+ >::type type;
+};
+
+template<class NodeType, class NodeCompareType, class SizeType, class HookType>
+struct intrusive_tree_dispatch
+ <NodeType, NodeCompareType, SizeType, HookType, boost::container::avl_tree>
+{
+ typedef typename dtl::bi::make_avltree
+ <NodeType
+ ,dtl::bi::compare<NodeCompareType>
+ ,dtl::bi::base_hook<HookType>
+ ,dtl::bi::constant_time_size<true>
+ ,dtl::bi::size_type<SizeType>
+ >::type type;
+};
+
+template<class NodeType, class NodeCompareType, class SizeType, class HookType>
+struct intrusive_tree_dispatch
+ <NodeType, NodeCompareType, SizeType, HookType, boost::container::scapegoat_tree>
+{
+ typedef typename dtl::bi::make_sgtree
+ <NodeType
+ ,dtl::bi::compare<NodeCompareType>
+ ,dtl::bi::base_hook<HookType>
+ ,dtl::bi::floating_point<true>
+ ,dtl::bi::size_type<SizeType>
+ >::type type;
+};
+
+template<class NodeType, class NodeCompareType, class SizeType, class HookType>
+struct intrusive_tree_dispatch
+ <NodeType, NodeCompareType, SizeType, HookType, boost::container::splay_tree>
+{
+ typedef typename dtl::bi::make_splaytree
+ <NodeType
+ ,dtl::bi::compare<NodeCompareType>
+ ,dtl::bi::base_hook<HookType>
+ ,dtl::bi::constant_time_size<true>
+ ,dtl::bi::size_type<SizeType>
+ >::type type;
+};
+
+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<Allocator>::value_type value_type;
+ typedef typename boost::container::
+ allocator_traits<Allocator>::void_pointer void_pointer;
+ typedef typename boost::container::
+ allocator_traits<Allocator>::size_type size_type;
+ typedef typename dtl::tree_node
+ < value_type, void_pointer
+ , tree_type_value, OptimizeSize> node_t;
+ typedef value_to_node_compare
+ <node_t, ValueCompare> node_compare_type;
+ //Deducing the hook type from node_t (e.g. node_t::hook_type) would
+ //provoke an early instantiation of node_t that could ruin recursive
+ //tree definitions, so retype the complete type to avoid any problem.
+ typedef typename intrusive_tree_hook
+ <void_pointer, tree_type_value
+ , OptimizeSize>::type hook_type;
+ public:
+ typedef typename intrusive_tree_dispatch
+ < node_t, node_compare_type
+ , size_type, hook_type
+ , tree_type_value>::type type;
+};
+
+//Trait to detect manually rebalanceable tree types
+template<boost::container::tree_type_enum tree_type_value>
+struct is_manually_balanceable
+{ static const bool value = true; };
+
+template<> struct is_manually_balanceable<red_black_tree>
+{ static const bool value = false; };
+
+template<> struct is_manually_balanceable<avl_tree>
+{ static const bool value = false; };
+
+//Proxy traits to implement different operations depending on the
+//is_manually_balanceable<>::value
+template< boost::container::tree_type_enum tree_type_value
+ , bool IsManuallyRebalanceable = is_manually_balanceable<tree_type_value>::value>
+struct intrusive_tree_proxy
+{
+ template<class Icont>
+ BOOST_CONTAINER_FORCEINLINE static void rebalance(Icont &) {}
+};
+
+template<boost::container::tree_type_enum tree_type_value>
+struct intrusive_tree_proxy<tree_type_value, true>
+{
+ template<class Icont>
+ BOOST_CONTAINER_FORCEINLINE static void rebalance(Icont &c)
+ { c.rebalance(); }
+};
+
+} //namespace dtl {
+
+namespace dtl {
+
+//This functor will be used with Intrusive clone functions to obtain
+//already allocated nodes from a intrusive container instead of
+//allocating new ones. When the intrusive container runs out of nodes
+//the node holder is used instead.
+template<class AllocHolder, bool DoMove>
+class RecyclingCloner
+{
+ typedef typename AllocHolder::intrusive_container intrusive_container;
+ typedef typename AllocHolder::Node node_t;
+ typedef typename AllocHolder::NodePtr node_ptr_type;
+
+ public:
+ RecyclingCloner(AllocHolder &holder, intrusive_container &itree)
+ : m_holder(holder), m_icont(itree)
+ {}
+
+ BOOST_CONTAINER_FORCEINLINE static void do_assign(node_ptr_type &p, const node_t &other, bool_<true>)
+ { p->do_move_assign(const_cast<node_t &>(other).m_data); }
+
+ BOOST_CONTAINER_FORCEINLINE static void do_assign(node_ptr_type &p, const node_t &other, bool_<false>)
+ { p->do_assign(other.m_data); }
+
+ node_ptr_type operator()(const node_t &other) const
+ {
+ if(node_ptr_type p = m_icont.unlink_leftmost_without_rebalance()){
+ //First recycle a node (this can't throw)
+ BOOST_TRY{
+ //This can throw
+ this->do_assign(p, other, bool_<DoMove>());
+ return p;
+ }
+ BOOST_CATCH(...){
+ //If there is an exception destroy the whole source
+ m_holder.destroy_node(p);
+ while((p = m_icont.unlink_leftmost_without_rebalance())){
+ m_holder.destroy_node(p);
+ }
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ }
+ else{
+ return m_holder.create_node(other.m_data);
+ }
+ }
+
+ AllocHolder &m_holder;
+ intrusive_container &m_icont;
+};
+
+
+template<class KeyCompare, class KeyOfValue>
+struct key_node_compare
+ : public boost::intrusive::detail::ebo_functor_holder<KeyCompare>
+{
+ BOOST_CONTAINER_FORCEINLINE explicit key_node_compare(const KeyCompare &comp)
+ : base_t(comp)
+ {}
+
+ typedef boost::intrusive::detail::ebo_functor_holder<KeyCompare> base_t;
+ typedef KeyCompare key_compare;
+ typedef KeyOfValue key_of_value;
+ typedef typename KeyOfValue::type key_type;
+
+
+ template <class T, class VoidPointer, boost::container::tree_type_enum tree_type_value, bool OptimizeSize>
+ BOOST_CONTAINER_FORCEINLINE static const key_type &
+ key_from(const tree_node<T, VoidPointer, tree_type_value, OptimizeSize> &n)
+ {
+ return key_of_value()(n.get_data());
+ }
+
+ template <class T>
+ BOOST_CONTAINER_FORCEINLINE static const T &
+ key_from(const T &t)
+ {
+ return t;
+ }
+
+ BOOST_CONTAINER_FORCEINLINE const key_compare &key_comp() const
+ { return static_cast<const key_compare &>(*this); }
+
+ BOOST_CONTAINER_FORCEINLINE key_compare &key_comp()
+ { return static_cast<key_compare &>(*this); }
+
+ BOOST_CONTAINER_FORCEINLINE bool operator()(const key_type &key1, const key_type &key2) const
+ { return this->key_comp()(key1, key2); }
+
+ template<class U>
+ BOOST_CONTAINER_FORCEINLINE bool operator()(const key_type &key1, const U &nonkey2) const
+ { return this->key_comp()(key1, this->key_from(nonkey2)); }
+
+ template<class U>
+ BOOST_CONTAINER_FORCEINLINE bool operator()(const U &nonkey1, const key_type &key2) const
+ { return this->key_comp()(this->key_from(nonkey1), key2); }
+
+ template<class U, class V>
+ BOOST_CONTAINER_FORCEINLINE bool operator()(const U &nonkey1, const V &nonkey2) const
+ { return this->key_comp()(this->key_from(nonkey1), this->key_from(nonkey2)); }
+};
+
+template<class Options>
+struct get_tree_opt
+{
+ typedef Options type;
+};
+
+template<>
+struct get_tree_opt<void>
+{
+ typedef tree_assoc_defaults type;
+};
+
+template <class T, class KeyOfValue, class Compare, class Allocator, class Options>
+class tree
+ : public dtl::node_alloc_holder
+ < Allocator
+ , typename dtl::intrusive_tree_type
+ < Allocator, tree_value_compare
+ <typename allocator_traits<Allocator>::pointer, Compare, KeyOfValue>
+ , get_tree_opt<Options>::type::tree_type
+ , get_tree_opt<Options>::type::optimize_size
+ >::type
+ >
+{
+ typedef tree_value_compare
+ < typename allocator_traits<Allocator>::pointer
+ , Compare, KeyOfValue> ValComp;
+ typedef typename get_tree_opt<Options>::type options_type;
+ typedef typename dtl::intrusive_tree_type
+ < Allocator, ValComp
+ , options_type::tree_type
+ , options_type::optimize_size
+ >::type Icont;
+ typedef dtl::node_alloc_holder
+ <Allocator, Icont> AllocHolder;
+ typedef typename AllocHolder::NodePtr NodePtr;
+ typedef tree < 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 dtl::allocator_destroyer<NodeAlloc> Destroyer;
+ typedef typename AllocHolder::alloc_version alloc_version;
+ typedef intrusive_tree_proxy<options_type::tree_type> intrusive_tree_proxy_t;
+
+ BOOST_COPYABLE_AND_MOVABLE(tree)
+
+ public:
+
+ typedef typename KeyOfValue::type key_type;
+ typedef T value_type;
+ typedef Allocator allocator_type;
+ typedef Compare key_compare;
+ typedef ValComp value_compare;
+ 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;
+ typedef typename boost::container::
+ allocator_traits<Allocator>::const_reference const_reference;
+ typedef typename boost::container::
+ allocator_traits<Allocator>::size_type size_type;
+ typedef typename boost::container::
+ allocator_traits<Allocator>::difference_type difference_type;
+ typedef dtl::iterator_from_iiterator
+ <iiterator, false> iterator;
+ typedef dtl::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;
+ typedef node_handle
+ < NodeAlloc, void> node_type;
+ typedef insert_return_type_base
+ <iterator, node_type> insert_return_type;
+
+ typedef NodeAlloc stored_allocator_type;
+
+ private:
+
+ typedef key_node_compare<key_compare, KeyOfValue> KeyNodeCompare;
+
+ public:
+
+ BOOST_CONTAINER_FORCEINLINE tree()
+ : AllocHolder()
+ {}
+
+ BOOST_CONTAINER_FORCEINLINE explicit tree(const key_compare& comp)
+ : AllocHolder(ValComp(comp))
+ {}
+
+ BOOST_CONTAINER_FORCEINLINE explicit tree(const key_compare& comp, const allocator_type& a)
+ : AllocHolder(ValComp(comp), a)
+ {}
+
+ BOOST_CONTAINER_FORCEINLINE explicit tree(const allocator_type& a)
+ : AllocHolder(a)
+ {}
+
+ template <class InputIterator>
+ tree(bool unique_insertion, InputIterator first, InputIterator last)
+ : AllocHolder(value_compare(key_compare()))
+ {
+ this->tree_construct(unique_insertion, first, last);
+ //AllocHolder clears in case of exception
+ }
+
+ template <class InputIterator>
+ tree(bool unique_insertion, InputIterator first, InputIterator last, const key_compare& comp)
+ : AllocHolder(value_compare(comp))
+ {
+ this->tree_construct(unique_insertion, first, last);
+ //AllocHolder clears in case of exception
+ }
+
+ template <class InputIterator>
+ tree(bool unique_insertion, InputIterator first, InputIterator last, const key_compare& comp, const allocator_type& a)
+ : AllocHolder(value_compare(comp), a)
+ {
+ this->tree_construct(unique_insertion, first, last);
+ //AllocHolder clears in case of exception
+ }
+
+ //construct with ordered range
+ template <class InputIterator>
+ tree( ordered_range_t, InputIterator first, InputIterator last)
+ : AllocHolder(value_compare(key_compare()))
+ {
+ this->tree_construct(ordered_range_t(), first, last);
+ }
+
+ template <class InputIterator>
+ tree( ordered_range_t, InputIterator first, InputIterator last, const key_compare& comp)
+ : AllocHolder(value_compare(comp))
+ {
+ this->tree_construct(ordered_range_t(), first, last);
+ }
+
+ template <class InputIterator>
+ tree( ordered_range_t, InputIterator first, InputIterator last
+ , const key_compare& comp, const allocator_type& a)
+ : AllocHolder(value_compare(comp), a)
+ {
+ this->tree_construct(ordered_range_t(), first, last);
+ }
+
+ private:
+
+ template <class InputIterator>
+ void tree_construct(bool unique_insertion, InputIterator first, InputIterator last)
+ {
+ //Use cend() as hint to achieve linear time for
+ //ordered ranges as required by the standard
+ //for the constructor
+ if(unique_insertion){
+ const const_iterator end_it(this->cend());
+ for ( ; first != last; ++first){
+ this->insert_unique_convertible(end_it, *first);
+ }
+ }
+ else{
+ this->tree_construct_non_unique(first, last);
+ }
+ }
+
+ template <class InputIterator>
+ void tree_construct_non_unique(InputIterator first, InputIterator last
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename dtl::enable_if_or
+ < void
+ , dtl::is_same<alloc_version, version_1>
+ , dtl::is_input_iterator<InputIterator>
+ >::type * = 0
+ #endif
+ )
+ {
+ //Use cend() as hint to achieve linear time for
+ //ordered ranges as required by the standard
+ //for the constructor
+ const const_iterator end_it(this->cend());
+ for ( ; first != last; ++first){
+ this->insert_equal_convertible(end_it, *first);
+ }
+ }
+
+ template <class InputIterator>
+ void tree_construct_non_unique(InputIterator first, InputIterator last
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename dtl::disable_if_or
+ < void
+ , dtl::is_same<alloc_version, version_1>
+ , dtl::is_input_iterator<InputIterator>
+ >::type * = 0
+ #endif
+ )
+ {
+ //Optimized allocation and construction
+ this->allocate_many_and_construct
+ ( first, boost::container::iterator_distance(first, last)
+ , insert_equal_end_hint_functor<Node, Icont>(this->icont()));
+ }
+
+ template <class InputIterator>
+ void tree_construct( ordered_range_t, InputIterator first, InputIterator last
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename dtl::disable_if_or
+ < void
+ , dtl::is_same<alloc_version, version_1>
+ , dtl::is_input_iterator<InputIterator>
+ >::type * = 0
+ #endif
+ )
+ {
+ //Optimized allocation and construction
+ this->allocate_many_and_construct
+ ( first, boost::container::iterator_distance(first, last)
+ , dtl::push_back_functor<Node, Icont>(this->icont()));
+ //AllocHolder clears in case of exception
+ }
+
+ template <class InputIterator>
+ void tree_construct( ordered_range_t, InputIterator first, InputIterator last
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename dtl::enable_if_or
+ < void
+ , dtl::is_same<alloc_version, version_1>
+ , dtl::is_input_iterator<InputIterator>
+ >::type * = 0
+ #endif
+ )
+ {
+ for ( ; first != last; ++first){
+ this->push_back_impl(*first);
+ }
+ }
+
+ public:
+
+ BOOST_CONTAINER_FORCEINLINE tree(const tree& x)
+ : AllocHolder(x, x.value_comp())
+ {
+ this->icont().clone_from
+ (x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc()));
+ }
+
+ BOOST_CONTAINER_FORCEINLINE tree(BOOST_RV_REF(tree) x)
+ BOOST_NOEXCEPT_IF(boost::container::dtl::is_nothrow_move_constructible<Compare>::value)
+ : AllocHolder(BOOST_MOVE_BASE(AllocHolder, x), x.value_comp())
+ {}
+
+ BOOST_CONTAINER_FORCEINLINE tree(const tree& x, const allocator_type &a)
+ : AllocHolder(x.value_comp(), a)
+ {
+ this->icont().clone_from
+ (x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc()));
+ //AllocHolder clears in case of exception
+ }
+
+ tree(BOOST_RV_REF(tree) x, const allocator_type &a)
+ : AllocHolder(x.value_comp(), a)
+ {
+ if(this->node_alloc() == x.node_alloc()){
+ this->icont().swap(x.icont());
+ }
+ else{
+ this->icont().clone_from
+ (boost::move(x.icont()), typename AllocHolder::move_cloner(*this), Destroyer(this->node_alloc()));
+ }
+ //AllocHolder clears in case of exception
+ }
+
+ BOOST_CONTAINER_FORCEINLINE ~tree()
+ {} //AllocHolder clears the tree
+
+ tree& operator=(BOOST_COPY_ASSIGN_REF(tree) x)
+ {
+ if (&x != this){
+ NodeAlloc &this_alloc = this->get_stored_allocator();
+ const NodeAlloc &x_alloc = x.get_stored_allocator();
+ dtl::bool_<allocator_traits<NodeAlloc>::
+ propagate_on_container_copy_assignment::value> flag;
+ if(flag && this_alloc != x_alloc){
+ this->clear();
+ }
+ this->AllocHolder::copy_assign_alloc(x);
+ //Transfer all the nodes to a temporary tree
+ //If anything goes wrong, all the nodes will be destroyed
+ //automatically
+ Icont other_tree(::boost::move(this->icont()));
+
+ //Now recreate the source tree reusing nodes stored by other_tree
+ this->icont().clone_from
+ (x.icont()
+ , RecyclingCloner<AllocHolder, false>(*this, other_tree)
+ , Destroyer(this->node_alloc()));
+
+ //If there are remaining nodes, destroy them
+ NodePtr p;
+ while((p = other_tree.unlink_leftmost_without_rebalance())){
+ AllocHolder::destroy_node(p);
+ }
+ }
+ return *this;
+ }
+
+ tree& operator=(BOOST_RV_REF(tree) x)
+ BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value ||
+ allocator_traits_type::is_always_equal::value) &&
+ boost::container::dtl::is_nothrow_move_assignable<Compare>::value)
+ {
+ BOOST_ASSERT(this != &x);
+ NodeAlloc &this_alloc = this->node_alloc();
+ NodeAlloc &x_alloc = x.node_alloc();
+ const bool propagate_alloc = allocator_traits<NodeAlloc>::
+ propagate_on_container_move_assignment::value;
+ const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
+ //Resources can be transferred if both allocators are
+ //going to be equal after this function (either propagated or already equal)
+ if(propagate_alloc || allocators_equal){
+ //Destroy
+ this->clear();
+ //Move allocator if needed
+ this->AllocHolder::move_assign_alloc(x);
+ //Obtain resources
+ this->icont() = boost::move(x.icont());
+ }
+ //Else do a one by one move
+ else{
+ //Transfer all the nodes to a temporary tree
+ //If anything goes wrong, all the nodes will be destroyed
+ //automatically
+ Icont other_tree(::boost::move(this->icont()));
+
+ //Now recreate the source tree reusing nodes stored by other_tree
+ this->icont().clone_from
+ (::boost::move(x.icont())
+ , RecyclingCloner<AllocHolder, true>(*this, other_tree)
+ , Destroyer(this->node_alloc()));
+
+ //If there are remaining nodes, destroy them
+ NodePtr p;
+ while((p = other_tree.unlink_leftmost_without_rebalance())){
+ AllocHolder::destroy_node(p);
+ }
+ }
+ return *this;
+ }
+
+ public:
+ // accessors:
+ BOOST_CONTAINER_FORCEINLINE value_compare value_comp() const
+ { return this->icont().value_comp().predicate(); }
+
+ BOOST_CONTAINER_FORCEINLINE key_compare key_comp() const
+ { return this->icont().value_comp().predicate().key_comp(); }
+
+ BOOST_CONTAINER_FORCEINLINE allocator_type get_allocator() const
+ { return allocator_type(this->node_alloc()); }
+
+ BOOST_CONTAINER_FORCEINLINE const stored_allocator_type &get_stored_allocator() const
+ { return this->node_alloc(); }
+
+ BOOST_CONTAINER_FORCEINLINE stored_allocator_type &get_stored_allocator()
+ { return this->node_alloc(); }
+
+ BOOST_CONTAINER_FORCEINLINE iterator begin()
+ { return iterator(this->icont().begin()); }
+
+ BOOST_CONTAINER_FORCEINLINE const_iterator begin() const
+ { return this->cbegin(); }
+
+ BOOST_CONTAINER_FORCEINLINE iterator end()
+ { return iterator(this->icont().end()); }
+
+ BOOST_CONTAINER_FORCEINLINE const_iterator end() const
+ { return this->cend(); }
+
+ BOOST_CONTAINER_FORCEINLINE reverse_iterator rbegin()
+ { return reverse_iterator(end()); }
+
+ BOOST_CONTAINER_FORCEINLINE const_reverse_iterator rbegin() const
+ { return this->crbegin(); }
+
+ BOOST_CONTAINER_FORCEINLINE reverse_iterator rend()
+ { return reverse_iterator(begin()); }
+
+ BOOST_CONTAINER_FORCEINLINE const_reverse_iterator rend() const
+ { return this->crend(); }
+
+ //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE const_iterator cbegin() const
+ { return const_iterator(this->non_const_icont().begin()); }
+
+ //! <b>Effects</b>: Returns a const_iterator to the end of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE const_iterator cend() const
+ { return const_iterator(this->non_const_icont().end()); }
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE const_reverse_iterator crbegin() const
+ { return const_reverse_iterator(cend()); }
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE const_reverse_iterator crend() const
+ { return const_reverse_iterator(cbegin()); }
+
+ BOOST_CONTAINER_FORCEINLINE bool empty() const
+ { return !this->size(); }
+
+ BOOST_CONTAINER_FORCEINLINE size_type size() const
+ { return this->icont().size(); }
+
+ BOOST_CONTAINER_FORCEINLINE size_type max_size() const
+ { return AllocHolder::max_size(); }
+
+ BOOST_CONTAINER_FORCEINLINE void swap(ThisType& x)
+ BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value
+ && boost::container::dtl::is_nothrow_swappable<Compare>::value )
+ { AllocHolder::swap(x); }
+
+ public:
+
+ typedef typename Icont::insert_commit_data insert_commit_data;
+
+ // insert/erase
+ std::pair<iterator,bool> insert_unique_check
+ (const key_type& key, insert_commit_data &data)
+ {
+ std::pair<iiterator, bool> ret =
+ this->icont().insert_unique_check(key, KeyNodeCompare(key_comp()), data);
+ return std::pair<iterator, bool>(iterator(ret.first), ret.second);
+ }
+
+ std::pair<iterator,bool> insert_unique_check
+ (const_iterator hint, const key_type& key, insert_commit_data &data)
+ {
+ BOOST_ASSERT((priv_is_linked)(hint));
+ std::pair<iiterator, bool> ret =
+ this->icont().insert_unique_check(hint.get(), key, KeyNodeCompare(key_comp()), data);
+ return std::pair<iterator, bool>(iterator(ret.first), ret.second);
+ }
+
+ template<class MovableConvertible>
+ iterator insert_unique_commit
+ (BOOST_FWD_REF(MovableConvertible) v, insert_commit_data &data)
+ {
+ 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();
+ return ret;
+ }
+
+ template<class MovableConvertible>
+ 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()(v), data);
+ if(ret.second){
+ ret.first = this->insert_unique_commit(boost::forward<MovableConvertible>(v), data);
+ }
+ return ret;
+ }
+
+ private:
+
+ template<class KeyConvertible, class M>
+ iiterator priv_insert_or_assign_commit
+ (BOOST_FWD_REF(KeyConvertible) key, BOOST_FWD_REF(M) obj, insert_commit_data &data)
+ {
+ NodePtr tmp = AllocHolder::create_node(boost::forward<KeyConvertible>(key), boost::forward<M>(obj));
+ scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());
+ iiterator ret(this->icont().insert_unique_commit(*tmp, data));
+ destroy_deallocator.release();
+ return ret;
+ }
+
+ bool priv_is_linked(const_iterator const position) const
+ {
+ iiterator const cur(position.get());
+ return cur == this->icont().end() ||
+ cur == this->icont().root() ||
+ iiterator(cur).go_parent().go_left() == cur ||
+ iiterator(cur).go_parent().go_right() == cur;
+ }
+
+ template<class MovableConvertible>
+ void push_back_impl(BOOST_FWD_REF(MovableConvertible) v)
+ {
+ 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);
+ }
+
+ std::pair<iterator, bool> emplace_unique_impl(NodePtr p)
+ {
+ value_type &v = p->get_data();
+ insert_commit_data data;
+ scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(p, this->node_alloc());
+ std::pair<iterator,bool> ret =
+ this->insert_unique_check(KeyOfValue()(v), data);
+ if(!ret.second){
+ return ret;
+ }
+ //No throw insertion part, release rollback
+ destroy_deallocator.release();
+ return std::pair<iterator,bool>
+ ( iterator(this->icont().insert_unique_commit(*p, data))
+ , true );
+ }
+
+ iterator emplace_unique_hint_impl(const_iterator hint, NodePtr p)
+ {
+ BOOST_ASSERT((priv_is_linked)(hint));
+ value_type &v = p->get_data();
+ insert_commit_data data;
+ std::pair<iterator,bool> ret =
+ this->insert_unique_check(hint, KeyOfValue()(v), data);
+ if(!ret.second){
+ Destroyer(this->node_alloc())(p);
+ return ret.first;
+ }
+ return iterator(this->icont().insert_unique_commit(*p, data));
+ }
+
+ public:
+
+ #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ template <class... Args>
+ BOOST_CONTAINER_FORCEINLINE 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>
+ BOOST_CONTAINER_FORCEINLINE 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(BOOST_FWD_REF(Args)... args)
+ {
+ NodePtr tmp(AllocHolder::create_node(boost::forward<Args>(args)...));
+ 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;
+ }
+
+ template <class... Args>
+ iterator emplace_hint_equal(const_iterator hint, BOOST_FWD_REF(Args)... args)
+ {
+ BOOST_ASSERT((priv_is_linked)(hint));
+ NodePtr tmp(AllocHolder::create_node(boost::forward<Args>(args)...));
+ scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());
+ iterator ret(this->icont().insert_equal(hint.get(), *tmp));
+ destroy_deallocator.release();
+ return ret;
+ }
+
+ template <class KeyType, class... Args>
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> try_emplace
+ (const_iterator hint, BOOST_FWD_REF(KeyType) key, BOOST_FWD_REF(Args)... args)
+ {
+ insert_commit_data data;
+ const key_type & k = key; //Support emulated rvalue references
+ std::pair<iiterator, bool> ret =
+ hint == const_iterator() ? this->icont().insert_unique_check( k, KeyNodeCompare(key_comp()), data)
+ : this->icont().insert_unique_check(hint.get(), k, KeyNodeCompare(key_comp()), data);
+ if(ret.second){
+ ret.first = this->icont().insert_unique_commit
+ (*AllocHolder::create_node(try_emplace_t(), boost::forward<KeyType>(key), boost::forward<Args>(args)...), data);
+ }
+ return std::pair<iterator, bool>(iterator(ret.first), ret.second);
+ }
+
+ #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)\
+ {\
+ BOOST_ASSERT((priv_is_linked)(hint));\
+ 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;\
+ }\
+ \
+ template <class KeyType BOOST_MOVE_I##N BOOST_MOVE_CLASS##N>\
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool>\
+ try_emplace(const_iterator hint, BOOST_FWD_REF(KeyType) key BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ {\
+ insert_commit_data data;\
+ const key_type & k = key;\
+ std::pair<iiterator, bool> ret =\
+ hint == const_iterator() ? this->icont().insert_unique_check( k, KeyNodeCompare(key_comp()), data)\
+ : this->icont().insert_unique_check(hint.get(), k, KeyNodeCompare(key_comp()), data);\
+ if(ret.second){\
+ ret.first = this->icont().insert_unique_commit\
+ (*AllocHolder::create_node(try_emplace_t(), boost::forward<KeyType>(key) BOOST_MOVE_I##N BOOST_MOVE_FWD##N), data);\
+ }\
+ return std::pair<iterator, bool>(iterator(ret.first), ret.second);\
+ }\
+ //
+ BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_TREE_EMPLACE_CODE)
+ #undef BOOST_CONTAINER_TREE_EMPLACE_CODE
+
+ #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ template<class MovableConvertible>
+ iterator insert_unique_convertible(const_iterator hint, BOOST_FWD_REF(MovableConvertible) v)
+ {
+ BOOST_ASSERT((priv_is_linked)(hint));
+ insert_commit_data data;
+ std::pair<iterator,bool> ret =
+ this->insert_unique_check(hint, KeyOfValue()(v), data);
+ if(!ret.second)
+ return ret.first;
+ return this->insert_unique_commit(boost::forward<MovableConvertible>(v), data);
+ }
+
+ BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert_unique, value_type, iterator, this->insert_unique_convertible, const_iterator, const_iterator)
+
+ template <class InputIterator>
+ void insert_unique(InputIterator first, InputIterator last)
+ {
+ for( ; first != last; ++first)
+ this->insert_unique(*first);
+ }
+
+ iterator insert_equal(const value_type& v)
+ {
+ NodePtr tmp(AllocHolder::create_node(v));
+ 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;
+ }
+
+ template<class MovableConvertible>
+ iterator insert_equal(BOOST_FWD_REF(MovableConvertible) v)
+ {
+ 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();
+ return ret;
+ }
+
+ template<class MovableConvertible>
+ iterator insert_equal_convertible(const_iterator hint, BOOST_FWD_REF(MovableConvertible) v)
+ {
+ BOOST_ASSERT((priv_is_linked)(hint));
+ 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();
+ return ret;
+ }
+
+ BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert_equal, value_type, iterator, this->insert_equal_convertible, const_iterator, const_iterator)
+
+ template <class InputIterator>
+ void insert_equal(InputIterator first, InputIterator last)
+ {
+ for( ; first != last; ++first)
+ this->insert_equal(*first);
+ }
+
+ template<class KeyType, class M>
+ std::pair<iterator, bool> insert_or_assign(const_iterator hint, BOOST_FWD_REF(KeyType) key, BOOST_FWD_REF(M) obj)
+ {
+ insert_commit_data data;
+ const key_type & k = key; //Support emulated rvalue references
+ std::pair<iiterator, bool> ret =
+ hint == const_iterator() ? this->icont().insert_unique_check(k, KeyNodeCompare(key_comp()), data)
+ : this->icont().insert_unique_check(hint.get(), k, KeyNodeCompare(key_comp()), data);
+ if(ret.second){
+ ret.first = this->priv_insert_or_assign_commit(boost::forward<KeyType>(key), boost::forward<M>(obj), data);
+ }
+ else{
+ ret.first->get_data().second = boost::forward<M>(obj);
+ }
+ return std::pair<iterator, bool>(iterator(ret.first), ret.second);
+ }
+
+ iterator erase(const_iterator position)
+ {
+ BOOST_ASSERT(position != this->cend() && (priv_is_linked)(position));
+ return iterator(this->icont().erase_and_dispose(position.get(), Destroyer(this->node_alloc())));
+ }
+
+ BOOST_CONTAINER_FORCEINLINE size_type erase(const key_type& k)
+ { return AllocHolder::erase_key(k, KeyNodeCompare(key_comp()), alloc_version()); }
+
+ iterator erase(const_iterator first, const_iterator last)
+ {
+ BOOST_ASSERT(first == last || (first != this->cend() && (priv_is_linked)(first)));
+ BOOST_ASSERT(first == last || (priv_is_linked)(last));
+ return iterator(AllocHolder::erase_range(first.get(), last.get(), alloc_version()));
+ }
+
+ node_type extract(const key_type& k)
+ {
+ iterator const it = this->find(k);
+ if(this->end() != it){
+ return this->extract(it);
+ }
+ return node_type();
+ }
+
+ node_type extract(const_iterator position)
+ {
+ BOOST_ASSERT(position != this->cend() && (priv_is_linked)(position));
+ iiterator const iit(position.get());
+ this->icont().erase(iit);
+ return node_type(iit.operator->(), this->node_alloc());
+ }
+
+ insert_return_type insert_unique_node(BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)
+ {
+ return this->insert_unique_node(this->end(), boost::move(nh));
+ }
+
+ insert_return_type insert_unique_node(const_iterator hint, BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)
+ {
+ insert_return_type irt; //inserted == false, node.empty()
+ if(!nh.empty()){
+ insert_commit_data data;
+ std::pair<iterator,bool> ret =
+ this->insert_unique_check(hint, KeyOfValue()(nh.value()), data);
+ if(ret.second){
+ irt.inserted = true;
+ irt.position = iterator(this->icont().insert_unique_commit(*nh.get(), data));
+ nh.release();
+ }
+ else{
+ irt.position = ret.first;
+ irt.node = boost::move(nh);
+ }
+ }
+ else{
+ irt.position = this->end();
+ }
+ return BOOST_MOVE_RET(insert_return_type, irt);
+ }
+
+ iterator insert_equal_node(BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)
+ {
+ if(nh.empty()){
+ return this->end();
+ }
+ else{
+ NodePtr const p(nh.release());
+ return iterator(this->icont().insert_equal(*p));
+ }
+ }
+
+ iterator insert_equal_node(const_iterator hint, BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)
+ {
+ if(nh.empty()){
+ return this->end();
+ }
+ else{
+ NodePtr const p(nh.release());
+ return iterator(this->icont().insert_equal(hint.get(), *p));
+ }
+ }
+
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge_unique(tree<T, KeyOfValue, C2, Allocator, Options>& source)
+ { return this->icont().merge_unique(source.icont()); }
+
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge_equal(tree<T, KeyOfValue, C2, Allocator, Options>& source)
+ { return this->icont().merge_equal(source.icont()); }
+ BOOST_CONTAINER_FORCEINLINE void clear()
+ { AllocHolder::clear(alloc_version()); }
+
+ // search operations. Const and non-const overloads even if no iterator is returned
+ // so splay implementations can to their rebalancing when searching in non-const versions
+ BOOST_CONTAINER_FORCEINLINE iterator find(const key_type& k)
+ { return iterator(this->icont().find(k, KeyNodeCompare(key_comp()))); }
+
+ BOOST_CONTAINER_FORCEINLINE const_iterator find(const key_type& k) const
+ { return const_iterator(this->non_const_icont().find(k, KeyNodeCompare(key_comp()))); }
+
+ template <class K>
+ BOOST_CONTAINER_FORCEINLINE
+ typename dtl::enable_if_transparent<key_compare, K, iterator>::type
+ find(const K& k)
+ { return iterator(this->icont().find(k, KeyNodeCompare(key_comp()))); }
+
+ template <class K>
+ BOOST_CONTAINER_FORCEINLINE
+ typename dtl::enable_if_transparent<key_compare, K, const_iterator>::type
+ find(const K& k) const
+ { return const_iterator(this->non_const_icont().find(k, KeyNodeCompare(key_comp()))); }
+
+ BOOST_CONTAINER_FORCEINLINE size_type count(const key_type& k) const
+ { return size_type(this->icont().count(k, KeyNodeCompare(key_comp()))); }
+
+ template <class K>
+ BOOST_CONTAINER_FORCEINLINE
+ typename dtl::enable_if_transparent<key_compare, K, size_type>::type
+ count(const K& k) const
+ { return size_type(this->icont().count(k, KeyNodeCompare(key_comp()))); }
+
+ BOOST_CONTAINER_FORCEINLINE iterator lower_bound(const key_type& k)
+ { return iterator(this->icont().lower_bound(k, KeyNodeCompare(key_comp()))); }
+
+ BOOST_CONTAINER_FORCEINLINE const_iterator lower_bound(const key_type& k) const
+ { return const_iterator(this->non_const_icont().lower_bound(k, KeyNodeCompare(key_comp()))); }
+
+ template <class K>
+ BOOST_CONTAINER_FORCEINLINE
+ typename dtl::enable_if_transparent<key_compare, K, iterator>::type
+ lower_bound(const K& k)
+ { return iterator(this->icont().lower_bound(k, KeyNodeCompare(key_comp()))); }
+
+ template <class K>
+ BOOST_CONTAINER_FORCEINLINE
+ typename dtl::enable_if_transparent<key_compare, K, const_iterator>::type
+ lower_bound(const K& k) const
+ { return const_iterator(this->non_const_icont().lower_bound(k, KeyNodeCompare(key_comp()))); }
+
+ BOOST_CONTAINER_FORCEINLINE iterator upper_bound(const key_type& k)
+ { return iterator(this->icont().upper_bound(k, KeyNodeCompare(key_comp()))); }
+
+ BOOST_CONTAINER_FORCEINLINE const_iterator upper_bound(const key_type& k) const
+ { return const_iterator(this->non_const_icont().upper_bound(k, KeyNodeCompare(key_comp()))); }
+
+ template <class K>
+ BOOST_CONTAINER_FORCEINLINE
+ typename dtl::enable_if_transparent<key_compare, K, iterator>::type
+ upper_bound(const K& k)
+ { return iterator(this->icont().upper_bound(k, KeyNodeCompare(key_comp()))); }
+
+ template <class K>
+ BOOST_CONTAINER_FORCEINLINE
+ typename dtl::enable_if_transparent<key_compare, K, const_iterator>::type
+ upper_bound(const K& k) const
+ { return const_iterator(this->non_const_icont().upper_bound(k, KeyNodeCompare(key_comp()))); }
+
+ std::pair<iterator,iterator> equal_range(const key_type& k)
+ {
+ std::pair<iiterator, iiterator> ret =
+ this->icont().equal_range(k, KeyNodeCompare(key_comp()));
+ return std::pair<iterator,iterator>(iterator(ret.first), iterator(ret.second));
+ }
+
+ std::pair<const_iterator, const_iterator> equal_range(const key_type& k) const
+ {
+ std::pair<iiterator, iiterator> ret =
+ this->non_const_icont().equal_range(k, KeyNodeCompare(key_comp()));
+ return std::pair<const_iterator,const_iterator>
+ (const_iterator(ret.first), const_iterator(ret.second));
+ }
+
+ template <class K>
+ BOOST_CONTAINER_FORCEINLINE
+ typename dtl::enable_if_transparent<key_compare, K, std::pair<iterator,iterator> >::type
+ equal_range(const K& k)
+ {
+ std::pair<iiterator, iiterator> ret =
+ this->icont().equal_range(k, KeyNodeCompare(key_comp()));
+ return std::pair<iterator,iterator>(iterator(ret.first), iterator(ret.second));
+ }
+
+ template <class K>
+ BOOST_CONTAINER_FORCEINLINE
+ typename dtl::enable_if_transparent<key_compare, K, std::pair<const_iterator, const_iterator> >::type
+ equal_range(const K& k) const
+ {
+ std::pair<iiterator, iiterator> ret =
+ this->non_const_icont().equal_range(k, KeyNodeCompare(key_comp()));
+ return std::pair<const_iterator,const_iterator>
+ (const_iterator(ret.first), const_iterator(ret.second));
+ }
+
+ std::pair<iterator,iterator> lower_bound_range(const key_type& k)
+ {
+ std::pair<iiterator, iiterator> ret =
+ this->icont().lower_bound_range(k, KeyNodeCompare(key_comp()));
+ return std::pair<iterator,iterator>(iterator(ret.first), iterator(ret.second));
+ }
+
+ std::pair<const_iterator, const_iterator> lower_bound_range(const key_type& k) const
+ {
+ std::pair<iiterator, iiterator> ret =
+ this->non_const_icont().lower_bound_range(k, KeyNodeCompare(key_comp()));
+ return std::pair<const_iterator,const_iterator>
+ (const_iterator(ret.first), const_iterator(ret.second));
+ }
+
+ template <class K>
+ BOOST_CONTAINER_FORCEINLINE
+ typename dtl::enable_if_transparent<key_compare, K, std::pair<iterator,iterator> >::type
+ lower_bound_range(const K& k)
+ {
+ std::pair<iiterator, iiterator> ret =
+ this->icont().lower_bound_range(k, KeyNodeCompare(key_comp()));
+ return std::pair<iterator,iterator>(iterator(ret.first), iterator(ret.second));
+ }
+
+ template <class K>
+ BOOST_CONTAINER_FORCEINLINE
+ typename dtl::enable_if_transparent<key_compare, K, std::pair<const_iterator, const_iterator> >::type
+ lower_bound_range(const K& k) const
+ {
+ std::pair<iiterator, iiterator> ret =
+ this->non_const_icont().lower_bound_range(k, KeyNodeCompare(key_comp()));
+ return std::pair<const_iterator,const_iterator>
+ (const_iterator(ret.first), const_iterator(ret.second));
+ }
+
+ BOOST_CONTAINER_FORCEINLINE void rebalance()
+ { intrusive_tree_proxy_t::rebalance(this->icont()); }
+
+ BOOST_CONTAINER_FORCEINLINE friend bool operator==(const tree& x, const tree& y)
+ { return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin()); }
+
+ BOOST_CONTAINER_FORCEINLINE friend bool operator<(const tree& x, const tree& y)
+ { return ::boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
+
+ BOOST_CONTAINER_FORCEINLINE friend bool operator!=(const tree& x, const tree& y)
+ { return !(x == y); }
+
+ BOOST_CONTAINER_FORCEINLINE friend bool operator>(const tree& x, const tree& y)
+ { return y < x; }
+
+ BOOST_CONTAINER_FORCEINLINE friend bool operator<=(const tree& x, const tree& y)
+ { return !(y < x); }
+
+ BOOST_CONTAINER_FORCEINLINE friend bool operator>=(const tree& x, const tree& y)
+ { return !(x < y); }
+
+ BOOST_CONTAINER_FORCEINLINE friend void swap(tree& x, tree& y)
+ { x.swap(y); }
+};
+
+} //namespace dtl {
+} //namespace container {
+
+template <class T>
+struct has_trivial_destructor_after_move;
+
+//!has_trivial_destructor_after_move<> == true_type
+//!specialization for optimizations
+template <class T, class KeyOfValue, class Compare, class Allocator, class Options>
+struct has_trivial_destructor_after_move
+ <
+ ::boost::container::dtl::tree
+ <T, KeyOfValue, Compare, Allocator, Options>
+ >
+{
+ 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>
+
+#endif //BOOST_CONTAINER_TREE_HPP
diff --git a/include/boost/container/detail/type_traits.hpp b/include/boost/container/detail/type_traits.hpp
new file mode 100644
index 0000000..686cc40
--- /dev/null
+++ b/include/boost/container/detail/type_traits.hpp
@@ -0,0 +1,70 @@
+//////////////////////////////////////////////////////////////////////////////
+// (C) Copyright John Maddock 2000.
+// (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
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+// 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
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/move/detail/type_traits.hpp>
+
+namespace boost {
+namespace container {
+namespace dtl {
+
+using ::boost::move_detail::enable_if;
+using ::boost::move_detail::enable_if_and;
+using ::boost::move_detail::is_same;
+using ::boost::move_detail::is_different;
+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 dtl {
+} //namespace container {
+} //namespace boost {
+
+#endif //#ifndef BOOST_CONTAINER_CONTAINER_DETAIL_TYPE_TRAITS_HPP
diff --git a/include/boost/container/detail/value_functors.hpp b/include/boost/container/detail/value_functors.hpp
new file mode 100644
index 0000000..a2c494c
--- /dev/null
+++ b/include/boost/container/detail/value_functors.hpp
@@ -0,0 +1,36 @@
+#ifndef BOOST_CONTAINER_DETAIL_VALUE_FUNCTORS_HPP
+#define BOOST_CONTAINER_DETAIL_VALUE_FUNCTORS_HPP
+///////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2017-2017. 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_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+//Functors for member algorithm defaults
+template<class ValueType>
+struct value_less
+{
+ bool operator()(const ValueType &a, const ValueType &b) const
+ { return a < b; }
+};
+
+template<class ValueType>
+struct value_equal
+{
+ bool operator()(const ValueType &a, const ValueType &b) const
+ { return a == b; }
+};
+
+#endif //BOOST_CONTAINER_DETAIL_VALUE_FUNCTORS_HPP
diff --git a/include/boost/container/detail/value_init.hpp b/include/boost/container/detail/value_init.hpp
new file mode 100644
index 0000000..35b0aa1
--- /dev/null
+++ b/include/boost/container/detail/value_init.hpp
@@ -0,0 +1,51 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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_VALUE_INIT_HPP
+#define BOOST_CONTAINER_DETAIL_VALUE_INIT_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+
+namespace boost {
+namespace container {
+namespace dtl {
+
+template<class T>
+struct value_init
+{
+ value_init()
+ : m_t()
+ {}
+
+ operator T &() { return m_t; }
+
+ T &get() { return m_t; }
+
+ T m_t;
+};
+
+} //namespace dtl {
+} //namespace container {
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_CONTAINER_DETAIL_VALUE_INIT_HPP
diff --git a/include/boost/container/detail/variadic_templates_tools.hpp b/include/boost/container/detail/variadic_templates_tools.hpp
new file mode 100644
index 0000000..4f16fb0
--- /dev/null
+++ b/include/boost/container/detail/variadic_templates_tools.hpp
@@ -0,0 +1,163 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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_VARIADIC_TEMPLATES_TOOLS_HPP
+#define BOOST_CONTAINER_DETAIL_VARIADIC_TEMPLATES_TOOLS_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/move/utility_core.hpp>
+
+#include <boost/container/detail/type_traits.hpp>
+#include <cstddef> //std::size_t
+
+namespace boost {
+namespace container {
+namespace dtl {
+
+template<typename... Values>
+class tuple;
+
+template<> class tuple<>
+{};
+
+template<typename Head, typename... Tail>
+class tuple<Head, Tail...>
+ : private tuple<Tail...>
+{
+ typedef tuple<Tail...> inherited;
+
+ public:
+ tuple()
+ : inherited(), m_head()
+ {}
+
+ template<class U, class ...Args>
+ tuple(U &&u, Args && ...args)
+ : inherited(::boost::forward<Args>(args)...), m_head(::boost::forward<U>(u))
+ {}
+
+ // Construct tuple from another tuple.
+ template<typename... VValues>
+ tuple(const tuple<VValues...>& other)
+ : inherited(other.tail()), m_head(other.head())
+ {}
+
+ template<typename... VValues>
+ tuple& operator=(const tuple<VValues...>& other)
+ {
+ m_head = other.head();
+ tail() = other.tail();
+ return this;
+ }
+
+ typename add_reference<Head>::type head() { return m_head; }
+ typename add_reference<const Head>::type head() const { return m_head; }
+
+ inherited& tail() { return *this; }
+ const inherited& tail() const { return *this; }
+
+ protected:
+ Head m_head;
+};
+
+
+template<typename... Values>
+tuple<Values&&...> forward_as_tuple_impl(Values&&... values)
+{ return tuple<Values&&...>(::boost::forward<Values>(values)...); }
+
+template<int I, typename Tuple>
+struct tuple_element;
+
+template<int I, typename Head, typename... Tail>
+struct tuple_element<I, tuple<Head, Tail...> >
+{
+ typedef typename tuple_element<I-1, tuple<Tail...> >::type type;
+};
+
+template<typename Head, typename... Tail>
+struct tuple_element<0, tuple<Head, Tail...> >
+{
+ typedef Head type;
+};
+
+template<int I, typename Tuple>
+class get_impl;
+
+template<int I, typename Head, typename... Values>
+class get_impl<I, tuple<Head, Values...> >
+{
+ typedef typename tuple_element<I-1, tuple<Values...> >::type Element;
+ typedef get_impl<I-1, tuple<Values...> > Next;
+
+ public:
+ typedef typename add_reference<Element>::type type;
+ typedef typename add_const_reference<Element>::type const_type;
+ static type get(tuple<Head, Values...>& t) { return Next::get(t.tail()); }
+ static const_type get(const tuple<Head, Values...>& t) { return Next::get(t.tail()); }
+};
+
+template<typename Head, typename... Values>
+class get_impl<0, tuple<Head, Values...> >
+{
+ public:
+ typedef typename add_reference<Head>::type type;
+ typedef typename add_const_reference<Head>::type const_type;
+ static type get(tuple<Head, Values...>& t) { return t.head(); }
+ static const_type get(const tuple<Head, Values...>& t){ return t.head(); }
+};
+
+template<int I, typename... Values>
+typename get_impl<I, tuple<Values...> >::type get(tuple<Values...>& t)
+{ return get_impl<I, tuple<Values...> >::get(t); }
+
+template<int I, typename... Values>
+typename get_impl<I, tuple<Values...> >::const_type get(const tuple<Values...>& t)
+{ return get_impl<I, tuple<Values...> >::get(t); }
+
+////////////////////////////////////////////////////
+// Builds an index_tuple<0, 1, 2, ..., Num-1>, that will
+// be used to "unpack" into comma-separated values
+// in a function call.
+////////////////////////////////////////////////////
+
+template<std::size_t...> struct index_tuple{ typedef index_tuple type; };
+
+template<class S1, class S2> struct concat_index_tuple;
+
+template<std::size_t... I1, std::size_t... I2>
+struct concat_index_tuple<index_tuple<I1...>, index_tuple<I2...>>
+ : index_tuple<I1..., (sizeof...(I1)+I2)...>{};
+
+template<std::size_t N> struct build_number_seq;
+
+template<std::size_t N>
+struct build_number_seq
+ : concat_index_tuple<typename build_number_seq<N/2>::type
+ ,typename build_number_seq<N - N/2 >::type
+ >::type
+{};
+
+template<> struct build_number_seq<0> : index_tuple<>{};
+template<> struct build_number_seq<1> : index_tuple<0>{};
+
+}}} //namespace boost { namespace container { namespace dtl {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_CONTAINER_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
diff --git a/include/boost/container/detail/version_type.hpp b/include/boost/container/detail/version_type.hpp
new file mode 100644
index 0000000..c2531cc
--- /dev/null
+++ b/include/boost/container/detail/version_type.hpp
@@ -0,0 +1,110 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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.
+//
+//////////////////////////////////////////////////////////////////////////////
+//
+// This code comes from N1953 document by Howard E. Hinnant
+//
+//////////////////////////////////////////////////////////////////////////////
+
+
+#ifndef BOOST_CONTAINER_DETAIL_VERSION_TYPE_HPP
+#define BOOST_CONTAINER_DETAIL_VERSION_TYPE_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/detail/mpl.hpp>
+#include <boost/container/detail/type_traits.hpp>
+
+namespace boost{
+namespace container {
+namespace dtl {
+
+template <class T, unsigned V>
+struct version_type
+ : public dtl::integral_constant<unsigned, V>
+{
+ typedef T type;
+
+ version_type(const version_type<T, 0>&);
+};
+
+namespace impl{
+
+template <class T,
+ bool = dtl::is_convertible<version_type<T, 0>, typename T::version>::value>
+struct extract_version
+{
+ static const unsigned value = 1;
+};
+
+template <class T>
+struct extract_version<T, true>
+{
+ static const unsigned value = T::version::value;
+};
+
+template <class T>
+struct has_version
+{
+ private:
+ struct two {char _[2];};
+ template <class U> static two test(...);
+ template <class U> static char test(const typename U::version*);
+ public:
+ static const bool value = sizeof(test<T>(0)) == 1;
+ void dummy(){}
+};
+
+template <class T, bool = has_version<T>::value>
+struct version
+{
+ static const unsigned value = 1;
+};
+
+template <class T>
+struct version<T, true>
+{
+ static const unsigned value = extract_version<T>::value;
+};
+
+} //namespace impl
+
+template <class T>
+struct version
+ : public dtl::integral_constant<unsigned, impl::version<T>::value>
+{};
+
+template<class T, unsigned N>
+struct is_version
+{
+ static const bool value =
+ is_same< typename version<T>::type, integral_constant<unsigned, N> >::value;
+};
+
+} //namespace dtl {
+
+typedef dtl::integral_constant<unsigned, 0> version_0;
+typedef dtl::integral_constant<unsigned, 1> version_1;
+typedef dtl::integral_constant<unsigned, 2> version_2;
+
+} //namespace container {
+} //namespace boost{
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //#define BOOST_CONTAINER_DETAIL_VERSION_TYPE_HPP
diff --git a/include/boost/container/detail/workaround.hpp b/include/boost/container/detail/workaround.hpp
new file mode 100644
index 0000000..736326b
--- /dev/null
+++ b/include/boost/container/detail/workaround.hpp
@@ -0,0 +1,111 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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_WORKAROUND_HPP
+#define BOOST_CONTAINER_DETAIL_WORKAROUND_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)\
+ && !defined(BOOST_INTERPROCESS_DISABLE_VARIADIC_TMPL)
+ #define BOOST_CONTAINER_PERFECT_FORWARDING
+#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
+#endif
+
+#if defined(BOOST_GCC_VERSION)
+# if (BOOST_GCC_VERSION < 40700) || !defined(BOOST_GCC_CXX11)
+# define BOOST_CONTAINER_NO_CXX11_DELEGATING_CONSTRUCTORS
+# endif
+#elif defined(BOOST_MSVC)
+# if _MSC_FULL_VER < 180020827
+# define BOOST_CONTAINER_NO_CXX11_DELEGATING_CONSTRUCTORS
+# endif
+#elif defined(BOOST_CLANG)
+# if !__has_feature(cxx_delegating_constructors)
+# define BOOST_CONTAINER_NO_CXX11_DELEGATING_CONSTRUCTORS
+# endif
+#endif
+
+#if defined(BOOST_MSVC) && (_MSC_VER < 1400)
+ #define BOOST_CONTAINER_TEMPLATED_CONVERSION_OPERATOR_BROKEN
+#endif
+
+#if !defined(BOOST_NO_CXX11_HDR_TUPLE) || (defined(BOOST_MSVC) && (BOOST_MSVC == 1700 || BOOST_MSVC == 1600))
+#define BOOST_CONTAINER_PAIR_TEST_HAS_HEADER_TUPLE
+#endif
+
+//Macros for documentation purposes. For code, expands to the argument
+#define BOOST_CONTAINER_IMPDEF(TYPE) TYPE
+#define BOOST_CONTAINER_SEEDOC(TYPE) TYPE
+
+//Macros for memset optimization. In most platforms
+//memsetting pointers and floatings is safe and faster.
+//
+//If your platform does not offer these guarantees
+//define these to value zero.
+#ifndef BOOST_CONTAINER_MEMZEROED_FLOATING_POINT_IS_NOT_ZERO
+#define BOOST_CONTAINER_MEMZEROED_FLOATING_POINT_IS_ZERO 1
+#endif
+
+#ifndef BOOST_CONTAINER_MEMZEROED_POINTER_IS_NOT_NULL
+#define BOOST_CONTAINER_MEMZEROED_POINTER_IS_NULL
+#endif
+
+#define BOOST_CONTAINER_DOC1ST(TYPE1, TYPE2) TYPE2
+#define BOOST_CONTAINER_I ,
+#define BOOST_CONTAINER_DOCIGN(T) T
+#define BOOST_CONTAINER_DOCONLY(T)
+
+/*
+ we need to import/export our code only if the user has specifically
+ asked for it by defining either BOOST_ALL_DYN_LINK if they want all boost
+ libraries to be dynamically linked, or BOOST_CONTAINER_DYN_LINK
+ if they want just this one to be dynamically liked:
+*/
+#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_CONTAINER_DYN_LINK)
+
+ /* export if this is our own source, otherwise import: */
+ #ifdef BOOST_CONTAINER_SOURCE
+ # define BOOST_CONTAINER_DECL BOOST_SYMBOL_EXPORT
+ #else
+ # define BOOST_CONTAINER_DECL BOOST_SYMBOL_IMPORT
+
+ #endif /* BOOST_CONTAINER_SOURCE */
+#else
+ #define BOOST_CONTAINER_DECL
+#endif /* DYN_LINK */
+
+//#define BOOST_CONTAINER_DISABLE_FORCEINLINE
+
+#if defined(BOOST_CONTAINER_DISABLE_FORCEINLINE)
+ #define BOOST_CONTAINER_FORCEINLINE inline
+#elif defined(BOOST_CONTAINER_FORCEINLINE_IS_BOOST_FORCELINE)
+ #define BOOST_CONTAINER_FORCEINLINE BOOST_FORCEINLINE
+#elif defined(BOOST_MSVC) && defined(_DEBUG)
+ //"__forceinline" and MSVC seems to have some bugs in debug mode
+ #define BOOST_CONTAINER_FORCEINLINE inline
+#elif defined(__GNUC__) && ((__GNUC__ < 4) || (__GNUC__ == 4 && (__GNUC_MINOR__ < 5)))
+ //Older GCCs have problems with forceinline
+ #define BOOST_CONTAINER_FORCEINLINE inline
+#else
+ #define BOOST_CONTAINER_FORCEINLINE BOOST_FORCEINLINE
+#endif
+
+#endif //#ifndef BOOST_CONTAINER_DETAIL_WORKAROUND_HPP
diff --git a/include/boost/container/flat_map.hpp b/include/boost/container/flat_map.hpp
new file mode 100644
index 0000000..9679946
--- /dev/null
+++ b/include/boost/container/flat_map.hpp
@@ -0,0 +1,2890 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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_FLAT_MAP_HPP
+#define BOOST_CONTAINER_FLAT_MAP_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+// container
+#include <boost/container/allocator_traits.hpp>
+#include <boost/container/container_fwd.hpp>
+#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/container/detail/type_traits.hpp>
+#include <boost/container/detail/mpl.hpp>
+#include <boost/container/detail/algorithm.hpp> //equal()
+#include <boost/container/detail/container_or_allocator_rebind.hpp>
+// move
+#include <boost/move/utility_core.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)
+#include <initializer_list>
+#endif
+
+namespace boost {
+namespace container {
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+template <class Key, class T, class Compare, class AllocatorOrContainer>
+class flat_multimap;
+
+namespace dtl{
+
+template<class D, class S>
+BOOST_CONTAINER_FORCEINLINE static D &force(S &s)
+{ return *reinterpret_cast<D*>(&s); }
+
+template<class D, class S>
+BOOST_CONTAINER_FORCEINLINE static D force_copy(const S &s)
+{
+ const D *const vp = reinterpret_cast<const D *>(&s);
+ D ret_val(*vp);
+ return ret_val;
+}
+
+} //namespace dtl{
+
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+//! A flat_map is a kind of associative container that supports unique keys (contains at
+//! most one of each key value) and provides for fast retrieval of values of another
+//! type T based on the keys.
+//!
+//! A flat_map satisfies all of the requirements of a container, a reversible
+//! container and an associative container. A flat_map also provides
+//! most operations described for unique keys. For a
+//! flat_map<Key,T> the key_type is Key and the value_type is std::pair<Key,T>
+//! (unlike std::map<Key, T> which value_type is std::pair<<b>const</b> Key, T>).
+//!
+//! flat_map is similar to std::map but it's implemented by as an ordered sequence container.
+//! The underlying sequence container is by default <i>vector</i> but it can also work
+//! user-provided vector-like SequenceContainers (like <i>static_vector</i> or <i>small_vector</i>).
+//!
+//! Using vector-like sequence containers means that inserting a new element into a flat_map might invalidate
+//! previous iterators and references (unless that sequence container is <i>stable_vector</i> or a similar
+//! container that offers stable pointers and references). Similarly, erasing an element might invalidate
+//! iterators and references pointing to elements that come after (their keys are bigger) the erased element.
+//!
+//! This container provides random-access iterators.
+//!
+//! \tparam Key is the key_type of the map
+//! \tparam Value is the <code>mapped_type</code>
+//! \tparam Compare is the ordering function for Keys (e.g. <i>std::less<Key></i>).
+//! \tparam AllocatorOrContainer is either:
+//! - The allocator to allocate <code>value_type</code>s (e.g. <i>allocator< std::pair<Key, T> > </i>).
+//! (in this case <i>sequence_type</i> will be vector<value_type, AllocatorOrContainer>)
+//! - The SequenceContainer to be used as the underlying <i>sequence_type</i>. It must be a vector-like
+//! sequence container with random-access iterators..
+#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
+template <class Key, class T, class Compare = std::less<Key>, class AllocatorOrContainer = new_allocator< std::pair< Key, T> > >
+#else
+template <class Key, class T, class Compare, class AllocatorOrContainer>
+#endif
+class flat_map
+{
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ private:
+ BOOST_COPYABLE_AND_MOVABLE(flat_map)
+ //This is the tree that we should store if pair was movable
+ typedef dtl::flat_tree<
+ std::pair<Key, T>,
+ dtl::select1st<Key>,
+ Compare,
+ AllocatorOrContainer> tree_t;
+
+ //This is the real tree stored here. It's based on a movable pair
+ typedef dtl::flat_tree<
+ dtl::pair<Key, T>,
+ dtl::select1st<Key>,
+ Compare,
+ typename dtl::container_or_allocator_rebind<AllocatorOrContainer, dtl::pair<Key, T> >::type
+ > impl_tree_t;
+ impl_tree_t m_flat_tree; // flat tree representing 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;
+ #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ typedef std::initializer_list<impl_value_type> impl_initializer_list;
+ #endif
+
+ typedef dtl::flat_tree_value_compare
+ < Compare
+ , dtl::select1st<Key>
+ , std::pair<Key, T> > value_compare_t;
+ typedef typename tree_t::iterator iterator_t;
+ typedef typename tree_t::const_iterator const_iterator_t;
+ typedef typename tree_t::reverse_iterator reverse_iterator_t;
+ typedef typename tree_t::const_reverse_iterator const_reverse_iterator_t;
+
+ public:
+ typedef typename impl_tree_t::stored_allocator_type impl_stored_allocator_type;
+ typedef typename impl_tree_t::sequence_type impl_sequence_type;
+
+ BOOST_CONTAINER_FORCEINLINE impl_tree_t &tree()
+ { return m_flat_tree; }
+
+ BOOST_CONTAINER_FORCEINLINE const impl_tree_t &tree() const
+ { return m_flat_tree; }
+
+ private:
+ typedef typename tree_t::get_stored_allocator_const_return_t get_stored_allocator_const_return_t;
+ typedef typename tree_t::get_stored_allocator_noconst_return_t get_stored_allocator_noconst_return_t;
+ typedef typename impl_tree_t::get_stored_allocator_const_return_t impl_get_stored_allocator_const_return_t;
+ typedef typename impl_tree_t::get_stored_allocator_noconst_return_t impl_get_stored_allocator_noconst_return_t;
+
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ public:
+
+ //////////////////////////////////////////////
+ //
+ // types
+ //
+ //////////////////////////////////////////////
+ typedef Key key_type;
+ typedef T mapped_type;
+ typedef Compare key_compare;
+ typedef std::pair<Key, T> value_type;
+ typedef typename BOOST_CONTAINER_IMPDEF(tree_t::sequence_type) sequence_type;
+ typedef typename sequence_type::allocator_type allocator_type;
+ typedef ::boost::container::allocator_traits<allocator_type> allocator_traits_type;
+ typedef typename sequence_type::pointer pointer;
+ typedef typename sequence_type::const_pointer const_pointer;
+ typedef typename sequence_type::reference reference;
+ typedef typename sequence_type::const_reference const_reference;
+ typedef typename sequence_type::size_type size_type;
+ typedef typename sequence_type::difference_type difference_type;
+ typedef typename BOOST_CONTAINER_IMPDEF(tree_t::stored_allocator_type) stored_allocator_type;
+ typedef typename BOOST_CONTAINER_IMPDEF(tree_t::value_compare) value_compare;
+
+ typedef typename sequence_type::iterator iterator;
+ typedef typename sequence_type::const_iterator const_iterator;
+ typedef typename sequence_type::reverse_iterator reverse_iterator;
+ typedef typename sequence_type::const_reverse_iterator const_reverse_iterator;
+ typedef BOOST_CONTAINER_IMPDEF(impl_value_type) movable_value_type;
+
+ //AllocatorOrContainer::value_type must be std::pair<Key, T>
+ BOOST_STATIC_ASSERT((dtl::is_same<std::pair<Key, T>, typename allocator_type::value_type>::value));
+
+ //////////////////////////////////////////////
+ //
+ // construct/copy/destroy
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Default constructs an empty flat_map.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE flat_map() BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<AllocatorOrContainer>::value &&
+ dtl::is_nothrow_default_constructible<Compare>::value)
+ : m_flat_tree()
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified allocator.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE explicit flat_map(const allocator_type& a)
+ : m_flat_tree(dtl::force<const impl_allocator_type>(a))
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified
+ //! comparison object.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE explicit flat_map(const Compare& comp)
+ : m_flat_tree(comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified
+ //! comparison object and allocator.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE flat_map(const Compare& comp, const allocator_type& a)
+ : m_flat_tree(comp, dtl::force<const impl_allocator_type>(a))
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map and
+ //! and inserts elements from the range [first ,last ).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE flat_map(InputIterator first, InputIterator last)
+ : m_flat_tree(true, first, last)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified
+ //! allocator, and inserts elements from the range [first ,last ).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE flat_map(InputIterator first, InputIterator last, const allocator_type& a)
+ : m_flat_tree(true, first, last, dtl::force<const impl_allocator_type>(a))
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
+ //! and inserts elements from the range [first ,last ).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE flat_map(InputIterator first, InputIterator last, const Compare& comp)
+ : m_flat_tree(true, first, last, comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
+ //! allocator, and inserts elements from the range [first ,last ).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE flat_map(InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
+ : m_flat_tree(true, first, last, comp, dtl::force<const impl_allocator_type>(a))
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map
+ //! and inserts elements from the ordered range [first ,last). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_map(ordered_unique_range_t, InputIterator first, InputIterator last)
+ : m_flat_tree(ordered_range, first, last)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
+ //! inserts elements from the ordered range [first ,last). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_map(ordered_unique_range_t, InputIterator first, InputIterator last, const Compare& comp)
+ : m_flat_tree(ordered_range, first, last, comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
+ //! allocator, and inserts elements from the ordered range [first ,last). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_map(ordered_unique_range_t, InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
+ : m_flat_tree(ordered_range, first, last, comp, dtl::force<const impl_allocator_type>(a))
+ {}
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Constructs an empty flat_map and
+ //! inserts elements from the range [il.begin() ,il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ BOOST_CONTAINER_FORCEINLINE flat_map(std::initializer_list<value_type> il)
+ : m_flat_tree( true
+ , dtl::force<impl_initializer_list>(il).begin()
+ , dtl::force<impl_initializer_list>(il).end())
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified
+ //! allocator, and inserts elements from the range [il.begin() ,il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ BOOST_CONTAINER_FORCEINLINE flat_map(std::initializer_list<value_type> il, const allocator_type& a)
+ : m_flat_tree( true
+ , dtl::force<impl_initializer_list>(il).begin()
+ , dtl::force<impl_initializer_list>(il).end()
+ , dtl::force<const impl_allocator_type>(a))
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
+ //! inserts elements from the range [il.begin() ,il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ BOOST_CONTAINER_FORCEINLINE flat_map(std::initializer_list<value_type> il, const Compare& comp)
+ : m_flat_tree(true
+ , dtl::force<impl_initializer_list>(il).begin()
+ , dtl::force<impl_initializer_list>(il).end()
+ , comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
+ //! allocator, and inserts elements from the range [il.begin() ,il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ BOOST_CONTAINER_FORCEINLINE flat_map(std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
+ : m_flat_tree(true
+ , dtl::force<impl_initializer_list>(il).begin()
+ , dtl::force<impl_initializer_list>(il).end()
+ , comp
+ , dtl::force<const impl_allocator_type>(a))
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using and
+ //! inserts elements from the ordered unique range [il.begin(), il.end()). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be
+ //! unique values.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE flat_map(ordered_unique_range_t, std::initializer_list<value_type> il)
+ : m_flat_tree(ordered_unique_range
+ , dtl::force<impl_initializer_list>(il).begin()
+ , dtl::force<impl_initializer_list>(il).end())
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
+ //! inserts elements from the ordered unique range [il.begin(), il.end()). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be
+ //! unique values.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE flat_map(ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp)
+ : m_flat_tree(ordered_unique_range
+ , dtl::force<impl_initializer_list>(il).begin()
+ , dtl::force<impl_initializer_list>(il).end()
+ , comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
+ //! allocator, and inserts elements from the ordered unique range [il.begin(), il.end()). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be
+ //! unique values.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE flat_map(ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
+ : m_flat_tree( ordered_unique_range
+ , dtl::force<impl_initializer_list>(il).begin()
+ , dtl::force<impl_initializer_list>(il).end()
+ , comp
+ , dtl::force<const impl_allocator_type>(a))
+ {}
+#endif
+
+ //! <b>Effects</b>: Copy constructs a flat_map.
+ //!
+ //! <b>Complexity</b>: Linear in x.size().
+ BOOST_CONTAINER_FORCEINLINE flat_map(const flat_map& x)
+ : m_flat_tree(x.m_flat_tree)
+ {}
+
+ //! <b>Effects</b>: Move constructs a flat_map.
+ //! Constructs *this using x's resources.
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Postcondition</b>: x is emptied.
+ BOOST_CONTAINER_FORCEINLINE flat_map(BOOST_RV_REF(flat_map) x)
+ BOOST_NOEXCEPT_IF(boost::container::dtl::is_nothrow_move_constructible<Compare>::value)
+ : m_flat_tree(boost::move(x.m_flat_tree))
+ {}
+
+ //! <b>Effects</b>: Copy constructs a flat_map using the specified allocator.
+ //!
+ //! <b>Complexity</b>: Linear in x.size().
+ BOOST_CONTAINER_FORCEINLINE flat_map(const flat_map& x, const allocator_type &a)
+ : m_flat_tree(x.m_flat_tree, dtl::force<const impl_allocator_type>(a))
+ {}
+
+ //! <b>Effects</b>: Move constructs a flat_map using the specified allocator.
+ //! Constructs *this using x's resources.
+ //!
+ //! <b>Complexity</b>: Constant if x.get_allocator() == a, linear otherwise.
+ BOOST_CONTAINER_FORCEINLINE flat_map(BOOST_RV_REF(flat_map) x, const allocator_type &a)
+ : m_flat_tree(boost::move(x.m_flat_tree), dtl::force<const impl_allocator_type>(a))
+ {}
+
+ //! <b>Effects</b>: Makes *this a copy of x.
+ //!
+ //! <b>Complexity</b>: Linear in x.size().
+ BOOST_CONTAINER_FORCEINLINE flat_map& operator=(BOOST_COPY_ASSIGN_REF(flat_map) x)
+ { m_flat_tree = x.m_flat_tree; return *this; }
+
+ //! <b>Effects</b>: Move constructs a flat_map.
+ //! Constructs *this using x's resources.
+ //!
+ //! <b>Throws</b>: If allocator_traits_type::propagate_on_container_move_assignment
+ //! is false and (allocation throws or value_type's move constructor throws)
+ //!
+ //! <b>Complexity</b>: Constant if allocator_traits_type::
+ //! propagate_on_container_move_assignment is true or
+ //! this->get>allocator() == x.get_allocator(). Linear otherwise.
+ BOOST_CONTAINER_FORCEINLINE flat_map& operator=(BOOST_RV_REF(flat_map) x)
+ BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value ||
+ allocator_traits_type::is_always_equal::value) &&
+ boost::container::dtl::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)
+ //! <b>Effects</b>: Assign elements from il to *this
+ flat_map& operator=(std::initializer_list<value_type> il)
+ {
+ this->clear();
+ this->insert(il.begin(), il.end());
+ return *this;
+ }
+#endif
+
+ //! <b>Effects</b>: Returns a copy of the allocator that
+ //! was passed to the object's constructor.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE allocator_type get_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<allocator_type>(m_flat_tree.get_allocator()); }
+
+ //! <b>Effects</b>: Returns a reference to the internal allocator.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE get_stored_allocator_noconst_return_t get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ impl_get_stored_allocator_noconst_return_t r = m_flat_tree.get_stored_allocator();
+ return dtl::force<stored_allocator_type>(r);
+ }
+
+ //! <b>Effects</b>: Returns a reference to the internal allocator.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE get_stored_allocator_const_return_t get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ impl_get_stored_allocator_const_return_t r = m_flat_tree.get_stored_allocator();
+ return dtl::force<const stored_allocator_type>(r);
+ }
+
+ //////////////////////////////////////////////
+ //
+ // iterators
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Returns an iterator to the first element contained in the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE iterator begin() BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<iterator>(m_flat_tree.begin()); }
+
+ //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<const_iterator>(m_flat_tree.begin()); }
+
+ //! <b>Effects</b>: Returns an iterator to the end of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE iterator end() BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<iterator>(m_flat_tree.end()); }
+
+ //! <b>Effects</b>: Returns a const_iterator to the end of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<const_iterator>(m_flat_tree.end()); }
+
+ //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<reverse_iterator>(m_flat_tree.rbegin()); }
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<const_reverse_iterator>(m_flat_tree.rbegin()); }
+
+ //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<reverse_iterator>(m_flat_tree.rend()); }
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<const_reverse_iterator>(m_flat_tree.rend()); }
+
+ //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<const_iterator>(m_flat_tree.cbegin()); }
+
+ //! <b>Effects</b>: Returns a const_iterator to the end of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<const_iterator>(m_flat_tree.cend()); }
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<const_reverse_iterator>(m_flat_tree.crbegin()); }
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<const_reverse_iterator>(m_flat_tree.crend()); }
+
+ //////////////////////////////////////////////
+ //
+ // capacity
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Returns true if the container contains no elements.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE bool empty() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return m_flat_tree.empty(); }
+
+ //! <b>Effects</b>: Returns the number of the elements contained in the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE size_type size() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return m_flat_tree.size(); }
+
+ //! <b>Effects</b>: Returns the largest possible size of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return m_flat_tree.max_size(); }
+
+ //! <b>Effects</b>: Number of elements for which memory has been allocated.
+ //! capacity() is always greater than or equal to size().
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return m_flat_tree.capacity(); }
+
+ //! <b>Effects</b>: If n is less than or equal to capacity(), or the
+ //! underlying container has no `reserve` member, this call has no
+ //! effect. Otherwise, it is a request for allocation of additional memory.
+ //! If the request is successful, then capacity() is greater than or equal to
+ //! n; otherwise, capacity() is unchanged. In either case, size() is unchanged.
+ //!
+ //! <b>Throws</b>: If memory allocation allocation throws or T's copy constructor throws.
+ //!
+ //! <b>Note</b>: If capacity() is less than "cnt", iterators and references to
+ //! to values might be invalidated.
+ BOOST_CONTAINER_FORCEINLINE void reserve(size_type cnt)
+ { m_flat_tree.reserve(cnt); }
+
+ //! <b>Effects</b>: Tries to deallocate the excess of memory created
+ // with previous allocations. The size of the vector is unchanged
+ //!
+ //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to size().
+ BOOST_CONTAINER_FORCEINLINE void shrink_to_fit()
+ { m_flat_tree.shrink_to_fit(); }
+
+ //////////////////////////////////////////////
+ //
+ // element access
+ //
+ //////////////////////////////////////////////
+
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ //! Effects: If there is no key equivalent to x in the flat_map, inserts
+ //! value_type(x, T()) into the flat_map.
+ //!
+ //! Returns: A reference to the mapped_type corresponding to x in *this.
+ //!
+ //! Complexity: Logarithmic.
+ mapped_type &operator[](const key_type& k);
+
+ //! 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: A reference to the mapped_type corresponding to x in *this.
+ //!
+ //! Complexity: Logarithmic.
+ mapped_type &operator[](key_type &&k) ;
+ #elif defined(BOOST_MOVE_HELPERS_RETURN_SFINAE_BROKEN)
+ //in compilers like GCC 3.4, we can't catch temporaries
+ BOOST_CONTAINER_FORCEINLINE mapped_type& operator[](const key_type &k) { return this->priv_subscript(k); }
+ BOOST_CONTAINER_FORCEINLINE mapped_type& operator[](BOOST_RV_REF(key_type) k) { return this->priv_subscript(::boost::move(k)); }
+ #else
+ BOOST_MOVE_CONVERSION_AWARE_CATCH( operator[] , key_type, mapped_type&, this->priv_subscript)
+ #endif
+
+ //! Effects: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
+ //! to the mapped_type corresponding to the key k. If the key does not exist, inserts the new value
+ //! as if by insert, constructing it from value_type(k, forward<M>(obj)).
+ //!
+ //! No iterators or references are invalidated. If the insertion is successful, pointers and references
+ //! to the element obtained while it is held in the node handle are invalidated, and pointers and
+ //! references obtained to that element before it was extracted become valid.
+ //!
+ //! Returns: The bool component is true if the insertion took place and false if the assignment
+ //! took place. The iterator component is pointing at the element that was inserted or updated.
+ //!
+ //! Complexity: Logarithmic in the size of the container.
+ template <class M>
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> insert_or_assign(const key_type& k, BOOST_FWD_REF(M) obj)
+ {
+ return dtl::force_copy< std::pair<iterator, bool> >
+ (this->m_flat_tree.insert_or_assign
+ ( impl_const_iterator(), k, ::boost::forward<M>(obj))
+ );
+ }
+
+ //! Effects: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
+ //! to the mapped_type corresponding to the key k. If the key does not exist, inserts the new value
+ //! as if by insert, constructing it from value_type(k, move(obj)).
+ //!
+ //! No iterators or references are invalidated. If the insertion is successful, pointers and references
+ //! to the element obtained while it is held in the node handle are invalidated, and pointers and
+ //! references obtained to that element before it was extracted become valid.
+ //!
+ //! Returns: The bool component is true if the insertion took place and false if the assignment
+ //! took place. The iterator component is pointing at the element that was inserted or updated.
+ //!
+ //! Complexity: Logarithmic in the size of the container.
+ template <class M>
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> insert_or_assign(BOOST_RV_REF(key_type) k, BOOST_FWD_REF(M) obj)
+ {
+ return dtl::force_copy< std::pair<iterator, bool> >
+ (this->m_flat_tree.insert_or_assign
+ ( impl_const_iterator(), ::boost::move(k), ::boost::forward<M>(obj))
+ );
+ }
+
+ //! Effects: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
+ //! to the mapped_type corresponding to the key k. If the key does not exist, inserts the new value
+ //! as if by insert, constructing it from value_type(k, forward<M>(obj)) and the new element
+ //! to the container as close as possible to the position just before hint.
+ //!
+ //! No iterators or references are invalidated. If the insertion is successful, pointers and references
+ //! to the element obtained while it is held in the node handle are invalidated, and pointers and
+ //! references obtained to that element before it was extracted become valid.
+ //!
+ //! Returns: The bool component is true if the insertion took place and false if the assignment
+ //! took place. The iterator component is pointing at the element that was inserted or updated.
+ //!
+ //! Complexity: Logarithmic in the size of the container in general, but amortized constant if
+ //! the new element is inserted just before hint.
+ template <class M>
+ BOOST_CONTAINER_FORCEINLINE iterator insert_or_assign(const_iterator hint, const key_type& k, BOOST_FWD_REF(M) obj)
+ {
+ return dtl::force_copy< std::pair<iterator, bool> >
+ (this->m_flat_tree.insert_or_assign
+ ( dtl::force_copy<impl_const_iterator>(hint)
+ , k, ::boost::forward<M>(obj))
+ );
+ }
+
+ //! Effects: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
+ //! to the mapped_type corresponding to the key k. If the key does not exist, inserts the new value
+ //! as if by insert, constructing it from value_type(k, move(obj)) and the new element
+ //! to the container as close as possible to the position just before hint.
+ //!
+ //! No iterators or references are invalidated. If the insertion is successful, pointers and references
+ //! to the element obtained while it is held in the node handle are invalidated, and pointers and
+ //! references obtained to that element before it was extracted become valid.
+ //!
+ //! Returns: The bool component is true if the insertion took place and false if the assignment
+ //! took place. The iterator component is pointing at the element that was inserted or updated.
+ //!
+ //! Complexity: Logarithmic in the size of the container in general, but amortized constant if
+ //! the new element is inserted just before hint.
+ template <class M>
+ BOOST_CONTAINER_FORCEINLINE iterator insert_or_assign(const_iterator hint, BOOST_RV_REF(key_type) k, BOOST_FWD_REF(M) obj)
+ {
+ return dtl::force_copy< std::pair<iterator, bool> >
+ (this->m_flat_tree.insert_or_assign
+ ( dtl::force_copy<impl_const_iterator>(hint)
+ , ::boost::move(k), ::boost::forward<M>(obj))
+ );
+ }
+
+ //! @copydoc ::boost::container::flat_set::nth(size_type)
+ BOOST_CONTAINER_FORCEINLINE iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<iterator>(m_flat_tree.nth(n)); }
+
+ //! @copydoc ::boost::container::flat_set::nth(size_type) const
+ BOOST_CONTAINER_FORCEINLINE const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<iterator>(m_flat_tree.nth(n)); }
+
+ //! @copydoc ::boost::container::flat_set::index_of(iterator)
+ BOOST_CONTAINER_FORCEINLINE size_type index_of(iterator p) BOOST_NOEXCEPT_OR_NOTHROW
+ { return m_flat_tree.index_of(dtl::force_copy<impl_iterator>(p)); }
+
+ //! @copydoc ::boost::container::flat_set::index_of(const_iterator) const
+ BOOST_CONTAINER_FORCEINLINE size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW
+ { return m_flat_tree.index_of(dtl::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.
+ //!
+ //! Complexity: logarithmic.
+ T& at(const key_type& k)
+ {
+ iterator i = this->find(k);
+ if(i == this->end()){
+ throw_out_of_range("flat_map::at key not found");
+ }
+ return i->second;
+ }
+
+ //! 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
+ {
+ const_iterator i = this->find(k);
+ if(i == this->end()){
+ throw_out_of_range("flat_map::at key not found");
+ }
+ return i->second;
+ }
+
+ //////////////////////////////////////////////
+ //
+ // modifiers
+ //
+ //////////////////////////////////////////////
+
+ #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
+ //! with key equivalent to the key of x.
+ //!
+ //! <b>Returns</b>: The bool component of the returned pair is true if and only
+ //! if the insertion takes place, and the iterator component of the pair
+ //! points to the element with key equivalent to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time plus linear insertion
+ //! to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ template <class... Args>
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> emplace(BOOST_FWD_REF(Args)... args)
+ { return dtl::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
+ //! std::forward<Args>(args)... in the container if and only if there is
+ //! no element in the container with key equivalent to the key of x.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time (constant if x is inserted
+ //! right before p) plus insertion linear to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ template <class... Args>
+ BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args)
+ {
+ return dtl::force_copy<iterator>
+ (m_flat_tree.emplace_hint_unique( dtl::force_copy<impl_const_iterator>(hint)
+ , boost::forward<Args>(args)...));
+ }
+
+ //! <b>Requires</b>: value_type shall be EmplaceConstructible into map from piecewise_construct,
+ //! forward_as_tuple(k), forward_as_tuple(forward<Args>(args)...).
+ //!
+ //! <b>Effects</b>: If the map already contains an element whose key is equivalent to k, there is no effect. Otherwise
+ //! inserts an object of type value_type constructed with piecewise_construct, forward_as_tuple(k),
+ //! forward_as_tuple(forward<Args>(args)...).
+ //!
+ //! <b>Returns</b>: The bool component of the returned pair is true if and only if the
+ //! insertion took place. The returned iterator points to the map element whose key is equivalent to k.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ template <class... Args>
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> try_emplace(const key_type& k, BOOST_FWD_REF(Args)... args)
+ {
+ return dtl::force_copy< std::pair<iterator, bool> >(
+ m_flat_tree.try_emplace(impl_const_iterator(), k, boost::forward<Args>(args)...));
+ }
+
+ //! <b>Requires</b>: value_type shall be EmplaceConstructible into map from piecewise_construct,
+ //! forward_as_tuple(k), forward_as_tuple(forward<Args>(args)...).
+ //!
+ //! <b>Effects</b>: If the map already contains an element whose key is equivalent to k, there is no effect. Otherwise
+ //! inserts an object of type value_type constructed with piecewise_construct, forward_as_tuple(k),
+ //! forward_as_tuple(forward<Args>(args)...).
+ //!
+ //! <b>Returns</b>: The returned iterator points to the map element whose key is equivalent to k.
+ //!
+ //! <b>Complexity</b>: Logarithmic in general, but amortized constant if value
+ //! is inserted right before p.
+ template <class... Args>
+ BOOST_CONTAINER_FORCEINLINE iterator try_emplace(const_iterator hint, const key_type &k, BOOST_FWD_REF(Args)... args)
+ {
+ return dtl::force_copy<iterator>(m_flat_tree.try_emplace
+ (dtl::force_copy<impl_const_iterator>(hint), k, boost::forward<Args>(args)...).first);
+ }
+
+ //! <b>Requires</b>: value_type shall be EmplaceConstructible into map from piecewise_construct,
+ //! forward_as_tuple(move(k)), forward_as_tuple(forward<Args>(args)...).
+ //!
+ //! <b>Effects</b>: If the map already contains an element whose key is equivalent to k, there is no effect. Otherwise
+ //! inserts an object of type value_type constructed with piecewise_construct, forward_as_tuple(move(k)),
+ //! forward_as_tuple(forward<Args>(args)...).
+ //!
+ //! <b>Returns</b>: The bool component of the returned pair is true if and only if the
+ //! insertion took place. The returned iterator points to the map element whose key is equivalent to k.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ template <class... Args>
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> try_emplace(BOOST_RV_REF(key_type) k, BOOST_FWD_REF(Args)... args)
+ {
+ return dtl::force_copy< std::pair<iterator, bool> >
+ (m_flat_tree.try_emplace(impl_const_iterator(), boost::move(k), boost::forward<Args>(args)...));
+ }
+
+ //! <b>Requires</b>: value_type shall be EmplaceConstructible into map from piecewise_construct,
+ //! forward_as_tuple(move(k)), forward_as_tuple(forward<Args>(args)...).
+ //!
+ //! <b>Effects</b>: If the map already contains an element whose key is equivalent to k, there is no effect. Otherwise
+ //! inserts an object of type value_type constructed with piecewise_construct, forward_as_tuple(move(k)),
+ //! forward_as_tuple(forward<Args>(args)...).
+ //!
+ //! <b>Returns</b>: The returned iterator points to the map element whose key is equivalent to k.
+ //!
+ //! <b>Complexity</b>: Logarithmic in general, but amortized constant if value
+ //! is inserted right before p.
+ template <class... Args>
+ BOOST_CONTAINER_FORCEINLINE iterator try_emplace(const_iterator hint, BOOST_RV_REF(key_type) k, BOOST_FWD_REF(Args)... args)
+ {
+ return dtl::force_copy<iterator>
+ (m_flat_tree.try_emplace(dtl::force_copy
+ <impl_const_iterator>(hint), boost::move(k), boost::forward<Args>(args)...).first);
+ }
+
+ #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 \
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> emplace(BOOST_MOVE_UREF##N)\
+ {\
+ return dtl::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 \
+ BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ {\
+ return dtl::force_copy<iterator>(m_flat_tree.emplace_hint_unique\
+ (dtl::force_copy<impl_const_iterator>(hint) BOOST_MOVE_I##N BOOST_MOVE_FWD##N));\
+ }\
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> try_emplace(const key_type& k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ {\
+ return dtl::force_copy< std::pair<iterator, bool> >\
+ (m_flat_tree.try_emplace(impl_const_iterator(), k BOOST_MOVE_I##N BOOST_MOVE_FWD##N));\
+ }\
+ \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ BOOST_CONTAINER_FORCEINLINE iterator try_emplace(const_iterator hint, const key_type &k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ { return dtl::force_copy<iterator>(m_flat_tree.try_emplace\
+ (dtl::force_copy<impl_const_iterator>(hint), k BOOST_MOVE_I##N BOOST_MOVE_FWD##N).first); }\
+ \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> try_emplace(BOOST_RV_REF(key_type) k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ {\
+ return dtl::force_copy< std::pair<iterator, bool> >\
+ (m_flat_tree.try_emplace(impl_const_iterator(), boost::move(k) BOOST_MOVE_I##N BOOST_MOVE_FWD##N));\
+ }\
+ \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ BOOST_CONTAINER_FORCEINLINE iterator try_emplace(const_iterator hint, BOOST_RV_REF(key_type) k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ { return dtl::force_copy<iterator>(m_flat_tree.try_emplace\
+ (dtl::force_copy<impl_const_iterator>(hint), boost::move(k) BOOST_MOVE_I##N BOOST_MOVE_FWD##N).first); }\
+ //
+ BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_FLAT_MAP_EMPLACE_CODE)
+ #undef BOOST_CONTAINER_FLAT_MAP_EMPLACE_CODE
+
+ #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.
+ //!
+ //! <b>Returns</b>: The bool component of the returned pair is true if and only
+ //! if the insertion takes place, and the iterator component of the pair
+ //! points to the element with key equivalent to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time plus linear insertion
+ //! to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> insert(const value_type& x)
+ { return dtl::force_copy<std::pair<iterator,bool> >(
+ m_flat_tree.insert_unique(dtl::force<const impl_value_type>(x))); }
+
+ //! <b>Effects</b>: Inserts a new value_type move constructed from the pair if and
+ //! only if there is no element in the container with key equivalent to the key of x.
+ //!
+ //! <b>Returns</b>: The bool component of the returned pair is true if and only
+ //! if the insertion takes place, and the iterator component of the pair
+ //! points to the element with key equivalent to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time plus linear insertion
+ //! to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> insert(BOOST_RV_REF(value_type) x)
+ { return dtl::force_copy<std::pair<iterator,bool> >(
+ m_flat_tree.insert_unique(boost::move(dtl::force<impl_value_type>(x)))); }
+
+ //! <b>Effects</b>: Inserts a new value_type move constructed from the pair if and
+ //! only if there is no element in the container with key equivalent to the key of x.
+ //!
+ //! <b>Returns</b>: The bool component of the returned pair is true if and only
+ //! if the insertion takes place, and the iterator component of the pair
+ //! points to the element with key equivalent to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time plus linear insertion
+ //! to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> insert(BOOST_RV_REF(movable_value_type) x)
+ {
+ return dtl::force_copy<std::pair<iterator,bool> >
+ (m_flat_tree.insert_unique(boost::move(x)));
+ }
+
+ //! <b>Effects</b>: Inserts a copy of x in the container if and only if there is
+ //! no element in the container with key equivalent to the key of x.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time (constant if x is inserted
+ //! right before p) plus insertion linear to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, const value_type& x)
+ {
+ return dtl::force_copy<iterator>(
+ m_flat_tree.insert_unique( dtl::force_copy<impl_const_iterator>(p)
+ , dtl::force<const impl_value_type>(x)));
+ }
+
+ //! <b>Effects</b>: Inserts an element move constructed from x in the container.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time (constant if x is inserted
+ //! right before p) plus insertion linear to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(value_type) x)
+ {
+ return dtl::force_copy<iterator>
+ (m_flat_tree.insert_unique( dtl::force_copy<impl_const_iterator>(p)
+ , boost::move(dtl::force<impl_value_type>(x))));
+ }
+
+ //! <b>Effects</b>: Inserts an element move constructed from x in the container.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time (constant if x is inserted
+ //! right before p) plus insertion linear to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(movable_value_type) x)
+ {
+ return dtl::force_copy<iterator>(
+ m_flat_tree.insert_unique(dtl::force_copy<impl_const_iterator>(p), boost::move(x)));
+ }
+
+ //! <b>Requires</b>: first, last are not iterators into *this.
+ //!
+ //! <b>Effects</b>: inserts each element from the range [first,last) if and only
+ //! if there is no element with key equivalent to the key of that element.
+ //!
+ //! <b>Complexity</b>: N log(size()+N).
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE void insert(InputIterator first, InputIterator last)
+ { m_flat_tree.insert_unique(first, last); }
+
+ //! <b>Requires</b>: first, last are not iterators into *this.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate and must be
+ //! unique values.
+ //!
+ //! <b>Effects</b>: inserts each element from the range [first,last) if and only
+ //! if there is no element with key equivalent to the key of that element. This
+ //! function is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Complexity</b>: Linear.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE void insert(ordered_unique_range_t, InputIterator first, InputIterator last)
+ { m_flat_tree.insert_unique(ordered_unique_range, first, last); }
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()) if and only
+ //! if there is no element with key equivalent to the key of that element.
+ //!
+ //! <b>Complexity</b>: N log(N).
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il)
+ {
+ m_flat_tree.insert_unique( dtl::force<impl_initializer_list>(il).begin()
+ , dtl::force<impl_initializer_list>(il).end());
+ }
+
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be
+ //! unique values.
+ //!
+ //! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()) if and only
+ //! if there is no element with key equivalent to the key of that element. This
+ //! function is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Complexity</b>: Linear.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE void insert(ordered_unique_range_t, std::initializer_list<value_type> il)
+ {
+ m_flat_tree.insert_unique(ordered_unique_range
+ , dtl::force<impl_initializer_list>(il).begin()
+ , dtl::force<impl_initializer_list>(il).end());
+ }
+#endif
+
+ //! <b>Requires</b>: this->get_allocator() == source.get_allocator().
+ //!
+ //! <b>Effects</b>: Attempts to extract each element in source and insert it into a using
+ //! the comparison object of *this. If there is an element in a with key equivalent to the
+ //! key of an element from source, then that element is not extracted from source.
+ //!
+ //! <b>Postcondition</b>: Pointers and references to the transferred elements of source refer
+ //! to those same elements but as members of *this. Iterators referring to the transferred
+ //! elements will continue to refer to their elements, but they now behave as iterators into *this,
+ //! not into source.
+ //!
+ //! <b>Throws</b>: Nothing unless the comparison object throws.
+ //!
+ //! <b>Complexity</b>: N log(a.size() + N) (N has the value source.size())
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge(flat_map<Key, T, C2, AllocatorOrContainer>& source)
+ { m_flat_tree.merge_unique(source.tree()); }
+
+ //! @copydoc ::boost::container::flat_map::merge(flat_map<Key, T, C2, AllocatorOrContainer>&)
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_map<Key, T, C2, AllocatorOrContainer> BOOST_RV_REF_END source)
+ { return this->merge(static_cast<flat_map<Key, T, C2, AllocatorOrContainer>&>(source)); }
+
+ //! @copydoc ::boost::container::flat_map::merge(flat_map<Key, T, C2, AllocatorOrContainer>&)
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge(flat_multimap<Key, T, C2, AllocatorOrContainer>& source)
+ { m_flat_tree.merge_unique(source.tree()); }
+
+ //! @copydoc ::boost::container::flat_map::merge(flat_map<Key, T, C2, AllocatorOrContainer>&)
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_multimap<Key, T, C2, AllocatorOrContainer> BOOST_RV_REF_END source)
+ { return this->merge(static_cast<flat_multimap<Key, T, C2, AllocatorOrContainer>&>(source)); }
+
+ //! <b>Effects</b>: Erases the element pointed to by p.
+ //!
+ //! <b>Returns</b>: Returns an iterator pointing to the element immediately
+ //! following q prior to the element being erased. If no such element exists,
+ //! returns end().
+ //!
+ //! <b>Complexity</b>: Linear to the elements with keys bigger than p
+ //!
+ //! <b>Note</b>: Invalidates elements with keys
+ //! not less than the erased element.
+ BOOST_CONTAINER_FORCEINLINE iterator erase(const_iterator p)
+ {
+ return dtl::force_copy<iterator>
+ (m_flat_tree.erase(dtl::force_copy<impl_const_iterator>(p)));
+ }
+
+ //! <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>: Logarithmic search time plus erasure time
+ //! linear to the elements with bigger keys.
+ BOOST_CONTAINER_FORCEINLINE size_type erase(const key_type& x)
+ { return m_flat_tree.erase(x); }
+
+ //! <b>Effects</b>: Erases all the elements in the range [first, last).
+ //!
+ //! <b>Returns</b>: Returns last.
+ //!
+ //! <b>Complexity</b>: size()*N where N is the distance from first to last.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time plus erasure time
+ //! linear to the elements with bigger keys.
+ BOOST_CONTAINER_FORCEINLINE iterator erase(const_iterator first, const_iterator last)
+ {
+ return dtl::force_copy<iterator>(
+ m_flat_tree.erase( dtl::force_copy<impl_const_iterator>(first)
+ , dtl::force_copy<impl_const_iterator>(last)));
+ }
+
+ //! <b>Effects</b>: Swaps the contents of *this and x.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE void swap(flat_map& x)
+ BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value
+ && boost::container::dtl::is_nothrow_swappable<Compare>::value )
+ { m_flat_tree.swap(x.m_flat_tree); }
+
+ //! <b>Effects</b>: erase(a.begin(),a.end()).
+ //!
+ //! <b>Postcondition</b>: size() == 0.
+ //!
+ //! <b>Complexity</b>: linear in size().
+ BOOST_CONTAINER_FORCEINLINE void clear() BOOST_NOEXCEPT_OR_NOTHROW
+ { m_flat_tree.clear(); }
+
+ //////////////////////////////////////////////
+ //
+ // observers
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Returns the comparison object out
+ //! of which a was constructed.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE key_compare key_comp() const
+ { return dtl::force_copy<key_compare>(m_flat_tree.key_comp()); }
+
+ //! <b>Effects</b>: Returns an object of value_compare constructed out
+ //! of the comparison object.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE value_compare value_comp() const
+ { return value_compare(dtl::force_copy<key_compare>(m_flat_tree.key_comp())); }
+
+ //////////////////////////////////////////////
+ //
+ // map operations
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Returns</b>: An iterator pointing to an element with the key
+ //! equivalent to x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ BOOST_CONTAINER_FORCEINLINE iterator find(const key_type& x)
+ { return dtl::force_copy<iterator>(m_flat_tree.find(x)); }
+
+ //! <b>Returns</b>: A const_iterator pointing to an element with the key
+ //! equivalent to x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ BOOST_CONTAINER_FORCEINLINE const_iterator find(const key_type& x) const
+ { return dtl::force_copy<const_iterator>(m_flat_tree.find(x)); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Returns</b>: An iterator pointing to an element with the key
+ //! equivalent to x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ template<class K>
+ BOOST_CONTAINER_FORCEINLINE iterator find(const K& x)
+ { return dtl::force_copy<iterator>(m_flat_tree.find(x)); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <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.
+ template<class K>
+ BOOST_CONTAINER_FORCEINLINE const_iterator find(const K& x) const
+ { return dtl::force_copy<const_iterator>(m_flat_tree.find(x)); }
+
+ //! <b>Returns</b>: The number of elements with key equivalent to x.
+ //!
+ //! <b>Complexity</b>: log(size())+count(k)
+ BOOST_CONTAINER_FORCEINLINE size_type count(const key_type& x) const
+ { return static_cast<size_type>(m_flat_tree.find(x) != m_flat_tree.end()); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Returns</b>: The number of elements with key equivalent to x.
+ //!
+ //! <b>Complexity</b>: log(size())+count(k)
+ template<class K>
+ BOOST_CONTAINER_FORCEINLINE size_type count(const K& x) const
+ { return static_cast<size_type>(m_flat_tree.find(x) != m_flat_tree.end()); }
+
+ //! <b>Returns</b>: An iterator pointing to the first element with key not less
+ //! than k, or a.end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ BOOST_CONTAINER_FORCEINLINE iterator lower_bound(const key_type& x)
+ { return dtl::force_copy<iterator>(m_flat_tree.lower_bound(x)); }
+
+ //! <b>Returns</b>: A const iterator pointing to the first element with key not
+ //! less than k, or a.end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ BOOST_CONTAINER_FORCEINLINE const_iterator lower_bound(const key_type& x) const
+ { return dtl::force_copy<const_iterator>(m_flat_tree.lower_bound(x)); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the first element with key not less
+ //! than k, or a.end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ template<class K>
+ BOOST_CONTAINER_FORCEINLINE iterator lower_bound(const K& x)
+ { return dtl::force_copy<iterator>(m_flat_tree.lower_bound(x)); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <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.
+ template<class K>
+ BOOST_CONTAINER_FORCEINLINE const_iterator lower_bound(const K& x) const
+ { return dtl::force_copy<const_iterator>(m_flat_tree.lower_bound(x)); }
+
+ //! <b>Returns</b>: An iterator pointing to the first element with key not less
+ //! than x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ BOOST_CONTAINER_FORCEINLINE iterator upper_bound(const key_type& x)
+ { return dtl::force_copy<iterator>(m_flat_tree.upper_bound(x)); }
+
+ //! <b>Returns</b>: A const iterator pointing to the first element with key not
+ //! less than x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ BOOST_CONTAINER_FORCEINLINE const_iterator upper_bound(const key_type& x) const
+ { return dtl::force_copy<const_iterator>(m_flat_tree.upper_bound(x)); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the first element with key not less
+ //! than x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ template<class K>
+ BOOST_CONTAINER_FORCEINLINE iterator upper_bound(const K& x)
+ { return dtl::force_copy<iterator>(m_flat_tree.upper_bound(x)); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <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.
+ template<class K>
+ BOOST_CONTAINER_FORCEINLINE const_iterator upper_bound(const K& x) const
+ { return dtl::force_copy<const_iterator>(m_flat_tree.upper_bound(x)); }
+
+ //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator,iterator> equal_range(const key_type& x)
+ { return dtl::force_copy<std::pair<iterator,iterator> >(m_flat_tree.lower_bound_range(x)); }
+
+ //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ BOOST_CONTAINER_FORCEINLINE std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const
+ { return dtl::force_copy<std::pair<const_iterator,const_iterator> >(m_flat_tree.lower_bound_range(x)); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ template<class K>
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator,iterator> equal_range(const K& x)
+ { return dtl::force_copy<std::pair<iterator,iterator> >(m_flat_tree.lower_bound_range(x)); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ template<class K>
+ BOOST_CONTAINER_FORCEINLINE std::pair<const_iterator, const_iterator> equal_range(const K& x) const
+ { return dtl::force_copy<std::pair<const_iterator,const_iterator> >(m_flat_tree.lower_bound_range(x)); }
+
+ //! <b>Effects</b>: Extracts the internal sequence container.
+ //!
+ //! <b>Complexity</b>: Same as the move constructor of sequence_type, usually constant.
+ //!
+ //! <b>Postcondition</b>: this->empty()
+ //!
+ //! <b>Throws</b>: If secuence_type's move constructor throws
+ BOOST_CONTAINER_FORCEINLINE sequence_type extract_sequence()
+ {
+ return boost::move(dtl::force<sequence_type>(m_flat_tree.get_sequence_ref()));
+ }
+
+ //! <b>Effects</b>: Discards the internally hold sequence container and adopts the
+ //! one passed externally using the move assignment. Erases non-unique elements.
+ //!
+ //! <b>Complexity</b>: Assuming O(1) move assignment, O(NlogN) with N = seq.size()
+ //!
+ //! <b>Throws</b>: If the comparison or the move constructor throws
+ BOOST_CONTAINER_FORCEINLINE void adopt_sequence(BOOST_RV_REF(sequence_type) seq)
+ { this->m_flat_tree.adopt_sequence_unique(boost::move(dtl::force<impl_sequence_type>(seq))); }
+
+ //! <b>Requires</b>: seq shall be ordered according to this->compare()
+ //! and shall contain unique elements.
+ //!
+ //! <b>Effects</b>: Discards the internally hold sequence container and adopts the
+ //! one passed externally using the move assignment.
+ //!
+ //! <b>Complexity</b>: Assuming O(1) move assignment, O(1)
+ //!
+ //! <b>Throws</b>: If the move assignment throws
+ BOOST_CONTAINER_FORCEINLINE void adopt_sequence(ordered_unique_range_t, BOOST_RV_REF(sequence_type) seq)
+ { this->m_flat_tree.adopt_sequence_unique(ordered_unique_range_t(), boost::move(dtl::force<impl_sequence_type>(seq))); }
+
+ //! <b>Effects</b>: Returns true if x and y are equal
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ BOOST_CONTAINER_FORCEINLINE friend bool operator==(const flat_map& x, const flat_map& y)
+ { return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin()); }
+
+ //! <b>Effects</b>: Returns true if x and y are unequal
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ BOOST_CONTAINER_FORCEINLINE friend bool operator!=(const flat_map& x, const flat_map& y)
+ { return !(x == y); }
+
+ //! <b>Effects</b>: Returns true if x is less than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ BOOST_CONTAINER_FORCEINLINE friend bool operator<(const flat_map& x, const flat_map& y)
+ { return ::boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
+
+ //! <b>Effects</b>: Returns true if x is greater than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ BOOST_CONTAINER_FORCEINLINE friend bool operator>(const flat_map& x, const flat_map& y)
+ { return y < x; }
+
+ //! <b>Effects</b>: Returns true if x is equal or less than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ BOOST_CONTAINER_FORCEINLINE friend bool operator<=(const flat_map& x, const flat_map& y)
+ { return !(y < x); }
+
+ //! <b>Effects</b>: Returns true if x is equal or greater than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ BOOST_CONTAINER_FORCEINLINE friend bool operator>=(const flat_map& x, const flat_map& y)
+ { return !(x < y); }
+
+ //! <b>Effects</b>: x.swap(y)
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE friend void swap(flat_map& x, flat_map& y)
+ { x.swap(y); }
+
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ private:
+ mapped_type &priv_subscript(const key_type& k)
+ {
+ iterator i = lower_bound(k);
+ // i->first is greater than or equivalent to k.
+ if (i == end() || key_comp()(k, (*i).first)){
+ dtl::value_init<mapped_type> m;
+ i = insert(i, impl_value_type(k, ::boost::move(m.m_t)));
+ }
+ return (*i).second;
+ }
+ mapped_type &priv_subscript(BOOST_RV_REF(key_type) mk)
+ {
+ key_type &k = mk;
+ iterator i = lower_bound(k);
+ // i->first is greater than or equivalent to k.
+ if (i == end() || key_comp()(k, (*i).first)){
+ dtl::value_init<mapped_type> m;
+ i = insert(i, impl_value_type(boost::move(k), ::boost::move(m.m_t)));
+ }
+ return (*i).second;
+ }
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+};
+
+#if __cplusplus >= 201703L
+
+template <typename InputIterator>
+flat_map(InputIterator, InputIterator) ->
+ flat_map< typename dtl::remove_const< typename iterator_traits<InputIterator>::value_type::first_type>::type
+ , typename iterator_traits<InputIterator>::value_type::second_type>;
+
+template <typename InputIterator, typename Allocator>
+flat_map(InputIterator, InputIterator, Allocator const&) ->
+ flat_map< typename dtl::remove_const< typename iterator_traits<InputIterator>::value_type::first_type>::type
+ , typename iterator_traits<InputIterator>::value_type::second_type
+ , std::less<typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type>
+ , Allocator>;
+
+template <typename InputIterator, typename Compare>
+flat_map(InputIterator, InputIterator, Compare const&) ->
+ flat_map< typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type
+ , typename iterator_traits<InputIterator>::value_type::second_type
+ , Compare>;
+
+template <typename InputIterator, typename Compare, typename Allocator>
+flat_map(InputIterator, InputIterator, Compare const&, Allocator const&) ->
+ flat_map< typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type
+ , typename iterator_traits<InputIterator>::value_type::second_type
+ , Compare
+ , Allocator>;
+
+template <typename InputIterator>
+flat_map(ordered_unique_range_t, InputIterator, InputIterator) ->
+ flat_map< typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type
+ , typename iterator_traits<InputIterator>::value_type::second_type>;
+
+template <typename InputIterator, typename Allocator>
+flat_map(ordered_unique_range_t, InputIterator, InputIterator, Allocator const&) ->
+ flat_map< typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type
+ , typename iterator_traits<InputIterator>::value_type::second_type
+ , std::less<typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type>
+ , Allocator>;
+
+template <typename InputIterator, typename Compare>
+flat_map(ordered_unique_range_t, InputIterator, InputIterator, Compare const&) ->
+ flat_map< typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type
+ , typename iterator_traits<InputIterator>::value_type::second_type
+ , Compare>;
+
+template <typename InputIterator, typename Compare, typename Allocator>
+flat_map(ordered_unique_range_t, InputIterator, InputIterator, Compare const&, Allocator const&) ->
+ flat_map< typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type
+ , typename iterator_traits<InputIterator>::value_type::second_type
+ , Compare
+ , Allocator>;
+
+#endif
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+} //namespace container {
+
+//!has_trivial_destructor_after_move<> == true_type
+//!specialization for optimizations
+template <class Key, class T, class Compare, class AllocatorOrContainer>
+struct has_trivial_destructor_after_move<boost::container::flat_map<Key, T, Compare, AllocatorOrContainer> >
+{
+ typedef typename ::boost::container::allocator_traits<AllocatorOrContainer>::pointer pointer;
+ static const bool value = ::boost::has_trivial_destructor_after_move<AllocatorOrContainer>::value &&
+ ::boost::has_trivial_destructor_after_move<pointer>::value &&
+ ::boost::has_trivial_destructor_after_move<Compare>::value;
+};
+
+namespace container {
+
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+//! A flat_multimap is a kind of associative container that supports equivalent keys
+//! (possibly containing multiple copies of the same key value) and provides for
+//! fast retrieval of values of another type T based on the keys.
+//!
+//! A flat_multimap satisfies all of the requirements of a container and of a reversible
+//! container and of an associative container. For a
+//! flat_multimap<Key,T> the key_type is Key and the value_type is std::pair<Key,T>
+//! (unlike std::multimap<Key, T> which value_type is std::pair<<b>const</b> Key, T>).
+//!
+//! flat_multimap is similar to std::multimap but it's implemented by as an ordered sequence container.
+//! The underlying sequence container is by default <i>vector</i> but it can also work
+//! user-provided vector-like SequenceContainers (like <i>static_vector</i> or <i>small_vector</i>).
+//!
+//! Using vector-like sequence containers means that inserting a new element into a flat_multimap might invalidate
+//! previous iterators and references (unless that sequence container is <i>stable_vector</i> or a similar
+//! container that offers stable pointers and references). Similarly, erasing an element might invalidate
+//! iterators and references pointing to elements that come after (their keys are bigger) the erased element.
+//!
+//! This container provides random-access iterators.
+//!
+//! \tparam Key is the key_type of the map
+//! \tparam Value is the <code>mapped_type</code>
+//! \tparam Compare is the ordering function for Keys (e.g. <i>std::less<Key></i>).
+//! \tparam AllocatorOrContainer is either:
+//! - The allocator to allocate <code>value_type</code>s (e.g. <i>allocator< std::pair<Key, T> > </i>).
+//! (in this case <i>sequence_type</i> will be vector<value_type, AllocatorOrContainer>)
+//! - The SequenceContainer to be used as the underlying <i>sequence_type</i>. It must be a vector-like
+//! sequence container with random-access iterators.
+#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
+template <class Key, class T, class Compare = std::less<Key>, class AllocatorOrContainer = new_allocator< std::pair< Key, T> > >
+#else
+template <class Key, class T, class Compare, class AllocatorOrContainer>
+#endif
+class flat_multimap
+{
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ private:
+ BOOST_COPYABLE_AND_MOVABLE(flat_multimap)
+ typedef dtl::flat_tree<
+ std::pair<Key, T>,
+ dtl::select1st<Key>,
+ Compare,
+ AllocatorOrContainer> tree_t;
+ //This is the real tree stored here. It's based on a movable pair
+ typedef dtl::flat_tree<
+ dtl::pair<Key, T>,
+ dtl::select1st<Key>,
+ Compare,
+ typename dtl::container_or_allocator_rebind<AllocatorOrContainer, dtl::pair<Key, T> >::type
+ > impl_tree_t;
+ impl_tree_t m_flat_tree; // flat tree representing 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;
+ #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ typedef std::initializer_list<impl_value_type> impl_initializer_list;
+ #endif
+
+ typedef dtl::flat_tree_value_compare
+ < Compare
+ , dtl::select1st<Key>
+ , std::pair<Key, T> > value_compare_t;
+ typedef typename tree_t::iterator iterator_t;
+ typedef typename tree_t::const_iterator const_iterator_t;
+ typedef typename tree_t::reverse_iterator reverse_iterator_t;
+ typedef typename tree_t::const_reverse_iterator const_reverse_iterator_t;
+
+ public:
+ typedef typename impl_tree_t::stored_allocator_type impl_stored_allocator_type;
+ typedef typename impl_tree_t::sequence_type impl_sequence_type;
+
+ BOOST_CONTAINER_FORCEINLINE impl_tree_t &tree()
+ { return m_flat_tree; }
+
+ BOOST_CONTAINER_FORCEINLINE const impl_tree_t &tree() const
+ { return m_flat_tree; }
+
+ private:
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ public:
+
+ //////////////////////////////////////////////
+ //
+ // types
+ //
+ //////////////////////////////////////////////
+ typedef Key key_type;
+ typedef T mapped_type;
+ typedef Compare key_compare;
+ typedef std::pair<Key, T> value_type;
+ typedef typename BOOST_CONTAINER_IMPDEF(tree_t::sequence_type) sequence_type;
+ typedef typename sequence_type::allocator_type allocator_type;
+ typedef ::boost::container::allocator_traits<allocator_type> allocator_traits_type;
+ typedef typename sequence_type::pointer pointer;
+ typedef typename sequence_type::const_pointer const_pointer;
+ typedef typename sequence_type::reference reference;
+ typedef typename sequence_type::const_reference const_reference;
+ typedef typename sequence_type::size_type size_type;
+ typedef typename sequence_type::difference_type difference_type;
+ typedef typename BOOST_CONTAINER_IMPDEF(tree_t::stored_allocator_type) stored_allocator_type;
+ typedef typename BOOST_CONTAINER_IMPDEF(tree_t::value_compare) value_compare;
+
+ typedef typename sequence_type::iterator iterator;
+ typedef typename sequence_type::const_iterator const_iterator;
+ typedef typename sequence_type::reverse_iterator reverse_iterator;
+ typedef typename sequence_type::const_reverse_iterator const_reverse_iterator;
+ typedef BOOST_CONTAINER_IMPDEF(impl_value_type) movable_value_type;
+
+ //AllocatorOrContainer::value_type must be std::pair<Key, T>
+ BOOST_STATIC_ASSERT((dtl::is_same<std::pair<Key, T>, typename AllocatorOrContainer::value_type>::value));
+
+ //////////////////////////////////////////////
+ //
+ // construct/copy/destroy
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Default constructs an empty flat_map.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE flat_multimap()
+ BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<AllocatorOrContainer>::value &&
+ dtl::is_nothrow_default_constructible<Compare>::value)
+ : m_flat_tree()
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_multimap using the specified allocator.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE explicit flat_multimap(const allocator_type& a)
+ : m_flat_tree(dtl::force<const impl_allocator_type>(a))
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison
+ //! object .
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE explicit flat_multimap(const Compare& comp)
+ : m_flat_tree(comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison
+ //! object and allocator.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(const Compare& comp, const allocator_type& a)
+ : m_flat_tree(comp, dtl::force<const impl_allocator_type>(a))
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_multimap
+ //! and inserts elements from the range [first ,last ).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(InputIterator first, InputIterator last)
+ : m_flat_tree(false, first, last)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_multimap using the specified
+ //! allocator, and inserts elements from the range [first ,last ).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(InputIterator first, InputIterator last, const allocator_type& a)
+ : m_flat_tree(false, first, last, dtl::force<const impl_allocator_type>(a))
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object
+ //! and inserts elements from the range [first ,last ).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(InputIterator first, InputIterator last, const Compare& comp)
+ : m_flat_tree(false, first, last, comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object
+ //! and allocator, and inserts elements from the range [first ,last ).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
+ : m_flat_tree(false, first, last, comp, dtl::force<const impl_allocator_type>(a))
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_multimap
+ //! and inserts elements from the ordered range [first ,last). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(ordered_range_t, InputIterator first, InputIterator last)
+ : m_flat_tree(ordered_range, first, last)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object and
+ //! inserts elements from the ordered range [first ,last). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(ordered_range_t, InputIterator first, InputIterator last, const Compare& comp)
+ : m_flat_tree(ordered_range, first, last, comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object and
+ //! allocator, and inserts elements from the ordered range [first ,last). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(ordered_range_t, InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
+ : m_flat_tree(ordered_range, first, last, comp, a)
+ {}
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Constructs an empty flat_map and
+ //! inserts elements from the range [il.begin(), il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(std::initializer_list<value_type> il)
+ : m_flat_tree( false
+ , dtl::force<impl_initializer_list>(il).begin()
+ , dtl::force<impl_initializer_list>(il).end())
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified
+ //! allocator, and inserts elements from the range [il.begin(), il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(std::initializer_list<value_type> il, const allocator_type& a)
+ : m_flat_tree(false
+ , dtl::force<impl_initializer_list>(il).begin()
+ , dtl::force<impl_initializer_list>(il).end()
+ , dtl::force<const impl_allocator_type>(a))
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
+ //! inserts elements from the range [il.begin(), il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(std::initializer_list<value_type> il, const Compare& comp)
+ : m_flat_tree(false
+ , dtl::force<impl_initializer_list>(il).begin()
+ , dtl::force<impl_initializer_list>(il).end(), comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
+ //! allocator, and inserts elements from the range [il.begin(), il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
+ : m_flat_tree( false
+ , dtl::force<impl_initializer_list>(il).begin()
+ , dtl::force<impl_initializer_list>(il).end()
+ , comp, dtl::force<const impl_allocator_type>(a))
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_multimap and
+ //! inserts elements from the ordered range [il.begin(), il.end()). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(ordered_range_t, std::initializer_list<value_type> il)
+ : m_flat_tree( ordered_range
+ , dtl::force<impl_initializer_list>(il).begin()
+ , dtl::force<impl_initializer_list>(il).end())
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object and
+ //! inserts elements from the ordered range [il.begin(), il.end()). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp)
+ : m_flat_tree( ordered_range
+ , dtl::force<impl_initializer_list>(il).begin()
+ , dtl::force<impl_initializer_list>(il).end(), comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object and
+ //! allocator, and inserts elements from the ordered range [il.begin(), il.end()). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
+ : m_flat_tree( ordered_range
+ , dtl::force<impl_initializer_list>(il).begin()
+ , dtl::force<impl_initializer_list>(il).end()
+ , comp, dtl::force<const impl_allocator_type>(a))
+ {}
+#endif
+
+ //! <b>Effects</b>: Copy constructs a flat_multimap.
+ //!
+ //! <b>Complexity</b>: Linear in x.size().
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(const flat_multimap& x)
+ : m_flat_tree(x.m_flat_tree)
+ {}
+
+ //! <b>Effects</b>: Move constructs a flat_multimap. Constructs *this using x's resources.
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Postcondition</b>: x is emptied.
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(BOOST_RV_REF(flat_multimap) x)
+ BOOST_NOEXCEPT_IF(boost::container::dtl::is_nothrow_move_constructible<Compare>::value)
+ : m_flat_tree(boost::move(x.m_flat_tree))
+ {}
+
+ //! <b>Effects</b>: Copy constructs a flat_multimap using the specified allocator.
+ //!
+ //! <b>Complexity</b>: Linear in x.size().
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(const flat_multimap& x, const allocator_type &a)
+ : m_flat_tree(x.m_flat_tree, dtl::force<const impl_allocator_type>(a))
+ {}
+
+ //! <b>Effects</b>: Move constructs a flat_multimap using the specified allocator.
+ //! Constructs *this using x's resources.
+ //!
+ //! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise.
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap(BOOST_RV_REF(flat_multimap) x, const allocator_type &a)
+ : m_flat_tree(boost::move(x.m_flat_tree), dtl::force<const impl_allocator_type>(a))
+ {}
+
+ //! <b>Effects</b>: Makes *this a copy of x.
+ //!
+ //! <b>Complexity</b>: Linear in x.size().
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap& operator=(BOOST_COPY_ASSIGN_REF(flat_multimap) x)
+ { m_flat_tree = x.m_flat_tree; return *this; }
+
+ //! <b>Effects</b>: this->swap(x.get()).
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap& operator=(BOOST_RV_REF(flat_multimap) x)
+ BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value ||
+ allocator_traits_type::is_always_equal::value) &&
+ boost::container::dtl::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)
+ //! <b>Effects</b>: Assign content of il to *this
+ //!
+ //! <b>Complexity</b>: Linear in il.size().
+ BOOST_CONTAINER_FORCEINLINE
+ flat_multimap& operator=(std::initializer_list<value_type> il)
+ {
+ this->clear();
+ this->insert(il.begin(), il.end());
+ return *this;
+ }
+#endif
+
+ //! <b>Effects</b>: Returns a copy of the allocator that
+ //! was passed to the object's constructor.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
+ allocator_type get_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<allocator_type>(m_flat_tree.get_allocator()); }
+
+ //! <b>Effects</b>: Returns a reference to the internal allocator.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE
+ stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force<stored_allocator_type>(m_flat_tree.get_stored_allocator()); }
+
+ //! <b>Effects</b>: Returns a reference to the internal allocator.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE
+ const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force<const stored_allocator_type>(m_flat_tree.get_stored_allocator()); }
+
+ //////////////////////////////////////////////
+ //
+ // iterators
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Returns an iterator to the first element contained in the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
+ iterator begin() BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<iterator>(m_flat_tree.begin()); }
+
+ //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
+ const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<const_iterator>(m_flat_tree.begin()); }
+
+ //! <b>Effects</b>: Returns an iterator to the end of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
+ iterator end() BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<iterator>(m_flat_tree.end()); }
+
+ //! <b>Effects</b>: Returns a const_iterator to the end of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
+ const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<const_iterator>(m_flat_tree.end()); }
+
+ //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
+ reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<reverse_iterator>(m_flat_tree.rbegin()); }
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
+ const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<const_reverse_iterator>(m_flat_tree.rbegin()); }
+
+ //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
+ reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<reverse_iterator>(m_flat_tree.rend()); }
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
+ const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<const_reverse_iterator>(m_flat_tree.rend()); }
+
+ //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
+ const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<const_iterator>(m_flat_tree.cbegin()); }
+
+ //! <b>Effects</b>: Returns a const_iterator to the end of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
+ const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<const_iterator>(m_flat_tree.cend()); }
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
+ const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<const_reverse_iterator>(m_flat_tree.crbegin()); }
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
+ const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<const_reverse_iterator>(m_flat_tree.crend()); }
+
+ //////////////////////////////////////////////
+ //
+ // capacity
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Returns true if the container contains no elements.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
+ bool empty() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return m_flat_tree.empty(); }
+
+ //! <b>Effects</b>: Returns the number of the elements contained in the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
+ size_type size() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return m_flat_tree.size(); }
+
+ //! <b>Effects</b>: Returns the largest possible size of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
+ size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return m_flat_tree.max_size(); }
+
+ //! <b>Effects</b>: Number of elements for which memory has been allocated.
+ //! capacity() is always greater than or equal to size().
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
+ size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return m_flat_tree.capacity(); }
+
+ //! <b>Effects</b>: If n is less than or equal to capacity(), or the
+ //! underlying container has no `reserve` member, this call has no
+ //! effect. Otherwise, it is a request for allocation of additional memory.
+ //! If the request is successful, then capacity() is greater than or equal to
+ //! n; otherwise, capacity() is unchanged. In either case, size() is unchanged.
+ //!
+ //! <b>Throws</b>: If memory allocation allocation throws or T's copy constructor throws.
+ //!
+ //! <b>Note</b>: If capacity() is less than "cnt", iterators and references to
+ //! to values might be invalidated.
+ BOOST_CONTAINER_FORCEINLINE
+ void reserve(size_type cnt)
+ { m_flat_tree.reserve(cnt); }
+
+ //! <b>Effects</b>: Tries to deallocate the excess of memory created
+ // with previous allocations. The size of the vector is unchanged
+ //!
+ //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to size().
+ BOOST_CONTAINER_FORCEINLINE
+ void shrink_to_fit()
+ { m_flat_tree.shrink_to_fit(); }
+
+ //! @copydoc ::boost::container::flat_set::nth(size_type)
+ BOOST_CONTAINER_FORCEINLINE
+ iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<iterator>(m_flat_tree.nth(n)); }
+
+ //! @copydoc ::boost::container::flat_set::nth(size_type) const
+ BOOST_CONTAINER_FORCEINLINE
+ const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
+ { return dtl::force_copy<iterator>(m_flat_tree.nth(n)); }
+
+ //! @copydoc ::boost::container::flat_set::index_of(iterator)
+ BOOST_CONTAINER_FORCEINLINE
+ size_type index_of(iterator p) BOOST_NOEXCEPT_OR_NOTHROW
+ { return m_flat_tree.index_of(dtl::force_copy<impl_iterator>(p)); }
+
+ //! @copydoc ::boost::container::flat_set::index_of(const_iterator) const
+ BOOST_CONTAINER_FORCEINLINE
+ size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW
+ { return m_flat_tree.index_of(dtl::force_copy<impl_const_iterator>(p)); }
+
+ #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
+ //! newly inserted element.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time plus linear insertion
+ //! to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ template <class... Args>
+ BOOST_CONTAINER_FORCEINLINE
+ iterator emplace(BOOST_FWD_REF(Args)... args)
+ { return dtl::force_copy<iterator>(m_flat_tree.emplace_equal(boost::forward<Args>(args)...)); }
+
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... in the container.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time (constant time if the value
+ //! is to be inserted before p) plus linear insertion
+ //! to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ template <class... Args>
+ BOOST_CONTAINER_FORCEINLINE
+ iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args)
+ {
+ return dtl::force_copy<iterator>(m_flat_tree.emplace_hint_equal
+ (dtl::force_copy<impl_const_iterator>(hint), boost::forward<Args>(args)...));
+ }
+
+ #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 \
+ BOOST_CONTAINER_FORCEINLINE iterator emplace(BOOST_MOVE_UREF##N)\
+ { return dtl::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 \
+ BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ {\
+ return dtl::force_copy<iterator>(m_flat_tree.emplace_hint_equal\
+ (dtl::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 // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ //! <b>Effects</b>: Inserts x and returns the iterator pointing to the
+ //! newly inserted element.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time plus linear insertion
+ //! to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ BOOST_CONTAINER_FORCEINLINE iterator insert(const value_type& x)
+ {
+ return dtl::force_copy<iterator>(
+ m_flat_tree.insert_equal(dtl::force<const impl_value_type>(x)));
+ }
+
+ //! <b>Effects</b>: Inserts a new value move-constructed from x and returns
+ //! the iterator pointing to the newly inserted element.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time plus linear insertion
+ //! to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ BOOST_CONTAINER_FORCEINLINE iterator insert(BOOST_RV_REF(value_type) x)
+ { return dtl::force_copy<iterator>(m_flat_tree.insert_equal(boost::move(x))); }
+
+ //! <b>Effects</b>: Inserts a new value move-constructed from x and returns
+ //! the iterator pointing to the newly inserted element.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time plus linear insertion
+ //! to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ BOOST_CONTAINER_FORCEINLINE iterator insert(BOOST_RV_REF(impl_value_type) x)
+ { return dtl::force_copy<iterator>(m_flat_tree.insert_equal(boost::move(x))); }
+
+ //! <b>Effects</b>: Inserts a copy of x in the container.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time (constant time if the value
+ //! is to be inserted before p) plus linear insertion
+ //! to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, const value_type& x)
+ {
+ return dtl::force_copy<iterator>
+ (m_flat_tree.insert_equal( dtl::force_copy<impl_const_iterator>(p)
+ , dtl::force<const impl_value_type>(x)));
+ }
+
+ //! <b>Effects</b>: Inserts a value move constructed from x in the container.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time (constant time if the value
+ //! is to be inserted before p) plus linear insertion
+ //! to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(value_type) x)
+ {
+ return dtl::force_copy<iterator>
+ (m_flat_tree.insert_equal(dtl::force_copy<impl_const_iterator>(p)
+ , boost::move(x)));
+ }
+
+ //! <b>Effects</b>: Inserts a value move constructed from x in the container.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time (constant time if the value
+ //! is to be inserted before p) plus linear insertion
+ //! to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(impl_value_type) x)
+ {
+ return dtl::force_copy<iterator>(
+ m_flat_tree.insert_equal(dtl::force_copy<impl_const_iterator>(p), boost::move(x)));
+ }
+
+ //! <b>Requires</b>: first, last are not iterators into *this.
+ //!
+ //! <b>Effects</b>: inserts each element from the range [first,last) .
+ //!
+ //! <b>Complexity</b>: N log(N).
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE void insert(InputIterator first, InputIterator last)
+ { m_flat_tree.insert_equal(first, last); }
+
+ //! <b>Requires</b>: first, last are not iterators into *this.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
+ //!
+ //! <b>Effects</b>: inserts each element from the range [first,last) if and only
+ //! if there is no element with key equivalent to the key of that element. This
+ //! function is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Complexity</b>: Linear.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE void insert(ordered_range_t, InputIterator first, InputIterator last)
+ { m_flat_tree.insert_equal(ordered_range, first, last); }
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()) .
+ //!
+ //! <b>Complexity</b>: N log(N).
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il)
+ {
+ m_flat_tree.insert_equal( dtl::force<impl_initializer_list>(il).begin()
+ , dtl::force<impl_initializer_list>(il).end());
+ }
+
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate.
+ //!
+ //! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()) if and only
+ //! if there is no element with key equivalent to the key of that element. This
+ //! function is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Complexity</b>: Linear.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE void insert(ordered_range_t, std::initializer_list<value_type> il)
+ {
+ m_flat_tree.insert_equal( ordered_range
+ , dtl::force<impl_initializer_list>(il).begin()
+ , dtl::force<impl_initializer_list>(il).end());
+ }
+#endif
+
+ //! <b>Requires</b>: this->get_allocator() == source.get_allocator().
+ //!
+ //! <b>Effects</b>: Extracts each element in source and insert it into a using
+ //! the comparison object of *this.
+ //!
+ //! <b>Postcondition</b>: Pointers and references to the transferred elements of source refer
+ //! to those same elements but as members of *this. Iterators referring to the transferred
+ //! elements will continue to refer to their elements, but they now behave as iterators into *this,
+ //! not into source.
+ //!
+ //! <b>Throws</b>: Nothing unless the comparison object throws.
+ //!
+ //! <b>Complexity</b>: N log(a.size() + N) (N has the value source.size())
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge(flat_multimap<Key, T, C2, AllocatorOrContainer>& source)
+ { m_flat_tree.merge_equal(source.tree()); }
+
+ //! @copydoc ::boost::container::flat_multimap::merge(flat_multimap<Key, T, C2, AllocatorOrContainer>&)
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_multimap<Key, T, C2, AllocatorOrContainer> BOOST_RV_REF_END source)
+ { return this->merge(static_cast<flat_multimap<Key, T, C2, AllocatorOrContainer>&>(source)); }
+
+ //! @copydoc ::boost::container::flat_multimap::merge(flat_multimap<Key, T, C2, AllocatorOrContainer>&)
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge(flat_map<Key, T, C2, AllocatorOrContainer>& source)
+ { m_flat_tree.merge_equal(source.tree()); }
+
+ //! @copydoc ::boost::container::flat_multimap::merge(flat_map<Key, T, C2, AllocatorOrContainer>&)
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_map<Key, T, C2, AllocatorOrContainer> BOOST_RV_REF_END source)
+ { return this->merge(static_cast<flat_map<Key, T, C2, AllocatorOrContainer>&>(source)); }
+
+ //! <b>Effects</b>: Erases the element pointed to by p.
+ //!
+ //! <b>Returns</b>: Returns an iterator pointing to the element immediately
+ //! following q prior to the element being erased. If no such element exists,
+ //! returns end().
+ //!
+ //! <b>Complexity</b>: Linear to the elements with keys bigger than p
+ //!
+ //! <b>Note</b>: Invalidates elements with keys
+ //! not less than the erased element.
+ BOOST_CONTAINER_FORCEINLINE iterator erase(const_iterator p)
+ {
+ return dtl::force_copy<iterator>(
+ m_flat_tree.erase(dtl::force_copy<impl_const_iterator>(p)));
+ }
+
+ //! <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>: Logarithmic search time plus erasure time
+ //! linear to the elements with bigger keys.
+ BOOST_CONTAINER_FORCEINLINE size_type erase(const key_type& x)
+ { return m_flat_tree.erase(x); }
+
+ //! <b>Effects</b>: Erases all the elements in the range [first, last).
+ //!
+ //! <b>Returns</b>: Returns last.
+ //!
+ //! <b>Complexity</b>: size()*N where N is the distance from first to last.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time plus erasure time
+ //! linear to the elements with bigger keys.
+ BOOST_CONTAINER_FORCEINLINE iterator erase(const_iterator first, const_iterator last)
+ {
+ return dtl::force_copy<iterator>
+ (m_flat_tree.erase( dtl::force_copy<impl_const_iterator>(first)
+ , dtl::force_copy<impl_const_iterator>(last)));
+ }
+
+ //! <b>Effects</b>: Swaps the contents of *this and x.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE void swap(flat_multimap& x)
+ BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value
+ && boost::container::dtl::is_nothrow_swappable<Compare>::value )
+ { m_flat_tree.swap(x.m_flat_tree); }
+
+ //! <b>Effects</b>: erase(a.begin(),a.end()).
+ //!
+ //! <b>Postcondition</b>: size() == 0.
+ //!
+ //! <b>Complexity</b>: linear in size().
+ BOOST_CONTAINER_FORCEINLINE void clear() BOOST_NOEXCEPT_OR_NOTHROW
+ { m_flat_tree.clear(); }
+
+ //////////////////////////////////////////////
+ //
+ // observers
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Returns the comparison object out
+ //! of which a was constructed.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE key_compare key_comp() const
+ { return dtl::force_copy<key_compare>(m_flat_tree.key_comp()); }
+
+ //! <b>Effects</b>: Returns an object of value_compare constructed out
+ //! of the comparison object.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE value_compare value_comp() const
+ { return value_compare(dtl::force_copy<key_compare>(m_flat_tree.key_comp())); }
+
+ //////////////////////////////////////////////
+ //
+ // map operations
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Returns</b>: An iterator pointing to an element with the key
+ //! equivalent to x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ BOOST_CONTAINER_FORCEINLINE iterator find(const key_type& x)
+ { return dtl::force_copy<iterator>(m_flat_tree.find(x)); }
+
+ //! <b>Returns</b>: An const_iterator pointing to an element with the key
+ //! equivalent to x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ BOOST_CONTAINER_FORCEINLINE const_iterator find(const key_type& x) const
+ { return dtl::force_copy<const_iterator>(m_flat_tree.find(x)); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Returns</b>: An iterator pointing to an element with the key
+ //! equivalent to x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ template<class K>
+ BOOST_CONTAINER_FORCEINLINE iterator find(const K& x)
+ { return dtl::force_copy<iterator>(m_flat_tree.find(x)); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Returns</b>: An const_iterator pointing to an element with the key
+ //! equivalent to x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ template<class K>
+ BOOST_CONTAINER_FORCEINLINE const_iterator find(const K& x) const
+ { return dtl::force_copy<const_iterator>(m_flat_tree.find(x)); }
+
+ //! <b>Returns</b>: The number of elements with key equivalent to x.
+ //!
+ //! <b>Complexity</b>: log(size())+count(k)
+ BOOST_CONTAINER_FORCEINLINE size_type count(const key_type& x) const
+ { return m_flat_tree.count(x); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Returns</b>: The number of elements with key equivalent to x.
+ //!
+ //! <b>Complexity</b>: log(size())+count(k)
+ template<class K>
+ BOOST_CONTAINER_FORCEINLINE size_type count(const K& x) const
+ { return m_flat_tree.count(x); }
+
+ //! <b>Returns</b>: An iterator pointing to the first element with key not less
+ //! than k, or a.end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ BOOST_CONTAINER_FORCEINLINE iterator lower_bound(const key_type& x)
+ { return dtl::force_copy<iterator>(m_flat_tree.lower_bound(x)); }
+
+ //! <b>Returns</b>: An iterator pointing to the first element with key not less
+ //! than k, or a.end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ BOOST_CONTAINER_FORCEINLINE const_iterator lower_bound(const key_type& x) const
+ { return dtl::force_copy<const_iterator>(m_flat_tree.lower_bound(x)); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the first element with key not less
+ //! than k, or a.end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ template<class K>
+ BOOST_CONTAINER_FORCEINLINE iterator lower_bound(const K& x)
+ { return dtl::force_copy<iterator>(m_flat_tree.lower_bound(x)); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the first element with key not less
+ //! than k, or a.end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ template<class K>
+ BOOST_CONTAINER_FORCEINLINE const_iterator lower_bound(const K& x) const
+ { return dtl::force_copy<const_iterator>(m_flat_tree.lower_bound(x)); }
+
+ //! <b>Returns</b>: An iterator pointing to the first element with key not less
+ //! than x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ BOOST_CONTAINER_FORCEINLINE iterator upper_bound(const key_type& x)
+ {return dtl::force_copy<iterator>(m_flat_tree.upper_bound(x)); }
+
+ //! <b>Returns</b>: A const iterator pointing to the first element with key
+ //! not less than x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ BOOST_CONTAINER_FORCEINLINE const_iterator upper_bound(const key_type& x) const
+ { return dtl::force_copy<const_iterator>(m_flat_tree.upper_bound(x)); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the first element with key not less
+ //! than x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ template<class K>
+ BOOST_CONTAINER_FORCEINLINE iterator upper_bound(const K& x)
+ {return dtl::force_copy<iterator>(m_flat_tree.upper_bound(x)); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <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
+ template<class K>
+ BOOST_CONTAINER_FORCEINLINE const_iterator upper_bound(const K& x) const
+ { return dtl::force_copy<const_iterator>(m_flat_tree.upper_bound(x)); }
+
+ //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator,iterator> equal_range(const key_type& x)
+ { return dtl::force_copy<std::pair<iterator,iterator> >(m_flat_tree.equal_range(x)); }
+
+ //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ BOOST_CONTAINER_FORCEINLINE std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const
+ { return dtl::force_copy<std::pair<const_iterator,const_iterator> >(m_flat_tree.equal_range(x)); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ template<class K>
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator,iterator> equal_range(const K& x)
+ { return dtl::force_copy<std::pair<iterator,iterator> >(m_flat_tree.equal_range(x)); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ template<class K>
+ BOOST_CONTAINER_FORCEINLINE std::pair<const_iterator, const_iterator> equal_range(const K& x) const
+ { return dtl::force_copy<std::pair<const_iterator,const_iterator> >(m_flat_tree.equal_range(x)); }
+
+ //! <b>Effects</b>: Extracts the internal sequence container.
+ //!
+ //! <b>Complexity</b>: Same as the move constructor of sequence_type, usually constant.
+ //!
+ //! <b>Postcondition</b>: this->empty()
+ //!
+ //! <b>Throws</b>: If secuence_type's move constructor throws
+ BOOST_CONTAINER_FORCEINLINE sequence_type extract_sequence()
+ {
+ return boost::move(dtl::force<sequence_type>(m_flat_tree.get_sequence_ref()));
+ }
+
+ //! <b>Effects</b>: Discards the internally hold sequence container and adopts the
+ //! one passed externally using the move assignment.
+ //!
+ //! <b>Complexity</b>: Assuming O(1) move assignment, O(NlogN) with N = seq.size()
+ //!
+ //! <b>Throws</b>: If the comparison or the move constructor throws
+ BOOST_CONTAINER_FORCEINLINE void adopt_sequence(BOOST_RV_REF(sequence_type) seq)
+ { this->m_flat_tree.adopt_sequence_equal(boost::move(dtl::force<impl_sequence_type>(seq))); }
+
+ //! <b>Requires</b>: seq shall be ordered according to this->compare().
+ //!
+ //! <b>Effects</b>: Discards the internally hold sequence container and adopts the
+ //! one passed externally using the move assignment.
+ //!
+ //! <b>Complexity</b>: Assuming O(1) move assignment, O(1)
+ //!
+ //! <b>Throws</b>: If the move assignment throws
+ BOOST_CONTAINER_FORCEINLINE void adopt_sequence(ordered_range_t, BOOST_RV_REF(sequence_type) seq)
+ { this->m_flat_tree.adopt_sequence_equal(ordered_range_t(), boost::move(dtl::force<impl_sequence_type>(seq))); }
+
+ //! <b>Effects</b>: Returns true if x and y are equal
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ BOOST_CONTAINER_FORCEINLINE friend bool operator==(const flat_multimap& x, const flat_multimap& y)
+ { return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin()); }
+
+ //! <b>Effects</b>: Returns true if x and y are unequal
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ BOOST_CONTAINER_FORCEINLINE friend bool operator!=(const flat_multimap& x, const flat_multimap& y)
+ { return !(x == y); }
+
+ //! <b>Effects</b>: Returns true if x is less than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ BOOST_CONTAINER_FORCEINLINE friend bool operator<(const flat_multimap& x, const flat_multimap& y)
+ { return ::boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
+
+ //! <b>Effects</b>: Returns true if x is greater than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ BOOST_CONTAINER_FORCEINLINE friend bool operator>(const flat_multimap& x, const flat_multimap& y)
+ { return y < x; }
+
+ //! <b>Effects</b>: Returns true if x is equal or less than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ BOOST_CONTAINER_FORCEINLINE friend bool operator<=(const flat_multimap& x, const flat_multimap& y)
+ { return !(y < x); }
+
+ //! <b>Effects</b>: Returns true if x is equal or greater than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ BOOST_CONTAINER_FORCEINLINE friend bool operator>=(const flat_multimap& x, const flat_multimap& y)
+ { return !(x < y); }
+
+ //! <b>Effects</b>: x.swap(y)
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE friend void swap(flat_multimap& x, flat_multimap& y)
+ { x.swap(y); }
+};
+
+#if __cplusplus >= 201703L
+
+template <typename InputIterator>
+flat_multimap(InputIterator, InputIterator) ->
+ flat_multimap<typename dtl::remove_const< typename iterator_traits<InputIterator>::value_type::first_type>::type
+ , typename iterator_traits<InputIterator>::value_type::second_type>;
+
+template <typename InputIterator, typename Allocator>
+flat_multimap(InputIterator, InputIterator, Allocator const&) ->
+ flat_multimap<typename dtl::remove_const< typename iterator_traits<InputIterator>::value_type::first_type>::type
+ , typename iterator_traits<InputIterator>::value_type::second_type
+ , std::less<typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type>
+ , Allocator>;
+
+template <typename InputIterator, typename Compare>
+flat_multimap(InputIterator, InputIterator, Compare const&) ->
+ flat_multimap< typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type
+ , typename iterator_traits<InputIterator>::value_type::second_type
+ , Compare>;
+
+template <typename InputIterator, typename Compare, typename Allocator>
+flat_multimap(InputIterator, InputIterator, Compare const&, Allocator const&) ->
+ flat_multimap< typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type
+ , typename iterator_traits<InputIterator>::value_type::second_type
+ , Compare
+ , Allocator>;
+
+template <typename InputIterator>
+flat_multimap(ordered_range_t, InputIterator, InputIterator) ->
+ flat_multimap< typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type
+ , typename iterator_traits<InputIterator>::value_type::second_type>;
+
+template <typename InputIterator, typename Allocator>
+flat_multimap(ordered_range_t, InputIterator, InputIterator, Allocator const&) ->
+ flat_multimap< typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type
+ , typename iterator_traits<InputIterator>::value_type::second_type
+ , std::less<typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type>
+ , Allocator>;
+
+template <typename InputIterator, typename Compare>
+flat_multimap(ordered_range_t, InputIterator, InputIterator, Compare const&) ->
+ flat_multimap< typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type
+ , typename iterator_traits<InputIterator>::value_type::second_type
+ , Compare>;
+
+template <typename InputIterator, typename Compare, typename Allocator>
+flat_multimap(ordered_range_t, InputIterator, InputIterator, Compare const&, Allocator const&) ->
+ flat_multimap< typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type
+ , typename iterator_traits<InputIterator>::value_type::second_type
+ , Compare
+ , Allocator>;
+
+#endif
+
+}}
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+namespace boost {
+
+//!has_trivial_destructor_after_move<> == true_type
+//!specialization for optimizations
+template <class Key, class T, class Compare, class AllocatorOrContainer>
+struct has_trivial_destructor_after_move< boost::container::flat_multimap<Key, T, Compare, AllocatorOrContainer> >
+{
+ typedef typename ::boost::container::allocator_traits<AllocatorOrContainer>::pointer pointer;
+ static const bool value = ::boost::has_trivial_destructor_after_move<AllocatorOrContainer>::value &&
+ ::boost::has_trivial_destructor_after_move<pointer>::value &&
+ ::boost::has_trivial_destructor_after_move<Compare>::value;
+};
+
+} //namespace boost {
+
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif // BOOST_CONTAINER_FLAT_MAP_HPP
diff --git a/include/boost/container/flat_set.hpp b/include/boost/container/flat_set.hpp
new file mode 100644
index 0000000..cfea7c8
--- /dev/null
+++ b/include/boost/container/flat_set.hpp
@@ -0,0 +1,1847 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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_FLAT_SET_HPP
+#define BOOST_CONTAINER_FLAT_SET_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+
+// container
+#include <boost/container/allocator_traits.hpp>
+#include <boost/container/container_fwd.hpp>
+#include <boost/container/new_allocator.hpp> //new_allocator
+// container/detail
+#include <boost/container/detail/flat_tree.hpp>
+#include <boost/container/detail/mpl.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>
+// 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 {
+
+#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+template <class Key, class Compare, class AllocatorOrContainer>
+class flat_multiset;
+#endif
+
+//! flat_set is a Sorted Associative Container that stores objects of type Key.
+//! It is also a Unique Associative Container, meaning that no two elements are the same.
+//!
+//! flat_set is similar to std::set but it's implemented by as an ordered sequence container.
+//! The underlying sequence container is by default <i>vector</i> but it can also work
+//! user-provided vector-like SequenceContainers (like <i>static_vector</i> or <i>small_vector</i>).
+//!
+//! Using vector-like sequence containers means that inserting a new element into a flat_set might invalidate
+//! previous iterators and references (unless that sequence container is <i>stable_vector</i> or a similar
+//! container that offers stable pointers and references). Similarly, erasing an element might invalidate
+//! iterators and references pointing to elements that come after (their keys are bigger) the erased element.
+//!
+//! This container provides random-access iterators.
+//!
+//! \tparam Key is the type to be inserted in the set, which is also the key_type
+//! \tparam Compare is the comparison functor used to order keys
+//! \tparam AllocatorOrContainer is either:
+//! - The allocator to allocate <code>value_type</code>s (e.g. <i>allocator< std::pair<Key, T> > </i>).
+//! (in this case <i>sequence_type</i> will be vector<value_type, AllocatorOrContainer>)
+//! - The SequenceContainer to be used as the underlying <i>sequence_type</i>. It must be a vector-like
+//! sequence container with random-access iterators.
+#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
+template <class Key, class Compare = std::less<Key>, class AllocatorOrContainer = new_allocator<Key> >
+#else
+template <class Key, class Compare, class AllocatorOrContainer>
+#endif
+class flat_set
+ ///@cond
+ : public dtl::flat_tree<Key, dtl::identity<Key>, Compare, AllocatorOrContainer>
+ ///@endcond
+{
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ private:
+ BOOST_COPYABLE_AND_MOVABLE(flat_set)
+ typedef dtl::flat_tree<Key, dtl::identity<Key>, Compare, AllocatorOrContainer> tree_t;
+
+ public:
+ tree_t &tree()
+ { return *this; }
+
+ const tree_t &tree() const
+ { return *this; }
+
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ public:
+ //////////////////////////////////////////////
+ //
+ // types
+ //
+ //////////////////////////////////////////////
+ typedef Key key_type;
+ typedef Compare key_compare;
+ typedef Key value_type;
+ typedef typename BOOST_CONTAINER_IMPDEF(tree_t::sequence_type) sequence_type;
+ typedef typename sequence_type::allocator_type allocator_type;
+ typedef ::boost::container::allocator_traits<allocator_type> allocator_traits_type;
+ typedef typename sequence_type::pointer pointer;
+ typedef typename sequence_type::const_pointer const_pointer;
+ typedef typename sequence_type::reference reference;
+ typedef typename sequence_type::const_reference const_reference;
+ typedef typename sequence_type::size_type size_type;
+ typedef typename sequence_type::difference_type difference_type;
+ typedef typename BOOST_CONTAINER_IMPDEF(tree_t::stored_allocator_type) stored_allocator_type;
+ typedef typename BOOST_CONTAINER_IMPDEF(tree_t::value_compare) value_compare;
+
+ typedef typename sequence_type::iterator iterator;
+ typedef typename sequence_type::const_iterator const_iterator;
+ typedef typename sequence_type::reverse_iterator reverse_iterator;
+ typedef typename sequence_type::const_reverse_iterator const_reverse_iterator;
+
+ public:
+ //////////////////////////////////////////////
+ //
+ // construct/copy/destroy
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Default constructs an empty container.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
+ flat_set() BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<AllocatorOrContainer>::value &&
+ dtl::is_nothrow_default_constructible<Compare>::value)
+ : tree_t()
+ {}
+
+ //! <b>Effects</b>: Constructs an empty container using the specified
+ //! comparison object.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
+ explicit flat_set(const Compare& comp)
+ : tree_t(comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty container using the specified allocator.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
+ explicit flat_set(const allocator_type& a)
+ : tree_t(a)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty container using the specified
+ //! comparison object and allocator.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
+ flat_set(const Compare& comp, const allocator_type& a)
+ : tree_t(comp, a)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty container and
+ //! inserts elements from the range [first ,last ).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! comp and otherwise N logN, where N is last - first.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_set(InputIterator first, InputIterator last)
+ : tree_t(true, first, last)
+ {}
+
+ //! <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>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_set(InputIterator first, InputIterator last, const allocator_type& a)
+ : tree_t(true, first, last, a)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty container using the specified comparison object and
+ //! inserts elements from the range [first ,last ).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! comp and otherwise N logN, where N is last - first.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_set(InputIterator first, InputIterator last, const Compare& comp)
+ : tree_t(true, first, last, comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty container using the specified comparison object and
+ //! allocator, and inserts elements from the range [first ,last ).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! comp and otherwise N logN, where N is last - first.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_set(InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
+ : tree_t(true, first, last, comp, a)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty container and
+ //! inserts elements from the ordered unique range [first ,last). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate and must be
+ //! unique values.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_set(ordered_unique_range_t, InputIterator first, InputIterator last)
+ : tree_t(ordered_unique_range, first, last)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty container using the specified comparison object and
+ //! inserts elements from the ordered unique range [first ,last). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate and must be
+ //! unique values.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_set(ordered_unique_range_t, InputIterator first, InputIterator last, const Compare& comp)
+ : tree_t(ordered_unique_range, first, last, comp)
+ {}
+
+ //! <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.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate and must be
+ //! unique values.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE
+ flat_set(ordered_unique_range_t, InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
+ : tree_t(ordered_unique_range, first, last, comp, a)
+ {}
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Constructs an empty container and
+ //! inserts elements from the range [il.begin(), il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
+ //! comp and otherwise N logN, where N is il.begin() - il.end().
+ BOOST_CONTAINER_FORCEINLINE flat_set(std::initializer_list<value_type> il)
+ : tree_t(true, il.begin(), il.end())
+ {}
+
+ //! <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().
+ BOOST_CONTAINER_FORCEINLINE flat_set(std::initializer_list<value_type> il, const allocator_type& a)
+ : tree_t(true, il.begin(), il.end(), a)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty container using the specified comparison object and
+ //! inserts elements from the range [il.begin(), il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
+ //! comp and otherwise N logN, where N is il.begin() - il.end().
+ BOOST_CONTAINER_FORCEINLINE flat_set(std::initializer_list<value_type> il, const Compare& comp)
+ : tree_t(true, il.begin(), il.end(), comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty container using the specified comparison object and
+ //! allocator, and inserts elements from the range [il.begin(), il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
+ //! comp and otherwise N logN, where N is il.begin() - il.end().
+ BOOST_CONTAINER_FORCEINLINE flat_set(std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
+ : tree_t(true, il.begin(), il.end(), comp, a)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty container using the specified comparison object and
+ //! inserts elements from the ordered unique range [il.begin(), il.end()). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be
+ //! unique values.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE flat_set(ordered_unique_range_t, std::initializer_list<value_type> il)
+ : tree_t(ordered_unique_range, il.begin(), il.end())
+ {}
+
+ //! <b>Effects</b>: Constructs an empty container using the specified comparison object and
+ //! inserts elements from the ordered unique range [il.begin(), il.end()). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be
+ //! unique values.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE flat_set(ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp)
+ : tree_t(ordered_unique_range, il.begin(), il.end(), comp)
+ {}
+
+ //! <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
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be
+ //! unique values.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE flat_set(ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
+ : tree_t(ordered_unique_range, il.begin(), il.end(), comp, a)
+ {}
+#endif
+
+ //! <b>Effects</b>: Copy constructs the container.
+ //!
+ //! <b>Complexity</b>: Linear in x.size().
+ BOOST_CONTAINER_FORCEINLINE flat_set(const flat_set& x)
+ : tree_t(static_cast<const tree_t&>(x))
+ {}
+
+ //! <b>Effects</b>: Move constructs thecontainer. Constructs *this using x's resources.
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Postcondition</b>: x is emptied.
+ BOOST_CONTAINER_FORCEINLINE flat_set(BOOST_RV_REF(flat_set) x)
+ BOOST_NOEXCEPT_IF(boost::container::dtl::is_nothrow_move_constructible<Compare>::value)
+ : tree_t(BOOST_MOVE_BASE(tree_t, x))
+ {}
+
+ //! <b>Effects</b>: Copy constructs a container using the specified allocator.
+ //!
+ //! <b>Complexity</b>: Linear in x.size().
+ BOOST_CONTAINER_FORCEINLINE flat_set(const flat_set& x, const allocator_type &a)
+ : tree_t(static_cast<const tree_t&>(x), a)
+ {}
+
+ //! <b>Effects</b>: Move constructs a container using the specified allocator.
+ //! Constructs *this using x's resources.
+ //!
+ //! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise
+ BOOST_CONTAINER_FORCEINLINE flat_set(BOOST_RV_REF(flat_set) x, const allocator_type &a)
+ : tree_t(BOOST_MOVE_BASE(tree_t, x), a)
+ {}
+
+ //! <b>Effects</b>: Makes *this a copy of x.
+ //!
+ //! <b>Complexity</b>: Linear in x.size().
+ BOOST_CONTAINER_FORCEINLINE flat_set& operator=(BOOST_COPY_ASSIGN_REF(flat_set) x)
+ { return static_cast<flat_set&>(this->tree_t::operator=(static_cast<const tree_t&>(x))); }
+
+ //! <b>Throws</b>: If allocator_traits_type::propagate_on_container_move_assignment
+ //! is false and (allocation throws or value_type's move constructor throws)
+ //!
+ //! <b>Complexity</b>: Constant if allocator_traits_type::
+ //! propagate_on_container_move_assignment is true or
+ //! this->get>allocator() == x.get_allocator(). Linear otherwise.
+ BOOST_CONTAINER_FORCEINLINE flat_set& operator=(BOOST_RV_REF(flat_set) x)
+ BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value ||
+ allocator_traits_type::is_always_equal::value) &&
+ boost::container::dtl::is_nothrow_move_assignable<Compare>::value)
+ { return static_cast<flat_set&>(this->tree_t::operator=(BOOST_MOVE_BASE(tree_t, x))); }
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Copy all elements from il to *this.
+ //!
+ //! <b>Complexity</b>: Linear in il.size().
+ flat_set& operator=(std::initializer_list<value_type> il)
+ {
+ this->clear();
+ this->insert(il.begin(), il.end());
+ return *this;
+ }
+#endif
+
+ #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
+ //! <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_NOEXCEPT_OR_NOTHROW;
+
+ //! <b>Effects</b>: Returns a reference to the internal allocator.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! <b>Effects</b>: Returns a reference to the internal allocator.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ 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_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_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_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_NOEXCEPT_OR_NOTHROW;
+
+ //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ 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_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_NOEXCEPT_OR_NOTHROW;
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ 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.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ 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_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_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_NOEXCEPT_OR_NOTHROW;
+
+ //! <b>Effects</b>: Number of elements for which memory has been allocated.
+ //! capacity() is always greater than or equal to size().
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! <b>Effects</b>: If n is less than or equal to capacity(), or the
+ //! underlying container has no `reserve` member, this call has no
+ //! effect. Otherwise, it is a request for allocation of additional memory.
+ //! If the request is successful, then capacity() is greater than or equal to
+ //! n; otherwise, capacity() is unchanged. In either case, size() is unchanged.
+ //!
+ //! <b>Throws</b>: If memory allocation allocation throws or T's copy constructor throws.
+ //!
+ //! <b>Note</b>: If capacity() is less than "cnt", iterators and references to
+ //! to values might be invalidated.
+ void reserve(size_type cnt);
+
+ //! <b>Effects</b>: Tries to deallocate the excess of memory created
+ // with previous allocations. The size of the vector is unchanged
+ //!
+ //! <b>Throws</b>: If memory allocation throws, or Key's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to size().
+ void shrink_to_fit();
+
+ #endif // #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ //////////////////////////////////////////////
+ //
+ // modifiers
+ //
+ //////////////////////////////////////////////
+
+ #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
+ //! with key equivalent to the key of x.
+ //!
+ //! <b>Returns</b>: The bool component of the returned pair is true if and only
+ //! if the insertion takes place, and the iterator component of the pair
+ //! points to the element with key equivalent to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time plus linear insertion
+ //! to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ template <class... Args>
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> emplace(BOOST_FWD_REF(Args)... args)
+ { return this->tree_t::emplace_unique(boost::forward<Args>(args)...); }
+
+ //! <b>Effects</b>: Inserts an object of type Key constructed with
+ //! std::forward<Args>(args)... in the container if and only if there is
+ //! no element in the container with key equivalent to the key of x.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time (constant if x is inserted
+ //! right before p) plus insertion linear to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ template <class... Args>
+ BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator p, BOOST_FWD_REF(Args)... args)
+ { return this->tree_t::emplace_hint_unique(p, boost::forward<Args>(args)...); }
+
+ #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ #define BOOST_CONTAINER_FLAT_SET_EMPLACE_CODE(N) \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> emplace(BOOST_MOVE_UREF##N)\
+ { return this->tree_t::emplace_unique(BOOST_MOVE_FWD##N); }\
+ \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ { return this->tree_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 // !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
+ //! with key equivalent to the key of x.
+ //!
+ //! <b>Returns</b>: The bool component of the returned pair is true if and only
+ //! if the insertion takes place, and the iterator component of the pair
+ //! points to the element with key equivalent to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time plus linear insertion
+ //! to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ std::pair<iterator, bool> insert(const value_type &x);
+
+ //! <b>Effects</b>: Inserts a new value_type move constructed from the pair if and
+ //! only if there is no element in the container with key equivalent to the key of x.
+ //!
+ //! <b>Returns</b>: The bool component of the returned pair is true if and only
+ //! if the insertion takes place, and the iterator component of the pair
+ //! points to the element with key equivalent to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time plus linear insertion
+ //! to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ std::pair<iterator, bool> insert(value_type &&x);
+ #else
+ private:
+ typedef std::pair<iterator, bool> insert_return_pair;
+ public:
+ BOOST_MOVE_CONVERSION_AWARE_CATCH(insert, value_type, insert_return_pair, this->priv_insert)
+ #endif
+
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ //! <b>Effects</b>: Inserts a copy of x in the container if and only if there is
+ //! no element in the container with key equivalent to the key of x.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time (constant if x is inserted
+ //! right before p) plus insertion linear to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ iterator insert(const_iterator p, const value_type &x);
+
+ //! <b>Effects</b>: Inserts an element move constructed from x in the container.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time (constant if x is inserted
+ //! right before p) plus insertion linear to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ iterator insert(const_iterator p, value_type &&x);
+ #else
+ BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, value_type, iterator, this->priv_insert, const_iterator, const_iterator)
+ #endif
+
+ //! <b>Requires</b>: first, last are not iterators into *this.
+ //!
+ //! <b>Effects</b>: inserts each element from the range [first,last) if and only
+ //! if there is no element with key equivalent to the key of that element.
+ //!
+ //! <b>Complexity</b>: N log(N).
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE void insert(InputIterator first, InputIterator last)
+ { this->tree_t::insert_unique(first, last); }
+
+ //! <b>Requires</b>: first, last are not iterators into *this and
+ //! must be ordered according to the predicate and must be
+ //! unique values.
+ //!
+ //! <b>Effects</b>: inserts each element from the range [first,last) .This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Complexity</b>: Linear.
+ //!
+ //! <b>Note</b>: Non-standard extension. If an element is inserted it might invalidate elements.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE void insert(ordered_unique_range_t, InputIterator first, InputIterator last)
+ { this->tree_t::insert_unique(ordered_unique_range, first, last); }
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()) if and only
+ //! if there is no element with key equivalent to the key of that element.
+ //!
+ //! <b>Complexity</b>: N log(N).
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il)
+ { this->tree_t::insert_unique(il.begin(), il.end()); }
+
+ //! <b>Requires</b>: Range [il.begin(), il.end()) must be ordered according to the predicate
+ //! and must be unique values.
+ //!
+ //! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()) .This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Complexity</b>: Linear.
+ //!
+ //! <b>Note</b>: Non-standard extension. If an element is inserted it might invalidate elements.
+ BOOST_CONTAINER_FORCEINLINE void insert(ordered_unique_range_t, std::initializer_list<value_type> il)
+ { this->tree_t::insert_unique(ordered_unique_range, il.begin(), il.end()); }
+#endif
+
+ //! @copydoc ::boost::container::flat_map::merge(flat_map<Key, T, C2, AllocatorOrContainer>&)
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge(flat_set<Key, C2, AllocatorOrContainer>& source)
+ { this->tree_t::merge_unique(source.tree()); }
+
+ //! @copydoc ::boost::container::flat_set::merge(flat_set<Key, C2, AllocatorOrContainer>&)
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_set<Key, C2, AllocatorOrContainer> BOOST_RV_REF_END source)
+ { return this->merge(static_cast<flat_set<Key, C2, AllocatorOrContainer>&>(source)); }
+
+ //! @copydoc ::boost::container::flat_map::merge(flat_multimap<Key, T, C2, AllocatorOrContainer>&)
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge(flat_multiset<Key, C2, AllocatorOrContainer>& source)
+ { this->tree_t::merge_unique(source.tree()); }
+
+ //! @copydoc ::boost::container::flat_set::merge(flat_multiset<Key, C2, AllocatorOrContainer>&)
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_multiset<Key, C2, AllocatorOrContainer> BOOST_RV_REF_END source)
+ { return this->merge(static_cast<flat_multiset<Key, C2, AllocatorOrContainer>&>(source)); }
+
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ //! <b>Effects</b>: Erases the element pointed to by p.
+ //!
+ //! <b>Returns</b>: Returns an iterator pointing to the element immediately
+ //! following q prior to the element being erased. If no such element exists,
+ //! returns end().
+ //!
+ //! <b>Complexity</b>: Linear to the elements with keys bigger than p
+ //!
+ //! <b>Note</b>: Invalidates elements with keys
+ //! not less than the erased element.
+ iterator erase(const_iterator p);
+
+ //! <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>: Logarithmic search time plus erasure time
+ //! linear to the elements with bigger keys.
+ size_type erase(const key_type& x);
+
+ //! <b>Effects</b>: Erases all the elements in the range [first, last).
+ //!
+ //! <b>Returns</b>: Returns last.
+ //!
+ //! <b>Complexity</b>: size()*N where N is the distance from first to last.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time plus erasure time
+ //! linear to the elements with bigger keys.
+ iterator erase(const_iterator first, const_iterator last);
+
+ //! <b>Effects</b>: Swaps the contents of *this and x.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ void swap(flat_set& x)
+ BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value
+ && boost::container::dtl::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_NOEXCEPT_OR_NOTHROW;
+
+ //! <b>Effects</b>: Returns the comparison object out
+ //! of which a was constructed.
+ //!
+ //! <b>Complexity</b>: Constant.
+ key_compare key_comp() const;
+
+ //! <b>Effects</b>: Returns an object of value_compare constructed out
+ //! of the comparison object.
+ //!
+ //! <b>Complexity</b>: Constant.
+ value_compare value_comp() const;
+
+ //! <b>Returns</b>: An iterator pointing to an element with the key
+ //! equivalent to x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ iterator find(const key_type& x);
+
+ //! <b>Returns</b>: A const_iterator pointing to an element with the key
+ //! equivalent to x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ const_iterator find(const key_type& x) const;
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Returns</b>: An iterator pointing to an element with the key
+ //! equivalent to x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ template<typename K>
+ iterator find(const K& x);
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <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.
+ template<typename K>
+ const_iterator find(const K& 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>: 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(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.
+ //!
+ //! <b>Complexity</b>: log(size())+count(k)
+ BOOST_CONTAINER_FORCEINLINE size_type count(const key_type& x) const
+ { return static_cast<size_type>(this->tree_t::find(x) != this->tree_t::cend()); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Returns</b>: The number of elements with key equivalent to x.
+ //!
+ //! <b>Complexity</b>: log(size())+count(k)
+ template<typename K>
+ BOOST_CONTAINER_FORCEINLINE size_type count(const K& x) const
+ { return static_cast<size_type>(this->tree_t::find(x) != this->tree_t::cend()); }
+
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ //! <b>Returns</b>: An iterator pointing to the first element with key not less
+ //! than k, or a.end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ iterator lower_bound(const key_type& x);
+
+ //! <b>Returns</b>: A const iterator pointing to the first element with key not
+ //! less than k, or a.end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ const_iterator lower_bound(const key_type& x) const;
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the first element with key not less
+ //! than k, or a.end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ template<typename K>
+ iterator lower_bound(const K& x);
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <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
+ template<typename K>
+ const_iterator lower_bound(const K& x) const;
+
+ //! <b>Returns</b>: An iterator pointing to the first element with key not less
+ //! than x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ iterator upper_bound(const key_type& x);
+
+ //! <b>Returns</b>: A const iterator pointing to the first element with key not
+ //! less than x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ const_iterator upper_bound(const key_type& x) const;
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the first element with key not less
+ //! than x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ template<typename K>
+ iterator upper_bound(const K& x);
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <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
+ template<typename K>
+ const_iterator upper_bound(const K& x) const;
+
+ #endif // #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ BOOST_CONTAINER_FORCEINLINE std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const
+ { return this->tree_t::lower_bound_range(x); }
+
+ //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator,iterator> equal_range(const key_type& x)
+ { return this->tree_t::lower_bound_range(x); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ template<typename K>
+ std::pair<iterator,iterator> equal_range(const K& x)
+ { return this->tree_t::lower_bound_range(x); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ template<typename K>
+ std::pair<const_iterator,const_iterator> equal_range(const K& x) const
+ { return this->tree_t::lower_bound_range(x); }
+
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ //! <b>Effects</b>: Returns true if x and y are equal
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator==(const flat_set& x, const flat_set& y);
+
+ //! <b>Effects</b>: Returns true if x and y are unequal
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator!=(const flat_set& x, const flat_set& y);
+
+ //! <b>Effects</b>: Returns true if x is less than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator<(const flat_set& x, const flat_set& y);
+
+ //! <b>Effects</b>: Returns true if x is greater than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator>(const flat_set& x, const flat_set& y);
+
+ //! <b>Effects</b>: Returns true if x is equal or less than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator<=(const flat_set& x, const flat_set& y);
+
+ //! <b>Effects</b>: Returns true if x is equal or greater than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator>=(const flat_set& x, const flat_set& y);
+
+ //! <b>Effects</b>: x.swap(y)
+ //!
+ //! <b>Complexity</b>: Constant.
+ friend void swap(flat_set& x, flat_set& y);
+
+ //! <b>Effects</b>: Extracts the internal sequence container.
+ //!
+ //! <b>Complexity</b>: Same as the move constructor of sequence_type, usually constant.
+ //!
+ //! <b>Postcondition</b>: this->empty()
+ //!
+ //! <b>Throws</b>: If secuence_type's move constructor throws
+ sequence_type extract_sequence();
+
+ #endif //#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ //! <b>Effects</b>: Discards the internally hold sequence container and adopts the
+ //! one passed externally using the move assignment. Erases non-unique elements.
+ //!
+ //! <b>Complexity</b>: Assuming O(1) move assignment, O(NlogN) with N = seq.size()
+ //!
+ //! <b>Throws</b>: If the comparison or the move constructor throws
+ BOOST_CONTAINER_FORCEINLINE void adopt_sequence(BOOST_RV_REF(sequence_type) seq)
+ { this->tree_t::adopt_sequence_unique(boost::move(seq)); }
+
+ //! <b>Requires</b>: seq shall be ordered according to this->compare()
+ //! and shall contain unique elements.
+ //!
+ //! <b>Effects</b>: Discards the internally hold sequence container and adopts the
+ //! one passed externally using the move assignment.
+ //!
+ //! <b>Complexity</b>: Assuming O(1) move assignment, O(1)
+ //!
+ //! <b>Throws</b>: If the move assignment throws
+ BOOST_CONTAINER_FORCEINLINE void adopt_sequence(ordered_unique_range_t, BOOST_RV_REF(sequence_type) seq)
+ { this->tree_t::adopt_sequence_unique(ordered_unique_range_t(), boost::move(seq)); }
+
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ private:
+ template<class KeyType>
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> priv_insert(BOOST_FWD_REF(KeyType) x)
+ { return this->tree_t::insert_unique(::boost::forward<KeyType>(x)); }
+
+ template<class KeyType>
+ BOOST_CONTAINER_FORCEINLINE iterator priv_insert(const_iterator p, BOOST_FWD_REF(KeyType) x)
+ { return this->tree_t::insert_unique(p, ::boost::forward<KeyType>(x)); }
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+};
+
+#if __cplusplus >= 201703L
+
+template <typename InputIterator>
+flat_set(InputIterator, InputIterator) ->
+ flat_set<typename iterator_traits<InputIterator>::value_type>;
+
+template <typename InputIterator, typename Allocator>
+flat_set(InputIterator, InputIterator, Allocator const&) ->
+ flat_set<typename iterator_traits<InputIterator>::value_type, std::less<typename iterator_traits<InputIterator>::value_type>, Allocator>;
+
+template <typename InputIterator, typename Compare>
+flat_set(InputIterator, InputIterator, Compare const&) ->
+ flat_set<typename iterator_traits<InputIterator>::value_type, Compare>;
+
+template <typename InputIterator, typename Compare, typename Allocator>
+flat_set(InputIterator, InputIterator, Compare const&, Allocator const&) ->
+ flat_set<typename iterator_traits<InputIterator>::value_type, Compare, Allocator>;
+
+template <typename InputIterator>
+flat_set(ordered_unique_range_t, InputIterator, InputIterator) ->
+ flat_set<typename iterator_traits<InputIterator>::value_type>;
+
+template <typename InputIterator, typename Allocator>
+flat_set(ordered_unique_range_t, InputIterator, InputIterator, Allocator const&) ->
+ flat_set<typename iterator_traits<InputIterator>::value_type, std::less<typename iterator_traits<InputIterator>::value_type>, Allocator>;
+
+template <typename InputIterator, typename Compare>
+flat_set(ordered_unique_range_t, InputIterator, InputIterator, Compare const&) ->
+ flat_set<typename iterator_traits<InputIterator>::value_type, Compare>;
+
+template <typename InputIterator, typename Compare, typename Allocator>
+flat_set(ordered_unique_range_t, InputIterator, InputIterator, Compare const&, Allocator const&) ->
+ flat_set<typename iterator_traits<InputIterator>::value_type, Compare, Allocator>;
+
+#endif
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+} //namespace container {
+
+//!has_trivial_destructor_after_move<> == true_type
+//!specialization for optimizations
+template <class Key, class Compare, class AllocatorOrContainer>
+struct has_trivial_destructor_after_move<boost::container::flat_set<Key, Compare, AllocatorOrContainer> >
+{
+ typedef typename ::boost::container::allocator_traits<AllocatorOrContainer>::pointer pointer;
+ static const bool value = ::boost::has_trivial_destructor_after_move<AllocatorOrContainer>::value &&
+ ::boost::has_trivial_destructor_after_move<pointer>::value &&
+ ::boost::has_trivial_destructor_after_move<Compare>::value;
+};
+
+namespace container {
+
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+//! flat_multiset is a Sorted Associative Container that stores objects of type Key and
+//! can store multiple copies of the same key value.
+//!
+//! flat_multiset is similar to std::multiset but it's implemented by as an ordered sequence container.
+//! The underlying sequence container is by default <i>vector</i> but it can also work
+//! user-provided vector-like SequenceContainers (like <i>static_vector</i> or <i>small_vector</i>).
+//!
+//! Using vector-like sequence containers means that inserting a new element into a flat_multiset might invalidate
+//! previous iterators and references (unless that sequence container is <i>stable_vector</i> or a similar
+//! container that offers stable pointers and references). Similarly, erasing an element might invalidate
+//! iterators and references pointing to elements that come after (their keys are bigger) the erased element.
+//!
+//! This container provides random-access iterators.
+//!
+//! \tparam Key is the type to be inserted in the multiset, which is also the key_type
+//! \tparam Compare is the comparison functor used to order keys
+//! \tparam AllocatorOrContainer is either:
+//! - The allocator to allocate <code>value_type</code>s (e.g. <i>allocator< std::pair<Key, T> > </i>).
+//! (in this case <i>sequence_type</i> will be vector<value_type, AllocatorOrContainer>)
+//! - The SequenceContainer to be used as the underlying <i>sequence_type</i>. It must be a vector-like
+//! sequence container with random-access iterators.
+#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
+template <class Key, class Compare = std::less<Key>, class AllocatorOrContainer = new_allocator<Key> >
+#else
+template <class Key, class Compare, class AllocatorOrContainer>
+#endif
+class flat_multiset
+ ///@cond
+ : public dtl::flat_tree<Key, dtl::identity<Key>, Compare, AllocatorOrContainer>
+ ///@endcond
+{
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ private:
+ BOOST_COPYABLE_AND_MOVABLE(flat_multiset)
+ typedef dtl::flat_tree<Key, dtl::identity<Key>, Compare, AllocatorOrContainer> tree_t;
+
+ public:
+ tree_t &tree()
+ { return *this; }
+
+ const tree_t &tree() const
+ { return *this; }
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ public:
+ //////////////////////////////////////////////
+ //
+ // types
+ //
+ //////////////////////////////////////////////
+ typedef Key key_type;
+ typedef Compare key_compare;
+ typedef Key value_type;
+ typedef typename BOOST_CONTAINER_IMPDEF(tree_t::sequence_type) sequence_type;
+ typedef typename sequence_type::allocator_type allocator_type;
+ typedef ::boost::container::allocator_traits<allocator_type> allocator_traits_type;
+ typedef typename sequence_type::pointer pointer;
+ typedef typename sequence_type::const_pointer const_pointer;
+ typedef typename sequence_type::reference reference;
+ typedef typename sequence_type::const_reference const_reference;
+ typedef typename sequence_type::size_type size_type;
+ typedef typename sequence_type::difference_type difference_type;
+ typedef typename BOOST_CONTAINER_IMPDEF(tree_t::stored_allocator_type) stored_allocator_type;
+ typedef typename BOOST_CONTAINER_IMPDEF(tree_t::value_compare) value_compare;
+
+ typedef typename sequence_type::iterator iterator;
+ typedef typename sequence_type::const_iterator const_iterator;
+ typedef typename sequence_type::reverse_iterator reverse_iterator;
+ typedef typename sequence_type::const_reverse_iterator const_reverse_iterator;
+
+ //! @copydoc ::boost::container::flat_set::flat_set()
+ BOOST_CONTAINER_FORCEINLINE flat_multiset() BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<AllocatorOrContainer>::value &&
+ dtl::is_nothrow_default_constructible<Compare>::value)
+ : tree_t()
+ {}
+
+ //! @copydoc ::boost::container::flat_set::flat_set(const Compare&)
+ BOOST_CONTAINER_FORCEINLINE explicit flat_multiset(const Compare& comp)
+ : tree_t(comp)
+ {}
+
+ //! @copydoc ::boost::container::flat_set::flat_set(const allocator_type&)
+ BOOST_CONTAINER_FORCEINLINE explicit flat_multiset(const allocator_type& a)
+ : tree_t(a)
+ {}
+
+ //! @copydoc ::boost::container::flat_set::flat_set(const Compare&, const allocator_type&)
+ BOOST_CONTAINER_FORCEINLINE flat_multiset(const Compare& comp, const allocator_type& a)
+ : tree_t(comp, a)
+ {}
+
+ //! @copydoc ::boost::container::flat_set::flat_set(InputIterator, InputIterator)
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE flat_multiset(InputIterator first, InputIterator last)
+ : tree_t(false, first, last)
+ {}
+
+ //! @copydoc ::boost::container::flat_set::flat_set(InputIterator, InputIterator, const allocator_type&)
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE flat_multiset(InputIterator first, InputIterator last, const allocator_type& a)
+ : tree_t(false, first, last, a)
+ {}
+
+ //! @copydoc ::boost::container::flat_set::flat_set(InputIterator, InputIterator, const Compare& comp)
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE flat_multiset(InputIterator first, InputIterator last, const Compare& comp)
+ : tree_t(false, first, last, comp)
+ {}
+
+ //! @copydoc ::boost::container::flat_set::flat_set(InputIterator, InputIterator, const Compare& comp, const allocator_type&)
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE flat_multiset(InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
+ : tree_t(false, first, last, comp, a)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_multiset and
+ //! inserts elements from the ordered range [first ,last ). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE flat_multiset(ordered_range_t, InputIterator first, InputIterator last)
+ : tree_t(ordered_range, first, last)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_multiset using the specified comparison object and
+ //! inserts elements from the ordered range [first ,last ). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE flat_multiset(ordered_range_t, InputIterator first, InputIterator last, const Compare& comp)
+ : tree_t(ordered_range, first, last, comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty flat_multiset using the specified comparison object and
+ //! allocator, and inserts elements from the ordered range [first, last ). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE flat_multiset(ordered_range_t, InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
+ : tree_t(ordered_range, first, last, comp, a)
+ {}
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! @copydoc ::boost::container::flat_set::flat_set(std::initializer_list<value_type)
+ BOOST_CONTAINER_FORCEINLINE flat_multiset(std::initializer_list<value_type> il)
+ : tree_t(false, il.begin(), il.end())
+ {}
+
+ //! @copydoc ::boost::container::flat_set::flat_set(std::initializer_list<value_type>, const allocator_type&)
+ BOOST_CONTAINER_FORCEINLINE flat_multiset(std::initializer_list<value_type> il, const allocator_type& a)
+ : tree_t(false, il.begin(), il.end(), a)
+ {}
+
+ //! @copydoc ::boost::container::flat_set::flat_set(std::initializer_list<value_type>, const Compare& comp)
+ BOOST_CONTAINER_FORCEINLINE flat_multiset(std::initializer_list<value_type> il, const Compare& comp)
+ : tree_t(false, il.begin(), il.end(), comp)
+ {}
+
+ //! @copydoc ::boost::container::flat_set::flat_set(std::initializer_list<value_type>, const Compare& comp, const allocator_type&)
+ BOOST_CONTAINER_FORCEINLINE flat_multiset(std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
+ : tree_t(false, il.begin(), il.end(), comp, a)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty containerand
+ //! inserts elements from the ordered unique range [il.begin(), il.end()). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE flat_multiset(ordered_range_t, std::initializer_list<value_type> il)
+ : tree_t(ordered_range, il.begin(), il.end())
+ {}
+
+ //! <b>Effects</b>: Constructs an empty container using the specified comparison object and
+ //! inserts elements from the ordered unique range [il.begin(), il.end()). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE flat_multiset(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp)
+ : tree_t(ordered_range, il.begin(), il.end(), comp)
+ {}
+
+ //! <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
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE flat_multiset(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
+ : tree_t(ordered_range, il.begin(), il.end(), comp, a)
+ {}
+#endif
+
+ //! @copydoc ::boost::container::flat_set::flat_set(const flat_set &)
+ BOOST_CONTAINER_FORCEINLINE flat_multiset(const flat_multiset& x)
+ : tree_t(static_cast<const tree_t&>(x))
+ {}
+
+ //! @copydoc ::boost::container::flat_set::flat_set(flat_set &&)
+ BOOST_CONTAINER_FORCEINLINE flat_multiset(BOOST_RV_REF(flat_multiset) x)
+ BOOST_NOEXCEPT_IF(boost::container::dtl::is_nothrow_move_constructible<Compare>::value)
+ : tree_t(boost::move(static_cast<tree_t&>(x)))
+ {}
+
+ //! @copydoc ::boost::container::flat_set::flat_set(const flat_set &, const allocator_type &)
+ BOOST_CONTAINER_FORCEINLINE flat_multiset(const flat_multiset& x, const allocator_type &a)
+ : tree_t(static_cast<const tree_t&>(x), a)
+ {}
+
+ //! @copydoc ::boost::container::flat_set::flat_set(flat_set &&, const allocator_type &)
+ BOOST_CONTAINER_FORCEINLINE flat_multiset(BOOST_RV_REF(flat_multiset) x, const allocator_type &a)
+ : tree_t(BOOST_MOVE_BASE(tree_t, x), a)
+ {}
+
+ //! @copydoc ::boost::container::flat_set::operator=(const flat_set &)
+ BOOST_CONTAINER_FORCEINLINE flat_multiset& operator=(BOOST_COPY_ASSIGN_REF(flat_multiset) x)
+ { return static_cast<flat_multiset&>(this->tree_t::operator=(static_cast<const tree_t&>(x))); }
+
+ //! @copydoc ::boost::container::flat_set::operator=(flat_set &&)
+ BOOST_CONTAINER_FORCEINLINE flat_multiset& operator=(BOOST_RV_REF(flat_multiset) x)
+ BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value ||
+ allocator_traits_type::is_always_equal::value) &&
+ boost::container::dtl::is_nothrow_move_assignable<Compare>::value)
+ { return static_cast<flat_multiset&>(this->tree_t::operator=(BOOST_MOVE_BASE(tree_t, x))); }
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! @copydoc ::boost::container::flat_set::operator=(std::initializer_list<value_type>)
+ flat_multiset& operator=(std::initializer_list<value_type> il)
+ {
+ this->clear();
+ this->insert(il.begin(), il.end());
+ return *this;
+ }
+#endif
+
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ //! @copydoc ::boost::container::flat_set::get_allocator()
+ allocator_type get_allocator() const BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @copydoc ::boost::container::flat_set::get_stored_allocator()
+ 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_NOEXCEPT_OR_NOTHROW;
+
+ //! @copydoc ::boost::container::flat_set::begin()
+ 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_NOEXCEPT_OR_NOTHROW;
+
+ //! @copydoc ::boost::container::flat_set::end()
+ iterator end() BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @copydoc ::boost::container::flat_set::end() const
+ const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @copydoc ::boost::container::flat_set::cend() const
+ const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @copydoc ::boost::container::flat_set::rbegin()
+ reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @copydoc ::boost::container::flat_set::rbegin() const
+ const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @copydoc ::boost::container::flat_set::crbegin() const
+ const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @copydoc ::boost::container::flat_set::rend()
+ reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @copydoc ::boost::container::flat_set::rend() const
+ const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @copydoc ::boost::container::flat_set::crend() const
+ const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @copydoc ::boost::container::flat_set::empty() const
+ bool empty() const BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @copydoc ::boost::container::flat_set::size() const
+ size_type size() const BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @copydoc ::boost::container::flat_set::max_size() const
+ size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @copydoc ::boost::container::flat_set::capacity() const
+ size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @copydoc ::boost::container::flat_set::reserve(size_type)
+ void reserve(size_type cnt);
+
+ //! @copydoc ::boost::container::flat_set::shrink_to_fit()
+ void shrink_to_fit();
+
+ #endif // #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ //////////////////////////////////////////////
+ //
+ // modifiers
+ //
+ //////////////////////////////////////////////
+
+ #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
+ //! newly inserted element.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time plus linear insertion
+ //! to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ template <class... Args>
+ BOOST_CONTAINER_FORCEINLINE iterator emplace(BOOST_FWD_REF(Args)... args)
+ { return this->tree_t::emplace_equal(boost::forward<Args>(args)...); }
+
+ //! <b>Effects</b>: Inserts an object of type Key constructed with
+ //! std::forward<Args>(args)... in the container.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time (constant if x is inserted
+ //! right before p) plus insertion linear to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ template <class... Args>
+ BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator p, BOOST_FWD_REF(Args)... args)
+ { return this->tree_t::emplace_hint_equal(p, boost::forward<Args>(args)...); }
+
+ #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ #define BOOST_CONTAINER_FLAT_MULTISET_EMPLACE_CODE(N) \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ BOOST_CONTAINER_FORCEINLINE iterator emplace(BOOST_MOVE_UREF##N)\
+ { return this->tree_t::emplace_equal(BOOST_MOVE_FWD##N); }\
+ \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ { return this->tree_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 // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ //! <b>Effects</b>: Inserts x and returns the iterator pointing to the
+ //! newly inserted element.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time plus linear insertion
+ //! to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ iterator insert(const value_type &x);
+
+ //! <b>Effects</b>: Inserts a new value_type move constructed from x
+ //! and returns the iterator pointing to the newly inserted element.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time plus linear insertion
+ //! to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ iterator insert(value_type &&x);
+ #else
+ BOOST_MOVE_CONVERSION_AWARE_CATCH(insert, value_type, iterator, this->priv_insert)
+ #endif
+
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ //! <b>Effects</b>: Inserts a copy of x in the container.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time (constant if x is inserted
+ //! right before p) plus insertion linear to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ iterator insert(const_iterator p, const value_type &x);
+
+ //! <b>Effects</b>: Inserts a new value move constructed from x in the container.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic search time (constant if x is inserted
+ //! right before p) plus insertion linear to the elements with bigger keys than x.
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ iterator insert(const_iterator p, value_type &&x);
+ #else
+ BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, value_type, iterator, this->priv_insert, const_iterator, const_iterator)
+ #endif
+
+ //! <b>Requires</b>: first, last are not iterators into *this.
+ //!
+ //! <b>Effects</b>: inserts each element from the range [first,last) .
+ //!
+ //! <b>Complexity</b>: N log(N).
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE void insert(InputIterator first, InputIterator last)
+ { this->tree_t::insert_equal(first, last); }
+
+ //! <b>Requires</b>: first, last are not iterators into *this and
+ //! must be ordered according to the predicate.
+ //!
+ //! <b>Effects</b>: inserts each element from the range [first,last) .This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Complexity</b>: Linear.
+ //!
+ //! <b>Note</b>: Non-standard extension. If an element is inserted it might invalidate elements.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE void insert(ordered_range_t, InputIterator first, InputIterator last)
+ { this->tree_t::insert_equal(ordered_range, first, last); }
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()).
+ //!
+ //! <b>Complexity</b>: N log(N).
+ //!
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il)
+ { this->tree_t::insert_equal(il.begin(), il.end()); }
+
+ //! <b>Requires</b>: Range [il.begin(), il.end()) must be ordered according to the predicate.
+ //!
+ //! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Complexity</b>: Linear.
+ //!
+ //! <b>Note</b>: Non-standard extension. If an element is inserted it might invalidate elements.
+ BOOST_CONTAINER_FORCEINLINE void insert(ordered_range_t, std::initializer_list<value_type> il)
+ { this->tree_t::insert_equal(ordered_range, il.begin(), il.end()); }
+#endif
+
+ //! @copydoc ::boost::container::flat_multimap::merge(flat_multimap<Key, T, C2, AllocatorOrContainer>&)
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge(flat_multiset<Key, C2, AllocatorOrContainer>& source)
+ { this->tree_t::merge_equal(source.tree()); }
+
+ //! @copydoc ::boost::container::flat_multiset::merge(flat_multiset<Key, C2, AllocatorOrContainer>&)
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_multiset<Key, C2, AllocatorOrContainer> BOOST_RV_REF_END source)
+ { return this->merge(static_cast<flat_multiset<Key, C2, AllocatorOrContainer>&>(source)); }
+
+ //! @copydoc ::boost::container::flat_multimap::merge(flat_map<Key, T, C2, AllocatorOrContainer>&)
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge(flat_set<Key, C2, AllocatorOrContainer>& source)
+ { this->tree_t::merge_equal(source.tree()); }
+
+ //! @copydoc ::boost::container::flat_multiset::merge(flat_set<Key, C2, AllocatorOrContainer>&)
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG flat_set<Key, C2, AllocatorOrContainer> BOOST_RV_REF_END source)
+ { return this->merge(static_cast<flat_set<Key, C2, AllocatorOrContainer>&>(source)); }
+
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ //! @copydoc ::boost::container::flat_set::erase(const_iterator)
+ iterator erase(const_iterator p);
+
+ //! @copydoc ::boost::container::flat_set::erase(const key_type&)
+ size_type erase(const key_type& x);
+
+ //! @copydoc ::boost::container::flat_set::erase(const_iterator,const_iterator)
+ iterator erase(const_iterator first, const_iterator last);
+
+ //! @copydoc ::boost::container::flat_set::swap
+ void swap(flat_multiset& x)
+ BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value
+ && boost::container::dtl::is_nothrow_swappable<Compare>::value );
+
+ //! @copydoc ::boost::container::flat_set::clear
+ void clear() BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @copydoc ::boost::container::flat_set::key_comp
+ key_compare key_comp() const;
+
+ //! @copydoc ::boost::container::flat_set::value_comp
+ value_compare value_comp() const;
+
+ //! @copydoc ::boost::container::flat_set::find(const key_type& )
+ iterator find(const key_type& x);
+
+ //! @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;
+
+ //! @copydoc ::boost::container::flat_set::lower_bound(const key_type& )
+ iterator lower_bound(const key_type& x);
+
+ //! @copydoc ::boost::container::flat_set::lower_bound(const key_type& ) const
+ const_iterator lower_bound(const key_type& x) const;
+
+ //! @copydoc ::boost::container::flat_set::upper_bound(const key_type& )
+ iterator upper_bound(const key_type& x);
+
+ //! @copydoc ::boost::container::flat_set::upper_bound(const key_type& ) const
+ const_iterator upper_bound(const key_type& x) const;
+
+ //! @copydoc ::boost::container::flat_set::equal_range(const key_type& ) const
+ std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const;
+
+ //! @copydoc ::boost::container::flat_set::equal_range(const key_type& )
+ std::pair<iterator,iterator> equal_range(const key_type& x);
+
+ //! <b>Effects</b>: Returns true if x and y are equal
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator==(const flat_multiset& x, const flat_multiset& y);
+
+ //! <b>Effects</b>: Returns true if x and y are unequal
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator!=(const flat_multiset& x, const flat_multiset& y);
+
+ //! <b>Effects</b>: Returns true if x is less than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator<(const flat_multiset& x, const flat_multiset& y);
+
+ //! <b>Effects</b>: Returns true if x is greater than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator>(const flat_multiset& x, const flat_multiset& y);
+
+ //! <b>Effects</b>: Returns true if x is equal or less than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator<=(const flat_multiset& x, const flat_multiset& y);
+
+ //! <b>Effects</b>: Returns true if x is equal or greater than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator>=(const flat_multiset& x, const flat_multiset& y);
+
+ //! <b>Effects</b>: x.swap(y)
+ //!
+ //! <b>Complexity</b>: Constant.
+ friend void swap(flat_multiset& x, flat_multiset& y);
+
+ //! <b>Effects</b>: Extracts the internal sequence container.
+ //!
+ //! <b>Complexity</b>: Same as the move constructor of sequence_type, usually constant.
+ //!
+ //! <b>Postcondition</b>: this->empty()
+ //!
+ //! <b>Throws</b>: If secuence_type's move constructor throws
+ sequence_type extract_sequence();
+
+ #endif //#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ //! <b>Effects</b>: Discards the internally hold sequence container and adopts the
+ //! one passed externally using the move assignment.
+ //!
+ //! <b>Complexity</b>: Assuming O(1) move assignment, O(NlogN) with N = seq.size()
+ //!
+ //! <b>Throws</b>: If the comparison or the move constructor throws
+ BOOST_CONTAINER_FORCEINLINE void adopt_sequence(BOOST_RV_REF(sequence_type) seq)
+ { this->tree_t::adopt_sequence_equal(boost::move(seq)); }
+
+ //! <b>Requires</b>: seq shall be ordered according to this->compare()
+ //!
+ //! <b>Effects</b>: Discards the internally hold sequence container and adopts the
+ //! one passed externally using the move assignment.
+ //!
+ //! <b>Complexity</b>: Assuming O(1) move assignment, O(1)
+ //!
+ //! <b>Throws</b>: If the move assignment throws
+ BOOST_CONTAINER_FORCEINLINE void adopt_sequence(ordered_range_t, BOOST_RV_REF(sequence_type) seq)
+ { this->tree_t::adopt_sequence_equal(ordered_range_t(), boost::move(seq)); }
+
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ private:
+ template <class KeyType>
+ BOOST_CONTAINER_FORCEINLINE iterator priv_insert(BOOST_FWD_REF(KeyType) x)
+ { return this->tree_t::insert_equal(::boost::forward<KeyType>(x)); }
+
+ template <class KeyType>
+ BOOST_CONTAINER_FORCEINLINE iterator priv_insert(const_iterator p, BOOST_FWD_REF(KeyType) x)
+ { return this->tree_t::insert_equal(p, ::boost::forward<KeyType>(x)); }
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+};
+
+#if __cplusplus >= 201703L
+
+template <typename InputIterator>
+flat_multiset(InputIterator, InputIterator) ->
+ flat_multiset<typename iterator_traits<InputIterator>::value_type>;
+
+template <typename InputIterator, typename Allocator>
+flat_multiset(InputIterator, InputIterator, Allocator const&) ->
+ flat_multiset< typename iterator_traits<InputIterator>::value_type
+ , std::less<typename iterator_traits<InputIterator>::value_type>
+ , Allocator>;
+
+template <typename InputIterator, typename Compare>
+flat_multiset(InputIterator, InputIterator, Compare const&) ->
+ flat_multiset<typename iterator_traits<InputIterator>::value_type, Compare>;
+
+template <typename InputIterator, typename Compare, typename Allocator>
+flat_multiset(InputIterator, InputIterator, Compare const&, Allocator const&) ->
+ flat_multiset<typename iterator_traits<InputIterator>::value_type, Compare, Allocator>;
+
+template <typename InputIterator>
+flat_multiset(ordered_range_t, InputIterator, InputIterator) ->
+ flat_multiset<typename iterator_traits<InputIterator>::value_type>;
+
+template <typename InputIterator, typename Allocator>
+flat_multiset(ordered_range_t, InputIterator, InputIterator, Allocator const&) ->
+ flat_multiset< typename iterator_traits<InputIterator>::value_type
+ , std::less<typename iterator_traits<InputIterator>::value_type>
+ , Allocator>;
+
+template <typename InputIterator, typename Compare>
+flat_multiset(ordered_range_t, InputIterator, InputIterator, Compare const&) ->
+ flat_multiset< typename iterator_traits<InputIterator>::value_type, Compare>;
+
+template <typename InputIterator, typename Compare, typename Allocator>
+flat_multiset(ordered_range_t, InputIterator, InputIterator, Compare const&, Allocator const&) ->
+ flat_multiset<typename iterator_traits<InputIterator>::value_type, Compare, Allocator>;
+
+#endif
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+} //namespace container {
+
+//!has_trivial_destructor_after_move<> == true_type
+//!specialization for optimizations
+template <class Key, class Compare, class AllocatorOrContainer>
+struct has_trivial_destructor_after_move<boost::container::flat_multiset<Key, Compare, AllocatorOrContainer> >
+{
+ typedef typename ::boost::container::allocator_traits<AllocatorOrContainer>::pointer pointer;
+ static const bool value = ::boost::has_trivial_destructor_after_move<AllocatorOrContainer>::value &&
+ ::boost::has_trivial_destructor_after_move<pointer>::value &&
+ ::boost::has_trivial_destructor_after_move<Compare>::value;
+};
+
+namespace container {
+
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+}}
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif // BOOST_CONTAINER_FLAT_SET_HPP
diff --git a/include/boost/container/list.hpp b/include/boost/container/list.hpp
new file mode 100644
index 0000000..68892bc
--- /dev/null
+++ b/include/boost/container/list.hpp
@@ -0,0 +1,1499 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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 http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#ifndef BOOST_CONTAINER_LIST_HPP
+#define BOOST_CONTAINER_LIST_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+
+// container
+#include <boost/container/container_fwd.hpp>
+#include <boost/container/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/detail/node_alloc_holder.hpp>
+#include <boost/container/detail/version_type.hpp>
+#include <boost/container/detail/value_functors.hpp>
+// move
+#include <boost/move/utility_core.hpp>
+#include <boost/move/iterator.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/intrusive/list.hpp>
+// other
+#include <boost/assert.hpp>
+// std
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+#include <initializer_list>
+#endif
+
+namespace boost {
+namespace container {
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+namespace dtl {
+
+template<class VoidPointer>
+struct list_hook
+{
+ typedef typename dtl::bi::make_list_base_hook
+ <dtl::bi::void_pointer<VoidPointer>, dtl::bi::link_mode<dtl::bi::normal_link> >::type type;
+};
+
+template <class T, class VoidPointer>
+struct list_node
+ : public list_hook<VoidPointer>::type
+{
+ private:
+ list_node();
+
+ public:
+ typedef T value_type;
+ typedef typename list_hook<VoidPointer>::type hook_type;
+
+ T m_data;
+
+ T &get_data()
+ { return this->m_data; }
+
+ const T &get_data() const
+ { return this->m_data; }
+};
+
+template <class T, class VoidPointer>
+struct iiterator_node_value_type< list_node<T,VoidPointer> > {
+ typedef T type;
+};
+
+template<class Allocator>
+struct intrusive_list_type
+{
+ typedef boost::container::allocator_traits<Allocator> allocator_traits_type;
+ typedef typename allocator_traits_type::value_type value_type;
+ typedef typename boost::intrusive::pointer_traits
+ <typename allocator_traits_type::pointer>::template
+ rebind_pointer<void>::type
+ void_pointer;
+ typedef typename dtl::list_node
+ <value_type, void_pointer> node_type;
+ typedef typename dtl::bi::make_list
+ < node_type
+ , dtl::bi::base_hook<typename list_hook<void_pointer>::type>
+ , dtl::bi::constant_time_size<true>
+ , dtl::bi::size_type
+ <typename allocator_traits_type::size_type>
+ >::type container_type;
+ typedef container_type type ;
+};
+
+} //namespace dtl {
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+//! A list is a doubly linked list. That is, it is a Sequence that supports both
+//! forward and backward traversal, and (amortized) constant time insertion and
+//! removal of elements at the beginning or the end, or in the middle. Lists have
+//! the important property that insertion and splicing do not invalidate iterators
+//! to list elements, and that even removal invalidates only the iterators that point
+//! to the elements that are removed. The ordering of iterators may be changed
+//! (that is, list<T>::iterator might have a different predecessor or successor
+//! after a list operation than it did before), but the iterators themselves will
+//! not be invalidated or made to point to different elements unless that invalidation
+//! or mutation is explicit.
+//!
+//! \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 = new_allocator<T> >
+#else
+template <class T, class Allocator>
+#endif
+class list
+ : protected dtl::node_alloc_holder
+ <Allocator, typename dtl::intrusive_list_type<Allocator>::type>
+{
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ typedef typename
+ dtl::intrusive_list_type<Allocator>::type Icont;
+ typedef dtl::node_alloc_holder<Allocator, Icont> AllocHolder;
+ typedef typename AllocHolder::NodePtr NodePtr;
+ typedef typename AllocHolder::NodeAlloc NodeAlloc;
+ typedef typename AllocHolder::ValAlloc ValAlloc;
+ typedef typename AllocHolder::Node Node;
+ typedef dtl::allocator_destroyer<NodeAlloc> Destroyer;
+ typedef typename AllocHolder::alloc_version alloc_version;
+ typedef boost::container::allocator_traits<Allocator> allocator_traits_type;
+ typedef boost::container::equal_to_value<Allocator> equal_to_value_type;
+
+ BOOST_COPYABLE_AND_MOVABLE(list)
+
+ typedef dtl::iterator_from_iiterator<typename Icont::iterator, false> iterator_impl;
+ typedef dtl::iterator_from_iiterator<typename Icont::iterator, true> const_iterator_impl;
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ public:
+ //////////////////////////////////////////////
+ //
+ // types
+ //
+ //////////////////////////////////////////////
+
+ typedef 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;
+ typedef typename ::boost::container::allocator_traits<Allocator>::const_reference const_reference;
+ typedef typename ::boost::container::allocator_traits<Allocator>::size_type size_type;
+ typedef typename ::boost::container::allocator_traits<Allocator>::difference_type difference_type;
+ typedef Allocator allocator_type;
+ 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(boost::container::reverse_iterator<iterator>) reverse_iterator;
+ typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<const_iterator>) const_reverse_iterator;
+
+ //////////////////////////////////////////////
+ //
+ // construct/copy/destroy
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Default constructs a list.
+ //!
+ //! <b>Throws</b>: If allocator_type's default constructor throws.
+ //!
+ //! <b>Complexity</b>: Constant.
+ list() BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<Allocator>::value)
+ : AllocHolder()
+ {}
+
+ //! <b>Effects</b>: Constructs a list taking the allocator as parameter.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ explicit list(const allocator_type &a) BOOST_NOEXCEPT_OR_NOTHROW
+ : AllocHolder(a)
+ {}
+
+ //! <b>Effects</b>: Constructs a list
+ //! and inserts n value-initialized value_types.
+ //!
+ //! <b>Throws</b>: If allocator_type's default constructor
+ //! throws or T's default or copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to n.
+ explicit list(size_type n)
+ : AllocHolder(Allocator())
+ { 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 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); }
+
+ //! <b>Effects</b>: Copy constructs a list.
+ //!
+ //! <b>Postcondition</b>: x == *this.
+ //!
+ //! <b>Throws</b>: If allocator_type's default constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to the elements x contains.
+ list(const list& x)
+ : AllocHolder(x)
+ { this->insert(this->cbegin(), x.begin(), x.end()); }
+
+ //! <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) BOOST_NOEXCEPT_OR_NOTHROW
+ : AllocHolder(BOOST_MOVE_BASE(AllocHolder, x))
+ {}
+
+ //! <b>Effects</b>: Copy constructs a list using the specified allocator.
+ //!
+ //! <b>Postcondition</b>: x == *this.
+ //!
+ //! <b>Throws</b>: If allocator_type's default constructor or copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to the elements x contains.
+ list(const list& x, const allocator_type &a)
+ : AllocHolder(a)
+ { this->insert(this->cbegin(), x.begin(), x.end()); }
+
+ //! <b>Effects</b>: Move constructor sing the specified allocator.
+ //! Moves x's resources to *this.
+ //!
+ //! <b>Throws</b>: If allocation or value_type's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise.
+ list(BOOST_RV_REF(list) x, const allocator_type &a)
+ : AllocHolder(a)
+ {
+ if(this->node_alloc() == x.node_alloc()){
+ this->icont().swap(x.icont());
+ }
+ else{
+ this->insert(this->cbegin(), boost::make_move_iterator(x.begin()), boost::make_move_iterator(x.end()));
+ }
+ }
+
+ //! <b>Effects</b>: Constructs a list that will use a copy of allocator a
+ //! and inserts a copy of the range [first, last) in the list.
+ //!
+ //! <b>Throws</b>: If allocator_type's default constructor
+ //! throws or T's constructor taking a dereferenced InIt throws.
+ //!
+ //! <b>Complexity</b>: Linear to the range [first, last).
+ template <class InpIt>
+ list(InpIt first, InpIt last, const Allocator &a = Allocator())
+ : AllocHolder(a)
+ { this->insert(this->cbegin(), first, last); }
+
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Constructs a list that will use a copy of allocator a
+ //! and inserts a copy of the range [il.begin(), il.end()) in the list.
+ //!
+ //! <b>Throws</b>: If allocator_type's default constructor
+ //! throws or T's constructor taking a dereferenced
+ //! std::initializer_list iterator throws.
+ //!
+ //! <b>Complexity</b>: Linear to the range [il.begin(), il.end()).
+ list(std::initializer_list<value_type> il, const Allocator &a = Allocator())
+ : AllocHolder(a)
+ { this->insert(this->cbegin(), il.begin(), il.end()); }
+#endif
+
+ //! <b>Effects</b>: Destroys the list. All stored values are destroyed
+ //! and used memory is deallocated.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements.
+ ~list() BOOST_NOEXCEPT_OR_NOTHROW
+ {} //AllocHolder clears the list
+
+ //! <b>Effects</b>: Makes *this contain the same elements as x.
+ //!
+ //! <b>Postcondition</b>: this->size() == x.size(). *this contains a copy
+ //! of each of x's elements.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in x.
+ list& operator=(BOOST_COPY_ASSIGN_REF(list) x)
+ {
+ if (&x != this){
+ NodeAlloc &this_alloc = this->node_alloc();
+ const NodeAlloc &x_alloc = x.node_alloc();
+ dtl::bool_<allocator_traits_type::
+ propagate_on_container_copy_assignment::value> flag;
+ if(flag && this_alloc != x_alloc){
+ this->clear();
+ }
+ this->AllocHolder::copy_assign_alloc(x);
+ this->assign(x.begin(), x.end());
+ }
+ return *this;
+ }
+
+ //! <b>Effects</b>: Move assignment. All x's values are transferred to *this.
+ //!
+ //! <b>Postcondition</b>: x.empty(). *this contains a the elements x had
+ //! before the function.
+ //!
+ //! <b>Throws</b>: If allocator_traits_type::propagate_on_container_move_assignment
+ //! is false and (allocation throws or value_type's move constructor throws)
+ //!
+ //! <b>Complexity</b>: Constant if allocator_traits_type::
+ //! propagate_on_container_move_assignment is true or
+ //! this->get>allocator() == x.get_allocator(). Linear otherwise.
+ list& operator=(BOOST_RV_REF(list) x)
+ 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();
+ NodeAlloc &x_alloc = x.node_alloc();
+ const bool propagate_alloc = allocator_traits_type::
+ propagate_on_container_move_assignment::value;
+ const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
+ //Resources can be transferred if both allocators are
+ //going to be equal after this function (either propagated or already equal)
+ if(propagate_alloc || allocators_equal){
+ //Destroy
+ this->clear();
+ //Move allocator if needed
+ this->AllocHolder::move_assign_alloc(x);
+ //Obtain resources
+ this->icont() = boost::move(x.icont());
+ }
+ //Else do a one by one move
+ else{
+ this->assign( boost::make_move_iterator(x.begin())
+ , boost::make_move_iterator(x.end()));
+ }
+ return *this;
+ }
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Makes *this contain the same elements as il.
+ //!
+ //! <b>Postcondition</b>: this->size() == il.size(). *this contains a copy
+ //! of each of x's elements.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in x.
+ list& operator=(std::initializer_list<value_type> il)
+ {
+ assign(il.begin(), il.end());
+ return *this;
+ }
+#endif
+
+ //! <b>Effects</b>: Assigns the n copies of val to *this.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to n.
+ void assign(size_type n, const T& val)
+ {
+ typedef constant_iterator<value_type, difference_type> cvalue_iterator;
+ return this->assign(cvalue_iterator(val, n), cvalue_iterator());
+ }
+
+ //! <b>Effects</b>: Assigns the range [first, last) to *this.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or
+ //! T's constructor from dereferencing InpIt throws.
+ //!
+ //! <b>Complexity</b>: Linear to n.
+ template <class InpIt>
+ void assign(InpIt first, InpIt last
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename dtl::disable_if_convertible<InpIt, size_type>::type * = 0
+ #endif
+ )
+ {
+ iterator first1 = this->begin();
+ const iterator last1 = this->end();
+ for ( ; first1 != last1 && first != last; ++first1, ++first)
+ *first1 = *first;
+ if (first == last)
+ this->erase(first1, last1);
+ else{
+ this->insert(last1, first, last);
+ }
+ }
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Assigns the range [il.begin(), il.end()) to *this.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or
+ //! T's constructor from dereferencing std::initializer_list iterator throws.
+ //!
+ //! <b>Complexity</b>: Linear to n.
+ void assign(std::initializer_list<value_type> il)
+ { assign(il.begin(), il.end()); }
+#endif
+
+ //! <b>Effects</b>: Returns a copy of the internal allocator.
+ //!
+ //! <b>Throws</b>: If allocator's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Constant.
+ 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.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->node_alloc(); }
+
+ //! <b>Effects</b>: Returns a reference to the internal allocator.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->node_alloc(); }
+
+ //////////////////////////////////////////////
+ //
+ // iterators
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Returns an iterator to the first element contained in the list.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ 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.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->cbegin(); }
+
+ //! <b>Effects</b>: Returns an iterator to the end of the list.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ iterator end() BOOST_NOEXCEPT_OR_NOTHROW
+ { return iterator(this->icont().end()); }
+
+ //! <b>Effects</b>: Returns a const_iterator to the end of the list.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->cend(); }
+
+ //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
+ //! of the reversed list.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW
+ { return reverse_iterator(end()); }
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
+ //! of the reversed list.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->crbegin(); }
+
+ //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
+ //! of the reversed list.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW
+ { return reverse_iterator(begin()); }
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
+ //! of the reversed list.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ 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.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ 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.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ 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
+ //! of the reversed list.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ 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
+ //! of the reversed list.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return const_reverse_iterator(this->cbegin()); }
+
+ //////////////////////////////////////////////
+ //
+ // capacity
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Returns true if the list contains no elements.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ bool empty() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return !this->size(); }
+
+ //! <b>Effects</b>: Returns the number of the elements contained in the list.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ size_type size() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->icont().size(); }
+
+ //! <b>Effects</b>: Returns the largest possible size of the list.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ 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
+ //! the size becomes n. New elements are value initialized.
+ //!
+ //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to the difference between size() and new_size.
+ void resize(size_type new_size)
+ {
+ if(!priv_try_shrink(new_size)){
+ typedef value_init_construct_iterator<value_type, difference_type> value_init_iterator;
+ this->insert(this->cend(), value_init_iterator(new_size - this->size()), value_init_iterator());
+ }
+ }
+
+ //! <b>Effects</b>: Inserts or erases elements at the end such that
+ //! the size becomes n. New elements are copy constructed from x.
+ //!
+ //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to the difference between size() and new_size.
+ void resize(size_type new_size, const T& x)
+ {
+ if(!priv_try_shrink(new_size)){
+ this->insert(this->cend(), new_size - this->size(), x);
+ }
+ }
+
+ //////////////////////////////////////////////
+ //
+ // element access
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Requires</b>: !empty()
+ //!
+ //! <b>Effects</b>: Returns a reference to the first element
+ //! from the beginning of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ reference front() BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(!this->empty());
+ return *this->begin();
+ }
+
+ //! <b>Requires</b>: !empty()
+ //!
+ //! <b>Effects</b>: Returns a const reference to the first element
+ //! from the beginning of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reference front() const BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(!this->empty());
+ return *this->begin();
+ }
+
+ //! <b>Requires</b>: !empty()
+ //!
+ //! <b>Effects</b>: Returns a reference to the first element
+ //! from the beginning of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ reference back() BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(!this->empty());
+ return *(--this->end());
+ }
+
+ //! <b>Requires</b>: !empty()
+ //!
+ //! <b>Effects</b>: Returns a const reference to the first element
+ //! from the beginning of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reference back() const BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(!this->empty());
+ return *(--this->end());
+ }
+
+ //////////////////////////////////////////////
+ //
+ // modifiers
+ //
+ //////////////////////////////////////////////
+
+ #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.
+ //!
+ //! <b>Returns</b>: A reference to the created object.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or
+ //! T's in-place constructor throws.
+ //!
+ //! <b>Complexity</b>: Constant
+ template <class... Args>
+ reference emplace_back(BOOST_FWD_REF(Args)... args)
+ { return *this->emplace(this->cend(), boost::forward<Args>(args)...); }
+
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... in the beginning of the list.
+ //!
+ //! <b>Returns</b>: A reference to the created object.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or
+ //! T's in-place constructor throws.
+ //!
+ //! <b>Complexity</b>: Constant
+ template <class... Args>
+ reference emplace_front(BOOST_FWD_REF(Args)... args)
+ { return *this->emplace(this->cbegin(), boost::forward<Args>(args)...); }
+
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... before p.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or
+ //! T's in-place constructor throws.
+ //!
+ //! <b>Complexity</b>: Constant
+ template <class... Args>
+ iterator emplace(const_iterator position, BOOST_FWD_REF(Args)... args)
+ {
+ BOOST_ASSERT((priv_is_linked)(position));
+ NodePtr pnode(AllocHolder::create_node(boost::forward<Args>(args)...));
+ return iterator(this->icont().insert(position.get(), *pnode));
+ }
+
+ #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 \
+ reference emplace_back(BOOST_MOVE_UREF##N)\
+ { return *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 \
+ reference emplace_front(BOOST_MOVE_UREF##N)\
+ { return *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 position BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ {\
+ BOOST_ASSERT(position == this->cend() || (--(++position) == position) );\
+ NodePtr pnode (AllocHolder::create_node(BOOST_MOVE_FWD##N));\
+ return iterator(this->icont().insert(position.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.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or
+ //! T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Amortized constant time.
+ void push_front(const T &x);
+
+ //! <b>Effects</b>: Constructs a new element in the beginning of the list
+ //! and moves the resources of x to this new element.
+ //!
+ //! <b>Throws</b>: If memory allocation throws.
+ //!
+ //! <b>Complexity</b>: Amortized constant time.
+ void push_front(T &&x);
+ #else
+ BOOST_MOVE_CONVERSION_AWARE_CATCH(push_front, T, void, priv_push_front)
+ #endif
+
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ //! <b>Effects</b>: Inserts a copy of x at the end of the list.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or
+ //! T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Amortized constant time.
+ void push_back(const T &x);
+
+ //! <b>Effects</b>: Constructs a new element in the end of the list
+ //! and moves the resources of x to this new element.
+ //!
+ //! <b>Throws</b>: If memory allocation throws.
+ //!
+ //! <b>Complexity</b>: Amortized constant time.
+ void push_back(T &&x);
+ #else
+ BOOST_MOVE_CONVERSION_AWARE_CATCH(push_back, T, void, priv_push_back)
+ #endif
+
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ //! <b>Requires</b>: p must be a valid iterator of *this.
+ //!
+ //! <b>Effects</b>: Insert a copy of x before p.
+ //!
+ //! <b>Returns</b>: an iterator to the inserted element.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or x's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Amortized constant time.
+ iterator insert(const_iterator p, const T &x);
+
+ //! <b>Requires</b>: p must be a valid iterator of *this.
+ //!
+ //! <b>Effects</b>: Insert a new element before p with x's resources.
+ //!
+ //! <b>Returns</b>: an iterator to the inserted element.
+ //!
+ //! <b>Throws</b>: If memory allocation throws.
+ //!
+ //! <b>Complexity</b>: Amortized constant time.
+ iterator insert(const_iterator p, T &&x);
+ #else
+ BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator, const_iterator)
+ #endif
+
+ //! <b>Requires</b>: p must be a valid iterator of *this.
+ //!
+ //! <b>Effects</b>: Inserts n copies of x before p.
+ //!
+ //! <b>Returns</b>: an iterator to the first inserted element or p if n is 0.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to n.
+ iterator insert(const_iterator position, size_type n, const T& x)
+ {
+ //range check is done by insert
+ typedef constant_iterator<value_type, difference_type> cvalue_iterator;
+ return this->insert(position, cvalue_iterator(x, n), cvalue_iterator());
+ }
+
+ //! <b>Requires</b>: p must be a valid iterator of *this.
+ //!
+ //! <b>Effects</b>: Insert a copy of the [first, last) range before p.
+ //!
+ //! <b>Returns</b>: an iterator to the first inserted element or p if first == last.
+ //!
+ //! <b>Throws</b>: If memory allocation throws, T's constructor from a
+ //! dereferenced InpIt throws.
+ //!
+ //! <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 dtl::enable_if_c
+ < !dtl::is_convertible<InpIt, size_type>::value
+ && (dtl::is_input_iterator<InpIt>::value
+ || dtl::is_same<alloc_version, version_1>::value
+ )
+ >::type * = 0
+ #endif
+ )
+ {
+ BOOST_ASSERT((priv_is_linked)(p));
+ const typename Icont::iterator ipos(p.get());
+ iterator ret_it(ipos);
+ if(first != last){
+ ret_it = iterator(this->icont().insert(ipos, *this->create_node_from_it(first)));
+ ++first;
+ }
+ for (; first != last; ++first){
+ this->icont().insert(ipos, *this->create_node_from_it(first));
+ }
+ return ret_it;
+ }
+
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ template <class FwdIt>
+ iterator insert(const_iterator position, FwdIt first, FwdIt last
+ , typename dtl::enable_if_c
+ < !dtl::is_convertible<FwdIt, size_type>::value
+ && !(dtl::is_input_iterator<FwdIt>::value
+ || dtl::is_same<alloc_version, version_1>::value
+ )
+ >::type * = 0
+ )
+ {
+ BOOST_ASSERT((priv_is_linked)(position));
+ //Optimized allocation and construction
+ insertion_functor func(this->icont(), position.get());
+ iterator before_p(position.get());
+ --before_p;
+ this->allocate_many_and_construct(first, boost::container::iterator_distance(first, last), func);
+ return ++before_p;
+ }
+ #endif
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Requires</b>: p must be a valid iterator of *this.
+ //!
+ //! <b>Effects</b>: Insert a copy of the [il.begin(), il.end()) range before p.
+ //!
+ //! <b>Returns</b>: an iterator to the first inserted element or p if if.begin() == il.end().
+ //!
+ //! <b>Throws</b>: If memory allocation throws, T's constructor from a
+ //! dereferenced std::initializer_list iterator throws.
+ //!
+ //! <b>Complexity</b>: Linear to distance [il.begin(), il.end()).
+ iterator insert(const_iterator p, std::initializer_list<value_type> il)
+ {
+ //position range check is done by insert()
+ return insert(p, il.begin(), il.end());
+ }
+#endif
+
+ //! <b>Effects</b>: Removes the first element from the list.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Amortized constant time.
+ void pop_front() BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(!this->empty());
+ this->erase(this->cbegin());
+ }
+
+ //! <b>Effects</b>: Removes the last element from the list.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Amortized constant time.
+ void pop_back() BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(!this->empty());
+ const_iterator tmp = this->cend();
+ this->erase(--tmp);
+ }
+
+ //! <b>Requires</b>: p must be a valid iterator of *this.
+ //!
+ //! <b>Effects</b>: Erases the element at p.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Amortized constant time.
+ iterator erase(const_iterator p) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(p != this->cend() && (priv_is_linked)(p));
+ 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.
+ //!
+ //! <b>Effects</b>: Erases the elements pointed by [first, last).
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Linear to the distance between first and last.
+ iterator erase(const_iterator first, const_iterator last) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(first == last || (first != this->cend() && (priv_is_linked)(first)));
+ BOOST_ASSERT(first == last || (priv_is_linked)(last));
+ return iterator(AllocHolder::erase_range(first.get(), last.get(), alloc_version()));
+ }
+
+ //! <b>Effects</b>: Swaps the contents of *this and x.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <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)
+ {
+ BOOST_ASSERT(allocator_traits_type::propagate_on_container_swap::value ||
+ allocator_traits_type::is_always_equal::value ||
+ this->get_stored_allocator() == x.get_stored_allocator());
+ AllocHolder::swap(x);
+ }
+
+ //! <b>Effects</b>: Erases all the elements of the list.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the list.
+ void clear() BOOST_NOEXCEPT_OR_NOTHROW
+ { AllocHolder::clear(alloc_version()); }
+
+ //////////////////////////////////////////////
+ //
+ // slist operations
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Requires</b>: p must point to an element contained
+ //! by the list. x != *this. this' allocator and x's allocator shall compare equal
+ //!
+ //! <b>Effects</b>: Transfers all the elements of list x to this list, before the
+ //! the element pointed by p. No destructors or copy constructors are called.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <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_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT((priv_is_linked)(p));
+ BOOST_ASSERT(this != &x);
+ BOOST_ASSERT(this->node_alloc() == x.node_alloc());
+ this->icont().splice(p.get(), x.icont());
+ }
+
+ //! <b>Requires</b>: p must point to an element contained
+ //! by the list. x != *this. this' allocator and x's allocator shall compare equal
+ //!
+ //! <b>Effects</b>: Transfers all the elements of list x to this list, before the
+ //! the element pointed by p. No destructors or copy constructors are called.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <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_NOEXCEPT_OR_NOTHROW
+ {
+ //Checks done in splice
+ this->splice(p, static_cast<list&>(x));
+ }
+
+ //! <b>Requires</b>: p must point to an element contained
+ //! by this list. i must point to an element contained in list x.
+ //! this' allocator and x's allocator shall compare equal
+ //!
+ //! <b>Effects</b>: Transfers the value pointed by i, from list x to this list,
+ //! before the element pointed by p. No destructors or copy constructors are called.
+ //! If p == i or p == ++i, this function is a null operation.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <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_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT((priv_is_linked)(p));
+ BOOST_ASSERT(this->node_alloc() == x.node_alloc());
+ this->icont().splice(p.get(), x.icont(), i.get());
+ }
+
+ //! <b>Requires</b>: p must point to an element contained
+ //! by this list. i must point to an element contained in list x.
+ //! this' allocator and x's allocator shall compare equal.
+ //!
+ //! <b>Effects</b>: Transfers the value pointed by i, from list x to this list,
+ //! before the element pointed by p. No destructors or copy constructors are called.
+ //! If p == i or p == ++i, this function is a null operation.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <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_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(this != &x);
+ //Additional checks done in splice()
+ this->splice(p, static_cast<list&>(x), i);
+ }
+
+ //! <b>Requires</b>: p must point to an element contained
+ //! by this list. first and last must point to elements contained in list x.
+ //! 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 element pointed by p. No destructors or copy constructors are called.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements transferred.
+ //!
+ //! <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_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT((priv_is_linked)(p));
+ BOOST_ASSERT(first == last || (first != x.cend() && x.priv_is_linked(first)));
+ BOOST_ASSERT(first == last || x.priv_is_linked(last));
+ BOOST_ASSERT(this->node_alloc() == x.node_alloc());
+ this->icont().splice(p.get(), x.icont(), first.get(), last.get());
+ }
+
+ //! <b>Requires</b>: p must point to an element contained
+ //! by this list. first and last must point to elements contained in list x.
+ //! 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 element pointed by p. No destructors or copy constructors are called.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements transferred.
+ //!
+ //! <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_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(this != &x);
+ //Additional checks done in splice()
+ 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 == 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 element pointed by p. No destructors or copy constructors are called.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <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.
+ //!
+ //! <b>Note</b>: Non-standard extension
+ 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);
+ }
+
+ //! <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 == 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 element pointed by p. No destructors or copy constructors are called.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <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.
+ //!
+ //! <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_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.
+ //!
+ //! <b>Throws</b>: If comparison throws.
+ //!
+ //! <b>Complexity</b>: Linear time. It performs exactly size() comparisons for equality.
+ //!
+ //! <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_type(value)); }
+
+ //! <b>Effects</b>: Removes all the elements for which a specified
+ //! predicate is satisfied.
+ //!
+ //! <b>Throws</b>: If pred throws.
+ //!
+ //! <b>Complexity</b>: Linear time. It performs exactly size() calls to the predicate.
+ //!
+ //! <b>Note</b>: The relative order of elements that are not removed is unchanged,
+ //! and iterators to elements that are not removed remain valid.
+ template <class Pred>
+ void remove_if(Pred pred)
+ {
+ 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
+ //! elements that are equal from the list.
+ //!
+ //! <b>Throws</b>: If comparison throws.
+ //!
+ //! <b>Complexity</b>: Linear time (size()-1 comparisons equality comparisons).
+ //!
+ //! <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 unique()
+ { this->unique(value_equal_t()); }
+
+ //! <b>Effects</b>: Removes adjacent duplicate elements or adjacent
+ //! elements that satisfy some binary predicate from the list.
+ //!
+ //! <b>Throws</b>: If pred throws.
+ //!
+ //! <b>Complexity</b>: Linear time (size()-1 comparisons calls to pred()).
+ //!
+ //! <b>Note</b>: The relative order of elements that are not removed is unchanged,
+ //! and iterators to elements that are not removed remain valid.
+ template <class BinaryPredicate>
+ void unique(BinaryPredicate binary_pred)
+ {
+ 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.
+ //!
+ //! <b>Effects</b>: This function removes all of x's elements and inserts them
+ //! in order into *this according to std::less<value_type>. The merge is stable;
+ //! that is, if an element from *this is equivalent to one from x, then the element
+ //! from *this will precede the one from x.
+ //!
+ //! <b>Throws</b>: If comparison throws.
+ //!
+ //! <b>Complexity</b>: This function is linear time: it performs at most
+ //! size() + x.size() - 1 comparisons.
+ void merge(list &x)
+ { this->merge(x, value_less_t()); }
+
+ //! <b>Requires</b>: The lists x and *this must be distinct.
+ //!
+ //! <b>Effects</b>: This function removes all of x's elements and inserts them
+ //! in order into *this according to std::less<value_type>. The merge is stable;
+ //! that is, if an element from *this is equivalent to one from x, then the element
+ //! from *this will precede the one from x.
+ //!
+ //! <b>Throws</b>: If comparison throws.
+ //!
+ //! <b>Complexity</b>: This function is linear time: it performs at most
+ //! size() + x.size() - 1 comparisons.
+ void merge(BOOST_RV_REF(list) x)
+ { this->merge(static_cast<list&>(x)); }
+
+ //! <b>Requires</b>: p must be a comparison function that induces a strict weak
+ //! ordering and both *this and x must be sorted according to that ordering
+ //! The lists x and *this must be distinct.
+ //!
+ //! <b>Effects</b>: This function removes all of x's elements and inserts them
+ //! in order into *this. The merge is stable; that is, if an element from *this is
+ //! equivalent to one from x, then the element from *this will precede the one from x.
+ //!
+ //! <b>Throws</b>: If comp throws.
+ //!
+ //! <b>Complexity</b>: This function is linear time: it performs at most
+ //! size() + x.size() - 1 comparisons.
+ //!
+ //! <b>Note</b>: Iterators and references to *this are not invalidated.
+ template <class StrictWeakOrdering>
+ void merge(list &x, const StrictWeakOrdering &comp)
+ {
+ BOOST_ASSERT(this->node_alloc() == x.node_alloc());
+ 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
+ //! ordering and both *this and x must be sorted according to that ordering
+ //! The lists x and *this must be distinct.
+ //!
+ //! <b>Effects</b>: This function removes all of x's elements and inserts them
+ //! in order into *this. The merge is stable; that is, if an element from *this is
+ //! equivalent to one from x, then the element from *this will precede the one from x.
+ //!
+ //! <b>Throws</b>: If comp throws.
+ //!
+ //! <b>Complexity</b>: This function is linear time: it performs at most
+ //! size() + x.size() - 1 comparisons.
+ //!
+ //! <b>Note</b>: Iterators and references to *this are not invalidated.
+ template <class StrictWeakOrdering>
+ void merge(BOOST_RV_REF(list) x, StrictWeakOrdering comp)
+ { this->merge(static_cast<list&>(x), comp); }
+
+ //! <b>Effects</b>: This function sorts the list *this according to std::less<value_type>.
+ //! The sort is stable, that is, the relative order of equivalent elements is preserved.
+ //!
+ //! <b>Throws</b>: If comparison throws.
+ //!
+ //! <b>Notes</b>: Iterators and references are not invalidated.
+ //!
+ //! <b>Complexity</b>: The number of comparisons is approximately N log N, where N
+ //! is the list's size.
+ void sort()
+ { this->sort(value_less_t()); }
+
+ //! <b>Effects</b>: This function sorts the list *this according to std::less<value_type>.
+ //! The sort is stable, that is, the relative order of equivalent elements is preserved.
+ //!
+ //! <b>Throws</b>: If comp throws.
+ //!
+ //! <b>Notes</b>: Iterators and references are not invalidated.
+ //!
+ //! <b>Complexity</b>: The number of comparisons is approximately N log N, where N
+ //! is the list's size.
+ template <class StrictWeakOrdering>
+ void sort(StrictWeakOrdering comp)
+ {
+ // nothing if the list has length 0 or 1.
+ if (this->size() < 2)
+ return;
+ 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.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: This function is linear time.
+ //!
+ //! <b>Note</b>: Iterators and references are not invalidated
+ 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)
+ { return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin()); }
+
+ //! <b>Effects</b>: Returns true if x and y are unequal
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator!=(const list& x, const list& y)
+ { return !(x == y); }
+
+ //! <b>Effects</b>: Returns true if x is less than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator<(const list& x, const list& y)
+ { return boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
+
+ //! <b>Effects</b>: Returns true if x is greater than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator>(const list& x, const list& y)
+ { return y < x; }
+
+ //! <b>Effects</b>: Returns true if x is equal or less than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator<=(const list& x, const list& y)
+ { return !(y < x); }
+
+ //! <b>Effects</b>: Returns true if x is equal or greater than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator>=(const list& x, const list& y)
+ { return !(x < y); }
+
+ //! <b>Effects</b>: x.swap(y)
+ //!
+ //! <b>Complexity</b>: Constant.
+ friend void swap(list& x, list& y)
+ { x.swap(y); }
+
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ private:
+
+ static bool priv_is_linked(const_iterator const position)
+ {
+ const_iterator cur(position);
+ //This list is circular including end nodes
+ return (--(++cur)) == position && (++(--cur)) == position;
+ }
+
+ bool priv_try_shrink(size_type new_size)
+ {
+ const size_type len = this->size();
+ if(len > new_size){
+ const const_iterator iend = this->cend();
+ size_type to_erase = len - new_size;
+ const_iterator ifirst;
+ if(to_erase < len/2u){
+ ifirst = iend;
+ while(to_erase--){
+ --ifirst;
+ }
+ }
+ else{
+ ifirst = this->cbegin();
+ size_type to_skip = len - to_erase;
+ while(to_skip--){
+ ++ifirst;
+ }
+ }
+ this->erase(ifirst, iend);
+ return true;
+ }
+ else{
+ return false;
+ }
+ }
+
+ iterator priv_insert(const_iterator p, const T &x)
+ {
+ BOOST_ASSERT((priv_is_linked)(p));
+ NodePtr tmp = AllocHolder::create_node(x);
+ return iterator(this->icont().insert(p.get(), *tmp));
+ }
+
+ iterator priv_insert(const_iterator p, BOOST_RV_REF(T) x)
+ {
+ BOOST_ASSERT((priv_is_linked)(p));
+ NodePtr tmp = AllocHolder::create_node(boost::move(x));
+ return iterator(this->icont().insert(p.get(), *tmp));
+ }
+
+ void priv_push_back (const T &x)
+ { this->insert(this->cend(), x); }
+
+ void priv_push_back (BOOST_RV_REF(T) x)
+ { this->insert(this->cend(), boost::move(x)); }
+
+ void priv_push_front (const T &x)
+ { this->insert(this->cbegin(), x); }
+
+ void priv_push_front (BOOST_RV_REF(T) x)
+ { this->insert(this->cbegin(), boost::move(x)); }
+
+ class insertion_functor;
+ friend class insertion_functor;
+
+ class insertion_functor
+ {
+ Icont &icont_;
+ typedef typename Icont::const_iterator iconst_iterator;
+ const iconst_iterator pos_;
+
+ public:
+ insertion_functor(Icont &icont, typename Icont::const_iterator pos)
+ : icont_(icont), pos_(pos)
+ {}
+
+ void operator()(Node &n)
+ {
+ this->icont_.insert(pos_, n);
+ }
+ };
+
+ typedef value_less<value_type> value_less_t;
+ typedef value_equal<value_type> value_equal_t;
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+};
+
+#if __cplusplus >= 201703L
+template <typename InputIterator>
+list(InputIterator, InputIterator) ->
+ list<typename iterator_traits<InputIterator>::value_type>;
+
+template <typename InputIterator, typename Allocator>
+list(InputIterator, InputIterator, Allocator const&) ->
+ list<typename iterator_traits<InputIterator>::value_type, Allocator>;
+#endif
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+} //namespace container {
+
+//!has_trivial_destructor_after_move<> == true_type
+//!specialization for optimizations
+template <class T, class Allocator>
+struct has_trivial_destructor_after_move<boost::container::list<T, Allocator> >
+{
+ typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer;
+ static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value &&
+ ::boost::has_trivial_destructor_after_move<pointer>::value;
+};
+
+namespace container {
+
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+}}
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif // BOOST_CONTAINER_LIST_HPP
diff --git a/include/boost/container/map.hpp b/include/boost/container/map.hpp
new file mode 100644
index 0000000..a88b6a5
--- /dev/null
+++ b/include/boost/container/map.hpp
@@ -0,0 +1,2233 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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_MAP_HPP
+#define BOOST_CONTAINER_MAP_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+
+// container
+#include <boost/container/container_fwd.hpp>
+#include <boost/container/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/container/detail/pair.hpp>
+#include <boost/container/detail/pair_key_mapped_of_value.hpp>
+
+// move
+#include <boost/move/traits.hpp>
+#include <boost/move/utility_core.hpp>
+// 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/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/core/no_exceptions_support.hpp>
+// std
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+#include <initializer_list>
+#endif
+
+namespace boost {
+namespace container {
+
+#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+//! A map is a kind of associative container that supports unique keys (contains at
+//! most one of each key value) and provides for fast retrieval of values of another
+//! type T based on the keys. The map class supports bidirectional iterators.
+//!
+//! A map satisfies all of the requirements of a container and of a reversible
+//! container and of an associative container. The <code>value_type</code> stored
+//! by this container is the value_type is std::pair<const Key, T>.
+//!
+//! \tparam Key is the key_type of the map
+//! \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 Options 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 = new_allocator< std::pair< const Key, T> >, class Options = tree_assoc_defaults >
+#else
+template <class Key, class T, class Compare, class Allocator, class Options>
+#endif
+class map
+ ///@cond
+ : public dtl::tree
+ < std::pair<const Key, T>
+ , dtl::select1st<Key>
+ , Compare, Allocator, Options>
+ ///@endcond
+{
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ private:
+ BOOST_COPYABLE_AND_MOVABLE(map)
+
+ typedef dtl::select1st<Key> select_1st_t;
+ typedef std::pair<const Key, T> value_type_impl;
+ typedef dtl::tree
+ <value_type_impl, select_1st_t, Compare, Allocator, Options> base_t;
+ typedef dtl::pair <Key, T> movable_value_type_impl;
+ typedef typename base_t::value_compare value_compare_impl;
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ public:
+ //////////////////////////////////////////////
+ //
+ // types
+ //
+ //////////////////////////////////////////////
+
+ typedef Key key_type;
+ typedef ::boost::container::allocator_traits<Allocator> allocator_traits_type;
+ typedef T mapped_type;
+ typedef typename boost::container::allocator_traits<Allocator>::value_type value_type;
+ typedef typename boost::container::allocator_traits<Allocator>::pointer pointer;
+ typedef typename boost::container::allocator_traits<Allocator>::const_pointer const_pointer;
+ typedef typename boost::container::allocator_traits<Allocator>::reference reference;
+ typedef typename boost::container::allocator_traits<Allocator>::const_reference const_reference;
+ typedef typename boost::container::allocator_traits<Allocator>::size_type size_type;
+ typedef typename boost::container::allocator_traits<Allocator>::difference_type difference_type;
+ typedef Allocator allocator_type;
+ typedef typename BOOST_CONTAINER_IMPDEF(base_t::stored_allocator_type) stored_allocator_type;
+ typedef BOOST_CONTAINER_IMPDEF(value_compare_impl) value_compare;
+ typedef Compare key_compare;
+ typedef typename BOOST_CONTAINER_IMPDEF(base_t::iterator) iterator;
+ typedef typename BOOST_CONTAINER_IMPDEF(base_t::const_iterator) const_iterator;
+ typedef typename BOOST_CONTAINER_IMPDEF(base_t::reverse_iterator) reverse_iterator;
+ typedef typename BOOST_CONTAINER_IMPDEF(base_t::const_reverse_iterator) const_reverse_iterator;
+ typedef std::pair<key_type, mapped_type> nonconst_value_type;
+ typedef BOOST_CONTAINER_IMPDEF(movable_value_type_impl) movable_value_type;
+ typedef BOOST_CONTAINER_IMPDEF(node_handle<
+ typename base_t::stored_allocator_type
+ BOOST_MOVE_I pair_key_mapped_of_value
+ <key_type BOOST_MOVE_I mapped_type> >) node_type;
+ typedef BOOST_CONTAINER_IMPDEF
+ (insert_return_type_base<iterator BOOST_MOVE_I node_type>) insert_return_type;
+
+ //allocator_type::value_type type must be std::pair<CONST Key, T>
+ BOOST_STATIC_ASSERT((dtl::is_same<typename allocator_type::value_type, std::pair<const Key, T> >::value));
+
+ //////////////////////////////////////////////
+ //
+ // construct/copy/destroy
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Default constructs an empty map.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE
+ map() BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<Allocator>::value &&
+ dtl::is_nothrow_default_constructible<Compare>::value)
+ : base_t()
+ {}
+
+ //! <b>Effects</b>: Constructs an empty map using the specified comparison object
+ //! and allocator.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE map(const Compare& comp, const allocator_type& a)
+ : base_t(comp, a)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty map using the specified comparison object.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE explicit map(const Compare& comp)
+ : base_t(comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty map using the specified allocator.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE explicit map(const allocator_type& a)
+ : base_t(a)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty map and
+ //! inserts elements from the range [first ,last ).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE map(InputIterator first, InputIterator last)
+ : base_t(true, first, last)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty map using the specified
+ //! allocator, and inserts elements from the range [first ,last ).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE map(InputIterator first, InputIterator last, const allocator_type& a)
+ : base_t(true, first, last, Compare(), a)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty map using the specified comparison object and
+ //! inserts elements from the range [first ,last ).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE map(InputIterator first, InputIterator last, const Compare& comp)
+ : base_t(true, first, last, comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty map using the specified comparison object and
+ //! allocator, and inserts elements from the range [first ,last ).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE map(InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
+ : base_t(true, first, last, comp, a)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty map and
+ //! inserts elements from the ordered unique range [first ,last). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate and must be
+ //! unique values.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE map( ordered_unique_range_t, InputIterator first, InputIterator last)
+ : base_t(ordered_range, first, last)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty map using the specified comparison object and
+ //! inserts elements from the ordered unique range [first ,last). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate and must be
+ //! unique values.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE map( ordered_unique_range_t, InputIterator first, InputIterator last, const Compare& comp)
+ : base_t(ordered_range, first, last, comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty map using the specified comparison object and
+ //! allocator, and inserts elements from the ordered unique range [first ,last). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate and must be
+ //! unique values.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE map( ordered_unique_range_t, InputIterator first, InputIterator last
+ , const Compare& comp, const allocator_type& a)
+ : base_t(ordered_range, first, last, comp, a)
+ {}
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Constructs an empty map and
+ //! inserts elements from the range [il.begin(), il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted according
+ //! to the predicate and otherwise N logN, where N is il.first() - il.end().
+ BOOST_CONTAINER_FORCEINLINE map(std::initializer_list<value_type> il)
+ : base_t(true, il.begin(), il.end())
+ {}
+
+ //! <b>Effects</b>: Constructs an empty map using the specified comparison object and
+ //! inserts elements from the range [il.begin(), il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is il.first() - il.end().
+ BOOST_CONTAINER_FORCEINLINE map(std::initializer_list<value_type> il, const Compare& comp)
+ : base_t(true, il.begin(), il.end(), comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty map using the specified
+ //! allocator, and inserts elements from the range [il.begin(), il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is il.first() - il.end().
+ BOOST_CONTAINER_FORCEINLINE map(std::initializer_list<value_type> il, const allocator_type& a)
+ : base_t(true, il.begin(), il.end(), Compare(), a)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty map using the specified comparison object and
+ //! allocator, and inserts elements from the range [il.begin(), il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is il.first() - il.end().
+ BOOST_CONTAINER_FORCEINLINE map(std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
+ : base_t(true, il.begin(), il.end(), comp, a)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty map and inserts elements from the ordered unique range [il.begin(), il.end()).
+ //! This function is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be
+ //! unique values.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE map(ordered_unique_range_t, std::initializer_list<value_type> il)
+ : base_t(ordered_range, il.begin(), il.end())
+ {}
+
+ //! <b>Effects</b>: Constructs an empty map using the specified comparison object,
+ //! and inserts elements from the ordered unique range [il.begin(), il.end()). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be
+ //! unique values.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE map(ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp)
+ : base_t(ordered_range, il.begin(), il.end(), comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty map using the specified comparison object and
+ //! allocator, and inserts elements from the ordered unique range [il.begin(), il.end()). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be
+ //! unique values.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE map( ordered_unique_range_t, std::initializer_list<value_type> il
+ , const Compare& comp, const allocator_type& a)
+ : base_t(ordered_range, il.begin(), il.end(), comp, a)
+ {}
+
+#endif
+
+ //! <b>Effects</b>: Copy constructs a map.
+ //!
+ //! <b>Complexity</b>: Linear in x.size().
+ BOOST_CONTAINER_FORCEINLINE map(const map& x)
+ : base_t(static_cast<const base_t&>(x))
+ {}
+
+ //! <b>Effects</b>: Move constructs a map. Constructs *this using x's resources.
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Postcondition</b>: x is emptied.
+ BOOST_CONTAINER_FORCEINLINE map(BOOST_RV_REF(map) x)
+ BOOST_NOEXCEPT_IF(boost::container::dtl::is_nothrow_move_constructible<Compare>::value)
+ : base_t(BOOST_MOVE_BASE(base_t, x))
+ {}
+
+ //! <b>Effects</b>: Copy constructs a map using the specified allocator.
+ //!
+ //! <b>Complexity</b>: Linear in x.size().
+ BOOST_CONTAINER_FORCEINLINE map(const map& x, const allocator_type &a)
+ : base_t(static_cast<const base_t&>(x), a)
+ {}
+
+ //! <b>Effects</b>: Move constructs a map using the specified allocator.
+ //! Constructs *this using x's resources.
+ //!
+ //! <b>Complexity</b>: Constant if x == x.get_allocator(), linear otherwise.
+ //!
+ //! <b>Postcondition</b>: x is emptied.
+ BOOST_CONTAINER_FORCEINLINE map(BOOST_RV_REF(map) x, const allocator_type &a)
+ : base_t(BOOST_MOVE_BASE(base_t, x), a)
+ {}
+
+ //! <b>Effects</b>: Makes *this a copy of x.
+ //!
+ //! <b>Complexity</b>: Linear in x.size().
+ BOOST_CONTAINER_FORCEINLINE map& operator=(BOOST_COPY_ASSIGN_REF(map) x)
+ { return static_cast<map&>(this->base_t::operator=(static_cast<const base_t&>(x))); }
+
+ //! <b>Effects</b>: this->swap(x.get()).
+ //!
+ //! <b>Throws</b>: If allocator_traits_type::propagate_on_container_move_assignment
+ //! is false and (allocation throws or value_type's move constructor throws)
+ //!
+ //! <b>Complexity</b>: Constant if allocator_traits_type::
+ //! propagate_on_container_move_assignment is true or
+ //! this->get>allocator() == x.get_allocator(). Linear otherwise.
+ BOOST_CONTAINER_FORCEINLINE map& operator=(BOOST_RV_REF(map) x)
+ BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value ||
+ allocator_traits_type::is_always_equal::value) &&
+ boost::container::dtl::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.
+ //!
+ BOOST_CONTAINER_FORCEINLINE map& operator=(std::initializer_list<value_type> il)
+ {
+ this->clear();
+ insert(il.begin(), il.end());
+ return *this;
+ }
+#endif
+
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ //! <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;
+
+ //! <b>Effects</b>: Returns a reference to the internal allocator.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! <b>Effects</b>: Returns a reference to the internal allocator.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ 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_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_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_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_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_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_NOEXCEPT_OR_NOTHROW;
+
+ //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ 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.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ 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.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ 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_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_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_NOEXCEPT_OR_NOTHROW;
+
+ #endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ //! <b>Effects</b>: If there is no key equivalent to x in the map, inserts
+ //! value_type(x, T()) into the map.
+ //!
+ //! <b>Returns</b>: A reference to the mapped_type corresponding to x in *this.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ mapped_type& operator[](const key_type &k);
+
+ //! <b>Effects</b>: 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)
+ //!
+ //! <b>Returns</b>: A reference to the mapped_type corresponding to x in *this.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ mapped_type& operator[](key_type &&k);
+ #elif defined(BOOST_MOVE_HELPERS_RETURN_SFINAE_BROKEN)
+ //in compilers like GCC 3.4, we can't catch temporaries
+ BOOST_CONTAINER_FORCEINLINE mapped_type& operator[](const key_type &k) { return this->priv_subscript(k); }
+ BOOST_CONTAINER_FORCEINLINE mapped_type& operator[](BOOST_RV_REF(key_type) k) { return this->priv_subscript(::boost::move(k)); }
+ #else
+ BOOST_MOVE_CONVERSION_AWARE_CATCH( operator[] , key_type, mapped_type&, this->priv_subscript)
+ #endif
+
+ //! <b>Effects</b>: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
+ //! to the mapped_type corresponding to the key k. If the key does not exist, inserts the new value
+ //! as if by insert, constructing it from value_type(k, forward<M>(obj)).
+ //!
+ //! No iterators or references are invalidated. If the insertion is successful, pointers and references
+ //! to the element obtained while it is held in the node handle are invalidated, and pointers and
+ //! references obtained to that element before it was extracted become valid.
+ //!
+ //! <b>Returns</b>: The bool component is true if the insertion took place and false if the assignment
+ //! took place. The iterator component is pointing at the element that was inserted or updated.
+ //!
+ //! <b>Complexity</b>: Logarithmic in the size of the container.
+ template <class M>
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> insert_or_assign(const key_type& k, BOOST_FWD_REF(M) obj)
+ { return this->base_t::insert_or_assign(const_iterator(), k, ::boost::forward<M>(obj)); }
+
+ //! <b>Effects</b>: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
+ //! to the mapped_type corresponding to the key k. If the key does not exist, inserts the new value
+ //! as if by insert, constructing it from value_type(k, move(obj)).
+ //!
+ //! No iterators or references are invalidated. If the insertion is successful, pointers and references
+ //! to the element obtained while it is held in the node handle are invalidated, and pointers and
+ //! references obtained to that element before it was extracted become valid.
+ //!
+ //! <b>Returns</b>: The bool component is true if the insertion took place and false if the assignment
+ //! took place. The iterator component is pointing at the element that was inserted or updated.
+ //!
+ //! <b>Complexity</b>: Logarithmic in the size of the container.
+ template <class M>
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> insert_or_assign(BOOST_RV_REF(key_type) k, BOOST_FWD_REF(M) obj)
+ { return this->base_t::insert_or_assign(const_iterator(), ::boost::move(k), ::boost::forward<M>(obj)); }
+
+ //! <b>Effects</b>: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
+ //! to the mapped_type corresponding to the key k. If the key does not exist, inserts the new value
+ //! as if by insert, constructing it from value_type(k, forward<M>(obj)) and the new element
+ //! to the container as close as possible to the position just before hint.
+ //!
+ //! No iterators or references are invalidated. If the insertion is successful, pointers and references
+ //! to the element obtained while it is held in the node handle are invalidated, and pointers and
+ //! references obtained to that element before it was extracted become valid.
+ //!
+ //! <b>Returns</b>: The bool component is true if the insertion took place and false if the assignment
+ //! took place. The iterator component is pointing at the element that was inserted or updated.
+ //!
+ //! <b>Complexity</b>: Logarithmic in the size of the container in general, but amortized constant if
+ //! the new element is inserted just before hint.
+ template <class M>
+ BOOST_CONTAINER_FORCEINLINE iterator insert_or_assign(const_iterator hint, const key_type& k, BOOST_FWD_REF(M) obj)
+ { return this->base_t::insert_or_assign(hint, k, ::boost::forward<M>(obj)); }
+
+ //! <b>Effects</b>: If a key equivalent to k already exists in the container, assigns forward<M>(obj)
+ //! to the mapped_type corresponding to the key k. If the key does not exist, inserts the new value
+ //! as if by insert, constructing it from value_type(k, move(obj)) and the new element
+ //! to the container as close as possible to the position just before hint.
+ //!
+ //! No iterators or references are invalidated. If the insertion is successful, pointers and references
+ //! to the element obtained while it is held in the node handle are invalidated, and pointers and
+ //! references obtained to that element before it was extracted become valid.
+ //!
+ //! <b>Returns</b>: The bool component is true if the insertion took place and false if the assignment
+ //! took place. The iterator component is pointing at the element that was inserted or updated.
+ //!
+ //! <b>Complexity</b>: Logarithmic in the size of the container in general, but amortized constant if
+ //! the new element is inserted just before hint.
+ template <class M>
+ BOOST_CONTAINER_FORCEINLINE iterator insert_or_assign(const_iterator hint, BOOST_RV_REF(key_type) k, BOOST_FWD_REF(M) obj)
+ { return this->base_t::insert_or_assign(hint, ::boost::move(k), ::boost::forward<M>(obj)); }
+
+ //! <b>Returns</b>: 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.
+ //! <b>Complexity</b>: logarithmic.
+ T& at(const key_type& k)
+ {
+ iterator i = this->find(k);
+ if(i == this->end()){
+ throw_out_of_range("map::at key not found");
+ }
+ return i->second;
+ }
+
+ //! <b>Returns</b>: 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.
+ //! <b>Complexity</b>: logarithmic.
+ const T& at(const key_type& k) const
+ {
+ const_iterator i = this->find(k);
+ if(i == this->end()){
+ throw_out_of_range("map::at key not found");
+ }
+ return i->second;
+ }
+
+ //////////////////////////////////////////////
+ //
+ // modifiers
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Inserts x if and only if there is no element in the container
+ //! with key equivalent to the key of x.
+ //!
+ //! <b>Returns</b>: The bool component of the returned pair is true if and only
+ //! if the insertion takes place, and the iterator component of the pair
+ //! points to the element with key equivalent to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> insert(const value_type& x)
+ { return this->base_t::insert_unique(x); }
+
+ //! <b>Effects</b>: Inserts a new value_type created from the pair if and only if
+ //! there is no element in the container with key equivalent to the key of x.
+ //!
+ //! <b>Returns</b>: The bool component of the returned pair is true if and only
+ //! if the insertion takes place, and the iterator component of the pair
+ //! points to the element with key equivalent to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> insert(const nonconst_value_type& x)
+ { return this->try_emplace(x.first, x.second); }
+
+ //! <b>Effects</b>: Inserts a new value_type move constructed from the pair if and
+ //! only if there is no element in the container with key equivalent to the key of x.
+ //!
+ //! <b>Returns</b>: The bool component of the returned pair is true if and only
+ //! if the insertion takes place, and the iterator component of the pair
+ //! points to the element with key equivalent to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> insert(BOOST_RV_REF(nonconst_value_type) x)
+ { return this->try_emplace(boost::move(x.first), boost::move(x.second)); }
+
+ //! <b>Effects</b>: Inserts a new value_type move constructed from the pair if and
+ //! only if there is no element in the container with key equivalent to the key of x.
+ //!
+ //! <b>Returns</b>: The bool component of the returned pair is true if and only
+ //! if the insertion takes place, and the iterator component of the pair
+ //! points to the element with key equivalent to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> insert(BOOST_RV_REF(movable_value_type) x)
+ { return this->try_emplace(boost::move(x.first), boost::move(x.second)); }
+
+ //! <b>Effects</b>: Move constructs a new value from x if and only if there is
+ //! no element in the container with key equivalent to the key of x.
+ //!
+ //! <b>Returns</b>: The bool component of the returned pair is true if and only
+ //! if the insertion takes place, and the iterator component of the pair
+ //! points to the element with key equivalent to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> insert(BOOST_RV_REF(value_type) x)
+ { return this->base_t::insert_unique(boost::move(x)); }
+
+ //! <b>Effects</b>: Inserts a copy of x in the container if and only if there is
+ //! no element in the container with key equivalent to the key of x.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
+ //! is inserted right before p.
+ BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, const value_type& x)
+ { return this->base_t::insert_unique(p, x); }
+
+ //! <b>Effects</b>: Move constructs a new value from x if and only if there is
+ //! no element in the container with key equivalent to the key of x.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
+ //! is inserted right before p.
+ BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(nonconst_value_type) x)
+ { return this->try_emplace(p, boost::move(x.first), boost::move(x.second)); }
+
+ //! <b>Effects</b>: Move constructs a new value from x if and only if there is
+ //! no element in the container with key equivalent to the key of x.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
+ //! is inserted right before p.
+ BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(movable_value_type) x)
+ { return this->try_emplace(p, boost::move(x.first), boost::move(x.second)); }
+
+ //! <b>Effects</b>: Inserts a copy of x in the container.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ iterator insert(const_iterator p, const nonconst_value_type& x)
+ { return this->try_emplace(p, x.first, x.second); }
+
+ //! <b>Effects</b>: Inserts an element move constructed from x in the container.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(value_type) x)
+ { return this->base_t::insert_unique(p, boost::move(x)); }
+
+ //! <b>Requires</b>: first, last are not iterators into *this.
+ //!
+ //! <b>Effects</b>: inserts each element from the range [first,last) if and only
+ //! if there is no element with key equivalent to the key of that element.
+ //!
+ //! <b>Complexity</b>: At most N log(size()+N) (N is the distance from first to last)
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE void insert(InputIterator first, InputIterator last)
+ { this->base_t::insert_unique(first, last); }
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()) if and only
+ //! if there is no element with key equivalent to the key of that element.
+ //!
+ //! <b>Complexity</b>: At most N log(size()+N) (N is the distance from il.begin() to il.end())
+ BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il)
+ { this->base_t::insert_unique(il.begin(), il.end()); }
+#endif
+
+ //! <b>Requires</b>: nh is empty or this->get_allocator() == nh.get_allocator().
+ //!
+ //! <b>Effects</b>: If nh is empty, has no effect. Otherwise, inserts the element owned
+ //! by nh if and only if there is no element in the container with a key equivalent to nh.key().
+ //!
+ //! <b>Returns</b>: If nh is empty, insert_return_type.inserted is false, insert_return_type.position
+ //! is end(), and insert_return_type.node is empty. Otherwise if the insertion took place,
+ //! insert_return_type.inserted is true, insert_return_type.position points to the inserted element,
+ //! and insert_return_type.node is empty; if the insertion failed, insert_return_type.inserted is
+ //! false, insert_return_type.node has the previous value of nh, and insert_return_type.position
+ //! points to an element with a key equivalent to nh.key().
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ insert_return_type insert(BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)
+ {
+ typename base_t::node_type n(boost::move(nh));
+ typename base_t::insert_return_type base_ret(this->base_t::insert_unique_node(boost::move(n)));
+ return insert_return_type (base_ret.inserted, base_ret.position, boost::move(base_ret.node));
+ }
+
+ //! <b>Effects</b>: Same as `insert(node_type && nh)` but the element is inserted as close as possible
+ //! to the position just prior to "hint".
+ //!
+ //! <b>Complexity</b>: logarithmic in general, but amortized constant if the element is inserted
+ //! right before "hint".
+ insert_return_type insert(const_iterator hint, BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)
+ {
+ typename base_t::node_type n(boost::move(nh));
+ typename base_t::insert_return_type base_ret(this->base_t::insert_unique_node(hint, boost::move(n)));
+ return insert_return_type (base_ret.inserted, base_ret.position, boost::move(base_ret.node));
+ }
+
+ #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
+ //! no element in the container with an equivalent key.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: The bool component of the returned pair is true if and only
+ //! if the insertion takes place, and the iterator component of the pair
+ //! points to the element with key equivalent to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
+ //! is inserted right before p.
+ template <class... Args>
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> emplace(BOOST_FWD_REF(Args)... args)
+ { return this->base_t::emplace_unique(boost::forward<Args>(args)...); }
+
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... in the container if and only if there is
+ //! no element in the container with an equivalent key.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
+ //! is inserted right before p.
+ template <class... Args>
+ BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator p, BOOST_FWD_REF(Args)... args)
+ { return this->base_t::emplace_hint_unique(p, boost::forward<Args>(args)...); }
+
+ //! <b>Requires</b>: value_type shall be EmplaceConstructible into map from piecewise_construct,
+ //! forward_as_tuple(k), forward_as_tuple(forward<Args>(args)...).
+ //!
+ //! <b>Effects</b>: If the map already contains an element whose key is equivalent to k, there is no effect. Otherwise
+ //! inserts an object of type value_type constructed with piecewise_construct, forward_as_tuple(k),
+ //! forward_as_tuple(forward<Args>(args)...).
+ //!
+ //! <b>Returns</b>: The bool component of the returned pair is true if and only if the
+ //! insertion took place. The returned iterator points to the map element whose key is equivalent to k.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ template <class... Args>
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> try_emplace(const key_type& k, BOOST_FWD_REF(Args)... args)
+ { return this->base_t::try_emplace(const_iterator(), k, boost::forward<Args>(args)...); }
+
+ //! <b>Requires</b>: value_type shall be EmplaceConstructible into map from piecewise_construct,
+ //! forward_as_tuple(k), forward_as_tuple(forward<Args>(args)...).
+ //!
+ //! <b>Effects</b>: If the map already contains an element whose key is equivalent to k, there is no effect. Otherwise
+ //! inserts an object of type value_type constructed with piecewise_construct, forward_as_tuple(k),
+ //! forward_as_tuple(forward<Args>(args)...).
+ //!
+ //! <b>Returns</b>: The returned iterator points to the map element whose key is equivalent to k.
+ //!
+ //! <b>Complexity</b>: Logarithmic in general, but amortized constant if value
+ //! is inserted right before p.
+ template <class... Args>
+ BOOST_CONTAINER_FORCEINLINE iterator try_emplace(const_iterator hint, const key_type &k, BOOST_FWD_REF(Args)... args)
+ { return this->base_t::try_emplace(hint, k, boost::forward<Args>(args)...).first; }
+
+ //! <b>Requires</b>: value_type shall be EmplaceConstructible into map from piecewise_construct,
+ //! forward_as_tuple(move(k)), forward_as_tuple(forward<Args>(args)...).
+ //!
+ //! <b>Effects</b>: If the map already contains an element whose key is equivalent to k, there is no effect. Otherwise
+ //! inserts an object of type value_type constructed with piecewise_construct, forward_as_tuple(move(k)),
+ //! forward_as_tuple(forward<Args>(args)...).
+ //!
+ //! <b>Returns</b>: The bool component of the returned pair is true if and only if the
+ //! insertion took place. The returned iterator points to the map element whose key is equivalent to k.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ template <class... Args>
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> try_emplace(BOOST_RV_REF(key_type) k, BOOST_FWD_REF(Args)... args)
+ { return this->base_t::try_emplace(const_iterator(), boost::move(k), boost::forward<Args>(args)...); }
+
+ //! <b>Requires</b>: value_type shall be EmplaceConstructible into map from piecewise_construct,
+ //! forward_as_tuple(move(k)), forward_as_tuple(forward<Args>(args)...).
+ //!
+ //! <b>Effects</b>: If the map already contains an element whose key is equivalent to k, there is no effect. Otherwise
+ //! inserts an object of type value_type constructed with piecewise_construct, forward_as_tuple(move(k)),
+ //! forward_as_tuple(forward<Args>(args)...).
+ //!
+ //! <b>Returns</b>: The returned iterator points to the map element whose key is equivalent to k.
+ //!
+ //! <b>Complexity</b>: Logarithmic in general, but amortized constant if value
+ //! is inserted right before p.
+ template <class... Args>
+ BOOST_CONTAINER_FORCEINLINE iterator try_emplace(const_iterator hint, BOOST_RV_REF(key_type) k, BOOST_FWD_REF(Args)... args)
+ { return this->base_t::try_emplace(hint, boost::move(k), boost::forward<Args>(args)...).first; }
+
+ #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ #define BOOST_CONTAINER_MAP_EMPLACE_CODE(N) \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> emplace(BOOST_MOVE_UREF##N)\
+ { return this->base_t::emplace_unique(BOOST_MOVE_FWD##N); }\
+ \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ { return this->base_t::emplace_hint_unique(hint BOOST_MOVE_I##N BOOST_MOVE_FWD##N); }\
+ \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> try_emplace(const key_type& k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ { return this->base_t::try_emplace(const_iterator(), k BOOST_MOVE_I##N BOOST_MOVE_FWD##N); }\
+ \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ BOOST_CONTAINER_FORCEINLINE iterator try_emplace(const_iterator hint, const key_type &k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ { return this->base_t::try_emplace(hint, k BOOST_MOVE_I##N BOOST_MOVE_FWD##N).first; }\
+ \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> try_emplace(BOOST_RV_REF(key_type) k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ { return this->base_t::try_emplace(const_iterator(), boost::move(k) BOOST_MOVE_I##N BOOST_MOVE_FWD##N); }\
+ \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ BOOST_CONTAINER_FORCEINLINE iterator try_emplace(const_iterator hint, BOOST_RV_REF(key_type) k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ { return this->base_t::try_emplace(hint, boost::move(k) BOOST_MOVE_I##N BOOST_MOVE_FWD##N).first; }\
+ //
+ BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_MAP_EMPLACE_CODE)
+ #undef BOOST_CONTAINER_MAP_EMPLACE_CODE
+
+ #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ //! <b>Effects</b>: Erases the element pointed to by p.
+ //!
+ //! <b>Returns</b>: Returns an iterator pointing to the element immediately
+ //! following q prior to the element being erased. If no such element exists,
+ //! returns end().
+ //!
+ //! <b>Complexity</b>: Amortized constant time
+ 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_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_NOEXCEPT_OR_NOTHROW;
+
+ #endif
+
+ //! <b>Effects</b>: Removes the first element in the container with key equivalent to k.
+ //!
+ //! <b>Returns</b>: A node_type owning the element if found, otherwise an empty node_type.
+ //!
+ //! <b>Complexity</b>: log(a.size()).
+ node_type extract(const key_type& k)
+ {
+ typename base_t::node_type base_nh(this->base_t::extract(k));
+ node_type nh(boost::move(base_nh));
+ return BOOST_MOVE_RET(node_type, nh);
+ }
+
+ //! <b>Effects</b>: Removes the element pointed to by "position".
+ //!
+ //! <b>Returns</b>: A node_type owning the element, otherwise an empty node_type.
+ //!
+ //! <b>Complexity</b>: Amortized constant.
+ node_type extract(const_iterator position)
+ {
+ typename base_t::node_type base_nh(this->base_t::extract(position));
+ node_type nh(boost::move(base_nh));
+ return BOOST_MOVE_RET(node_type, nh);
+ }
+
+ //! <b>Requires</b>: this->get_allocator() == source.get_allocator().
+ //!
+ //! <b>Effects</b>: Attempts to extract each element in source and insert it into a using
+ //! the comparison object of *this. If there is an element in a with key equivalent to the
+ //! key of an element from source, then that element is not extracted from source.
+ //!
+ //! <b>Postcondition</b>: Pointers and references to the transferred elements of source refer
+ //! to those same elements but as members of *this. Iterators referring to the transferred
+ //! elements will continue to refer to their elements, but they now behave as iterators into *this,
+ //! not into source.
+ //!
+ //! <b>Throws</b>: Nothing unless the comparison object throws.
+ //!
+ //! <b>Complexity</b>: N log(a.size() + N) (N has the value source.size())
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge(map<Key, T, C2, Allocator, Options>& source)
+ {
+ typedef dtl::tree
+ <value_type_impl, select_1st_t, C2, Allocator, Options> base2_t;
+ this->merge_unique(static_cast<base2_t&>(source));
+ }
+
+ //! @copydoc ::boost::container::map::merge(map<Key, T, C2, Allocator, Options>&)
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG map<Key, T, C2, Allocator, Options> BOOST_RV_REF_END source)
+ { return this->merge(static_cast<map<Key, T, C2, Allocator, Options>&>(source)); }
+
+ //! @copydoc ::boost::container::map::merge(map<Key, T, C2, Allocator, Options>&)
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge(multimap<Key, T, C2, Allocator, Options>& source)
+ {
+ typedef dtl::tree
+ <value_type_impl, select_1st_t, C2, Allocator, Options> base2_t;
+ this->base_t::merge_unique(static_cast<base2_t&>(source));
+ }
+
+ //! @copydoc ::boost::container::map::merge(map<Key, T, C2, Allocator, Options>&)
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG multimap<Key, T, C2, Allocator, Options> BOOST_RV_REF_END source)
+ { return this->merge(static_cast<multimap<Key, T, C2, Allocator, Options>&>(source)); }
+
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ //! <b>Effects</b>: Swaps the contents of *this and x.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ void swap(map& x)
+ BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value
+ && boost::container::dtl::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_NOEXCEPT_OR_NOTHROW;
+
+ //! <b>Effects</b>: Returns the comparison object out
+ //! of which a was constructed.
+ //!
+ //! <b>Complexity</b>: Constant.
+ key_compare key_comp() const;
+
+ //! <b>Effects</b>: Returns an object of value_compare constructed out
+ //! of the comparison object.
+ //!
+ //! <b>Complexity</b>: Constant.
+ value_compare value_comp() const;
+
+ //! <b>Returns</b>: An iterator pointing to an element with the key
+ //! equivalent to x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ iterator find(const key_type& x);
+
+ //! <b>Returns</b>: A const_iterator pointing to an element with the key
+ //! equivalent to x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ const_iterator find(const key_type& x) const;
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Returns</b>: An iterator pointing to an element with the key
+ //! equivalent to x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ template<typename K>
+ iterator find(const K& x);
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <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.
+ template<typename K>
+ const_iterator find(const K& x) const;
+
+ #endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ //! <b>Returns</b>: The number of elements with key equivalent to x.
+ //!
+ //! <b>Complexity</b>: log(size())+count(k)
+ BOOST_CONTAINER_FORCEINLINE size_type count(const key_type& x) const
+ { return static_cast<size_type>(this->find(x) != this->cend()); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Returns</b>: The number of elements with key equivalent to x.
+ //!
+ //! <b>Complexity</b>: log(size())+count(k)
+ template<typename K>
+ BOOST_CONTAINER_FORCEINLINE size_type count(const K& x) const
+ { return static_cast<size_type>(this->find(x) != this->cend()); }
+
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ //! <b>Returns</b>: An iterator pointing to the first element with key not less
+ //! than k, or a.end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ iterator lower_bound(const key_type& x);
+
+ //! <b>Returns</b>: A const iterator pointing to the first element with key not
+ //! less than k, or a.end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ const_iterator lower_bound(const key_type& x) const;
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the first element with key not less
+ //! than k, or a.end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ template<typename K>
+ iterator lower_bound(const K& x);
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <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
+ template<typename K>
+ const_iterator lower_bound(const K& x) const;
+
+ //! <b>Returns</b>: An iterator pointing to the first element with key not less
+ //! than x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ iterator upper_bound(const key_type& x);
+
+ //! <b>Returns</b>: A const iterator pointing to the first element with key not
+ //! less than x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ const_iterator upper_bound(const key_type& x) const;
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the first element with key not less
+ //! than x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ template<typename K>
+ iterator upper_bound(const K& x);
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <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
+ template<typename K>
+ const_iterator upper_bound(const K& x) const;
+
+ //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ std::pair<iterator,iterator> equal_range(const key_type& x);
+
+ //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ std::pair<const_iterator,const_iterator> equal_range(const key_type& x) const;
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ template<typename K>
+ std::pair<iterator,iterator> equal_range(const K& x);
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ template<typename K>
+ std::pair<const_iterator,const_iterator> equal_range(const K& x) const;
+
+ //! <b>Effects</b>: Rebalances the tree. It's a no-op for Red-Black and AVL trees.
+ //!
+ //! <b>Complexity</b>: Linear
+ void rebalance();
+
+ //! <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 map& x, const map& y);
+
+ //! <b>Effects</b>: Returns true if x and y are unequal
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator!=(const map& x, const map& y);
+
+ //! <b>Effects</b>: Returns true if x is less than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator<(const map& x, const map& y);
+
+ //! <b>Effects</b>: Returns true if x is greater than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator>(const map& x, const map& y);
+
+ //! <b>Effects</b>: Returns true if x is equal or less than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator<=(const map& x, const map& y);
+
+ //! <b>Effects</b>: Returns true if x is equal or greater than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator>=(const map& x, const map& y);
+
+ //! <b>Effects</b>: x.swap(y)
+ //!
+ //! <b>Complexity</b>: Constant.
+ friend void swap(map& x, map& y);
+
+ #endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ private:
+ template<class KeyConvertible>
+ BOOST_CONTAINER_FORCEINLINE mapped_type& priv_subscript(BOOST_FWD_REF(KeyConvertible) k)
+ {
+ return this->try_emplace(boost::forward<KeyConvertible>(k)).first->second;
+ }
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+};
+
+#if __cplusplus >= 201703L
+
+template <typename InputIterator>
+map(InputIterator, InputIterator) ->
+ map< typename dtl::remove_const< typename iterator_traits<InputIterator>::value_type::first_type>::type
+ , typename iterator_traits<InputIterator>::value_type::second_type>;
+
+template <typename InputIterator, typename Allocator>
+map(InputIterator, InputIterator, Allocator const&) ->
+ map< typename dtl::remove_const< typename iterator_traits<InputIterator>::value_type::first_type>::type
+ , typename iterator_traits<InputIterator>::value_type::second_type
+ , std::less<typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type>
+ , Allocator>;
+
+template <typename InputIterator, typename Compare>
+map(InputIterator, InputIterator, Compare const&) ->
+ map< typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type
+ , typename iterator_traits<InputIterator>::value_type::second_type
+ , Compare>;
+
+template <typename InputIterator, typename Compare, typename Allocator>
+map(InputIterator, InputIterator, Compare const&, Allocator const&) ->
+ map< typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type
+ , typename iterator_traits<InputIterator>::value_type::second_type
+ , Compare
+ , Allocator>;
+
+template <typename InputIterator>
+map(ordered_unique_range_t, InputIterator, InputIterator) ->
+ map< typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type
+ , typename iterator_traits<InputIterator>::value_type::second_type>;
+
+template <typename InputIterator, typename Allocator>
+map(ordered_unique_range_t, InputIterator, InputIterator, Allocator const&) ->
+ map< typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type
+ , typename iterator_traits<InputIterator>::value_type::second_type
+ , std::less<typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type>
+ , Allocator>;
+
+template <typename InputIterator, typename Compare>
+map(ordered_unique_range_t, InputIterator, InputIterator, Compare const&) ->
+ map< typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type
+ , typename iterator_traits<InputIterator>::value_type::second_type
+ , Compare>;
+
+template <typename InputIterator, typename Compare, typename Allocator>
+map(ordered_unique_range_t, InputIterator, InputIterator, Compare const&, Allocator const&) ->
+ map< typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type
+ , typename iterator_traits<InputIterator>::value_type::second_type
+ , Compare
+ , Allocator>;
+
+#endif
+
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+} //namespace container {
+
+//!has_trivial_destructor_after_move<> == true_type
+//!specialization for optimizations
+template <class Key, class T, class Compare, class Allocator>
+struct has_trivial_destructor_after_move<boost::container::map<Key, T, Compare, 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 &&
+ ::boost::has_trivial_destructor_after_move<Compare>::value;
+};
+
+namespace container {
+
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+//! A multimap is a kind of associative container that supports equivalent keys
+//! (possibly containing multiple copies of the same key value) and provides for
+//! fast retrieval of values of another type T based on the keys. The multimap class
+//! supports bidirectional iterators.
+//!
+//! A multimap satisfies all of the requirements of a container and of a reversible
+//! container and of an associative container. The <code>value_type</code> stored
+//! 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 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 Options 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 = new_allocator< std::pair< const Key, T> >, class Options = tree_assoc_defaults>
+#else
+template <class Key, class T, class Compare, class Allocator, class Options>
+#endif
+class multimap
+ ///@cond
+ : public dtl::tree
+ < std::pair<const Key, T>
+ , dtl::select1st<Key>
+ , Compare, Allocator, Options>
+ ///@endcond
+{
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ private:
+ BOOST_COPYABLE_AND_MOVABLE(multimap)
+
+ typedef dtl::select1st<Key> select_1st_t;
+ typedef std::pair<const Key, T> value_type_impl;
+ typedef dtl::tree
+ <value_type_impl, select_1st_t, Compare, Allocator, Options> base_t;
+ typedef dtl::pair <Key, T> movable_value_type_impl;
+ typedef typename base_t::value_compare value_compare_impl;
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ typedef ::boost::container::allocator_traits<Allocator> allocator_traits_type;
+
+ public:
+ //////////////////////////////////////////////
+ //
+ // types
+ //
+ //////////////////////////////////////////////
+
+ typedef Key key_type;
+ typedef T mapped_type;
+ typedef typename boost::container::allocator_traits<Allocator>::value_type value_type;
+ typedef typename boost::container::allocator_traits<Allocator>::pointer pointer;
+ typedef typename boost::container::allocator_traits<Allocator>::const_pointer const_pointer;
+ typedef typename boost::container::allocator_traits<Allocator>::reference reference;
+ typedef typename boost::container::allocator_traits<Allocator>::const_reference const_reference;
+ typedef typename boost::container::allocator_traits<Allocator>::size_type size_type;
+ typedef typename boost::container::allocator_traits<Allocator>::difference_type difference_type;
+ typedef Allocator allocator_type;
+ typedef typename BOOST_CONTAINER_IMPDEF(base_t::stored_allocator_type) stored_allocator_type;
+ typedef BOOST_CONTAINER_IMPDEF(value_compare_impl) value_compare;
+ typedef Compare key_compare;
+ typedef typename BOOST_CONTAINER_IMPDEF(base_t::iterator) iterator;
+ typedef typename BOOST_CONTAINER_IMPDEF(base_t::const_iterator) const_iterator;
+ typedef typename BOOST_CONTAINER_IMPDEF(base_t::reverse_iterator) reverse_iterator;
+ typedef typename BOOST_CONTAINER_IMPDEF(base_t::const_reverse_iterator) const_reverse_iterator;
+ typedef std::pair<key_type, mapped_type> nonconst_value_type;
+ typedef BOOST_CONTAINER_IMPDEF(movable_value_type_impl) movable_value_type;
+ typedef BOOST_CONTAINER_IMPDEF(node_handle<
+ typename base_t::stored_allocator_type
+ BOOST_MOVE_I pair_key_mapped_of_value
+ <key_type BOOST_MOVE_I mapped_type> >) node_type;
+
+ //allocator_type::value_type type must be std::pair<CONST Key, T>
+ BOOST_STATIC_ASSERT((dtl::is_same<typename allocator_type::value_type, std::pair<const Key, T> >::value));
+
+ //////////////////////////////////////////////
+ //
+ // construct/copy/destroy
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Default constructs an empty multimap.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE multimap()
+ BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<Allocator>::value &&
+ dtl::is_nothrow_default_constructible<Compare>::value)
+ : base_t()
+ {}
+
+ //! <b>Effects</b>: Constructs an empty multimap using the specified allocator
+ //! object and allocator.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE explicit multimap(const allocator_type& a)
+ : base_t(a)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty multimap using the specified comparison.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE explicit multimap(const Compare& comp)
+ : base_t(comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty multimap using the specified comparison and allocator.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE multimap(const Compare& comp, const allocator_type& a)
+ : base_t(comp, a)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty multimap and
+ //! inserts elements from the range [first ,last ).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE multimap(InputIterator first, InputIterator last)
+ : base_t(false, first, last)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty multimap using the specified
+ //! allocator, and inserts elements from the range [first ,last ).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE multimap(InputIterator first, InputIterator last, const allocator_type& a)
+ : base_t(false, first, last, Compare(), a)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty multimap using the specified comparison object and
+ //! inserts elements from the range [first ,last ).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE multimap(InputIterator first, InputIterator last, const Compare& comp)
+ : base_t(false, first, last, comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty multimap using the specified comparison object
+ //! and allocator, and inserts elements from the range [first ,last ).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE multimap(InputIterator first, InputIterator last,
+ const Compare& comp, const allocator_type& a)
+ : base_t(false, first, last, comp, a)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty multimap and
+ //! inserts elements from the ordered range [first ,last). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE multimap(ordered_range_t, InputIterator first, InputIterator last)
+ : base_t(ordered_range, first, last)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty multimap using the specified comparison object and
+ //! inserts elements from the ordered range [first ,last). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE multimap(ordered_range_t, InputIterator first, InputIterator last, const Compare& comp)
+ : base_t(ordered_range, first, last, comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty multimap using the specified comparison object and
+ //! allocator, and inserts elements from the ordered range [first ,last). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE multimap(ordered_range_t, InputIterator first, InputIterator last, const Compare& comp,
+ const allocator_type& a)
+ : base_t(ordered_range, first, last, comp, a)
+ {}
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Constructs an empty multimap and
+ //! and inserts elements from the range [il.begin(), il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is il.first() - il.end().
+ BOOST_CONTAINER_FORCEINLINE multimap(std::initializer_list<value_type> il)
+ : base_t(false, il.begin(), il.end())
+ {}
+
+ //! <b>Effects</b>: Constructs an empty multimap using the specified
+ //! allocator, and inserts elements from the range [il.begin(), il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is il.first() - il.end().
+ BOOST_CONTAINER_FORCEINLINE multimap(std::initializer_list<value_type> il, const allocator_type& a)
+ : base_t(false, il.begin(), il.end(), Compare(), a)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty multimap using the specified comparison object and
+ //! inserts elements from the range [il.begin(), il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is il.first() - il.end().
+ BOOST_CONTAINER_FORCEINLINE multimap(std::initializer_list<value_type> il, const Compare& comp)
+ : base_t(false, il.begin(), il.end(), comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty multimap using the specified comparison object and
+ //! allocator, and inserts elements from the range [il.begin(), il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is il.first() - il.end().
+ BOOST_CONTAINER_FORCEINLINE multimap(std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
+ : base_t(false, il.begin(), il.end(), comp, a)
+ {}
+
+
+ //! <b>Effects</b>: Constructs an empty map and
+ //! inserts elements from the ordered range [il.begin(), il.end()). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE multimap(ordered_range_t, std::initializer_list<value_type> il)
+ : base_t(ordered_range, il.begin(), il.end())
+ {}
+
+ //! <b>Effects</b>: Constructs an empty map using the specified comparison object and
+ //! inserts elements from the ordered range [il.begin(), il.end()). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE multimap(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp)
+ : base_t(ordered_range, il.begin(), il.end(), comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty map and
+ //! inserts elements from the ordered range [il.begin(), il.end()). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE multimap(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
+ : base_t(ordered_range, il.begin(), il.end(), comp, a)
+ {}
+
+#endif
+
+ //! <b>Effects</b>: Copy constructs a multimap.
+ //!
+ //! <b>Complexity</b>: Linear in x.size().
+ BOOST_CONTAINER_FORCEINLINE multimap(const multimap& x)
+ : base_t(static_cast<const base_t&>(x))
+ {}
+
+ //! <b>Effects</b>: Move constructs a multimap. Constructs *this using x's resources.
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Postcondition</b>: x is emptied.
+ BOOST_CONTAINER_FORCEINLINE multimap(BOOST_RV_REF(multimap) x)
+ BOOST_NOEXCEPT_IF(boost::container::dtl::is_nothrow_move_constructible<Compare>::value)
+ : base_t(BOOST_MOVE_BASE(base_t, x))
+ {}
+
+ //! <b>Effects</b>: Copy constructs a multimap.
+ //!
+ //! <b>Complexity</b>: Linear in x.size().
+ BOOST_CONTAINER_FORCEINLINE multimap(const multimap& x, const allocator_type &a)
+ : base_t(static_cast<const base_t&>(x), a)
+ {}
+
+ //! <b>Effects</b>: Move constructs a multimap using the specified allocator.
+ //! Constructs *this using x's resources.
+ //! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise.
+ //!
+ //! <b>Postcondition</b>: x is emptied.
+ BOOST_CONTAINER_FORCEINLINE multimap(BOOST_RV_REF(multimap) x, const allocator_type &a)
+ : base_t(BOOST_MOVE_BASE(base_t, x), a)
+ {}
+
+ //! <b>Effects</b>: Makes *this a copy of x.
+ //!
+ //! <b>Complexity</b>: Linear in x.size().
+ BOOST_CONTAINER_FORCEINLINE multimap& operator=(BOOST_COPY_ASSIGN_REF(multimap) x)
+ { return static_cast<multimap&>(this->base_t::operator=(static_cast<const base_t&>(x))); }
+
+ //! <b>Effects</b>: this->swap(x.get()).
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE multimap& operator=(BOOST_RV_REF(multimap) x)
+ BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value ||
+ allocator_traits_type::is_always_equal::value) &&
+ boost::container::dtl::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.
+ //!
+ BOOST_CONTAINER_FORCEINLINE multimap& operator=(std::initializer_list<value_type> il)
+ {
+ this->clear();
+ insert(il.begin(), il.end());
+ return *this;
+ }
+#endif
+
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ //! @copydoc ::boost::container::set::get_allocator()
+ allocator_type get_allocator() const;
+
+ //! @copydoc ::boost::container::set::get_stored_allocator()
+ stored_allocator_type &get_stored_allocator();
+
+ //! @copydoc ::boost::container::set::get_stored_allocator() const
+ const stored_allocator_type &get_stored_allocator() const;
+
+ //! @copydoc ::boost::container::set::begin()
+ iterator begin();
+
+ //! @copydoc ::boost::container::set::begin() const
+ const_iterator begin() const;
+
+ //! @copydoc ::boost::container::set::cbegin() const
+ const_iterator cbegin() const;
+
+ //! @copydoc ::boost::container::set::end()
+ iterator end() BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @copydoc ::boost::container::set::end() const
+ const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @copydoc ::boost::container::set::cend() const
+ const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @copydoc ::boost::container::set::rbegin()
+ reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @copydoc ::boost::container::set::rbegin() const
+ const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @copydoc ::boost::container::set::crbegin() const
+ const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @copydoc ::boost::container::set::rend()
+ reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @copydoc ::boost::container::set::rend() const
+ const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @copydoc ::boost::container::set::crend() const
+ const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @copydoc ::boost::container::set::empty() const
+ bool empty() const;
+
+ //! @copydoc ::boost::container::set::size() const
+ size_type size() const;
+
+ //! @copydoc ::boost::container::set::max_size() const
+ size_type max_size() const;
+
+ #endif //#if 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.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
+ //! is inserted right before p.
+ template <class... Args>
+ BOOST_CONTAINER_FORCEINLINE iterator emplace(BOOST_FWD_REF(Args)... args)
+ { return this->base_t::emplace_equal(boost::forward<Args>(args)...); }
+
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... in the container.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
+ //! is inserted right before p.
+ template <class... Args>
+ BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator p, BOOST_FWD_REF(Args)... args)
+ { return this->base_t::emplace_hint_equal(p, boost::forward<Args>(args)...); }
+
+ #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ #define BOOST_CONTAINER_MULTIMAP_EMPLACE_CODE(N) \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ BOOST_CONTAINER_FORCEINLINE iterator emplace(BOOST_MOVE_UREF##N)\
+ { return this->base_t::emplace_equal(BOOST_MOVE_FWD##N); }\
+ \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ { return this->base_t::emplace_hint_equal(hint BOOST_MOVE_I##N BOOST_MOVE_FWD##N); }\
+ //
+ BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_MULTIMAP_EMPLACE_CODE)
+ #undef BOOST_CONTAINER_MULTIMAP_EMPLACE_CODE
+
+ #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ //! <b>Effects</b>: Inserts x and returns the iterator pointing to the
+ //! newly inserted element.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ BOOST_CONTAINER_FORCEINLINE iterator insert(const value_type& x)
+ { return this->base_t::insert_equal(x); }
+
+ //! <b>Effects</b>: Inserts a new value constructed from x and returns
+ //! the iterator pointing to the newly inserted element.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ BOOST_CONTAINER_FORCEINLINE iterator insert(const nonconst_value_type& x)
+ { return this->base_t::emplace_equal(x); }
+
+ //! <b>Effects</b>: Inserts a new value move-constructed from x and returns
+ //! the iterator pointing to the newly inserted element.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ BOOST_CONTAINER_FORCEINLINE iterator insert(BOOST_RV_REF(nonconst_value_type) x)
+ { return this->base_t::emplace_equal(boost::move(x)); }
+
+ //! <b>Effects</b>: Inserts a new value move-constructed from x and returns
+ //! the iterator pointing to the newly inserted element.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ iterator insert(BOOST_RV_REF(movable_value_type) x)
+ { return this->base_t::emplace_equal(boost::move(x)); }
+
+ //! <b>Effects</b>: Inserts a copy of x in the container.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
+ //! is inserted right before p.
+ BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, const value_type& x)
+ { return this->base_t::insert_equal(p, x); }
+
+ //! <b>Effects</b>: Inserts a new value constructed from x in the container.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
+ //! is inserted right before p.
+ BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, const nonconst_value_type& x)
+ { return this->base_t::emplace_hint_equal(p, x); }
+
+ //! <b>Effects</b>: Inserts a new value move constructed from x in the container.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
+ //! is inserted right before p.
+ BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(nonconst_value_type) x)
+ { return this->base_t::emplace_hint_equal(p, boost::move(x)); }
+
+ //! <b>Effects</b>: Inserts a new value move constructed from x in the container.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
+ //! is inserted right before p.
+ BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator p, BOOST_RV_REF(movable_value_type) x)
+ { return this->base_t::emplace_hint_equal(p, boost::move(x)); }
+
+ //! <b>Requires</b>: first, last are not iterators into *this.
+ //!
+ //! <b>Effects</b>: inserts each element from the range [first,last) .
+ //!
+ //! <b>Complexity</b>: At most N log(size()+N) (N is the distance from first to last)
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE void insert(InputIterator first, InputIterator last)
+ { this->base_t::insert_equal(first, last); }
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: inserts each element from the range [il.begin(), il.end().
+ //!
+ //! <b>Complexity</b>: At most N log(size()+N) (N is the distance from il.begin() to il.end())
+ BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il)
+ { this->base_t::insert_equal(il.begin(), il.end()); }
+#endif
+
+ //! <b>Requires</b>: nh is empty or this->get_allocator() == nh.get_allocator().
+ //!
+ //! <b>Effects/Returns</b>: If nh is empty, has no effect and returns end(). Otherwise, inserts
+ //! the element owned by nh and returns an iterator pointing to the newly inserted element.
+ //! If a range containing elements with keys equivalent to nh.key() exists,
+ //! the element is inserted at the end of that range. nh is always emptied.
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ iterator insert(BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)
+ {
+ typename base_t::node_type n(boost::move(nh));
+ return this->base_t::insert_equal_node(boost::move(n));
+ }
+
+ //! <b>Effects</b>: Same as `insert(node_type && nh)` but the element is inserted as close as possible
+ //! to the position just prior to "hint".
+ //!
+ //! <b>Complexity</b>: logarithmic in general, but amortized constant if the element is inserted
+ //! right before "hint".
+ iterator insert(const_iterator hint, BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)
+ {
+ typename base_t::node_type n(boost::move(nh));
+ return this->base_t::insert_equal_node(hint, boost::move(n));
+ }
+
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ //! @copydoc ::boost::container::set::erase(const_iterator)
+ iterator erase(const_iterator p);
+
+ //! @copydoc ::boost::container::set::erase(const key_type&)
+ size_type erase(const key_type& x);
+
+ //! @copydoc ::boost::container::set::erase(const_iterator,const_iterator)
+ iterator erase(const_iterator first, const_iterator last);
+ #endif
+
+ //! @copydoc ::boost::container::map::extract(const key_type&)
+ node_type extract(const key_type& k)
+ {
+ typename base_t::node_type base_nh(this->base_t::extract(k));
+ return node_type(boost::move(base_nh));
+ }
+
+ //! @copydoc ::boost::container::map::extract(const_iterator)
+ node_type extract(const_iterator position)
+ {
+ typename base_t::node_type base_nh(this->base_t::extract(position));
+ return node_type (boost::move(base_nh));
+ }
+
+ //! <b>Requires</b>: this->get_allocator() == source.get_allocator().
+ //!
+ //! <b>Effects</b>: Extracts each element in source and insert it into a using
+ //! the comparison object of *this.
+ //!
+ //! <b>Postcondition</b>: Pointers and references to the transferred elements of source refer
+ //! to those same elements but as members of *this. Iterators referring to the transferred
+ //! elements will continue to refer to their elements, but they now behave as iterators into *this,
+ //! not into source.
+ //!
+ //! <b>Throws</b>: Nothing unless the comparison object throws.
+ //!
+ //! <b>Complexity</b>: N log(a.size() + N) (N has the value source.size())
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge(multimap<Key, T, C2, Allocator, Options>& source)
+ {
+ typedef dtl::tree
+ <value_type_impl, select_1st_t, C2, Allocator, Options> base2_t;
+ this->base_t::merge_equal(static_cast<base2_t&>(source));
+ }
+
+ //! @copydoc ::boost::container::multimap::merge(multimap<Key, T, C2, Allocator, Options>&)
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG multimap<Key, T, C2, Allocator, Options> BOOST_RV_REF_END source)
+ { return this->merge(static_cast<multimap<Key, T, C2, Allocator, Options>&>(source)); }
+
+ //! @copydoc ::boost::container::multimap::merge(multimap<Key, T, C2, Allocator, Options>&)
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge(map<Key, T, C2, Allocator, Options>& source)
+ {
+ typedef dtl::tree
+ <value_type_impl, select_1st_t, C2, Allocator, Options> base2_t;
+ this->base_t::merge_equal(static_cast<base2_t&>(source));
+ }
+
+ //! @copydoc ::boost::container::multimap::merge(multimap<Key, T, C2, Allocator, Options>&)
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG map<Key, T, C2, Allocator, Options> BOOST_RV_REF_END source)
+ { return this->merge(static_cast<map<Key, T, C2, Allocator, Options>&>(source)); }
+
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ //! @copydoc ::boost::container::set::swap
+ void swap(multiset& x)
+ BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value
+ && boost::container::dtl::is_nothrow_swappable<Compare>::value );
+
+ //! @copydoc ::boost::container::set::clear
+ void clear() BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @copydoc ::boost::container::set::key_comp
+ key_compare key_comp() const;
+
+ //! @copydoc ::boost::container::set::value_comp
+ value_compare value_comp() const;
+
+ //! <b>Returns</b>: An iterator pointing to an element with the key
+ //! equivalent to x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ iterator find(const key_type& x);
+
+ //! <b>Returns</b>: A const iterator pointing to an element with the key
+ //! equivalent to x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ const_iterator find(const key_type& x) const;
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Returns</b>: An iterator pointing to an element with the key
+ //! equivalent to x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ template<typename K>
+ iterator find(const K& x);
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <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.
+ template<typename K>
+ const_iterator find(const K& x) const;
+
+ //! <b>Returns</b>: The number of elements with key equivalent to x.
+ //!
+ //! <b>Complexity</b>: log(size())+count(k)
+ size_type count(const key_type& x) const;
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Returns</b>: The number of elements with key equivalent to x.
+ //!
+ //! <b>Complexity</b>: log(size())+count(k)
+ template<typename K>
+ size_type count(const K& x) const;
+
+ //! <b>Returns</b>: An iterator pointing to the first element with key not less
+ //! than k, or a.end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ iterator lower_bound(const key_type& x);
+
+ //! <b>Returns</b>: A const iterator pointing to the first element with key not
+ //! less than k, or a.end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ const_iterator lower_bound(const key_type& x) const;
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the first element with key not less
+ //! than k, or a.end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ template<typename K>
+ iterator lower_bound(const K& x);
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <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
+ template<typename K>
+ const_iterator lower_bound(const K& x) const;
+
+ //! <b>Returns</b>: An iterator pointing to the first element with key not less
+ //! than x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ iterator upper_bound(const key_type& x);
+
+ //! <b>Returns</b>: A const iterator pointing to the first element with key not
+ //! less than x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ const_iterator upper_bound(const key_type& x) const;
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the first element with key not less
+ //! than x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ template<typename K>
+ iterator upper_bound(const K& x);
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <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
+ template<typename K>
+ const_iterator upper_bound(const K& x) const;
+
+ //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ std::pair<iterator,iterator> equal_range(const key_type& x);
+
+ //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ std::pair<const_iterator,const_iterator> equal_range(const key_type& x) const;
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ template<typename K>
+ std::pair<iterator,iterator> equal_range(const K& x);
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ template<typename K>
+ std::pair<const_iterator,const_iterator> equal_range(const K& x) const;
+
+ //! <b>Effects</b>: Rebalances the tree. It's a no-op for Red-Black and AVL trees.
+ //!
+ //! <b>Complexity</b>: Linear
+ void rebalance();
+
+ //! <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 multimap& x, const multimap& y);
+
+ //! <b>Effects</b>: Returns true if x and y are unequal
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator!=(const multimap& x, const multimap& y);
+
+ //! <b>Effects</b>: Returns true if x is less than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator<(const multimap& x, const multimap& y);
+
+ //! <b>Effects</b>: Returns true if x is greater than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator>(const multimap& x, const multimap& y);
+
+ //! <b>Effects</b>: Returns true if x is equal or less than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator<=(const multimap& x, const multimap& y);
+
+ //! <b>Effects</b>: Returns true if x is equal or greater than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator>=(const multimap& x, const multimap& y);
+
+ //! <b>Effects</b>: x.swap(y)
+ //!
+ //! <b>Complexity</b>: Constant.
+ friend void swap(multimap& x, multimap& y);
+
+ #endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+};
+
+#if __cplusplus >= 201703L
+
+template <typename InputIterator>
+multimap(InputIterator, InputIterator) ->
+ multimap<typename dtl::remove_const< typename iterator_traits<InputIterator>::value_type::first_type>::type
+ , typename iterator_traits<InputIterator>::value_type::second_type>;
+
+template <typename InputIterator, typename Allocator>
+multimap(InputIterator, InputIterator, Allocator const&) ->
+ multimap<typename dtl::remove_const< typename iterator_traits<InputIterator>::value_type::first_type>::type
+ , typename iterator_traits<InputIterator>::value_type::second_type
+ , std::less<typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type>
+ , Allocator>;
+
+template <typename InputIterator, typename Compare>
+multimap(InputIterator, InputIterator, Compare const&) ->
+ multimap< typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type
+ , typename iterator_traits<InputIterator>::value_type::second_type
+ , Compare>;
+
+template <typename InputIterator, typename Compare, typename Allocator>
+multimap(InputIterator, InputIterator, Compare const&, Allocator const&) ->
+ multimap< typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type
+ , typename iterator_traits<InputIterator>::value_type::second_type
+ , Compare
+ , Allocator>;
+
+template <typename InputIterator>
+multimap(ordered_range_t, InputIterator, InputIterator) ->
+ multimap< typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type
+ , typename iterator_traits<InputIterator>::value_type::second_type>;
+
+template <typename InputIterator, typename Allocator>
+multimap(ordered_range_t, InputIterator, InputIterator, Allocator const&) ->
+ multimap< typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type
+ , typename iterator_traits<InputIterator>::value_type::second_type
+ , std::less<typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type>
+ , Allocator>;
+
+template <typename InputIterator, typename Compare>
+multimap(ordered_range_t, InputIterator, InputIterator, Compare const&) ->
+ multimap< typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type
+ , typename iterator_traits<InputIterator>::value_type::second_type
+ , Compare>;
+
+template <typename InputIterator, typename Compare, typename Allocator>
+multimap(ordered_range_t, InputIterator, InputIterator, Compare const&, Allocator const&) ->
+ multimap< typename dtl::remove_const<typename iterator_traits<InputIterator>::value_type::first_type>::type
+ , typename iterator_traits<InputIterator>::value_type::second_type
+ , Compare
+ , Allocator>;
+
+#endif
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+} //namespace container {
+
+//!has_trivial_destructor_after_move<> == true_type
+//!specialization for optimizations
+template <class Key, class T, class Compare, class Allocator>
+struct has_trivial_destructor_after_move<boost::container::multimap<Key, T, Compare, 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 &&
+ ::boost::has_trivial_destructor_after_move<Compare>::value;
+};
+
+namespace container {
+
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+}}
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif // BOOST_CONTAINER_MAP_HPP
+
diff --git a/include/boost/container/new_allocator.hpp b/include/boost/container/new_allocator.hpp
new file mode 100644
index 0000000..51065ef
--- /dev/null
+++ b/include/boost/container/new_allocator.hpp
@@ -0,0 +1,179 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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 {
+
+/// @cond
+
+template<bool Value>
+struct new_allocator_bool
+{ static const bool value = Value; };
+
+template<class T>
+class new_allocator;
+
+/// @endcond
+
+//! 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_NEW_ALLOCATOR_HPP
diff --git a/include/boost/container/node_allocator.hpp b/include/boost/container/node_allocator.hpp
new file mode 100644
index 0000000..b5c20a6
--- /dev/null
+++ b/include/boost/container/node_allocator.hpp
@@ -0,0 +1,341 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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_POOLED_NODE_ALLOCATOR_HPP
+#define BOOST_CONTAINER_POOLED_NODE_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/container_fwd.hpp>
+#include <boost/container/throw_exception.hpp>
+#include <boost/container/detail/node_pool.hpp>
+#include <boost/container/detail/mpl.hpp>
+#include <boost/container/detail/multiallocation_chain.hpp>
+#include <boost/container/detail/dlmalloc.hpp>
+#include <boost/container/detail/singleton.hpp>
+
+#include <boost/assert.hpp>
+#include <boost/static_assert.hpp>
+#include <cstddef>
+
+namespace boost {
+namespace container {
+
+//!An STL node allocator that uses a modified DlMalloc as memory
+//!source.
+//!
+//!This node allocator shares a segregated storage between all instances
+//!of node_allocator with equal sizeof(T).
+//!
+//!NodesPerBlock is the number of nodes allocated at once when the allocator
+//!runs out of nodes
+#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
+template
+ < class T
+ , std::size_t NodesPerBlock = NodeAlloc_nodes_per_block>
+#else
+template
+ < class T
+ , std::size_t NodesPerBlock
+ , std::size_t Version>
+#endif
+class node_allocator
+{
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ //! If Version is 1, the allocator is a STL conforming allocator. If Version is 2,
+ //! the allocator offers advanced expand in place and burst allocation capabilities.
+ public:
+ typedef unsigned int allocation_type;
+ typedef node_allocator<T, NodesPerBlock, Version> self_t;
+
+ static const std::size_t nodes_per_block = NodesPerBlock;
+
+ BOOST_STATIC_ASSERT((Version <=2));
+ #endif
+
+ public:
+ //-------
+ typedef T value_type;
+ typedef T * pointer;
+ typedef const T * const_pointer;
+ typedef typename ::boost::container::
+ dtl::unvoid_ref<T>::type reference;
+ typedef typename ::boost::container::
+ dtl::unvoid_ref<const T>::type const_reference;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+
+ typedef boost::container::dtl::
+ version_type<self_t, Version> version;
+
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ typedef boost::container::dtl::
+ basic_multiallocation_chain<void*> multiallocation_chain_void;
+ typedef boost::container::dtl::
+ transform_multiallocation_chain
+ <multiallocation_chain_void, T> multiallocation_chain;
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ //!Obtains node_allocator from
+ //!node_allocator
+ template<class T2>
+ struct rebind
+ {
+ typedef node_allocator< T2, NodesPerBlock
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ , Version
+ #endif
+ > other;
+ };
+
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ private:
+ //!Not assignable from related node_allocator
+ template<class T2, std::size_t N2>
+ node_allocator& operator=
+ (const node_allocator<T2, N2>&);
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ public:
+
+ //!Default constructor
+ node_allocator() BOOST_NOEXCEPT_OR_NOTHROW
+ {}
+
+ //!Copy constructor from other node_allocator.
+ node_allocator(const node_allocator &) BOOST_NOEXCEPT_OR_NOTHROW
+ {}
+
+ //!Copy constructor from related node_allocator.
+ template<class T2>
+ node_allocator
+ (const node_allocator<T2, NodesPerBlock
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ , Version
+ #endif
+ > &) BOOST_NOEXCEPT_OR_NOTHROW
+ {}
+
+ //!Destructor
+ ~node_allocator() BOOST_NOEXCEPT_OR_NOTHROW
+ {}
+
+ //!Returns the number of elements that could be allocated.
+ //!Never throws
+ size_type max_size() const
+ { 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(BOOST_UNLIKELY(count > this->max_size()))
+ boost::container::throw_bad_alloc();
+
+ if(Version == 1 && count == 1){
+ typedef dtl::shared_node_pool
+ <sizeof(T), NodesPerBlock> shared_pool_t;
+ typedef dtl::singleton_default<shared_pool_t> singleton_t;
+ return pointer(static_cast<T*>(singleton_t::instance().allocate_node()));
+ }
+ else{
+ void *ret = dlmalloc_malloc(count*sizeof(T));
+ if(BOOST_UNLIKELY(!ret))
+ boost::container::throw_bad_alloc();
+ return static_cast<pointer>(ret);
+ }
+ }
+
+ //!Deallocate allocated memory.
+ //!Never throws
+ void deallocate(const pointer &ptr, size_type count) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ (void)count;
+ if(Version == 1 && count == 1){
+ typedef dtl::shared_node_pool
+ <sizeof(T), NodesPerBlock> shared_pool_t;
+ typedef dtl::singleton_default<shared_pool_t> singleton_t;
+ singleton_t::instance().deallocate_node(ptr);
+ }
+ else{
+ dlmalloc_free(ptr);
+ }
+ }
+
+ //!Deallocates all free blocks of the pool
+ static void deallocate_free_blocks() BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ typedef dtl::shared_node_pool
+ <sizeof(T), NodesPerBlock> shared_pool_t;
+ typedef dtl::singleton_default<shared_pool_t> singleton_t;
+ singleton_t::instance().deallocate_free_blocks();
+ }
+
+ pointer allocation_command
+ (allocation_type command, size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse)
+ {
+ BOOST_STATIC_ASSERT(( Version > 1 ));
+ 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_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_STATIC_ASSERT(( Version > 1 ));
+ return dlmalloc_size(p);
+ }
+
+ //!Allocates just one object. Memory allocated with this function
+ //!must be deallocated only with deallocate_one().
+ //!Throws bad_alloc if there is no enough memory
+ pointer allocate_one()
+ {
+ BOOST_STATIC_ASSERT(( Version > 1 ));
+ typedef dtl::shared_node_pool
+ <sizeof(T), NodesPerBlock> shared_pool_t;
+ typedef dtl::singleton_default<shared_pool_t> singleton_t;
+ return (pointer)singleton_t::instance().allocate_node();
+ }
+
+ //!Allocates many elements of size == 1.
+ //!Elements must be individually deallocated with deallocate_one()
+ void allocate_individual(std::size_t num_elements, multiallocation_chain &chain)
+ {
+ BOOST_STATIC_ASSERT(( Version > 1 ));
+ typedef dtl::shared_node_pool
+ <sizeof(T), NodesPerBlock> shared_pool_t;
+ typedef dtl::singleton_default<shared_pool_t> singleton_t;
+ typename shared_pool_t::multiallocation_chain ch;
+ singleton_t::instance().allocate_nodes(num_elements, ch);
+ chain.incorporate_after(chain.before_begin(), (T*)&*ch.begin(), (T*)&*ch.last(), ch.size());
+ }
+
+ //!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_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_STATIC_ASSERT(( Version > 1 ));
+ typedef dtl::shared_node_pool
+ <sizeof(T), NodesPerBlock> shared_pool_t;
+ typedef dtl::singleton_default<shared_pool_t> singleton_t;
+ singleton_t::instance().deallocate_node(p);
+ }
+
+ void deallocate_individual(multiallocation_chain &chain) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_STATIC_ASSERT(( Version > 1 ));
+ typedef dtl::shared_node_pool
+ <sizeof(T), NodesPerBlock> shared_pool_t;
+ typedef dtl::singleton_default<shared_pool_t> singleton_t;
+ typename shared_pool_t::multiallocation_chain ch(&*chain.begin(), &*chain.last(), chain.size());
+ singleton_t::instance().deallocate_nodes(ch);
+ }
+
+ //!Allocates many elements of size elem_size.
+ //!Elements must be individually deallocated with deallocate()
+ void allocate_many(size_type elem_size, std::size_t n_elements, multiallocation_chain &chain)
+ {
+ BOOST_STATIC_ASSERT(( Version > 1 ));
+ dlmalloc_memchain ch;
+ BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
+ if(BOOST_UNLIKELY(!dlmalloc_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_LASTMEM(&ch)
+ , (T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch)
+ , BOOST_CONTAINER_MEMCHAIN_SIZE(&ch));
+ }
+
+ //!Allocates n_elements elements, each one of size elem_sizes[i]
+ //!Elements must be individually deallocated with deallocate()
+ void allocate_many(const size_type *elem_sizes, size_type n_elements, multiallocation_chain &chain)
+ {
+ BOOST_STATIC_ASSERT(( Version > 1 ));
+ dlmalloc_memchain ch;
+ dlmalloc_multialloc_arrays(n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch);
+ if(BOOST_UNLIKELY(BOOST_CONTAINER_MEMCHAIN_EMPTY(&ch))){
+ boost::container::throw_bad_alloc();
+ }
+ chain.incorporate_after( chain.before_begin()
+ , (T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch)
+ , (T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch)
+ , BOOST_CONTAINER_MEMCHAIN_SIZE(&ch));
+ }
+
+ void deallocate_many(multiallocation_chain &chain) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_STATIC_ASSERT(( Version > 1 ));
+ void *first = &*chain.begin();
+ void *last = &*chain.last();
+ size_t num = chain.size();
+ dlmalloc_memchain ch;
+ BOOST_CONTAINER_MEMCHAIN_INIT_FROM(&ch, first, last, num);
+ dlmalloc_multidealloc(&ch);
+ }
+
+ //!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_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_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_NOEXCEPT_OR_NOTHROW
+ { return false; }
+
+ private:
+ pointer priv_allocation_command
+ (allocation_type command, std::size_t limit_size
+ ,size_type &prefer_in_recvd_out_size
+ ,pointer &reuse)
+ {
+ std::size_t const preferred_size = prefer_in_recvd_out_size;
+ dlmalloc_command_ret_t ret = {0 , 0};
+ 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;
+ {
+ void* reuse_ptr_void = reuse;
+ ret = dlmalloc_allocation_command(command, sizeof(T), l_size, p_size, &r_size, reuse_ptr_void);
+ reuse = static_cast<T*>(reuse_ptr_void);
+ }
+ prefer_in_recvd_out_size = r_size/sizeof(T);
+ return (pointer)ret.first;
+ }
+};
+
+} //namespace container {
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_CONTAINER_POOLED_NODE_ALLOCATOR_HPP
diff --git a/include/boost/container/node_handle.hpp b/include/boost/container/node_handle.hpp
new file mode 100644
index 0000000..ef1d71f
--- /dev/null
+++ b/include/boost/container/node_handle.hpp
@@ -0,0 +1,443 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2016-2016. 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_NODE_HANDLE_HPP
+#define BOOST_CONTAINER_NODE_HANDLE_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/static_assert.hpp>
+#include <boost/container/detail/placement_new.hpp>
+#include <boost/move/detail/to_raw_pointer.hpp>
+#include <boost/container/allocator_traits.hpp>
+#include <boost/container/detail/mpl.hpp>
+
+#include <boost/move/utility_core.hpp>
+#include <boost/move/adl_move_swap.hpp>
+
+#include <boost/type_traits/aligned_storage.hpp>
+
+
+//!\file
+
+namespace boost {
+namespace container {
+
+///@cond
+
+template<class Value, class KeyMapped>
+struct node_handle_keymapped_traits
+{
+ typedef typename KeyMapped::key_type key_type;
+ typedef typename KeyMapped::mapped_type mapped_type;
+};
+
+template<class Value>
+struct node_handle_keymapped_traits<Value, void>
+{
+ typedef Value key_type;
+ typedef Value mapped_type;
+};
+
+class node_handle_friend
+{
+ public:
+
+ template<class NH>
+ BOOST_CONTAINER_FORCEINLINE static void destroy_alloc(NH &nh) BOOST_NOEXCEPT
+ { nh.destroy_alloc(); }
+
+ template<class NH>
+ BOOST_CONTAINER_FORCEINLINE static typename NH::node_pointer &get_node_pointer(NH &nh) BOOST_NOEXCEPT
+ { return nh.get_node_pointer(); }
+};
+
+
+///@endcond
+
+//! A node_handle is an object that accepts ownership of a single element from an associative container.
+//! It may be used to transfer that ownership to another container with compatible nodes. Containers
+//! with compatible nodes have the same node handle type. Elements may be transferred in either direction
+//! between container types in the same row:.
+//!
+//! Container types with compatible nodes
+//!
+//! map<K, T, C1, A> <-> map<K, T, C2, A>
+//!
+//! map<K, T, C1, A> <-> multimap<K, T, C2, A>
+//!
+//! set<K, C1, A> <-> set<K, C2, A>
+//!
+//! set<K, C1, A> <-> multiset<K, C2, A>
+//!
+//! If a node handle is not empty, then it contains an allocator that is equal to the allocator of the container
+//! when the element was extracted. If a node handle is empty, it contains no allocator.
+template <class NodeAllocator, class KeyMapped = void>
+class node_handle
+{
+ typedef NodeAllocator nallocator_type;
+ typedef allocator_traits<NodeAllocator> nator_traits;
+ typedef typename nator_traits::value_type priv_node_t;
+ typedef typename priv_node_t::value_type priv_value_t;
+ typedef node_handle_keymapped_traits<priv_value_t, KeyMapped> keymapped_t;
+
+ public:
+ typedef priv_value_t value_type;
+ typedef typename keymapped_t::key_type key_type;
+ typedef typename keymapped_t::mapped_type mapped_type;
+ typedef typename nator_traits::template portable_rebind_alloc
+ <value_type>::type allocator_type;
+
+ typedef priv_node_t container_node_type;
+ friend class node_handle_friend;
+
+ ///@cond
+ private:
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(node_handle)
+
+ typedef typename nator_traits::pointer node_pointer;
+ typedef ::boost::aligned_storage
+ < sizeof(nallocator_type)
+ , boost::alignment_of<nallocator_type>::value> nalloc_storage_t;
+
+ node_pointer m_ptr;
+ nalloc_storage_t m_nalloc_storage;
+
+ void move_construct_alloc(nallocator_type &al)
+ { ::new(m_nalloc_storage.address(), boost_container_new_t()) nallocator_type(::boost::move(al)); }
+
+ void destroy_deallocate_node()
+ {
+ nator_traits::destroy(this->node_alloc(), boost::movelib::to_raw_pointer(m_ptr));
+ nator_traits::deallocate(this->node_alloc(), m_ptr, 1u);
+ }
+
+ template<class OtherNodeHandle>
+ void move_construct_end(OtherNodeHandle &nh)
+ {
+ if(m_ptr){
+ ::new (m_nalloc_storage.address(), boost_container_new_t()) nallocator_type(::boost::move(nh.node_alloc()));
+ node_handle_friend::destroy_alloc(nh);
+ node_handle_friend::get_node_pointer(nh) = node_pointer();
+ }
+ BOOST_ASSERT(nh.empty());
+ }
+
+ void destroy_alloc() BOOST_NOEXCEPT
+ { static_cast<nallocator_type*>(m_nalloc_storage.address())->~nallocator_type(); }
+
+ node_pointer &get_node_pointer() BOOST_NOEXCEPT
+ { return m_ptr; }
+
+ ///@endcond
+
+ public:
+ //! <b>Effects</b>: Initializes m_ptr to nullptr.
+ //!
+ //! <b>Postcondition</b>: this->empty()
+ BOOST_CXX14_CONSTEXPR node_handle() BOOST_NOEXCEPT
+ : m_ptr()
+ { }
+
+ //! <b>Effects</b>: Constructs a node_handle object initializing internal pointer with p.
+ //! If p != nullptr copy constructs internal allocator from al.
+ node_handle(node_pointer p, const nallocator_type &al) BOOST_NOEXCEPT
+ : m_ptr(p)
+ {
+ if(m_ptr){
+ ::new (m_nalloc_storage.address(), boost_container_new_t()) nallocator_type(al);
+ }
+ }
+
+ //! <b>Effects</b>: Constructs a node_handle object initializing internal pointer with a related nh's internal pointer
+ //! and assigns nullptr to the later. If nh's internal pointer was not nullptr, move constructs internal
+ //! allocator with nh's internal allocator and destroy nh's internal allocator.
+ //!
+ //! <b>Postcondition</b>: nh.empty()
+ //!
+ //! <b>Note</b>: Two node_handle's are related if only one of KeyMapped template parameter
+ //! of a node handle is void.
+ template<class KeyMapped2>
+ node_handle( BOOST_RV_REF_BEG node_handle<NodeAllocator, KeyMapped2> BOOST_RV_REF_END nh
+ , typename dtl::enable_if_c
+ < ((unsigned)dtl::is_same<KeyMapped, void>::value +
+ (unsigned)dtl::is_same<KeyMapped2, void>::value) == 1u
+ >::type* = 0) BOOST_NOEXCEPT
+ : m_ptr(nh.get())
+ { this->move_construct_end(nh); }
+
+ //! <b>Effects</b>: Constructs a node_handle object initializing internal pointer with nh's internal pointer
+ //! and assigns nullptr to the later. If nh's internal pointer was not nullptr, move constructs internal
+ //! allocator with nh's internal allocator and destroy nh's internal allocator.
+ //!
+ //! <b>Postcondition</b>: nh.empty()
+ node_handle (BOOST_RV_REF(node_handle) nh) BOOST_NOEXCEPT
+ : m_ptr(nh.m_ptr)
+ { this->move_construct_end(nh); }
+
+ //! <b>Effects</b>: If !this->empty(), destroys the value_type subobject in the container_node_type object
+ //! pointed to by c by calling allocator_traits<impl_defined>::destroy, then deallocates m_ptr by calling
+ //! nator_traits::rebind_traits<container_node_type>::deallocate.
+ ~node_handle() BOOST_NOEXCEPT
+ {
+ if(!this->empty()){
+ this->destroy_deallocate_node();
+ this->destroy_alloc();
+ }
+ }
+
+ //! <b>Requires</b>: Either this->empty(), or nator_traits::propagate_on_container_move_assignment is true, or
+ //! node_alloc() == nh.node_alloc().
+ //!
+ //! <b>Effects</b>: If m_ptr != nullptr, destroys the value_type subobject in the container_node_type object
+ //! pointed to by m_ptr by calling nator_traits::destroy, then deallocates m_ptr by calling
+ //! nator_traits::deallocate. Assigns nh.m_ptr to m_ptr. If this->empty()
+ //! or nator_traits::propagate_on_container_move_assignment is true, move assigns nh.node_alloc() to
+ //! node_alloc(). Assigns nullptr to nh.m_ptr and assigns nullopt to nh.node_alloc().
+ //!
+ //! <b>Returns</b>: *this.
+ //!
+ //! <b>Throws</b>: Nothing.
+ node_handle & operator=(BOOST_RV_REF(node_handle) nh) BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT(this->empty() || nator_traits::propagate_on_container_move_assignment::value
+ || nator_traits::equal(node_alloc(), nh.node_alloc()));
+
+ bool const was_this_non_null = !this->empty();
+ bool const was_nh_non_null = !nh.empty();
+
+ if(was_nh_non_null){
+ if(was_this_non_null){
+ this->destroy_deallocate_node();
+ if(nator_traits::propagate_on_container_move_assignment::value){
+ this->node_alloc() = ::boost::move(nh.node_alloc());
+ }
+ }
+ else{
+ this->move_construct_alloc(nh.node_alloc());
+ }
+ m_ptr = nh.m_ptr;
+ nh.m_ptr = node_pointer();
+ nh.destroy_alloc();
+ }
+ else if(was_this_non_null){
+ this->destroy_deallocate_node();
+ this->destroy_alloc();
+ m_ptr = node_pointer();
+ }
+ return *this;
+ }
+
+ //! <b>Requires</b>: empty() == false.
+ //!
+ //! <b>Returns</b>: A reference to the value_type subobject in the container_node_type object pointed to by m_ptr
+ //!
+ //! <b>Throws</b>: Nothing.
+ value_type& value() const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT((dtl::is_same<KeyMapped, void>::value));
+ BOOST_ASSERT(!empty());
+ return m_ptr->get_data();
+ }
+
+ //! <b>Requires</b>: empty() == false.
+ //!
+ //! <b>Returns</b>: A non-const reference to the key_type member of the value_type subobject in the
+ //! container_node_type object pointed to by m_ptr.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Requires</b>: Modifying the key through the returned reference is permitted.
+ key_type& key() const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT((!dtl::is_same<KeyMapped, void>::value));
+ BOOST_ASSERT(!empty());
+ return const_cast<key_type &>(KeyMapped().key_of_value(m_ptr->get_data()));
+ }
+
+ //! <b>Requires</b>: empty() == false.
+ //!
+ //! <b>Returns</b>: A reference to the mapped_type member of the value_type subobject
+ //! in the container_node_type object pointed to by m_ptr
+ //!
+ //! <b>Throws</b>: Nothing.
+ mapped_type& mapped() const BOOST_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT((!dtl::is_same<KeyMapped, void>::value));
+ BOOST_ASSERT(!empty());
+ return KeyMapped().mapped_of_value(m_ptr->get_data());
+ }
+
+ //! <b>Requires</b>: empty() == false.
+ //!
+ //! <b>Returns</b>: A copy of the internally hold allocator.
+ //!
+ //! <b>Throws</b>: Nothing.
+ allocator_type get_allocator() const
+ {
+ BOOST_ASSERT(!empty());
+ return this->node_alloc();
+ }
+
+ //! <b>Returns</b>: m_ptr != nullptr.
+ //!
+ #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
+ BOOST_CONTAINER_FORCEINLINE explicit operator bool
+ #else
+ private: struct bool_conversion {int for_bool; int for_arg(); }; typedef int bool_conversion::* explicit_bool_arg;
+ public: BOOST_CONTAINER_FORCEINLINE operator explicit_bool_arg
+ #endif
+ ()const BOOST_NOEXCEPT
+ { return m_ptr ? &bool_conversion::for_bool : explicit_bool_arg(0); }
+
+ //! <b>Returns</b>: m_ptr == nullptr.
+ //!
+ bool empty() const BOOST_NOEXCEPT
+ {
+ return !this->m_ptr;
+ }
+
+ //! <b>Requires</b>: this->empty(), or nh.empty(), or nator_traits::propagate_on_container_swap is true, or
+ //! node_alloc() == nh.node_alloc().
+ //!
+ //! <b>Effects</b>: Calls swap(m_ptr, nh.m_ptr). If this->empty(), or nh.empty(), or nator_traits::propagate_on_-
+ //! container_swap is true calls swap(node_alloc(), nh.node_alloc()).
+ void swap(node_handle &nh)
+ BOOST_NOEXCEPT_IF(nator_traits::propagate_on_container_swap::value || nator_traits::is_always_equal::value)
+ {
+ BOOST_ASSERT(this->empty() || nh.empty() || nator_traits::propagate_on_container_swap::value
+ || nator_traits::equal(node_alloc(), nh.node_alloc()));
+
+ bool const was_this_non_null = !this->empty();
+ bool const was_nh_non_null = !nh.empty();
+
+ if(was_nh_non_null){
+ if(was_this_non_null){
+ if(nator_traits::propagate_on_container_swap::value){
+ ::boost::adl_move_swap(this->node_alloc(), nh.node_alloc());
+ }
+ }
+ else{
+ this->move_construct_alloc(nh.node_alloc());
+ nh.destroy_alloc();
+ }
+ }
+ else if(was_this_non_null){
+ nh.move_construct_alloc(this->node_alloc());
+ this->destroy_alloc();
+ }
+ ::boost::adl_move_swap(m_ptr, nh.m_ptr);
+ }
+
+ //! <b>Effects</b>: If this->empty() returns nullptr, otherwise returns m_ptr
+ //! resets m_ptr to nullptr and destroys the internal allocator.
+ //!
+ //! <b>Postcondition</b>: this->empty()
+ //!
+ //! <b>Note</b>: Non-standard extensions
+ node_pointer release() BOOST_NOEXCEPT
+ {
+ node_pointer p(m_ptr);
+ m_ptr = node_pointer();
+ if(p)
+ this->destroy_alloc();
+ return p;
+ }
+
+ //! <b>Effects</b>: Returns m_ptr.
+ //!
+ //! <b>Note</b>: Non-standard extensions
+ node_pointer get() const BOOST_NOEXCEPT
+ {
+ return m_ptr;
+ }
+
+ //! <b>Effects</b>: Returns a reference to the internal node allocator.
+ //!
+ //! <b>Note</b>: Non-standard extensions
+ nallocator_type &node_alloc() BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT(!empty());
+ return *static_cast<nallocator_type*>(m_nalloc_storage.address());
+ }
+
+
+ //! <b>Effects</b>: Returns a reference to the internal node allocator.
+ //!
+ //! <b>Note</b>: Non-standard extensions
+ const nallocator_type &node_alloc() const BOOST_NOEXCEPT
+ {
+ BOOST_ASSERT(!empty());
+ return *static_cast<const nallocator_type*>(m_nalloc_storage.address());
+ }
+
+ //! <b>Effects</b>: x.swap(y).
+ //!
+ friend void swap(node_handle & x, node_handle & y) BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT(x.swap(y)))
+ { x.swap(y); }
+};
+
+//! A class template used to describe the results of inserting a
+//! Container::node_type in a Container with unique keys.
+//! Includes at least the following non-static public data members:
+//!
+//! <ul><li>bool inserted</li>;
+//! <li>Iterator position</li>;
+//! <li>NodeType node</li></ul>
+//!
+//! This type is MoveConstructible, MoveAssignable, DefaultConstructible,
+//! Destructible, and lvalues of that type are swappable
+template<class Iterator, class NodeType>
+struct insert_return_type_base
+{
+ private:
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(insert_return_type_base)
+
+ public:
+ insert_return_type_base()
+ : inserted(false), position(), node()
+ {}
+
+ insert_return_type_base(BOOST_RV_REF(insert_return_type_base) other)
+ : inserted(other.inserted), position(other.position), node(boost::move(other.node))
+ {}
+
+ template<class RelatedIt, class RelatedNode>
+ insert_return_type_base(bool insert, RelatedIt it, BOOST_RV_REF(RelatedNode) node)
+ : inserted(insert), position(it), node(boost::move(node))
+ {}
+
+ insert_return_type_base & operator=(BOOST_RV_REF(insert_return_type_base) other)
+ {
+ inserted = other.inserted;
+ position = other.position;
+ node = boost::move(other.node);
+ return *this;
+ }
+
+ bool inserted;
+ Iterator position;
+ NodeType node;
+};
+
+} //namespace container {
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //BOOST_CONTAINER_NODE_HANDLE_HPP
diff --git a/include/boost/container/options.hpp b/include/boost/container/options.hpp
new file mode 100644
index 0000000..2ac7783
--- /dev/null
+++ b/include/boost/container/options.hpp
@@ -0,0 +1,245 @@
+/////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2013-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_OPTIONS_HPP
+#define BOOST_CONTAINER_OPTIONS_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/container_fwd.hpp>
+#include <boost/intrusive/pack_options.hpp>
+
+namespace boost {
+namespace container {
+
+////////////////////////////////////////////////////////////////
+//
+//
+// OPTIONS FOR ASSOCIATIVE TREE-BASED CONTAINERS
+//
+//
+////////////////////////////////////////////////////////////////
+
+//! Enumeration used to configure ordered associative containers
+//! with a concrete tree implementation.
+enum tree_type_enum
+{
+ red_black_tree,
+ avl_tree,
+ scapegoat_tree,
+ splay_tree
+};
+
+#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+template<tree_type_enum TreeType, bool OptimizeSize>
+struct tree_opt
+{
+ static const boost::container::tree_type_enum tree_type = TreeType;
+ static const bool optimize_size = OptimizeSize;
+};
+
+typedef tree_opt<red_black_tree, true> tree_assoc_defaults;
+
+#endif //!defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+//!This option setter specifies the underlying tree type
+//!(red-black, AVL, Scapegoat or Splay) for ordered associative containers
+BOOST_INTRUSIVE_OPTION_CONSTANT(tree_type, tree_type_enum, TreeType, tree_type)
+
+//!This option setter specifies if node size is optimized
+//!storing rebalancing data masked into pointers for ordered associative containers
+BOOST_INTRUSIVE_OPTION_CONSTANT(optimize_size, bool, Enabled, optimize_size)
+
+//! Helper metafunction to combine options into a single type to be used
+//! by \c boost::container::set, \c boost::container::multiset
+//! \c boost::container::map and \c boost::container::multimap.
+//! Supported options are: \c boost::container::optimize_size and \c boost::container::tree_type
+#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) || defined(BOOST_CONTAINER_VARIADIC_TEMPLATES)
+template<class ...Options>
+#else
+template<class O1 = void, class O2 = void, class O3 = void, class O4 = void>
+#endif
+struct tree_assoc_options
+{
+ /// @cond
+ typedef typename ::boost::intrusive::pack_options
+ < tree_assoc_defaults,
+ #if !defined(BOOST_CONTAINER_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type packed_options;
+ typedef tree_opt<packed_options::tree_type, packed_options::optimize_size> implementation_defined;
+ /// @endcond
+ typedef implementation_defined type;
+};
+
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+//! Helper alias metafunction to combine options into a single type to be used
+//! by tree-based associative containers
+template<class ...Options>
+using tree_assoc_options_t = typename boost::container::tree_assoc_options<Options...>::type;
+
+#endif
+
+////////////////////////////////////////////////////////////////
+//
+//
+// OPTIONS FOR VECTOR-BASED CONTAINERS
+//
+//
+////////////////////////////////////////////////////////////////
+
+#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+template<class AllocTraits, class StoredSizeType>
+struct get_stored_size_type_with_alloctraits
+{
+ typedef StoredSizeType type;
+};
+
+template<class AllocTraits>
+struct get_stored_size_type_with_alloctraits<AllocTraits, void>
+{
+ typedef typename AllocTraits::size_type type;
+};
+
+template<class GrowthType, class StoredSizeType>
+struct vector_opt
+{
+ typedef GrowthType growth_factor_type;
+ typedef StoredSizeType stored_size_type;
+
+ template<class AllocTraits>
+ struct get_stored_size_type
+ : get_stored_size_type_with_alloctraits<AllocTraits, StoredSizeType>
+ {};
+};
+
+class default_next_capacity;
+
+typedef vector_opt<void, void> vector_null_opt;
+
+#else //!defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+//!This growth factor argument specifies that the container should increase it's
+//!capacity a 50% when existing capacity is exhausted.
+struct growth_factor_50{};
+
+//!This growth factor argument specifies that the container should increase it's
+//!capacity a 60% when existing capacity is exhausted.
+struct growth_factor_60{};
+
+//!This growth factor argument specifies that the container should increase it's
+//!capacity a 100% (doubling its capacity) when existing capacity is exhausted.
+struct growth_factor_100{};
+
+#endif //!defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+//!This option setter specifies the growth factor strategy of the underlying vector.
+//!
+//!\tparam GrowthFactor A function object that has the following signature:<br/><br/>
+//!`template<class SizeType>`<br/>
+//!`SizeType operator()(SizeType cur_cap, SizeType add_min_cap, SizeType max_cap) const;`.<br/><br/>
+//!`cur_cap` is the current capacity, `add_min_cap` is the minimum additional capacity
+//!we want to achieve and `max_cap` is the maximum capacity that the allocator or other
+//!factors allow. The implementation should return a value between `cur_cap` + `add_min_cap`
+//!and `max_cap`. `cur_cap` + `add_min_cap` is guaranteed not to overflow/wraparound,
+//! but the implementation should handle wraparound produced by the growth factor.
+//!
+//!Predefined growth factors that can be passed as arguments to this option are:
+//!\c boost::container::growth_factor_50
+//!\c boost::container::growth_factor_60
+//!\c boost::container::growth_factor_100
+//!
+//!If this option is not specified, a default will be used by the container.
+BOOST_INTRUSIVE_OPTION_TYPE(growth_factor, GrowthFactor, GrowthFactor, growth_factor_type)
+
+//!This option specifies the unsigned integer type that a user wants the container
+//!to use to hold size-related information inside a container (e.g. current size, current capacity).
+//!
+//!\tparam StoredSizeType A unsigned integer type. It shall be smaller than than the size
+//! of the size_type deduced from `allocator_traits<A>::size_type` or the same type.
+//!
+//!If the maximum capacity() to be used is limited, a user can try to use 8-bit, 16-bit
+//!(e.g. in 32-bit machines), or 32-bit size types (e.g. in a 64 bit machine) to see if some
+//!memory can be saved for empty vectors. This could potentially performance benefits due to better
+//!cache usage.
+//!
+//!Note that alignment requirements can disallow theoritical space savings. Example:
+//!\c vector holds a pointer and two size types (for size and capacity), in a 32 bit machine
+//!a 8 bit size type (total size: 4 byte pointer + 2 x 1 byte sizes = 6 bytes)
+//!will not save space when comparing two 16-bit size types because usually
+//!a 32 bit alignment is required for vector and the size will be rounded to 8 bytes. In a 64-bit
+//!machine a 16 bit size type does not usually save memory when comparing to a 32-bit size type.
+//!Measure the size of the resulting container and do not assume a smaller \c stored_size
+//!will always lead to a smaller sizeof(container).
+//!
+//!If a user tries to insert more elements than representable by \c stored_size, vector
+//!will throw a length_error.
+//!
+//!If this option is not specified, `allocator_traits<A>::size_type` (usually std::size_t) will
+//!be used to store size-related information inside the container.
+BOOST_INTRUSIVE_OPTION_TYPE(stored_size, StoredSizeType, StoredSizeType, stored_size_type)
+
+//! Helper metafunction to combine options into a single type to be used
+//! by \c boost::container::vector.
+//! Supported options are: \c boost::container::growth_factor and \c boost::container::stored_size
+#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED) || defined(BOOST_CONTAINER_VARIADIC_TEMPLATES)
+template<class ...Options>
+#else
+template<class O1 = void, class O2 = void, class O3 = void, class O4 = void>
+#endif
+struct vector_options
+{
+ /// @cond
+ typedef typename ::boost::intrusive::pack_options
+ < vector_null_opt,
+ #if !defined(BOOST_CONTAINER_VARIADIC_TEMPLATES)
+ O1, O2, O3, O4
+ #else
+ Options...
+ #endif
+ >::type packed_options;
+ typedef vector_opt< typename packed_options::growth_factor_type
+ , typename packed_options::stored_size_type> implementation_defined;
+ /// @endcond
+ typedef implementation_defined type;
+};
+
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+//! Helper alias metafunction to combine options into a single type to be used
+//! by \c boost::container::vector.
+//! Supported options are: \c boost::container::growth_factor and \c boost::container::stored_size
+template<class ...Options>
+using vector_options_t = typename boost::container::vector_options<Options...>::type;
+
+#endif
+
+
+} //namespace container {
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_CONTAINER_OPTIONS_HPP
diff --git a/include/boost/container/pmr/deque.hpp b/include/boost/container/pmr/deque.hpp
new file mode 100644
index 0000000..acb7da3
--- /dev/null
+++ b/include/boost/container/pmr/deque.hpp
@@ -0,0 +1,45 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_PMR_DEQUE_HPP
+#define BOOST_CONTAINER_PMR_DEQUE_HPP
+
+#if defined (_MSC_VER)
+# pragma once
+#endif
+
+#include <boost/container/deque.hpp>
+#include <boost/container/pmr/polymorphic_allocator.hpp>
+
+namespace boost {
+namespace container {
+namespace pmr {
+
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+template <class T>
+using deque = boost::container::deque<T, polymorphic_allocator<T>>;
+
+#endif
+
+//! A portable metafunction to obtain a deque
+//! that uses a polymorphic allocator
+template<class T>
+struct deque_of
+{
+ typedef boost::container::deque
+ < T, polymorphic_allocator<T> > type;
+};
+
+} //namespace pmr {
+} //namespace container {
+} //namespace boost {
+
+#endif //BOOST_CONTAINER_PMR_DEQUE_HPP
diff --git a/include/boost/container/pmr/flat_map.hpp b/include/boost/container/pmr/flat_map.hpp
new file mode 100644
index 0000000..76c697b
--- /dev/null
+++ b/include/boost/container/pmr/flat_map.hpp
@@ -0,0 +1,63 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_PMR_FLAT_MAP_HPP
+#define BOOST_CONTAINER_PMR_FLAT_MAP_HPP
+
+#if defined (_MSC_VER)
+# pragma once
+#endif
+
+#include <boost/container/flat_map.hpp>
+#include <boost/container/pmr/polymorphic_allocator.hpp>
+
+namespace boost {
+namespace container {
+namespace pmr {
+
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+template <class Key
+ ,class T
+ ,class Compare = std::less<Key > >
+using flat_map = boost::container::flat_map<Key, T, Compare, polymorphic_allocator<std::pair<Key, T> > >;
+
+template <class Key
+ ,class T
+ ,class Compare = std::less<Key> >
+using flat_multimap = boost::container::flat_multimap<Key, T, Compare, polymorphic_allocator<std::pair<Key, T> > >;
+
+#endif
+
+//! A portable metafunction to obtain a flat_map
+//! that uses a polymorphic allocator
+template <class Key
+ ,class T
+ ,class Compare = std::less<Key> >
+struct flat_map_of
+{
+ typedef boost::container::flat_map<Key, T, Compare, polymorphic_allocator<std::pair<Key, T> > > type;
+};
+
+//! A portable metafunction to obtain a flat_multimap
+//! that uses a polymorphic allocator
+template <class Key
+ ,class T
+ ,class Compare = std::less<Key> >
+struct flat_multimap_of
+{
+ typedef boost::container::flat_multimap<Key, T, Compare, polymorphic_allocator<std::pair<Key, T> > > type;
+};
+
+} //namespace pmr {
+} //namespace container {
+} //namespace boost {
+
+#endif //BOOST_CONTAINER_PMR_FLAT_MAP_HPP
diff --git a/include/boost/container/pmr/flat_set.hpp b/include/boost/container/pmr/flat_set.hpp
new file mode 100644
index 0000000..f072c95
--- /dev/null
+++ b/include/boost/container/pmr/flat_set.hpp
@@ -0,0 +1,59 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_PMR_SET_HPP
+#define BOOST_CONTAINER_PMR_SET_HPP
+
+#if defined (_MSC_VER)
+# pragma once
+#endif
+
+#include <boost/container/flat_set.hpp>
+#include <boost/container/pmr/polymorphic_allocator.hpp>
+
+namespace boost {
+namespace container {
+namespace pmr {
+
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+template <class Key
+ ,class Compare = std::less<Key> >
+using flat_set = boost::container::flat_set<Key, Compare, polymorphic_allocator<Key> >;
+
+template <class Key
+ ,class Compare = std::less<Key> >
+using flat_multiset = boost::container::flat_multiset<Key, Compare, polymorphic_allocator<Key> >;
+
+#endif
+
+//! A portable metafunction to obtain a flat_set
+//! that uses a polymorphic allocator
+template <class Key
+ ,class Compare = std::less<Key> >
+struct flat_set_of
+{
+ typedef boost::container::flat_set<Key, Compare, polymorphic_allocator<Key> > type;
+};
+
+//! A portable metafunction to obtain a flat_multiset
+//! that uses a polymorphic allocator
+template <class Key
+ ,class Compare = std::less<Key> >
+struct flat_multiset_of
+{
+ typedef boost::container::flat_multiset<Key, Compare, polymorphic_allocator<Key> > type;
+};
+
+} //namespace pmr {
+} //namespace container {
+} //namespace boost {
+
+#endif //BOOST_CONTAINER_PMR_SET_HPP
diff --git a/include/boost/container/pmr/global_resource.hpp b/include/boost/container/pmr/global_resource.hpp
new file mode 100644
index 0000000..219309b
--- /dev/null
+++ b/include/boost/container/pmr/global_resource.hpp
@@ -0,0 +1,66 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_PMR_GLOBAL_RESOURCE_HPP
+#define BOOST_CONTAINER_PMR_GLOBAL_RESOURCE_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/auto_link.hpp>
+
+#include <cstddef>
+
+namespace boost {
+namespace container {
+namespace pmr {
+
+/// @cond
+class memory_resource;
+/// @endcond
+
+//! <b>Returns</b>: A pointer to a static-duration object of a type derived from
+//! memory_resource that can serve as a resource for allocating memory using
+//! global `operator new` and global `operator delete`. The same value is returned every time this function
+//! is called. For return value p and memory resource r, p->is_equal(r) returns &r == p.
+BOOST_CONTAINER_DECL memory_resource* new_delete_resource() BOOST_NOEXCEPT;
+
+//! <b>Returns</b>: A pointer to a static-duration object of a type derived from
+//! memory_resource for which allocate() always throws bad_alloc and for which
+//! deallocate() has no effect. The same value is returned every time this function
+//! is called. For return value p and memory resource r, p->is_equal(r) returns &r == p.
+BOOST_CONTAINER_DECL memory_resource* null_memory_resource() BOOST_NOEXCEPT;
+
+//! <b>Effects</b>: If r is non-null, sets the value of the default memory resource
+//! pointer to r, otherwise sets the default memory resource pointer to new_delete_resource().
+//!
+//! <b>Postconditions</b>: get_default_resource() == r.
+//!
+//! <b>Returns</b>: The previous value of the default memory resource pointer.
+//!
+//! <b>Remarks</b>: Calling the set_default_resource and get_default_resource functions shall
+//! not incur a data race. A call to the set_default_resource function shall synchronize
+//! with subsequent calls to the set_default_resource and get_default_resource functions.
+BOOST_CONTAINER_DECL memory_resource* set_default_resource(memory_resource* r) BOOST_NOEXCEPT;
+
+//! <b>Returns</b>: The current value of the default
+//! memory resource pointer.
+BOOST_CONTAINER_DECL memory_resource* get_default_resource() BOOST_NOEXCEPT;
+
+} //namespace pmr {
+} //namespace container {
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //BOOST_CONTAINER_PMR_GLOBAL_RESOURCE_HPP
diff --git a/include/boost/container/pmr/list.hpp b/include/boost/container/pmr/list.hpp
new file mode 100644
index 0000000..f3676a3
--- /dev/null
+++ b/include/boost/container/pmr/list.hpp
@@ -0,0 +1,45 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_PMR_LIST_HPP
+#define BOOST_CONTAINER_PMR_LIST_HPP
+
+#if defined (_MSC_VER)
+# pragma once
+#endif
+
+#include <boost/container/list.hpp>
+#include <boost/container/pmr/polymorphic_allocator.hpp>
+
+namespace boost {
+namespace container {
+namespace pmr {
+
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+template <class T>
+using list = boost::container::list<T, polymorphic_allocator<T>>;
+
+#endif
+
+//! A portable metafunction to obtain a list
+//! that uses a polymorphic allocator
+template<class T>
+struct list_of
+{
+ typedef boost::container::list
+ < T, polymorphic_allocator<T> > type;
+};
+
+} //namespace pmr {
+} //namespace container {
+} //namespace boost {
+
+#endif //BOOST_CONTAINER_PMR_VECTOR_HPP
diff --git a/include/boost/container/pmr/map.hpp b/include/boost/container/pmr/map.hpp
new file mode 100644
index 0000000..7182160
--- /dev/null
+++ b/include/boost/container/pmr/map.hpp
@@ -0,0 +1,67 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_PMR_MAP_HPP
+#define BOOST_CONTAINER_PMR_MAP_HPP
+
+#if defined (_MSC_VER)
+# pragma once
+#endif
+
+#include <boost/container/map.hpp>
+#include <boost/container/pmr/polymorphic_allocator.hpp>
+
+namespace boost {
+namespace container {
+namespace pmr {
+
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+template <class Key
+ ,class T
+ ,class Compare = std::less<Key>
+ ,class Options = void >
+using map = boost::container::map<Key, T, Compare, polymorphic_allocator<std::pair<const Key, T> >, Options>;
+
+template <class Key
+ ,class T
+ ,class Compare = std::less<Key>
+ ,class Options = void >
+using multimap = boost::container::multimap<Key, T, Compare, polymorphic_allocator<std::pair<const Key, T> >, Options>;
+
+#endif
+
+//! A portable metafunction to obtain a map
+//! that uses a polymorphic allocator
+template <class Key
+ ,class T
+ ,class Compare = std::less<Key>
+ ,class Options = void >
+struct map_of
+{
+ typedef boost::container::map<Key, T, Compare, polymorphic_allocator<std::pair<const Key, T> >, Options> type;
+};
+
+//! A portable metafunction to obtain a multimap
+//! that uses a polymorphic allocator
+template <class Key
+ ,class T
+ ,class Compare = std::less<Key>
+ ,class Options = void >
+struct multimap_of
+{
+ typedef boost::container::multimap<Key, T, Compare, polymorphic_allocator<std::pair<const Key, T> >, Options> type;
+};
+
+} //namespace pmr {
+} //namespace container {
+} //namespace boost {
+
+#endif //BOOST_CONTAINER_PMR_MAP_HPP
diff --git a/include/boost/container/pmr/memory_resource.hpp b/include/boost/container/pmr/memory_resource.hpp
new file mode 100644
index 0000000..72338a7
--- /dev/null
+++ b/include/boost/container/pmr/memory_resource.hpp
@@ -0,0 +1,101 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_PMR_MEMORY_RESOURCE_HPP
+#define BOOST_CONTAINER_PMR_MEMORY_RESOURCE_HPP
+
+#if defined (_MSC_VER)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+#include <boost/move/detail/type_traits.hpp>
+#include <cstddef>
+
+namespace boost {
+namespace container {
+namespace pmr {
+
+//! The memory_resource class is an abstract interface to an
+//! unbounded set of classes encapsulating memory resources.
+class memory_resource
+{
+ public:
+ // For exposition only
+ static BOOST_CONSTEXPR_OR_CONST std::size_t max_align =
+ boost::move_detail::alignment_of<boost::move_detail::max_align_t>::value;
+
+ //! <b>Effects</b>: Destroys
+ //! this memory_resource.
+ virtual ~memory_resource(){}
+
+ //! <b>Effects</b>: Equivalent to
+ //! `return do_allocate(bytes, alignment);`
+ void* allocate(std::size_t bytes, std::size_t alignment = max_align)
+ { return this->do_allocate(bytes, alignment); }
+
+ //! <b>Effects</b>: Equivalent to
+ //! `return do_deallocate(bytes, alignment);`
+ void deallocate(void* p, std::size_t bytes, std::size_t alignment = max_align)
+ { return this->do_deallocate(p, bytes, alignment); }
+
+ //! <b>Effects</b>: Equivalent to
+ //! `return return do_is_equal(other);`
+ bool is_equal(const memory_resource& other) const BOOST_NOEXCEPT
+ { return this->do_is_equal(other); }
+
+ //! <b>Returns</b>:
+ //! `&a == &b || a.is_equal(b)`.
+ friend bool operator==(const memory_resource& a, const memory_resource& b) BOOST_NOEXCEPT
+ { return &a == &b || a.is_equal(b); }
+
+ //! <b>Returns</b>:
+ //! !(a == b).
+ friend bool operator!=(const memory_resource& a, const memory_resource& b) BOOST_NOEXCEPT
+ { return !(a == b); }
+
+ protected:
+ //! <b>Requires</b>: Alignment shall be a power of two.
+ //!
+ //! <b>Returns</b>: A derived class shall implement this function to return a pointer
+ //! to allocated storage with a size of at least bytes. The returned storage is
+ //! aligned to the specified alignment, if such alignment is supported; otherwise
+ //! it is aligned to max_align.
+ //!
+ //! <b>Throws</b>: A derived class implementation shall throw an appropriate exception if
+ //! it is unable to allocate memory with the requested size and alignment.
+ virtual void* do_allocate(std::size_t bytes, std::size_t alignment) = 0;
+
+ //! <b>Requires</b>: p shall have been returned from a prior call to
+ //! `allocate(bytes, alignment)` on a memory resource equal to *this, and the storage
+ //! at p shall not yet have been deallocated.
+ //!
+ //! <b>Effects</b>: A derived class shall implement this function to dispose of allocated storage.
+ //!
+ //! <b>Throws</b>: Nothing.
+ virtual void do_deallocate(void* p, std::size_t bytes, std::size_t alignment) = 0;
+
+ //! <b>Returns</b>: A derived class shall implement this function to return true if memory
+ //! allocated from this can be deallocated from other and vice-versa; otherwise it shall
+ //! return false. <i>[Note: The most-derived type of other might not match the type of this.
+ //! For a derived class, D, a typical implementation of this function will compute
+ //! `dynamic_cast<const D*>(&other)` and go no further (i.e., return false)
+ //! if it returns nullptr. - end note]</i>.
+ virtual bool do_is_equal(const memory_resource& other) const BOOST_NOEXCEPT = 0;
+};
+
+} //namespace pmr {
+} //namespace container {
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //BOOST_CONTAINER_PMR_MEMORY_RESOURCE_HPP
diff --git a/include/boost/container/pmr/monotonic_buffer_resource.hpp b/include/boost/container/pmr/monotonic_buffer_resource.hpp
new file mode 100644
index 0000000..5a176a3
--- /dev/null
+++ b/include/boost/container/pmr/monotonic_buffer_resource.hpp
@@ -0,0 +1,182 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_PMR_MONOTONIC_BUFFER_RESOURCE_HPP
+#define BOOST_CONTAINER_PMR_MONOTONIC_BUFFER_RESOURCE_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/auto_link.hpp>
+#include <boost/container/pmr/memory_resource.hpp>
+#include <boost/container/detail/block_slist.hpp>
+
+#include <cstddef>
+
+namespace boost {
+namespace container {
+namespace pmr {
+
+//! A monotonic_buffer_resource is a special-purpose memory resource intended for
+//! very fast memory allocations in situations where memory is used to build up a
+//! few objects and then is released all at once when the memory resource object
+//! is destroyed. It has the following qualities:
+//!
+//! - A call to deallocate has no effect, thus the amount of memory consumed
+//! increases monotonically until the resource is destroyed.
+//!
+//! - The program can supply an initial buffer, which the allocator uses to satisfy
+//! memory requests.
+//!
+//! - When the initial buffer (if any) is exhausted, it obtains additional buffers
+//! from an upstream memory resource supplied at construction. Each additional
+//! buffer is larger than the previous one, following a geometric progression.
+//!
+//! - It is intended for access from one thread of control at a time. Specifically,
+//! calls to allocate and deallocate do not synchronize with one another.
+//!
+//! - It owns the allocated memory and frees it on destruction, even if deallocate has
+//! not been called for some of the allocated blocks.
+class BOOST_CONTAINER_DECL monotonic_buffer_resource
+ : public memory_resource
+{
+ block_slist m_memory_blocks;
+ void * m_current_buffer;
+ std::size_t m_current_buffer_size;
+ std::size_t m_next_buffer_size;
+ void * const m_initial_buffer;
+ std::size_t const m_initial_buffer_size;
+
+ /// @cond
+ void increase_next_buffer();
+ void increase_next_buffer_at_least_to(std::size_t minimum_size);
+ void *allocate_from_current(std::size_t aligner, std::size_t bytes);
+ /// @endcond
+
+ public:
+
+ //! The number of bytes that will be requested by the default in the first call
+ //! to the upstream allocator
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ static const std::size_t initial_next_buffer_size = 32u*sizeof(void*);
+
+ //! <b>Requires</b>: `upstream` shall be the address of a valid memory resource or `nullptr`
+ //!
+ //! <b>Effects</b>: If `upstream` is not nullptr, sets the internal resource to `upstream`,
+ //! to get_default_resource() otherwise.
+ //! Sets the internal `current_buffer` to `nullptr` and the internal `next_buffer_size` to an
+ //! implementation-defined size.
+ explicit monotonic_buffer_resource(memory_resource* upstream = 0) BOOST_NOEXCEPT;
+
+ //! <b>Requires</b>: `upstream` shall be the address of a valid memory resource or `nullptr`
+ //! and `initial_size` shall be greater than zero.
+ //!
+ //! <b>Effects</b>: If `upstream` is not nullptr, sets the internal resource to `upstream`,
+ //! to get_default_resource() otherwise. Sets the internal `current_buffer` to `nullptr` and
+ //! `next_buffer_size` to at least `initial_size`.
+ explicit monotonic_buffer_resource(std::size_t initial_size, memory_resource* upstream = 0) BOOST_NOEXCEPT;
+
+ //! <b>Requires</b>: `upstream` shall be the address of a valid memory resource or `nullptr`,
+ //! `buffer_size` shall be no larger than the number of bytes in buffer.
+ //!
+ //! <b>Effects</b>: If `upstream` is not nullptr, sets the internal resource to `upstream`,
+ //! to get_default_resource() otherwise. Sets the internal `current_buffer` to `buffer`,
+ //! and `next_buffer_size` to `buffer_size` (but not less than an implementation-defined size),
+ //! then increases `next_buffer_size` by an implementation-defined growth factor (which need not be integral).
+ monotonic_buffer_resource(void* buffer, std::size_t buffer_size, memory_resource* upstream = 0) BOOST_NOEXCEPT;
+
+ #if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ monotonic_buffer_resource(const monotonic_buffer_resource&) = delete;
+ monotonic_buffer_resource operator=(const monotonic_buffer_resource&) = delete;
+ #else
+ private:
+ monotonic_buffer_resource (const monotonic_buffer_resource&);
+ monotonic_buffer_resource operator=(const monotonic_buffer_resource&);
+ public:
+ #endif
+
+ //! <b>Effects</b>: Calls
+ //! `this->release()`.
+ virtual ~monotonic_buffer_resource();
+
+ //! <b>Effects</b>: `upstream_resource()->deallocate()` as necessary to release all allocated memory.
+ //! [Note: memory is released back to `upstream_resource()` even if some blocks that were allocated
+ //! from this have not been deallocated from this. - end note]
+ void release() BOOST_NOEXCEPT;
+
+ //! <b>Returns</b>: The value of
+ //! the internal resource.
+ memory_resource* upstream_resource() const BOOST_NOEXCEPT;
+
+ //! <b>Returns</b>:
+ //! The number of bytes of storage available for the specified alignment and
+ //! the number of bytes wasted due to the requested alignment.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ std::size_t remaining_storage(std::size_t alignment, std::size_t &wasted_due_to_alignment) const BOOST_NOEXCEPT;
+
+ //! <b>Returns</b>:
+ //! The number of bytes of storage available for the specified alignment.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ std::size_t remaining_storage(std::size_t alignment = 1u) const BOOST_NOEXCEPT;
+
+ //! <b>Returns</b>:
+ //! The address pointing to the start of the current free storage.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ const void *current_buffer() const BOOST_NOEXCEPT;
+
+ //! <b>Returns</b>:
+ //! The number of bytes that will be requested for the next buffer once the
+ //! current one is exhausted.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ std::size_t next_buffer_size() const BOOST_NOEXCEPT;
+
+ protected:
+
+ //! <b>Returns</b>: A pointer to allocated storage with a size of at least `bytes`. The size
+ //! and alignment of the allocated memory shall meet the requirements for a class derived
+ //! from `memory_resource`.
+ //!
+ //! <b>Effects</b>: If the unused space in the internal `current_buffer` can fit a block with the specified
+ //! bytes and alignment, then allocate the return block from the internal `current_buffer`; otherwise sets
+ //! the internal `current_buffer` to `upstream_resource()->allocate(n, m)`, where `n` is not less than
+ //! `max(bytes, next_buffer_size)` and `m` is not less than alignment, and increase
+ //! `next_buffer_size` by an implementation-defined growth factor (which need not be integral),
+ //! then allocate the return block from the newly-allocated internal `current_buffer`.
+ //!
+ //! <b>Throws</b>: Nothing unless `upstream_resource()->allocate()` throws.
+ virtual void* do_allocate(std::size_t bytes, std::size_t alignment);
+
+ //! <b>Effects</b>: None
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Remarks</b>: Memory used by this resource increases monotonically until its destruction.
+ virtual void do_deallocate(void* p, std::size_t bytes, std::size_t alignment) BOOST_NOEXCEPT;
+
+ //! <b>Returns</b>:
+ //! `this == dynamic_cast<const monotonic_buffer_resource*>(&other)`.
+ virtual bool do_is_equal(const memory_resource& other) const BOOST_NOEXCEPT;
+};
+
+} //namespace pmr {
+} //namespace container {
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //BOOST_CONTAINER_PMR_MONOTONIC_BUFFER_RESOURCE_HPP
diff --git a/include/boost/container/pmr/polymorphic_allocator.hpp b/include/boost/container/pmr/polymorphic_allocator.hpp
new file mode 100644
index 0000000..8c04653
--- /dev/null
+++ b/include/boost/container/pmr/polymorphic_allocator.hpp
@@ -0,0 +1,166 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_PMR_POLYMORPHIC_ALLOCATOR_HPP
+#define BOOST_CONTAINER_PMR_POLYMORPHIC_ALLOCATOR_HPP
+
+#if defined (_MSC_VER)
+# pragma once
+#endif
+
+#include <boost/config.hpp>
+#include <boost/move/detail/type_traits.hpp>
+#include <boost/move/utility_core.hpp>
+#include <boost/container/detail/dispatch_uses_allocator.hpp>
+#include <boost/container/new_allocator.hpp>
+#include <boost/container/pmr/memory_resource.hpp>
+#include <boost/container/pmr/global_resource.hpp>
+
+#include <cstddef>
+
+namespace boost {
+namespace container {
+namespace pmr {
+
+//! A specialization of class template `polymorphic_allocator` conforms to the Allocator requirements.
+//! Constructed with different memory resources, different instances of the same specialization of
+//! `polymorphic_allocator` can exhibit entirely different allocation behavior. This runtime
+//! polymorphism allows objects that use polymorphic_allocator to behave as if they used different
+//! allocator types at run time even though they use the same static allocator type.
+template <class T>
+class polymorphic_allocator
+{
+ public:
+ typedef T value_type;
+
+ //! <b>Effects</b>: Sets m_resource to
+ //! `get_default_resource()`.
+ polymorphic_allocator() BOOST_NOEXCEPT
+ : m_resource(::boost::container::pmr::get_default_resource())
+ {}
+
+ //! <b>Requires</b>: r is non-null.
+ //!
+ //! <b>Effects</b>: Sets m_resource to r.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Notes</b>: This constructor provides an implicit conversion from memory_resource*.
+ //! Non-standard extension: if r is null m_resource is set to get_default_resource().
+ polymorphic_allocator(memory_resource* r)
+ : m_resource(r ? r : ::boost::container::pmr::get_default_resource())
+ {}
+
+ //! <b>Effects</b>: Sets m_resource to
+ //! other.resource().
+ polymorphic_allocator(const polymorphic_allocator& other)
+ : m_resource(other.m_resource)
+ {}
+
+ //! <b>Effects</b>: Sets m_resource to
+ //! other.resource().
+ template <class U>
+ polymorphic_allocator(const polymorphic_allocator<U>& other) BOOST_NOEXCEPT
+ : m_resource(other.resource())
+ {}
+
+ //! <b>Effects</b>: Sets m_resource to
+ //! other.resource().
+ polymorphic_allocator& operator=(const polymorphic_allocator& other)
+ { m_resource = other.m_resource; return *this; }
+
+ //! <b>Returns</b>: Equivalent to
+ //! `static_cast<T*>(m_resource->allocate(n * sizeof(T), alignof(T)))`.
+ T* allocate(size_t n)
+ { return static_cast<T*>(m_resource->allocate(n*sizeof(T), ::boost::move_detail::alignment_of<T>::value)); }
+
+ //! <b>Requires</b>: p was allocated from a memory resource, x, equal to *m_resource,
+ //! using `x.allocate(n * sizeof(T), alignof(T))`.
+ //!
+ //! <b>Effects</b>: Equivalent to m_resource->deallocate(p, n * sizeof(T), alignof(T)).
+ //!
+ //! <b>Throws</b>: Nothing.
+ void deallocate(T* p, size_t n)
+ { m_resource->deallocate(p, n*sizeof(T), ::boost::move_detail::alignment_of<T>::value); }
+
+ #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ //! <b>Requires</b>: Uses-allocator construction of T with allocator
+ //! `*this` and constructor arguments `std::forward<Args>(args)...`
+ //! is well-formed. [Note: uses-allocator construction is always well formed for
+ //! types that do not use allocators. - end note]
+ //!
+ //! <b>Effects</b>: Construct a T object at p by uses-allocator construction with allocator
+ //! `*this` and constructor arguments `std::forward<Args>(args)...`.
+ //!
+ //! <b>Throws</b>: Nothing unless the constructor for T throws.
+ template < typename U, class ...Args>
+ void construct(U* p, BOOST_FWD_REF(Args)...args)
+ {
+ new_allocator<U> na;
+ dtl::dispatch_uses_allocator
+ (na, *this, p, ::boost::forward<Args>(args)...);
+ }
+
+ #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ //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_CONTAINER_PMR_POLYMORPHIC_ALLOCATOR_CONSTRUCT_CODE(N) \
+ template < typename U BOOST_MOVE_I##N BOOST_MOVE_CLASSQ##N >\
+ void construct(U* p BOOST_MOVE_I##N BOOST_MOVE_UREFQ##N)\
+ {\
+ new_allocator<U> na;\
+ dtl::dispatch_uses_allocator\
+ (na, *this, p BOOST_MOVE_I##N BOOST_MOVE_FWDQ##N);\
+ }\
+ //
+ BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_PMR_POLYMORPHIC_ALLOCATOR_CONSTRUCT_CODE)
+ #undef BOOST_CONTAINER_PMR_POLYMORPHIC_ALLOCATOR_CONSTRUCT_CODE
+
+ #endif //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ //! <b>Effects</b>:
+ //! p->~U().
+ template <class U>
+ void destroy(U* p)
+ { (void)p; p->~U(); }
+
+ //! <b>Returns</b>: Equivalent to
+ //! `polymorphic_allocator()`.
+ polymorphic_allocator select_on_container_copy_construction() const
+ { return polymorphic_allocator(); }
+
+ //! <b>Returns</b>:
+ //! m_resource.
+ memory_resource* resource() const
+ { return m_resource; }
+
+ private:
+ memory_resource* m_resource;
+};
+
+//! <b>Returns</b>:
+//! `*a.resource() == *b.resource()`.
+template <class T1, class T2>
+bool operator==(const polymorphic_allocator<T1>& a, const polymorphic_allocator<T2>& b) BOOST_NOEXCEPT
+{ return *a.resource() == *b.resource(); }
+
+
+//! <b>Returns</b>:
+//! `! (a == b)`.
+template <class T1, class T2>
+bool operator!=(const polymorphic_allocator<T1>& a, const polymorphic_allocator<T2>& b) BOOST_NOEXCEPT
+{ return *a.resource() != *b.resource(); }
+
+} //namespace pmr {
+} //namespace container {
+} //namespace boost {
+
+#endif //BOOST_CONTAINER_PMR_POLYMORPHIC_ALLOCATOR_HPP
diff --git a/include/boost/container/pmr/pool_options.hpp b/include/boost/container/pmr/pool_options.hpp
new file mode 100644
index 0000000..e9f7289
--- /dev/null
+++ b/include/boost/container/pmr/pool_options.hpp
@@ -0,0 +1,52 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_PMR_POOL_OPTIONS_HPP
+#define BOOST_CONTAINER_PMR_POOL_OPTIONS_HPP
+
+#if defined (_MSC_VER)
+# pragma once
+#endif
+
+#include <cstddef>
+
+namespace boost {
+namespace container {
+namespace pmr {
+
+//! The members of pool_options comprise a set of constructor options for pool resources.
+//! The effect of each option on the pool resource behavior is described below:
+//!
+//! - `std::size_t max_blocks_per_chunk`: The maximum number of blocks that will be allocated
+//! at once from the upstream memory resource to replenish a pool. If the value of
+//! `max_blocks_per_chunk` is zero or is greater than an implementation-defined limit,
+//! that limit is used instead. The implementation may choose to use a smaller value
+//! than is specified in this field and may use different values for different pools.
+//!
+//! - `std::size_t largest_required_pool_block`: The largest allocation size that is required
+//! to be fulfilled using the pooling mechanism. Attempts to allocate a single block
+//! larger than this threshold will be allocated directly from the upstream memory
+//! resource. If largest_required_pool_block is zero or is greater than an
+//! implementation-defined limit, that limit is used instead. The implementation may
+//! choose a pass-through threshold larger than specified in this field.
+struct pool_options
+{
+ pool_options()
+ : max_blocks_per_chunk(0u), largest_required_pool_block(0u)
+ {}
+ std::size_t max_blocks_per_chunk;
+ std::size_t largest_required_pool_block;
+};
+
+} //namespace pmr {
+} //namespace container {
+} //namespace boost {
+
+#endif //BOOST_CONTAINER_PMR_POOL_OPTIONS_HPP
diff --git a/include/boost/container/pmr/resource_adaptor.hpp b/include/boost/container/pmr/resource_adaptor.hpp
new file mode 100644
index 0000000..f5ce5c8
--- /dev/null
+++ b/include/boost/container/pmr/resource_adaptor.hpp
@@ -0,0 +1,193 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_PMR_RESOURCE_ADAPTOR_HPP
+#define BOOST_CONTAINER_PMR_RESOURCE_ADAPTOR_HPP
+
+#if defined (_MSC_VER)
+# pragma once
+#endif
+
+#include <boost/config.hpp>
+#include <boost/container/pmr/memory_resource.hpp>
+#include <boost/container/allocator_traits.hpp>
+#include <boost/intrusive/detail/ebo_functor_holder.hpp>
+#include <boost/move/utility_core.hpp>
+
+namespace boost {
+namespace container {
+namespace pmr {
+
+//! An instance of resource_adaptor<Allocator> is an adaptor that wraps a memory_resource interface
+//! around Allocator. In order that resource_adaptor<X<T>> and resource_adaptor<X<U>> are the same
+//! type for any allocator template X and types T and U, resource_adaptor<Allocator> is rendered as
+//! an alias to this class template such that Allocator is rebound to a char value type in every
+//! specialization of the class template. The requirements on this class template are defined below.
+//! In addition to the Allocator requirements, the parameter to resource_adaptor shall meet
+//! the following additional requirements:
+//!
+//! - `typename allocator_traits<Allocator>:: pointer` shall be identical to
+//! `typename allocator_traits<Allocator>:: value_type*`.
+//!
+//! - `typename allocator_traits<Allocator>:: const_pointer` shall be identical to
+//! `typename allocator_traits<Allocator>:: value_type const*`.
+//!
+//! - `typename allocator_traits<Allocator>:: void_pointer` shall be identical to `void*`.
+//!
+//! - `typename allocator_traits<Allocator>:: const_void_pointer` shall be identical to `void const*`.
+template <class Allocator>
+class resource_adaptor_imp
+ : public memory_resource
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ , private ::boost::intrusive::detail::ebo_functor_holder<Allocator>
+ #endif
+{
+ #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
+ Allocator m_alloc;
+ #else
+ BOOST_COPYABLE_AND_MOVABLE(resource_adaptor_imp)
+ typedef ::boost::intrusive::detail::ebo_functor_holder<Allocator> ebo_alloc_t;
+ void static_assert_if_not_char_allocator() const
+ {
+ //This class can only be used with allocators type char
+ BOOST_STATIC_ASSERT((dtl::is_same<typename Allocator::value_type, char>::value));
+ }
+ #endif
+
+ public:
+ typedef Allocator allocator_type;
+
+ //! <b>Effects</b>: Default constructs
+ //! m_alloc.
+ resource_adaptor_imp()
+ { this->static_assert_if_not_char_allocator(); }
+
+ //! <b>Effects</b>: Copy constructs
+ //! m_alloc.
+ resource_adaptor_imp(const resource_adaptor_imp &other)
+ : ebo_alloc_t(other.ebo_alloc_t::get())
+ {}
+
+ //! <b>Effects</b>: Move constructs
+ //! m_alloc.
+ resource_adaptor_imp(BOOST_RV_REF(resource_adaptor_imp) other)
+ : ebo_alloc_t(::boost::move(other.get()))
+ {}
+
+ //! <b>Effects</b>: Initializes m_alloc with
+ //! a2.
+ explicit resource_adaptor_imp(const Allocator& a2)
+ : ebo_alloc_t(a2)
+ { this->static_assert_if_not_char_allocator(); }
+
+ //! <b>Effects</b>: Initializes m_alloc with
+ //! a2.
+ explicit resource_adaptor_imp(BOOST_RV_REF(Allocator) a2)
+ : ebo_alloc_t(::boost::move(a2))
+ { this->static_assert_if_not_char_allocator(); }
+
+ //! <b>Effects</b>: Copy assigns
+ //! m_alloc.
+ resource_adaptor_imp& operator=(BOOST_COPY_ASSIGN_REF(resource_adaptor_imp) other)
+ { this->ebo_alloc_t::get() = other.ebo_alloc_t::get(); return *this; }
+
+ //! <b>Effects</b>: Move assigns
+ //! m_alloc.
+ resource_adaptor_imp& operator=(BOOST_RV_REF(resource_adaptor_imp) other)
+ { this->ebo_alloc_t::get() = ::boost::move(other.ebo_alloc_t::get()); return *this; }
+
+ //! <b>Effects</b>: Returns m_alloc.
+ allocator_type &get_allocator()
+ { return this->ebo_alloc_t::get(); }
+
+ //! <b>Effects</b>: Returns m_alloc.
+ const allocator_type &get_allocator() const
+ { return this->ebo_alloc_t::get(); }
+
+ protected:
+ //! <b>Returns</b>: Allocated memory obtained by calling m_alloc.allocate. The size and alignment
+ //! of the allocated memory shall meet the requirements for a class derived from memory_resource.
+ virtual void* do_allocate(size_t bytes, size_t alignment)
+ { (void)alignment; return this->ebo_alloc_t::get().allocate(bytes); }
+
+ //! <b>Requires</b>: p was previously allocated using A.allocate, where A == m_alloc, and not
+ //! subsequently deallocated.
+ //!
+ //! <b>Effects</b>: Returns memory to the allocator using m_alloc.deallocate().
+ virtual void do_deallocate(void* p, size_t bytes, size_t alignment)
+ { (void)alignment; this->ebo_alloc_t::get().deallocate((char*)p, bytes); }
+
+ //! Let p be dynamic_cast<const resource_adaptor_imp*>(&other).
+ //!
+ //! <b>Returns</b>: false if p is null, otherwise the value of m_alloc == p->m_alloc.
+ virtual bool do_is_equal(const memory_resource& other) const BOOST_NOEXCEPT
+ {
+ const resource_adaptor_imp* p = dynamic_cast<const resource_adaptor_imp*>(&other);
+ return p && p->ebo_alloc_t::get() == this->ebo_alloc_t::get();
+ }
+};
+
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+//! `resource_adaptor<Allocator>` is rendered as an alias to resource_adaptor_imp class template
+//! such that Allocator is rebound to a char value type.
+template <class Allocator>
+using resource_adaptor = resource_adaptor_imp
+ <typename allocator_traits<Allocator>::template rebind_alloc<char> >;
+
+#else
+
+template <class Allocator>
+class resource_adaptor
+ : public resource_adaptor_imp
+ <typename allocator_traits<Allocator>::template portable_rebind_alloc<char>::type>
+{
+ typedef resource_adaptor_imp
+ <typename allocator_traits<Allocator>::template portable_rebind_alloc<char>::type> base_t;
+
+ BOOST_COPYABLE_AND_MOVABLE(resource_adaptor)
+
+ public:
+ resource_adaptor()
+ : base_t()
+ {}
+
+ resource_adaptor(const resource_adaptor &other)
+ : base_t(other)
+ {}
+
+ resource_adaptor(BOOST_RV_REF(resource_adaptor) other)
+ : base_t(BOOST_MOVE_BASE(base_t, other))
+ {}
+
+ explicit resource_adaptor(const Allocator& a2)
+ : base_t(a2)
+ {}
+
+ explicit resource_adaptor(BOOST_RV_REF(Allocator) a2)
+ : base_t(BOOST_MOVE_BASE(base_t, a2))
+ {}
+
+ resource_adaptor& operator=(BOOST_COPY_ASSIGN_REF(resource_adaptor) other)
+ { return static_cast<resource_adaptor&>(this->base_t::operator=(other)); }
+
+ resource_adaptor& operator=(BOOST_RV_REF(resource_adaptor) other)
+ { return static_cast<resource_adaptor&>(this->base_t::operator=(BOOST_MOVE_BASE(base_t, other))); }
+
+ //get_allocator and protected functions are properly inherited
+};
+
+#endif
+
+} //namespace pmr {
+} //namespace container {
+} //namespace boost {
+
+#endif //BOOST_CONTAINER_PMR_RESOURCE_ADAPTOR_HPP
diff --git a/include/boost/container/pmr/set.hpp b/include/boost/container/pmr/set.hpp
new file mode 100644
index 0000000..3201696
--- /dev/null
+++ b/include/boost/container/pmr/set.hpp
@@ -0,0 +1,63 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_PMR_SET_HPP
+#define BOOST_CONTAINER_PMR_SET_HPP
+
+#if defined (_MSC_VER)
+# pragma once
+#endif
+
+#include <boost/container/set.hpp>
+#include <boost/container/pmr/polymorphic_allocator.hpp>
+
+namespace boost {
+namespace container {
+namespace pmr {
+
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+template <class Key
+ ,class Compare = std::less<Key>
+ ,class Options = void >
+using set = boost::container::set<Key, Compare, polymorphic_allocator<Key>, Options>;
+
+template <class Key
+ ,class Compare = std::less<Key>
+ ,class Options = void >
+using multiset = boost::container::multiset<Key, Compare, polymorphic_allocator<Key>, Options>;
+
+#endif
+
+//! A portable metafunction to obtain a set
+//! that uses a polymorphic allocator
+template <class Key
+ ,class Compare = std::less<Key>
+ ,class Options = void >
+struct set_of
+{
+ typedef boost::container::set<Key, Compare, polymorphic_allocator<Key>, Options> type;
+};
+
+//! A portable metafunction to obtain a multiset
+//! that uses a polymorphic allocator
+template <class Key
+ ,class Compare = std::less<Key>
+ ,class Options = void >
+struct multiset_of
+{
+ typedef boost::container::multiset<Key, Compare, polymorphic_allocator<Key>, Options> type;
+};
+
+} //namespace pmr {
+} //namespace container {
+} //namespace boost {
+
+#endif //BOOST_CONTAINER_PMR_SET_HPP
diff --git a/include/boost/container/pmr/slist.hpp b/include/boost/container/pmr/slist.hpp
new file mode 100644
index 0000000..c90fd7d
--- /dev/null
+++ b/include/boost/container/pmr/slist.hpp
@@ -0,0 +1,45 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_PMR_SLIST_HPP
+#define BOOST_CONTAINER_PMR_SLIST_HPP
+
+#if defined (_MSC_VER)
+# pragma once
+#endif
+
+#include <boost/container/slist.hpp>
+#include <boost/container/pmr/polymorphic_allocator.hpp>
+
+namespace boost {
+namespace container {
+namespace pmr {
+
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+template <class T>
+using slist = boost::container::slist<T, polymorphic_allocator<T>>;
+
+#endif
+
+//! A portable metafunction to obtain a slist
+//! that uses a polymorphic allocator
+template<class T>
+struct slist_of
+{
+ typedef boost::container::slist
+ < T, polymorphic_allocator<T> > type;
+};
+
+} //namespace pmr {
+} //namespace container {
+} //namespace boost {
+
+#endif //BOOST_CONTAINER_PMR_VECTOR_HPP
diff --git a/include/boost/container/pmr/small_vector.hpp b/include/boost/container/pmr/small_vector.hpp
new file mode 100644
index 0000000..6eef149
--- /dev/null
+++ b/include/boost/container/pmr/small_vector.hpp
@@ -0,0 +1,45 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_PMR_SMALL_VECTOR_HPP
+#define BOOST_CONTAINER_PMR_SMALL_VECTOR_HPP
+
+#if defined (_MSC_VER)
+# pragma once
+#endif
+
+#include <boost/container/small_vector.hpp>
+#include <boost/container/pmr/polymorphic_allocator.hpp>
+
+namespace boost {
+namespace container {
+namespace pmr {
+
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+template <class T, std::size_t N>
+using small_vector = boost::container::small_vector<T, N, polymorphic_allocator<T>>;
+
+#endif
+
+//! A portable metafunction to obtain a small_vector
+//! that uses a polymorphic allocator
+template<class T, std::size_t N>
+struct small_vector_of
+{
+ typedef boost::container::small_vector
+ < T, N, polymorphic_allocator<T> > type;
+};
+
+} //namespace pmr {
+} //namespace container {
+} //namespace boost {
+
+#endif //BOOST_CONTAINER_PMR_SMALL_VECTOR_HPP
diff --git a/include/boost/container/pmr/stable_vector.hpp b/include/boost/container/pmr/stable_vector.hpp
new file mode 100644
index 0000000..d11c426
--- /dev/null
+++ b/include/boost/container/pmr/stable_vector.hpp
@@ -0,0 +1,45 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_PMR_STABLE_VECTOR_HPP
+#define BOOST_CONTAINER_PMR_STABLE_VECTOR_HPP
+
+#if defined (_MSC_VER)
+# pragma once
+#endif
+
+#include <boost/container/stable_vector.hpp>
+#include <boost/container/pmr/polymorphic_allocator.hpp>
+
+namespace boost {
+namespace container {
+namespace pmr {
+
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+template <class T>
+using stable_vector = boost::container::stable_vector<T, polymorphic_allocator<T>>;
+
+#endif
+
+//! A portable metafunction to obtain a stable_vector
+//! that uses a polymorphic allocator
+template<class T>
+struct stable_vector_of
+{
+ typedef boost::container::stable_vector
+ < T, polymorphic_allocator<T> > type;
+};
+
+} //namespace pmr {
+} //namespace container {
+} //namespace boost {
+
+#endif //BOOST_CONTAINER_PMR_STABLE_VECTOR_HPP
diff --git a/include/boost/container/pmr/string.hpp b/include/boost/container/pmr/string.hpp
new file mode 100644
index 0000000..c1eba67
--- /dev/null
+++ b/include/boost/container/pmr/string.hpp
@@ -0,0 +1,50 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_PMR_STRING_HPP
+#define BOOST_CONTAINER_PMR_STRING_HPP
+
+#if defined (_MSC_VER)
+# pragma once
+#endif
+
+#include <boost/container/string.hpp>
+#include <boost/container/pmr/polymorphic_allocator.hpp>
+
+namespace boost {
+namespace container {
+namespace pmr {
+
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+template <class CharT, class Traits = std::char_traits<CharT> >
+using basic_string =
+ boost::container::basic_string<CharT, Traits, polymorphic_allocator<CharT> >;
+
+#endif
+
+//! A portable metafunction to obtain a basic_string
+//! that uses a polymorphic allocator
+template <class CharT, class Traits = std::char_traits<CharT> >
+struct basic_string_of
+{
+ typedef boost::container::basic_string
+ <CharT, Traits, polymorphic_allocator<CharT> > type;
+};
+
+typedef basic_string_of<char>::type string;
+
+typedef basic_string_of<wchar_t>::type wstring;
+
+} //namespace pmr {
+} //namespace container {
+} //namespace boost {
+
+#endif //BOOST_CONTAINER_PMR_STRING_HPP
diff --git a/include/boost/container/pmr/synchronized_pool_resource.hpp b/include/boost/container/pmr/synchronized_pool_resource.hpp
new file mode 100644
index 0000000..516e6d2
--- /dev/null
+++ b/include/boost/container/pmr/synchronized_pool_resource.hpp
@@ -0,0 +1,139 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_PMR_SYNCHRONIZED_POOL_RESOURCE_HPP
+#define BOOST_CONTAINER_PMR_SYNCHRONIZED_POOL_RESOURCE_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/auto_link.hpp>
+#include <boost/container/pmr/memory_resource.hpp>
+#include <boost/container/detail/pool_resource.hpp>
+#include <boost/container/detail/thread_mutex.hpp>
+
+#include <cstddef>
+
+namespace boost {
+namespace container {
+namespace pmr {
+
+//! A synchronized_pool_resource is a general-purpose memory resources having
+//! the following qualities:
+//!
+//! - Each resource owns the allocated memory, and frees it on destruction,
+//! even if deallocate has not been called for some of the allocated blocks.
+//!
+//! - A pool resource consists of a collection of pools, serving
+//! requests for different block sizes. Each individual pool manages a
+//! collection of chunks that are in turn divided into blocks of uniform size,
+//! returned via calls to do_allocate. Each call to do_allocate(size, alignment)
+//! is dispatched to the pool serving the smallest blocks accommodating at
+//! least size bytes.
+//!
+//! - When a particular pool is exhausted, allocating a block from that pool
+//! results in the allocation of an additional chunk of memory from the upstream
+//! allocator (supplied at construction), thus replenishing the pool. With
+//! each successive replenishment, the chunk size obtained increases
+//! geometrically. [ Note: By allocating memory in chunks, the pooling strategy
+//! increases the chance that consecutive allocations will be close together
+//! in memory. - end note ]
+//!
+//! - Allocation requests that exceed the largest block size of any pool are
+//! fulfilled directly from the upstream allocator.
+//!
+//! - A pool_options struct may be passed to the pool resource constructors to
+//! tune the largest block size and the maximum chunk size.
+//!
+//! A synchronized_pool_resource may be accessed from multiple threads without
+//! external synchronization and may have thread-specific pools to reduce
+//! synchronization costs.
+class BOOST_CONTAINER_DECL synchronized_pool_resource
+ : public memory_resource
+{
+ dtl::thread_mutex m_mut;
+ pool_resource m_pool_resource;
+
+ public:
+
+ //! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::unsynchronized_pool_resource(const pool_options&,memory_resource*)
+ synchronized_pool_resource(const pool_options& opts, memory_resource* upstream) BOOST_NOEXCEPT;
+
+ //! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::unsynchronized_pool_resource()
+ synchronized_pool_resource() BOOST_NOEXCEPT;
+
+ //! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::unsynchronized_pool_resource(memory_resource*)
+ explicit synchronized_pool_resource(memory_resource* upstream) BOOST_NOEXCEPT;
+
+ //! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::unsynchronized_pool_resource(const pool_options&)
+ explicit synchronized_pool_resource(const pool_options& opts) BOOST_NOEXCEPT;
+
+ #if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ synchronized_pool_resource(const synchronized_pool_resource&) = delete;
+ synchronized_pool_resource operator=(const synchronized_pool_resource&) = delete;
+ #else
+ private:
+ synchronized_pool_resource (const synchronized_pool_resource&);
+ synchronized_pool_resource operator=(const synchronized_pool_resource&);
+ public:
+ #endif
+
+ //! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::~unsynchronized_pool_resource()
+ virtual ~synchronized_pool_resource();
+
+ //! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::release()
+ void release();
+
+ //! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::upstream_resource()const
+ memory_resource* upstream_resource() const;
+
+ //! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::options()const
+ pool_options options() const;
+
+ protected:
+
+ //! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::do_allocate()
+ virtual void* do_allocate(std::size_t bytes, std::size_t alignment);
+
+ //! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::do_deallocate(void*,std::size_t,std::size_t)
+ virtual void do_deallocate(void* p, std::size_t bytes, std::size_t alignment);
+
+ //! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::do_is_equal(const memory_resource&)const
+ virtual bool do_is_equal(const memory_resource& other) const BOOST_NOEXCEPT;
+
+ //Non-standard observers
+ public:
+
+ //! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::pool_count()
+ std::size_t pool_count() const;
+
+ //! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::pool_index(std::size_t)const
+ std::size_t pool_index(std::size_t bytes) const;
+
+ //! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::pool_next_blocks_per_chunk(std::size_t)const
+ std::size_t pool_next_blocks_per_chunk(std::size_t pool_idx) const;
+
+ //! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::pool_block(std::size_t)const
+ std::size_t pool_block(std::size_t pool_idx) const;
+
+ //! @copydoc ::boost::container::pmr::unsynchronized_pool_resource::pool_cached_blocks(std::size_t)const
+ std::size_t pool_cached_blocks(std::size_t pool_idx) const;
+};
+
+} //namespace pmr {
+} //namespace container {
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //BOOST_CONTAINER_PMR_SYNCHRONIZED_POOL_RESOURCE_HPP
diff --git a/include/boost/container/pmr/unsynchronized_pool_resource.hpp b/include/boost/container/pmr/unsynchronized_pool_resource.hpp
new file mode 100644
index 0000000..21d30b1
--- /dev/null
+++ b/include/boost/container/pmr/unsynchronized_pool_resource.hpp
@@ -0,0 +1,194 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_PMR_UNSYNCHRONIZED_POOL_RESOURCE_HPP
+#define BOOST_CONTAINER_PMR_UNSYNCHRONIZED_POOL_RESOURCE_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/auto_link.hpp>
+#include <boost/container/pmr/memory_resource.hpp>
+#include <boost/container/detail/pool_resource.hpp>
+
+#include <cstddef>
+
+namespace boost {
+namespace container {
+namespace pmr {
+
+//! A unsynchronized_pool_resource is a general-purpose memory resources having
+//! the following qualities:
+//!
+//! - Each resource owns the allocated memory, and frees it on destruction,
+//! even if deallocate has not been called for some of the allocated blocks.
+//!
+//! - A pool resource consists of a collection of pools, serving
+//! requests for different block sizes. Each individual pool manages a
+//! collection of chunks that are in turn divided into blocks of uniform size,
+//! returned via calls to do_allocate. Each call to do_allocate(size, alignment)
+//! is dispatched to the pool serving the smallest blocks accommodating at
+//! least size bytes.
+//!
+//! - When a particular pool is exhausted, allocating a block from that pool
+//! results in the allocation of an additional chunk of memory from the upstream
+//! allocator (supplied at construction), thus replenishing the pool. With
+//! each successive replenishment, the chunk size obtained increases
+//! geometrically. [ Note: By allocating memory in chunks, the pooling strategy
+//! increases the chance that consecutive allocations will be close together
+//! in memory. - end note ]
+//!
+//! - Allocation requests that exceed the largest block size of any pool are
+//! fulfilled directly from the upstream allocator.
+//!
+//! - A pool_options struct may be passed to the pool resource constructors to
+//! tune the largest block size and the maximum chunk size.
+//!
+//! An unsynchronized_pool_resource class may not be accessed from multiple threads
+//! simultaneously and thus avoids the cost of synchronization entirely in
+//! single-threaded applications.
+class BOOST_CONTAINER_DECL unsynchronized_pool_resource
+ : public memory_resource
+{
+ pool_resource m_resource;
+
+ public:
+
+ //! <b>Requires</b>: `upstream` is the address of a valid memory resource.
+ //!
+ //! <b>Effects</b>: Constructs a pool resource object that will obtain memory
+ //! from upstream whenever the pool resource is unable to satisfy a memory
+ //! request from its own internal data structures. The resulting object will hold
+ //! a copy of upstream, but will not own the resource to which upstream points.
+ //! [ Note: The intention is that calls to upstream->allocate() will be
+ //! substantially fewer than calls to this->allocate() in most cases. - end note
+ //! The behavior of the pooling mechanism is tuned according to the value of
+ //! the opts argument.
+ //!
+ //! <b>Throws</b>: Nothing unless upstream->allocate() throws. It is unspecified if
+ //! or under what conditions this constructor calls upstream->allocate().
+ unsynchronized_pool_resource(const pool_options& opts, memory_resource* upstream) BOOST_NOEXCEPT;
+
+ //! <b>Effects</b>: Same as
+ //! `unsynchronized_pool_resource(pool_options(), get_default_resource())`.
+ unsynchronized_pool_resource() BOOST_NOEXCEPT;
+
+ //! <b>Effects</b>: Same as
+ //! `unsynchronized_pool_resource(pool_options(), upstream)`.
+ explicit unsynchronized_pool_resource(memory_resource* upstream) BOOST_NOEXCEPT;
+
+ //! <b>Effects</b>: Same as
+ //! `unsynchronized_pool_resource(opts, get_default_resource())`.
+ explicit unsynchronized_pool_resource(const pool_options& opts) BOOST_NOEXCEPT;
+
+ #if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ unsynchronized_pool_resource(const unsynchronized_pool_resource&) = delete;
+ unsynchronized_pool_resource operator=(const unsynchronized_pool_resource&) = delete;
+ #else
+ private:
+ unsynchronized_pool_resource (const unsynchronized_pool_resource&);
+ unsynchronized_pool_resource operator=(const unsynchronized_pool_resource&);
+ public:
+ #endif
+
+ //! <b>Effects</b>: Calls
+ //! `this->release()`.
+ virtual ~unsynchronized_pool_resource();
+
+ //! <b>Effects</b>: Calls Calls `upstream_resource()->deallocate()` as necessary
+ //! to release all allocated memory. [ Note: memory is released back to
+ //! `upstream_resource()` even if deallocate has not been called for some
+ //! of the allocated blocks. - end note ]
+ void release();
+
+ //! <b>Returns</b>: The value of the upstream argument provided to the
+ //! constructor of this object.
+ memory_resource* upstream_resource() const;
+
+ //! <b>Returns</b>: The options that control the pooling behavior of this resource.
+ //! The values in the returned struct may differ from those supplied to the pool
+ //! resource constructor in that values of zero will be replaced with
+ //! implementation-defined defaults and sizes may be rounded to unspecified granularity.
+ pool_options options() const;
+
+ protected:
+
+ //! <b>Returns</b>: A pointer to allocated storage with a size of at least `bytes`.
+ //! The size and alignment of the allocated memory shall meet the requirements for
+ //! a class derived from `memory_resource`.
+ //!
+ //! <b>Effects</b>: If the pool selected for a block of size bytes is unable to
+ //! satisfy the memory request from its own internal data structures, it will call
+ //! `upstream_resource()->allocate()` to obtain more memory. If `bytes` is larger
+ //! than that which the largest pool can handle, then memory will be allocated
+ //! using `upstream_resource()->allocate()`.
+ //!
+ //! <b>Throws</b>: Nothing unless `upstream_resource()->allocate()` throws.
+ virtual void* do_allocate(std::size_t bytes, std::size_t alignment);
+
+ //! <b>Effects</b>: Return the memory at p to the pool. It is unspecified if or under
+ //! what circumstances this operation will result in a call to
+ //! `upstream_resource()->deallocate()`.
+ //!
+ //! <b>Throws</b>: Nothing.
+ virtual void do_deallocate(void* p, std::size_t bytes, std::size_t alignment);
+
+ //! <b>Returns</b>:
+ //! `this == dynamic_cast<const unsynchronized_pool_resource*>(&other)`.
+ virtual bool do_is_equal(const memory_resource& other) const BOOST_NOEXCEPT;
+
+ //Non-standard observers
+ public:
+ //! <b>Returns</b>: The number of pools that will be used in the pool resource.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ std::size_t pool_count() const;
+
+ //! <b>Returns</b>: The index of the pool that will be used to serve the allocation of `bytes`.
+ //! Returns `pool_count()` if `bytes` is bigger
+ //! than `options().largest_required_pool_block` (no pool will be used to serve this).
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ std::size_t pool_index(std::size_t bytes) const;
+
+ //! <b>Requires</b>: `pool_idx < pool_index()`
+ //!
+ //! <b>Returns</b>: The number blocks that will be allocated in the next chunk
+ //! from the pool specified by `pool_idx`.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ std::size_t pool_next_blocks_per_chunk(std::size_t pool_idx) const;
+
+ //! <b>Requires</b>: `pool_idx < pool_index()`
+ //!
+ //! <b>Returns</b>: The number of bytes of the block that the specified `pool_idx` pool manages.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ std::size_t pool_block(std::size_t pool_idx) const;
+
+ //! <b>Requires</b>: `pool_idx < pool_index()`
+ //!
+ //! <b>Returns</b>: The number of blocks that the specified `pool_idx` pool has cached
+ //! and will be served without calling the upstream_allocator.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ std::size_t pool_cached_blocks(std::size_t pool_idx) const;
+};
+
+} //namespace pmr {
+} //namespace container {
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //BOOST_CONTAINER_PMR_UNSYNCHRONIZED_POOL_RESOURCE_HPP
diff --git a/include/boost/container/pmr/vector.hpp b/include/boost/container/pmr/vector.hpp
new file mode 100644
index 0000000..2bd9c15
--- /dev/null
+++ b/include/boost/container/pmr/vector.hpp
@@ -0,0 +1,45 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_PMR_VECTOR_HPP
+#define BOOST_CONTAINER_PMR_VECTOR_HPP
+
+#if defined (_MSC_VER)
+# pragma once
+#endif
+
+#include <boost/container/vector.hpp>
+#include <boost/container/pmr/polymorphic_allocator.hpp>
+
+namespace boost {
+namespace container {
+namespace pmr {
+
+#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+
+template <class T>
+using vector = boost::container::vector<T, polymorphic_allocator<T>>;
+
+#endif
+
+//! A portable metafunction to obtain a vector
+//! that uses a polymorphic allocator
+template<class T>
+struct vector_of
+{
+ typedef boost::container::vector
+ < T, polymorphic_allocator<T> > type;
+};
+
+} //namespace pmr {
+} //namespace container {
+} //namespace boost {
+
+#endif //BOOST_CONTAINER_PMR_VECTOR_HPP
diff --git a/include/boost/container/scoped_allocator.hpp b/include/boost/container/scoped_allocator.hpp
new file mode 100644
index 0000000..6cd69fe
--- /dev/null
+++ b/include/boost/container/scoped_allocator.hpp
@@ -0,0 +1,907 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Pablo Halpern 2009. 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)
+//
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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_SCOPED_ALLOCATOR_HPP
+#define BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_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/scoped_allocator_fwd.hpp>
+#include <boost/container/detail/dispatch_uses_allocator.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 {
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+namespace dtl {
+
+template <typename Allocator>
+struct is_scoped_allocator_imp
+{
+ typedef char yes_type;
+ struct no_type{ char dummy[2]; };
+
+ template <typename T>
+ static yes_type test(typename T::outer_allocator_type*);
+
+ template <typename T>
+ static int test(...);
+
+ static const bool value = (sizeof(yes_type) == sizeof(test<Allocator>(0)));
+};
+
+template<class MaybeScopedAlloc, bool = is_scoped_allocator_imp<MaybeScopedAlloc>::value >
+struct outermost_allocator_type_impl
+{
+ typedef typename MaybeScopedAlloc::outer_allocator_type outer_type;
+ typedef typename outermost_allocator_type_impl<outer_type>::type type;
+};
+
+template<class MaybeScopedAlloc>
+struct outermost_allocator_type_impl<MaybeScopedAlloc, false>
+{
+ typedef MaybeScopedAlloc type;
+};
+
+template<class MaybeScopedAlloc, bool = is_scoped_allocator_imp<MaybeScopedAlloc>::value >
+struct outermost_allocator_imp
+{
+ typedef MaybeScopedAlloc type;
+
+ static type &get(MaybeScopedAlloc &a)
+ { return a; }
+
+ static const type &get(const MaybeScopedAlloc &a)
+ { return a; }
+};
+
+template<class MaybeScopedAlloc>
+struct outermost_allocator_imp<MaybeScopedAlloc, true>
+{
+ typedef typename MaybeScopedAlloc::outer_allocator_type outer_type;
+ typedef typename outermost_allocator_type_impl<outer_type>::type type;
+
+ static type &get(MaybeScopedAlloc &a)
+ { return outermost_allocator_imp<outer_type>::get(a.outer_allocator()); }
+
+ static const type &get(const MaybeScopedAlloc &a)
+ { return outermost_allocator_imp<outer_type>::get(a.outer_allocator()); }
+};
+
+} //namespace dtl {
+
+template <typename Allocator>
+struct is_scoped_allocator
+ : dtl::is_scoped_allocator_imp<Allocator>
+{};
+
+template <typename Allocator>
+struct outermost_allocator
+ : dtl::outermost_allocator_imp<Allocator>
+{};
+
+template <typename Allocator>
+typename outermost_allocator<Allocator>::type &
+ get_outermost_allocator(Allocator &a)
+{ return outermost_allocator<Allocator>::get(a); }
+
+template <typename Allocator>
+const typename outermost_allocator<Allocator>::type &
+ get_outermost_allocator(const Allocator &a)
+{ return outermost_allocator<Allocator>::get(a); }
+
+namespace dtl {
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+template <typename OuterAlloc, class ...InnerAllocs>
+class scoped_allocator_adaptor_base
+ : 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, InnerAllocs...> other;
+ };
+
+ typedef OuterAlloc outer_allocator_type;
+ typedef scoped_allocator_adaptor<InnerAllocs...> inner_allocator_type;
+ typedef allocator_traits<inner_allocator_type> inner_traits_type;
+ typedef scoped_allocator_adaptor
+ <OuterAlloc, InnerAllocs...> scoped_allocator_type;
+ typedef dtl::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 dtl::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 dtl::bool_<
+ outer_traits_type::propagate_on_container_swap::value ||
+ inner_allocator_type::propagate_on_container_swap::value
+ > propagate_on_container_swap;
+ typedef dtl::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, const InnerAllocs &...args)
+ : outer_allocator_type(::boost::forward<OuterA2>(outerAlloc))
+ , m_inner(args...)
+ {}
+
+ 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, InnerAllocs...>& 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, InnerAllocs...> 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() BOOST_NOEXCEPT_OR_NOTHROW
+ { return m_inner; }
+
+ inner_allocator_type const& inner_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return m_inner; }
+
+ outer_allocator_type & outer_allocator() BOOST_NOEXCEPT_OR_NOTHROW
+ { return static_cast<outer_allocator_type&>(*this); }
+
+ 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
+ {
+ 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;
+};
+
+#else //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+//Let's add a dummy first template parameter to allow creating
+//specializations up to maximum InnerAlloc count
+template <typename OuterAlloc, bool Dummy, BOOST_MOVE_CLASSDFLT9>
+class scoped_allocator_adaptor_base;
+
+//Specializations for the adaptor with InnerAlloc allocators
+
+#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 dtl::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 dtl::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 dtl::bool_<\
+ outer_traits_type::propagate_on_container_swap::value ||\
+ inner_allocator_type::propagate_on_container_swap::value\
+ > propagate_on_container_swap;\
+ \
+ typedef dtl::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;\
+};\
+//!
+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 BOOST_CONTAINER_SCOPEDALLOC_DUMMYTRUE>
+ : public OuterAlloc
+{
+ BOOST_COPYABLE_AND_MOVABLE(scoped_allocator_adaptor_base)
+ public:
+
+ template <class U>
+ struct rebind_base
+ {
+ typedef scoped_allocator_adaptor_base
+ <typename allocator_traits<OuterAlloc>::template portable_rebind_alloc<U>::type
+ BOOST_CONTAINER_SCOPEDALLOC_DUMMYTRUE > other;
+ };
+
+ typedef OuterAlloc outer_allocator_type;
+ typedef allocator_traits<OuterAlloc> outer_traits_type;
+ typedef scoped_allocator_adaptor<OuterAlloc> inner_allocator_type;
+ typedef inner_allocator_type scoped_allocator_type;
+ typedef allocator_traits<inner_allocator_type> inner_traits_type;
+ typedef typename outer_traits_type::
+ propagate_on_container_copy_assignment propagate_on_container_copy_assignment;
+ typedef typename outer_traits_type::
+ 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()
+ {}
+
+ template <class OuterA2>
+ scoped_allocator_adaptor_base(BOOST_FWD_REF(OuterA2) outerAlloc)
+ : outer_allocator_type(::boost::forward<OuterA2>(outerAlloc))
+ {}
+
+ scoped_allocator_adaptor_base(const scoped_allocator_adaptor_base& other)
+ : outer_allocator_type(other.outer_allocator())
+ {}
+
+ scoped_allocator_adaptor_base(BOOST_RV_REF(scoped_allocator_adaptor_base) other)
+ : outer_allocator_type(::boost::move(other.outer_allocator()))
+ {}
+
+ template <class OuterA2>
+ scoped_allocator_adaptor_base
+ (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 BOOST_CONTAINER_SCOPEDALLOC_DUMMYTRUE> BOOST_RV_REF_END other)
+ : outer_allocator_type(other.outer_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 &)
+ : outer_allocator_type(::boost::forward<OuterA2>(outerAlloc))
+ {}
+
+ public:
+ scoped_allocator_adaptor_base &operator=(BOOST_COPY_ASSIGN_REF(scoped_allocator_adaptor_base) other)
+ {
+ outer_allocator_type::operator=(other.outer_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()));
+ return *this;
+ }
+
+ void swap(scoped_allocator_adaptor_base &r)
+ {
+ boost::adl_move_swap(this->outer_allocator(), r.outer_allocator());
+ }
+
+ friend void swap(scoped_allocator_adaptor_base &l, scoped_allocator_adaptor_base &r)
+ { l.swap(r); }
+
+ inner_allocator_type& inner_allocator()
+ { return static_cast<inner_allocator_type&>(*this); }
+
+ inner_allocator_type const& inner_allocator() const
+ { return static_cast<const inner_allocator_type&>(*this); }
+
+ 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())
+ //Don't use inner_traits_type::select_on_container_copy_construction(this->inner_allocator())
+ //as inner_allocator() is equal to *this and that would trigger an infinite loop
+ , this->inner_allocator()
+ );
+ }
+};
+
+} //namespace dtl {
+
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+//Scoped allocator
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+#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
+
+#else // #if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST)
+
+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) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+template <typename OuterAlloc, BOOST_MOVE_CLASS9>
+class scoped_allocator_adaptor
+#endif
+
+ : public dtl::scoped_allocator_adaptor_base
+ <OuterAlloc BOOST_CONTAINER_SCOPEDALLOC_DUMMYTRUE, BOOST_CONTAINER_SCOPEDALLOC_ALLINNER>
+{
+ BOOST_COPYABLE_AND_MOVABLE(scoped_allocator_adaptor)
+
+ public:
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ typedef dtl::scoped_allocator_adaptor_base
+ <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;
+ //! Type: For exposition only
+ //!
+ typedef allocator_traits<OuterAlloc> outer_traits_type;
+ //! Type: <code>scoped_allocator_adaptor<OuterAlloc></code> if <code>sizeof...(InnerAllocs)</code> is zero; otherwise,
+ //! <code>scoped_allocator_adaptor<InnerAllocs...></code>.
+ typedef typename base_type::inner_allocator_type inner_allocator_type;
+ typedef allocator_traits<inner_allocator_type> inner_traits_type;
+ typedef typename outer_traits_type::value_type value_type;
+ typedef typename outer_traits_type::size_type size_type;
+ typedef typename outer_traits_type::difference_type difference_type;
+ typedef typename outer_traits_type::pointer pointer;
+ 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: 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: 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: 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
+ //! , InnerAllocs... ></code>
+ template <class U>
+ struct rebind
+ {
+ typedef scoped_allocator_adaptor
+ < typename outer_traits_type::template portable_rebind_alloc<U>::type
+ , BOOST_CONTAINER_SCOPEDALLOC_ALLINNER> other;
+ };
+
+ //! <b>Effects</b>: value-initializes the OuterAlloc base class
+ //! and the inner allocator object.
+ scoped_allocator_adaptor()
+ {}
+
+ ~scoped_allocator_adaptor()
+ {}
+
+ //! <b>Effects</b>: initializes each allocator within the adaptor with
+ //! the corresponding allocator from other.
+ scoped_allocator_adaptor(const scoped_allocator_adaptor& other)
+ : base_type(other.base())
+ {}
+
+ //! <b>Effects</b>: move constructs each allocator within the adaptor with
+ //! the corresponding allocator from other.
+ scoped_allocator_adaptor(BOOST_RV_REF(scoped_allocator_adaptor) other)
+ : base_type(::boost::move(other.base()))
+ {}
+
+ #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ //! <b>Requires</b>: OuterAlloc shall be constructible from OuterA2.
+ //!
+ //! <b>Effects</b>: initializes the OuterAlloc base class with boost::forward<OuterA2>(outerAlloc) and inner
+ //! with innerAllocs...(hence recursively initializing each allocator within the adaptor with the
+ //! corresponding allocator from the argument list).
+ template <class OuterA2>
+ scoped_allocator_adaptor(BOOST_FWD_REF(OuterA2) outerAlloc, const InnerAllocs & ...innerAllocs)
+ : base_type(::boost::forward<OuterA2>(outerAlloc), innerAllocs...)
+ {}
+ #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ #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)
+
+ //! <b>Requires</b>: OuterAlloc shall be constructible from OuterA2.
+ //!
+ //! <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, BOOST_CONTAINER_SCOPEDALLOC_ALLINNER> &other)
+ : base_type(other.base())
+ {}
+
+ //! <b>Requires</b>: OuterAlloc shall be constructible from OuterA2.
+ //!
+ //! <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, BOOST_CONTAINER_SCOPEDALLOC_ALLINNER> BOOST_RV_REF_END other)
+ : base_type(::boost::move(other.base()))
+ {}
+
+ scoped_allocator_adaptor &operator=(BOOST_COPY_ASSIGN_REF(scoped_allocator_adaptor) other)
+ { 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(other.base()))); }
+
+ #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
+ //! <b>Effects</b>: swaps *this with r.
+ //!
+ void swap(scoped_allocator_adaptor &r);
+
+ //! <b>Effects</b>: swaps *this with r.
+ //!
+ friend void swap(scoped_allocator_adaptor &l, scoped_allocator_adaptor &r);
+
+ //! <b>Returns</b>:
+ //! <code>static_cast<OuterAlloc&>(*this)</code>.
+ 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_NOEXCEPT_OR_NOTHROW;
+
+ //! <b>Returns</b>:
+ //! *this if <code>sizeof...(InnerAllocs)</code> is zero; otherwise, inner.
+ 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_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_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_NOEXCEPT_OR_NOTHROW
+ {
+ allocator_traits<typename outermost_allocator<OuterAlloc>::type>
+ ::destroy(get_outermost_allocator(this->outer_allocator()), p);
+ }
+
+ //! <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); }
+
+ //! <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); }
+
+ //! <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); }
+
+ #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
+ //! <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;
+ #endif //BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ base_type &base() { return *this; }
+
+ const base_type &base() const { return *this; }
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ //! <b>Effects</b>:
+ //! 1) If <code>uses_allocator<T, inner_allocator_type>::value</code> is false calls
+ //! <code>OUTERMOST_ALLOC_TRAITS(*this)::
+ //! construct(OUTERMOST(*this), p, std::forward<Args>(args)...)</code>.
+ //!
+ //! 2) Otherwise, if <code>uses_allocator<T, inner_allocator_type>::value</code> is true and
+ //! <code>is_constructible<T, allocator_arg_t, inner_allocator_type, Args...>:: value</code> is true, calls
+ //! <code>OUTERMOST_ALLOC_TRAITS(*this):: construct(OUTERMOST(*this), p, allocator_arg,
+ //! inner_allocator(), std::forward<Args>(args)...)</code>.
+ //!
+ //! [<b>Note</b>: In compilers without advanced decltype SFINAE support, <code>is_constructible</code> can't
+ //! be implemented so that condition will be replaced by
+ //! constructible_with_allocator_prefix<T>::value. -end note]
+ //!
+ //! 3) Otherwise, if uses_allocator<T, inner_allocator_type>::value is true and
+ //! <code>is_constructible<T, Args..., inner_allocator_type>:: value</code> is true, calls
+ //! <code>OUTERMOST_ALLOC_TRAITS(*this):: construct(OUTERMOST(*this), p,
+ //! std::forward<Args>(args)..., inner_allocator())</code>.
+ //!
+ //! [<b>Note</b>: In compilers without advanced decltype SFINAE support, <code>is_constructible</code> can't be
+ //! implemented so that condition will be replaced by
+ //! <code>constructible_with_allocator_suffix<T>:: value</code>. -end note]
+ //!
+ //! 4) Otherwise, the program is ill-formed.
+ //!
+ //! [<b>Note</b>: An error will result if <code>uses_allocator</code> evaluates
+ //! to true but the specific constructor does not take an allocator. This definition prevents a silent
+ //! failure to pass an inner allocator to a contained element. -end note]
+ template < typename T, class ...Args>
+ void construct(T* p, BOOST_FWD_REF(Args)...args)
+ {
+ dtl::dispatch_uses_allocator
+ ( (get_outermost_allocator)(this->outer_allocator())
+ , this->inner_allocator(), p, ::boost::forward<Args>(args)...);
+ }
+
+ #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ //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_CONTAINER_SCOPED_ALLOCATOR_CONSTRUCT_CODE(N) \
+ template < typename T BOOST_MOVE_I##N BOOST_MOVE_CLASSQ##N >\
+ void construct(T* p BOOST_MOVE_I##N BOOST_MOVE_UREFQ##N)\
+ {\
+ dtl::dispatch_uses_allocator\
+ ( (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)
+
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ public:
+ //Internal function
+ template <class OuterA2>
+ scoped_allocator_adaptor(internal_type_t, BOOST_FWD_REF(OuterA2) outer, const inner_allocator_type& inner)
+ : base_type(internal_type_t(), ::boost::forward<OuterA2>(outer), inner)
+ {}
+
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+};
+
+/// @cond
+
+template<bool ZeroInner>
+struct scoped_allocator_operator_equal
+{
+ //Optimize equal outer allocator types with
+ //allocator_traits::equal which uses is_always_equal
+ template<class IA>
+ static bool equal_outer(const IA &l, const IA &r)
+ { return allocator_traits<IA>::equal(l, r); }
+
+ //Otherwise compare it normally
+ template<class IA1, class IA2>
+ static bool equal_outer(const IA1 &l, const IA2 &r)
+ { return l == r; }
+
+ //Otherwise compare it normally
+ template<class IA>
+ static bool equal_inner(const IA &l, const IA &r)
+ { return allocator_traits<IA>::equal(l, r); }
+};
+
+template<>
+struct scoped_allocator_operator_equal<true>
+ : scoped_allocator_operator_equal<false>
+{
+ //when inner allocator count is zero,
+ //inner_allocator_type is the same as outer_allocator_type
+ //so both types can be different in operator==
+ template<class IA1, class IA2>
+ static bool equal_inner(const IA1 &, const IA2 &)
+ { return true; }
+};
+
+/// @endcond
+
+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::dtl::is_same<P0, void>::value;
+ #endif
+ typedef scoped_allocator_operator_equal<has_zero_inner> equal_t;
+ return equal_t::equal_outer(a.outer_allocator(), b.outer_allocator()) &&
+ equal_t::equal_inner(a.inner_allocator(), b.inner_allocator());
+}
+
+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 {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif // BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_HPP
diff --git a/include/boost/container/scoped_allocator_fwd.hpp b/include/boost/container/scoped_allocator_fwd.hpp
new file mode 100644
index 0000000..cddf7fa
--- /dev/null
+++ b/include/boost/container/scoped_allocator_fwd.hpp
@@ -0,0 +1,71 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_FWD_HPP
+#define BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_FWD_HPP
+
+//! \file
+//! This header file forward declares boost::container::scoped_allocator_adaptor
+
+#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>
+#include <boost/container/uses_allocator_fwd.hpp>
+
+#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+#include <boost/move/detail/fwd_macros.hpp>
+#endif
+
+namespace boost { namespace container {
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ #if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST)
+
+ 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 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_MOVE_CLASSDFLT9>
+ class scoped_allocator_adaptor;
+
+#endif
+
+
+#else //BOOST_CONTAINER_DOXYGEN_INVOKED
+
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+}} // namespace boost { namespace container {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif // BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_FWD_HPP
diff --git a/include/boost/container/set.hpp b/include/boost/container/set.hpp
new file mode 100644
index 0000000..e300898
--- /dev/null
+++ b/include/boost/container/set.hpp
@@ -0,0 +1,1622 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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_SET_HPP
+#define BOOST_CONTAINER_SET_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+// container
+#include <boost/container/container_fwd.hpp>
+// 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>
+// 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
+
+namespace boost {
+namespace container {
+
+#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+//! A set is a kind of associative container that supports unique keys (contains at
+//! most one of each key value) and provides for fast retrieval of the keys themselves.
+//! Class set supports bidirectional iterators.
+//!
+//! A set satisfies all of the requirements of a container and of a reversible container
+//! , and of an associative container. A set also provides most operations described in
+//! for unique keys.
+//!
+//! \tparam Key is the type to be inserted in the set, which is also the key_type
+//! \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 Options is an packed option type generated using using boost::container::tree_assoc_options.
+template <class Key, class Compare = std::less<Key>, class Allocator = new_allocator<Key>, class Options = void>
+#else
+template <class Key, class Compare, class Allocator, class Options>
+#endif
+class set
+ ///@cond
+ : public dtl::tree
+ < Key, dtl::identity<Key>, Compare, Allocator, Options>
+ ///@endcond
+{
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ private:
+ BOOST_COPYABLE_AND_MOVABLE(set)
+ typedef dtl::tree
+ < Key, dtl::identity<Key>, Compare, Allocator, Options> base_t;
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ public:
+ //////////////////////////////////////////////
+ //
+ // types
+ //
+ //////////////////////////////////////////////
+ typedef Key key_type;
+ typedef Key value_type;
+ typedef Compare key_compare;
+ typedef Compare value_compare;
+ typedef ::boost::container::allocator_traits<Allocator> allocator_traits_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;
+ typedef typename ::boost::container::allocator_traits<Allocator>::const_reference const_reference;
+ typedef typename ::boost::container::allocator_traits<Allocator>::size_type size_type;
+ typedef typename ::boost::container::allocator_traits<Allocator>::difference_type difference_type;
+ typedef Allocator allocator_type;
+ typedef typename BOOST_CONTAINER_IMPDEF(base_t::stored_allocator_type) stored_allocator_type;
+ typedef typename BOOST_CONTAINER_IMPDEF(base_t::iterator) iterator;
+ typedef typename BOOST_CONTAINER_IMPDEF(base_t::const_iterator) const_iterator;
+ typedef typename BOOST_CONTAINER_IMPDEF(base_t::reverse_iterator) reverse_iterator;
+ typedef typename BOOST_CONTAINER_IMPDEF(base_t::const_reverse_iterator) const_reverse_iterator;
+ typedef typename BOOST_CONTAINER_IMPDEF(base_t::node_type) node_type;
+ typedef typename BOOST_CONTAINER_IMPDEF(base_t::insert_return_type) insert_return_type;
+
+ //////////////////////////////////////////////
+ //
+ // construct/copy/destroy
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Default constructs an empty set.
+ //!
+ //! <b>Complexity</b>: Constant.
+
+ BOOST_CONTAINER_FORCEINLINE set()
+ BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<Allocator>::value &&
+ dtl::is_nothrow_default_constructible<Compare>::value)
+ : base_t()
+ {}
+
+ //! <b>Effects</b>: Constructs an empty set using the specified allocator object.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE explicit set(const allocator_type& a)
+ : base_t(a)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty set using the specified comparison object.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE explicit set(const Compare& comp)
+ : base_t(comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty set using the specified comparison object
+ //! and allocator.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE set(const Compare& comp, const allocator_type& a)
+ : base_t(comp, a)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty set using and
+ //! inserts elements from the range [first ,last ).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE set(InputIterator first, InputIterator last)
+ : base_t(true, first, last)
+ {}
+
+ //! <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
+ //! the predicate and otherwise N logN, where N is last - first.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE set(InputIterator first, InputIterator last, const allocator_type& a)
+ : base_t(true, first, last, key_compare(), a)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty set using the specified comparison object and
+ //! inserts elements from the range [first ,last ).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE set(InputIterator first, InputIterator last, const Compare& comp)
+ : base_t(true, first, last, comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty set using the specified comparison object and
+ //! allocator, and inserts elements from the range [first ,last ).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! the predicate and otherwise N logN, where N is last - first.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE set(InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
+ : base_t(true, first, last, comp, a)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty set and
+ //! inserts elements from the ordered unique range [first ,last). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate and must be
+ //! unique values.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE set( ordered_unique_range_t, InputIterator first, InputIterator last)
+ : base_t(ordered_range, first, last)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty set using the specified comparison object and
+ //! inserts elements from the ordered unique range [first ,last). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate and must be
+ //! unique values.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE set( ordered_unique_range_t, InputIterator first, InputIterator last, const Compare& comp )
+ : base_t(ordered_range, first, last, comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty set using the specified comparison object and
+ //! allocator, and inserts elements from the ordered unique range [first ,last). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate and must be
+ //! unique values.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE set( ordered_unique_range_t, InputIterator first, InputIterator last
+ , const Compare& comp, const allocator_type& a)
+ : base_t(ordered_range, first, last, comp, a)
+ {}
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Constructs an empty set and
+ //! inserts elements from the range [il.begin(), il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
+ //! the predicate and otherwise N logN, where N is il.begin() - il.end().
+ BOOST_CONTAINER_FORCEINLINE set(std::initializer_list<value_type> il)
+ : base_t(true, il.begin(), il.end())
+ {}
+
+ //! <b>Effects</b>: Constructs an empty set using the specified
+ //! allocator, and inserts elements from the range [il.begin(), il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
+ //! the predicate and otherwise N logN, where N is il.begin() - il.end().
+ BOOST_CONTAINER_FORCEINLINE set(std::initializer_list<value_type> il, const allocator_type& a)
+ : base_t(true, il.begin(), il.end(), Compare(), a)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty set using the specified comparison object and
+ //! inserts elements from the range [il.begin(), il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
+ //! the predicate and otherwise N logN, where N is il.begin() - il.end().
+ BOOST_CONTAINER_FORCEINLINE set(std::initializer_list<value_type> il, const Compare& comp )
+ : base_t(true, il.begin(), il.end(), comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty set using the specified comparison object and
+ //! allocator, and inserts elements from the range [il.begin(), il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
+ //! the predicate and otherwise N logN, where N is il.begin() - il.end().
+ BOOST_CONTAINER_FORCEINLINE set(std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
+ : base_t(true, il.begin(), il.end(), comp, a)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty set and
+ //! inserts elements from the ordered unique range [il.begin(), il.end()). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be
+ //! unique values.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE set( ordered_unique_range_t, std::initializer_list<value_type> il)
+ : base_t(ordered_range, il.begin(), il.end())
+ {}
+
+ //! <b>Effects</b>: Constructs an empty set using the specified comparison object and
+ //! inserts elements from the ordered unique range [il.begin(), il.end()). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be
+ //! unique values.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE set( ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp)
+ : base_t(ordered_range, il.begin(), il.end(), comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty set using the specified comparison object and
+ //! allocator, and inserts elements from the ordered unique range [il.begin(), il.end()). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be
+ //! unique values.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE set( ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
+ : base_t(ordered_range, il.begin(), il.end(), comp, a)
+ {}
+#endif
+
+ //! <b>Effects</b>: Copy constructs a set.
+ //!
+ //! <b>Complexity</b>: Linear in x.size().
+ BOOST_CONTAINER_FORCEINLINE set(const set& x)
+ : base_t(static_cast<const base_t&>(x))
+ {}
+
+ //! <b>Effects</b>: Move constructs a set. Constructs *this using x's resources.
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Postcondition</b>: x is emptied.
+ BOOST_CONTAINER_FORCEINLINE set(BOOST_RV_REF(set) x)
+ BOOST_NOEXCEPT_IF(boost::container::dtl::is_nothrow_move_constructible<Compare>::value)
+ : base_t(BOOST_MOVE_BASE(base_t, x))
+ {}
+
+ //! <b>Effects</b>: Copy constructs a set using the specified allocator.
+ //!
+ //! <b>Complexity</b>: Linear in x.size().
+ BOOST_CONTAINER_FORCEINLINE set(const set& x, const allocator_type &a)
+ : base_t(static_cast<const base_t&>(x), a)
+ {}
+
+ //! <b>Effects</b>: Move constructs a set using the specified allocator.
+ //! Constructs *this using x's resources.
+ //!
+ //! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise.
+ BOOST_CONTAINER_FORCEINLINE set(BOOST_RV_REF(set) x, const allocator_type &a)
+ : base_t(BOOST_MOVE_BASE(base_t, x), a)
+ {}
+
+ //! <b>Effects</b>: Makes *this a copy of x.
+ //!
+ //! <b>Complexity</b>: Linear in x.size().
+ BOOST_CONTAINER_FORCEINLINE set& operator=(BOOST_COPY_ASSIGN_REF(set) x)
+ { return static_cast<set&>(this->base_t::operator=(static_cast<const base_t&>(x))); }
+
+ //! <b>Effects</b>: this->swap(x.get()).
+ //!
+ //! <b>Throws</b>: If allocator_traits_type::propagate_on_container_move_assignment
+ //! is false and (allocation throws or value_type's move constructor throws)
+ //!
+ //! <b>Complexity</b>: Constant if allocator_traits_type::
+ //! propagate_on_container_move_assignment is true or
+ //! this->get>allocator() == x.get_allocator(). Linear otherwise.
+ BOOST_CONTAINER_FORCEINLINE set& operator=(BOOST_RV_REF(set) x)
+ BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value ||
+ allocator_traits_type::is_always_equal::value) &&
+ boost::container::dtl::is_nothrow_move_assignable<Compare>::value)
+ { return static_cast<set&>(this->base_t::operator=(BOOST_MOVE_BASE(base_t, x))); }
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Copy all elements from il to *this.
+ //!
+ //! <b>Complexity</b>: Linear in il.size().
+ set& operator=(std::initializer_list<value_type> il)
+ {
+ this->clear();
+ insert(il.begin(), il.end());
+ return *this;
+ }
+#endif
+
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ //! <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;
+
+ //! <b>Effects</b>: Returns a reference to the internal allocator.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ stored_allocator_type &get_stored_allocator();
+
+ //! <b>Effects</b>: Returns a reference to the internal allocator.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ const stored_allocator_type &get_stored_allocator() const;
+
+ //! <b>Effects</b>: Returns an iterator to the first element contained in the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant
+ iterator begin();
+
+ //! <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;
+
+ //! <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;
+
+ //! <b>Effects</b>: Returns an iterator to the end of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ iterator end();
+
+ //! <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;
+
+ //! <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;
+
+ //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ reverse_iterator rbegin();
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reverse_iterator rbegin() const;
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reverse_iterator crbegin() const;
+
+ //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ reverse_iterator rend();
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reverse_iterator rend() const;
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
+ //! of the reversed container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reverse_iterator crend() const;
+
+ //! <b>Effects</b>: Returns true if the container contains no elements.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ bool empty() const;
+
+ //! <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;
+
+ //! <b>Effects</b>: Returns the largest possible size of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ size_type max_size() const;
+ #endif // #if 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 with equivalent value.
+ //! and returns the iterator pointing to the
+ //! newly inserted element.
+ //!
+ //! <b>Returns</b>: The bool component of the returned pair is true if and only
+ //! if the insertion takes place, and the iterator component of the pair
+ //! points to the element with key equivalent to the key of x.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or
+ //! Key's in-place constructor throws.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ template <class... Args>
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> emplace(BOOST_FWD_REF(Args)... args)
+ { return this->base_t::emplace_unique(boost::forward<Args>(args)...); }
+
+ //! <b>Effects</b>: Inserts an object of type Key constructed with
+ //! std::forward<Args>(args)... if and only if there is
+ //! no element in the container with equivalent value.
+ //! p is a hint pointing to where the insert
+ //! should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ template <class... Args>
+ BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator p, BOOST_FWD_REF(Args)... args)
+ { return this->base_t::emplace_hint_unique(p, boost::forward<Args>(args)...); }
+
+ #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ #define BOOST_CONTAINER_SET_EMPLACE_CODE(N) \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator,bool> emplace(BOOST_MOVE_UREF##N)\
+ { return this->base_t::emplace_unique(BOOST_MOVE_FWD##N); }\
+ \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ { return this->base_t::emplace_hint_unique(hint BOOST_MOVE_I##N BOOST_MOVE_FWD##N); }\
+ //
+ BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SET_EMPLACE_CODE)
+ #undef BOOST_CONTAINER_SET_EMPLACE_CODE
+
+ #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
+ //! with key equivalent to the key of x.
+ //!
+ //! <b>Returns</b>: The bool component of the returned pair is true if and only
+ //! if the insertion takes place, and the iterator component of the pair
+ //! points to the element with key equivalent to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ std::pair<iterator, bool> insert(const value_type &x);
+
+ //! <b>Effects</b>: Move constructs a new value from x if and only if there is
+ //! no element in the container with key equivalent to the key of x.
+ //!
+ //! <b>Returns</b>: The bool component of the returned pair is true if and only
+ //! if the insertion takes place, and the iterator component of the pair
+ //! points to the element with key equivalent to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ std::pair<iterator, bool> insert(value_type &&x);
+ #else
+ private:
+ typedef std::pair<iterator, bool> insert_return_pair;
+ public:
+ BOOST_MOVE_CONVERSION_AWARE_CATCH(insert, value_type, insert_return_pair, this->priv_insert)
+ #endif
+
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ //! <b>Effects</b>: Inserts a copy of x in the container if and only if there is
+ //! no element in the container with key equivalent to the key of x.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
+ //! is inserted right before p.
+ iterator insert(const_iterator p, const value_type &x);
+
+ //! <b>Effects</b>: Inserts an element move constructed from x in the container.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ iterator insert(const_iterator p, value_type &&x);
+ #else
+ BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, value_type, iterator, this->priv_insert, const_iterator, const_iterator)
+ #endif
+
+ //! <b>Requires</b>: first, last are not iterators into *this.
+ //!
+ //! <b>Effects</b>: inserts each element from the range [first,last) if and only
+ //! if there is no element with key equivalent to the key of that element.
+ //!
+ //! <b>Complexity</b>: At most N log(size()+N) (N is the distance from first to last)
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE void insert(InputIterator first, InputIterator last)
+ { this->base_t::insert_unique(first, last); }
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: inserts each element from the range [il.begin(),il.end()) if and only
+ //! if there is no element with key equivalent to the key of that element.
+ //!
+ //! <b>Complexity</b>: At most N log(size()+N) (N is the distance from il.begin() to il.end())
+ BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il)
+ { this->base_t::insert_unique(il.begin(), il.end()); }
+#endif
+
+ //! @copydoc ::boost::container::map::insert(node_type&&)
+ BOOST_CONTAINER_FORCEINLINE insert_return_type insert(BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)
+ { return this->base_t::insert_unique_node(boost::move(nh)); }
+
+ //! @copydoc ::boost::container::map::insert(const_iterator, node_type&&)
+ BOOST_CONTAINER_FORCEINLINE insert_return_type insert(const_iterator hint, BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)
+ { return this->base_t::insert_unique_node(hint, boost::move(nh)); }
+
+ //! @copydoc ::boost::container::map::merge(map<Key, T, C2, Allocator, Options>&)
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge(set<Key, C2, Allocator, Options>& source)
+ {
+ typedef dtl::tree
+ <Key, dtl::identity<Key>, C2, Allocator, Options> base2_t;
+ this->base_t::merge_unique(static_cast<base2_t&>(source));
+ }
+
+ //! @copydoc ::boost::container::set::merge(set<Key, C2, Allocator, Options>&)
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG set<Key, C2, Allocator, Options> BOOST_RV_REF_END source)
+ { return this->merge(static_cast<set<Key, C2, Allocator, Options>&>(source)); }
+
+ //! @copydoc ::boost::container::map::merge(multimap<Key, T, C2, Allocator, Options>&)
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge(multiset<Key, C2, Allocator, Options>& source)
+ {
+ typedef dtl::tree
+ <Key, dtl::identity<Key>, C2, Allocator, Options> base2_t;
+ this->base_t::merge_unique(static_cast<base2_t&>(source));
+ }
+
+ //! @copydoc ::boost::container::set::merge(multiset<Key, C2, Allocator, Options>&)
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG multiset<Key, C2, Allocator, Options> BOOST_RV_REF_END source)
+ { return this->merge(static_cast<multiset<Key, C2, Allocator, Options>&>(source)); }
+
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ //! <b>Effects</b>: Erases the element pointed to by p.
+ //!
+ //! <b>Returns</b>: Returns an iterator pointing to the element immediately
+ //! following q prior to the element being erased. If no such element exists,
+ //! returns end().
+ //!
+ //! <b>Complexity</b>: Amortized constant time
+ iterator erase(const_iterator p);
+
+ //! <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);
+
+ //! <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);
+
+ //! @copydoc ::boost::container::map::extract(const_iterator)
+ node_type extract(const_iterator p);
+
+ //! @copydoc ::boost::container::map::extract(const key_type&)
+ node_type extract(const key_type& x);
+
+ //! <b>Effects</b>: Swaps the contents of *this and x.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ void swap(set& x)
+ BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value
+ && boost::container::dtl::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();
+
+ //! <b>Effects</b>: Returns the comparison object out
+ //! of which a was constructed.
+ //!
+ //! <b>Complexity</b>: Constant.
+ key_compare key_comp() const;
+
+ //! <b>Effects</b>: Returns an object of value_compare constructed out
+ //! of the comparison object.
+ //!
+ //! <b>Complexity</b>: Constant.
+ value_compare value_comp() const;
+
+ //! <b>Returns</b>: An iterator pointing to an element with the key
+ //! equivalent to x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ iterator find(const key_type& x);
+
+ //! <b>Returns</b>: A const_iterator pointing to an element with the key
+ //! equivalent to x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ const_iterator find(const key_type& x) const;
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Returns</b>: An iterator pointing to an element with the key
+ //! equivalent to x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ template<typename K>
+ iterator find(const K& x);
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <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.
+ template<typename K>
+ const_iterator find(const K& x) const;
+
+ #endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ //! <b>Returns</b>: The number of elements with key equivalent to x.
+ //!
+ //! <b>Complexity</b>: log(size())+count(k)
+ BOOST_CONTAINER_FORCEINLINE size_type count(const key_type& x) const
+ { return static_cast<size_type>(this->base_t::find(x) != this->base_t::cend()); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Returns</b>: The number of elements with key equivalent to x.
+ //!
+ //! <b>Complexity</b>: log(size())+count(k)
+ template<typename K>
+ BOOST_CONTAINER_FORCEINLINE size_type count(const K& x) const
+ { return static_cast<size_type>(this->find(x) != this->cend()); }
+
+ //! <b>Returns</b>: The number of elements with key equivalent to x.
+ //!
+ //! <b>Complexity</b>: log(size())+count(k)
+ BOOST_CONTAINER_FORCEINLINE size_type count(const key_type& x)
+ { return static_cast<size_type>(this->base_t::find(x) != this->base_t::end()); }
+
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ //! <b>Returns</b>: An iterator pointing to the first element with key not less
+ //! than k, or a.end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ iterator lower_bound(const key_type& x);
+
+ //! <b>Returns</b>: A const iterator pointing to the first element with key not
+ //! less than k, or a.end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ const_iterator lower_bound(const key_type& x) const;
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the first element with key not less
+ //! than k, or a.end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ template<typename K>
+ iterator lower_bound(const K& x);
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <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
+ template<typename K>
+ const_iterator lower_bound(const K& x) const;
+
+ //! <b>Returns</b>: An iterator pointing to the first element with key not less
+ //! than x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ iterator upper_bound(const key_type& x);
+
+ //! <b>Returns</b>: A const iterator pointing to the first element with key not
+ //! less than x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ const_iterator upper_bound(const key_type& x) const;
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the first element with key not less
+ //! than x, or end() if such an element is not found.
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ template<typename K>
+ iterator upper_bound(const K& x);
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <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
+ template<typename K>
+ const_iterator upper_bound(const K& x) const;
+
+ #endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator,iterator> equal_range(const key_type& x)
+ { return this->base_t::lower_bound_range(x); }
+
+ //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ BOOST_CONTAINER_FORCEINLINE std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const
+ { return this->base_t::lower_bound_range(x); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ template<typename K>
+ std::pair<iterator,iterator> equal_range(const K& x)
+ { return this->base_t::lower_bound_range(x); }
+
+ //! <b>Requires</b>: This overload is available only if
+ //! key_compare::is_transparent exists.
+ //!
+ //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
+ //!
+ //! <b>Complexity</b>: Logarithmic
+ template<typename K>
+ std::pair<const_iterator,const_iterator> equal_range(const K& x) const
+ { return this->base_t::lower_bound_range(x); }
+
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ //! <b>Effects</b>: Rebalances the tree. It's a no-op for Red-Black and AVL trees.
+ //!
+ //! <b>Complexity</b>: Linear
+ void rebalance();
+
+ //! <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 set& x, const set& y);
+
+ //! <b>Effects</b>: Returns true if x and y are unequal
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator!=(const set& x, const set& y);
+
+ //! <b>Effects</b>: Returns true if x is less than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator<(const set& x, const set& y);
+
+ //! <b>Effects</b>: Returns true if x is greater than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator>(const set& x, const set& y);
+
+ //! <b>Effects</b>: Returns true if x is equal or less than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator<=(const set& x, const set& y);
+
+ //! <b>Effects</b>: Returns true if x is equal or greater than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator>=(const set& x, const set& y);
+
+ //! <b>Effects</b>: x.swap(y)
+ //!
+ //! <b>Complexity</b>: Constant.
+ friend void swap(set& x, set& y);
+
+ #endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ private:
+ template <class KeyType>
+ BOOST_CONTAINER_FORCEINLINE std::pair<iterator, bool> priv_insert(BOOST_FWD_REF(KeyType) x)
+ { return this->base_t::insert_unique(::boost::forward<KeyType>(x)); }
+
+ template <class KeyType>
+ BOOST_CONTAINER_FORCEINLINE iterator priv_insert(const_iterator p, BOOST_FWD_REF(KeyType) x)
+ { return this->base_t::insert_unique(p, ::boost::forward<KeyType>(x)); }
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+};
+
+#if __cplusplus >= 201703L
+
+template <typename InputIterator>
+set(InputIterator, InputIterator) ->
+ set<typename iterator_traits<InputIterator>::value_type>;
+
+template <typename InputIterator, typename Allocator>
+set(InputIterator, InputIterator, Allocator const&) ->
+ set<typename iterator_traits<InputIterator>::value_type, std::less<typename iterator_traits<InputIterator>::value_type>, Allocator>;
+
+template <typename InputIterator, typename Compare>
+set(InputIterator, InputIterator, Compare const&) ->
+ set<typename iterator_traits<InputIterator>::value_type, Compare>;
+
+template <typename InputIterator, typename Compare, typename Allocator>
+set(InputIterator, InputIterator, Compare const&, Allocator const&) ->
+ set<typename iterator_traits<InputIterator>::value_type, Compare, Allocator>;
+
+template <typename InputIterator>
+set(ordered_unique_range_t, InputIterator, InputIterator) ->
+ set<typename iterator_traits<InputIterator>::value_type>;
+
+template <typename InputIterator, typename Allocator>
+set(ordered_unique_range_t, InputIterator, InputIterator, Allocator const&) ->
+ set<typename iterator_traits<InputIterator>::value_type, std::less<typename iterator_traits<InputIterator>::value_type>, Allocator>;
+
+template <typename InputIterator, typename Compare>
+set(ordered_unique_range_t, InputIterator, InputIterator, Compare const&) ->
+ set<typename iterator_traits<InputIterator>::value_type, Compare>;
+
+template <typename InputIterator, typename Compare, typename Allocator>
+set(ordered_unique_range_t, InputIterator, InputIterator, Compare const&, Allocator const&) ->
+ set<typename iterator_traits<InputIterator>::value_type, Compare, Allocator>;
+
+#endif
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+} //namespace container {
+
+//!has_trivial_destructor_after_move<> == true_type
+//!specialization for optimizations
+template <class Key, class Compare, class Options, class Allocator>
+struct has_trivial_destructor_after_move<boost::container::set<Key, Compare, Allocator, Options> >
+{
+ 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 {
+
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+//! A multiset is a kind of associative container that supports equivalent keys
+//! (possibly contains multiple copies of the same key value) and provides for
+//! fast retrieval of the keys themselves. Class multiset supports bidirectional iterators.
+//!
+//! A multiset satisfies all of the requirements of a container and of a reversible
+//! container, and of an associative container). multiset also provides most operations
+//! described for duplicate keys.
+//!
+//! \tparam Key is the type to be inserted in the set, which is also the key_type
+//! \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 Options is an packed option type generated using using boost::container::tree_assoc_options.
+template <class Key, class Compare = std::less<Key>, class Allocator = new_allocator<Key>, class Options = tree_assoc_defaults >
+#else
+template <class Key, class Compare, class Allocator, class Options>
+#endif
+class multiset
+ /// @cond
+ : public dtl::tree
+ <Key,dtl::identity<Key>, Compare, Allocator, Options>
+ /// @endcond
+{
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ private:
+ BOOST_COPYABLE_AND_MOVABLE(multiset)
+ typedef dtl::tree
+ <Key,dtl::identity<Key>, Compare, Allocator, Options> base_t;
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ public:
+
+ //////////////////////////////////////////////
+ //
+ // types
+ //
+ //////////////////////////////////////////////
+ typedef Key key_type;
+ typedef Key value_type;
+ typedef Compare key_compare;
+ typedef Compare value_compare;
+ typedef ::boost::container::allocator_traits<Allocator> allocator_traits_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;
+ typedef typename ::boost::container::allocator_traits<Allocator>::const_reference const_reference;
+ typedef typename ::boost::container::allocator_traits<Allocator>::size_type size_type;
+ typedef typename ::boost::container::allocator_traits<Allocator>::difference_type difference_type;
+ typedef Allocator allocator_type;
+ typedef typename BOOST_CONTAINER_IMPDEF(base_t::stored_allocator_type) stored_allocator_type;
+ typedef typename BOOST_CONTAINER_IMPDEF(base_t::iterator) iterator;
+ typedef typename BOOST_CONTAINER_IMPDEF(base_t::const_iterator) const_iterator;
+ typedef typename BOOST_CONTAINER_IMPDEF(base_t::reverse_iterator) reverse_iterator;
+ typedef typename BOOST_CONTAINER_IMPDEF(base_t::const_reverse_iterator) const_reverse_iterator;
+ typedef typename BOOST_CONTAINER_IMPDEF(base_t::node_type) node_type;
+
+ //////////////////////////////////////////////
+ //
+ // construct/copy/destroy
+ //
+ //////////////////////////////////////////////
+
+ //! @copydoc ::boost::container::set::set()
+ BOOST_CONTAINER_FORCEINLINE multiset()
+ BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<Allocator>::value &&
+ dtl::is_nothrow_default_constructible<Compare>::value)
+ : base_t()
+ {}
+
+ //! @copydoc ::boost::container::set::set(const allocator_type&)
+ BOOST_CONTAINER_FORCEINLINE explicit multiset(const allocator_type& a)
+ : base_t(a)
+ {}
+
+ //! @copydoc ::boost::container::set::set(const Compare&)
+ BOOST_CONTAINER_FORCEINLINE explicit multiset(const Compare& comp)
+ : base_t(comp)
+ {}
+
+ //! @copydoc ::boost::container::set::set(const Compare&, const allocator_type&)
+ BOOST_CONTAINER_FORCEINLINE multiset(const Compare& comp, const allocator_type& a)
+ : base_t(comp, a)
+ {}
+
+ //! @copydoc ::boost::container::set::set(InputIterator, InputIterator)
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE multiset(InputIterator first, InputIterator last)
+ : base_t(false, first, last)
+ {}
+
+ //! @copydoc ::boost::container::set::set(InputIterator, InputIterator, const allocator_type&)
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE multiset(InputIterator first, InputIterator last, const allocator_type& a)
+ : base_t(false, first, last, key_compare(), a)
+ {}
+
+ //! @copydoc ::boost::container::set::set(InputIterator, InputIterator, const Compare&)
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE multiset(InputIterator first, InputIterator last, const Compare& comp)
+ : base_t(false, first, last, comp)
+ {}
+
+ //! @copydoc ::boost::container::set::set(InputIterator, InputIterator, const Compare&, const allocator_type&)
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE multiset(InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
+ : base_t(false, first, last, comp, a)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty multiset and
+ //! and inserts elements from the ordered range [first ,last ). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE multiset( ordered_range_t, InputIterator first, InputIterator last )
+ : base_t(ordered_range, first, last)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty multiset using the specified comparison object and
+ //! inserts elements from the ordered range [first ,last ). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE multiset( ordered_range_t, InputIterator first, InputIterator last, const Compare& comp)
+ : base_t(ordered_range, first, last, comp)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty multiset using the specified comparison object and
+ //! allocator, and inserts elements from the ordered range [first ,last ). This function
+ //! is more efficient than the normal range creation for ordered ranges.
+ //!
+ //! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
+ //!
+ //! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE multiset( ordered_range_t, InputIterator first, InputIterator last, const Compare& comp, const allocator_type& a)
+ : base_t(ordered_range, first, last, comp, a)
+ {}
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! @copydoc ::boost::container::set::set(std::initializer_list<value_type>)
+ BOOST_CONTAINER_FORCEINLINE multiset(std::initializer_list<value_type> il)
+ : base_t(false, il.begin(), il.end())
+ {}
+
+ //! @copydoc ::boost::container::set::set(std::initializer_list<value_type>, const allocator_type&)
+ BOOST_CONTAINER_FORCEINLINE multiset(std::initializer_list<value_type> il, const allocator_type& a)
+ : base_t(false, il.begin(), il.end(), Compare(), a)
+ {}
+
+ //! @copydoc ::boost::container::set::set(std::initializer_list<value_type>, const Compare&)
+ BOOST_CONTAINER_FORCEINLINE multiset(std::initializer_list<value_type> il, const Compare& comp)
+ : base_t(false, il.begin(), il.end(), comp)
+ {}
+
+ //! @copydoc ::boost::container::set::set(std::initializer_list<value_type>, const Compare&, const allocator_type&)
+ BOOST_CONTAINER_FORCEINLINE multiset(std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
+ : base_t(false, il.begin(), il.end(), comp, a)
+ {}
+
+ //! @copydoc ::boost::container::set::set(ordered_unique_range_t, std::initializer_list<value_type>)
+ BOOST_CONTAINER_FORCEINLINE multiset(ordered_range_t, std::initializer_list<value_type> il)
+ : base_t(ordered_range, il.begin(), il.end())
+ {}
+
+ //! @copydoc ::boost::container::set::set(ordered_unique_range_t, std::initializer_list<value_type>, const Compare&)
+ BOOST_CONTAINER_FORCEINLINE multiset(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp)
+ : base_t(ordered_range, il.begin(), il.end(), comp)
+ {}
+
+ //! @copydoc ::boost::container::set::set(ordered_unique_range_t, std::initializer_list<value_type>, const Compare&, const allocator_type&)
+ BOOST_CONTAINER_FORCEINLINE multiset(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
+ : base_t(ordered_range, il.begin(), il.end(), comp, a)
+ {}
+#endif
+
+ //! @copydoc ::boost::container::set::set(const set &)
+ BOOST_CONTAINER_FORCEINLINE multiset(const multiset& x)
+ : base_t(static_cast<const base_t&>(x))
+ {}
+
+ //! @copydoc ::boost::container::set::set(set &&)
+ BOOST_CONTAINER_FORCEINLINE multiset(BOOST_RV_REF(multiset) x)
+ BOOST_NOEXCEPT_IF(boost::container::dtl::is_nothrow_move_constructible<Compare>::value)
+ : base_t(BOOST_MOVE_BASE(base_t, x))
+ {}
+
+ //! @copydoc ::boost::container::set::set(const set &, const allocator_type &)
+ BOOST_CONTAINER_FORCEINLINE multiset(const multiset& x, const allocator_type &a)
+ : base_t(static_cast<const base_t&>(x), a)
+ {}
+
+ //! @copydoc ::boost::container::set::set(set &&, const allocator_type &)
+ BOOST_CONTAINER_FORCEINLINE multiset(BOOST_RV_REF(multiset) x, const allocator_type &a)
+ : base_t(BOOST_MOVE_BASE(base_t, x), a)
+ {}
+
+ //! @copydoc ::boost::container::set::operator=(const set &)
+ BOOST_CONTAINER_FORCEINLINE multiset& operator=(BOOST_COPY_ASSIGN_REF(multiset) x)
+ { return static_cast<multiset&>(this->base_t::operator=(static_cast<const base_t&>(x))); }
+
+ //! @copydoc ::boost::container::set::operator=(set &&)
+ BOOST_CONTAINER_FORCEINLINE multiset& operator=(BOOST_RV_REF(multiset) x)
+ BOOST_NOEXCEPT_IF( (allocator_traits_type::propagate_on_container_move_assignment::value ||
+ allocator_traits_type::is_always_equal::value) &&
+ boost::container::dtl::is_nothrow_move_assignable<Compare>::value)
+ { return static_cast<multiset&>(this->base_t::operator=(BOOST_MOVE_BASE(base_t, x))); }
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! @copydoc ::boost::container::set::operator=(std::initializer_list<value_type>)
+ multiset& operator=(std::initializer_list<value_type> il)
+ {
+ this->clear();
+ insert(il.begin(), il.end());
+ return *this;
+ }
+#endif
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ //! @copydoc ::boost::container::set::get_allocator()
+ allocator_type get_allocator() const;
+
+ //! @copydoc ::boost::container::set::get_stored_allocator()
+ stored_allocator_type &get_stored_allocator();
+
+ //! @copydoc ::boost::container::set::get_stored_allocator() const
+ const stored_allocator_type &get_stored_allocator() const;
+
+ //! @copydoc ::boost::container::set::begin()
+ iterator begin();
+
+ //! @copydoc ::boost::container::set::begin() const
+ const_iterator begin() const;
+
+ //! @copydoc ::boost::container::set::cbegin() const
+ const_iterator cbegin() const;
+
+ //! @copydoc ::boost::container::set::end()
+ iterator end() BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @copydoc ::boost::container::set::end() const
+ const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @copydoc ::boost::container::set::cend() const
+ const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @copydoc ::boost::container::set::rbegin()
+ reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @copydoc ::boost::container::set::rbegin() const
+ const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @copydoc ::boost::container::set::crbegin() const
+ const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @copydoc ::boost::container::set::rend()
+ reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @copydoc ::boost::container::set::rend() const
+ const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @copydoc ::boost::container::set::crend() const
+ const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @copydoc ::boost::container::set::empty() const
+ bool empty() const;
+
+ //! @copydoc ::boost::container::set::size() const
+ size_type size() const;
+
+ //! @copydoc ::boost::container::set::max_size() const
+ size_type max_size() const;
+
+ #endif //#if 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
+ //! newly inserted element.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ template <class... Args>
+ BOOST_CONTAINER_FORCEINLINE iterator emplace(BOOST_FWD_REF(Args)... args)
+ { return this->base_t::emplace_equal(boost::forward<Args>(args)...); }
+
+ //! <b>Effects</b>: Inserts an object of type Key constructed with
+ //! std::forward<Args>(args)...
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
+ //! is inserted right before p.
+ template <class... Args>
+ BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator p, BOOST_FWD_REF(Args)... args)
+ { return this->base_t::emplace_hint_equal(p, boost::forward<Args>(args)...); }
+
+ #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ #define BOOST_CONTAINER_MULTISET_EMPLACE_CODE(N) \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ BOOST_CONTAINER_FORCEINLINE iterator emplace(BOOST_MOVE_UREF##N)\
+ { return this->base_t::emplace_equal(BOOST_MOVE_FWD##N); }\
+ \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ BOOST_CONTAINER_FORCEINLINE iterator emplace_hint(const_iterator hint BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ { return this->base_t::emplace_hint_equal(hint BOOST_MOVE_I##N BOOST_MOVE_FWD##N); }\
+ //
+ BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_MULTISET_EMPLACE_CODE)
+ #undef BOOST_CONTAINER_MULTISET_EMPLACE_CODE
+
+ #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
+ //! newly inserted element.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ iterator insert(const value_type &x);
+
+ //! <b>Effects</b>: Inserts a copy of x in the container.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
+ //! is inserted right before p.
+ iterator insert(value_type &&x);
+ #else
+ BOOST_MOVE_CONVERSION_AWARE_CATCH(insert, value_type, iterator, this->priv_insert)
+ #endif
+
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ //! <b>Effects</b>: Inserts a copy of x in the container.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
+ //! is inserted right before p.
+ iterator insert(const_iterator p, const value_type &x);
+
+ //! <b>Effects</b>: Inserts a value move constructed from x in the container.
+ //! p is a hint pointing to where the insert should start to search.
+ //!
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
+ //!
+ //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
+ //! is inserted right before p.
+ iterator insert(const_iterator p, value_type &&x);
+ #else
+ BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, value_type, iterator, this->priv_insert, const_iterator, const_iterator)
+ #endif
+
+ //! <b>Requires</b>: first, last are not iterators into *this.
+ //!
+ //! <b>Effects</b>: inserts each element from the range [first,last) .
+ //!
+ //! <b>Complexity</b>: At most N log(size()+N) (N is the distance from first to last)
+ template <class InputIterator>
+ BOOST_CONTAINER_FORCEINLINE void insert(InputIterator first, InputIterator last)
+ { this->base_t::insert_equal(first, last); }
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! @copydoc ::boost::container::set::insert(std::initializer_list<value_type>)
+ BOOST_CONTAINER_FORCEINLINE void insert(std::initializer_list<value_type> il)
+ { this->base_t::insert_equal(il.begin(), il.end()); }
+#endif
+
+ //! @copydoc ::boost::container::multimap::insert(node_type&&)
+ BOOST_CONTAINER_FORCEINLINE iterator insert(BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)
+ { return this->base_t::insert_equal_node(boost::move(nh)); }
+
+ //! @copydoc ::boost::container::multimap::insert(const_iterator, node_type&&)
+ BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator hint, BOOST_RV_REF_BEG_IF_CXX11 node_type BOOST_RV_REF_END_IF_CXX11 nh)
+ { return this->base_t::insert_equal_node(hint, boost::move(nh)); }
+
+ //! @copydoc ::boost::container::multimap::merge(multimap<Key, T, C2, Allocator, Options>&)
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge(multiset<Key, C2, Allocator, Options>& source)
+ {
+ typedef dtl::tree
+ <Key, dtl::identity<Key>, C2, Allocator, Options> base2_t;
+ this->base_t::merge_equal(static_cast<base2_t&>(source));
+ }
+
+ //! @copydoc ::boost::container::multiset::merge(multiset<Key, C2, Allocator, Options>&)
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG multiset<Key, C2, Allocator, Options> BOOST_RV_REF_END source)
+ { return this->merge(static_cast<multiset<Key, C2, Allocator, Options>&>(source)); }
+
+ //! @copydoc ::boost::container::multimap::merge(map<Key, T, C2, Allocator, Options>&)
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge(set<Key, C2, Allocator, Options>& source)
+ {
+ typedef dtl::tree
+ <Key, dtl::identity<Key>, C2, Allocator, Options> base2_t;
+ this->base_t::merge_equal(static_cast<base2_t&>(source));
+ }
+
+ //! @copydoc ::boost::container::multiset::merge(set<Key, C2, Allocator, Options>&)
+ template<class C2>
+ BOOST_CONTAINER_FORCEINLINE void merge(BOOST_RV_REF_BEG set<Key, C2, Allocator, Options> BOOST_RV_REF_END source)
+ { return this->merge(static_cast<set<Key, C2, Allocator, Options>&>(source)); }
+
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ //! @copydoc ::boost::container::set::erase(const_iterator)
+ iterator erase(const_iterator p);
+
+ //! @copydoc ::boost::container::set::erase(const key_type&)
+ size_type erase(const key_type& x);
+
+ //! @copydoc ::boost::container::set::erase(const_iterator,const_iterator)
+ iterator erase(const_iterator first, const_iterator last);
+
+ //! @copydoc ::boost::container::multimap::extract(const_iterator)
+ node_type extract(const_iterator p);
+
+ //! @copydoc ::boost::container::multimap::extract(const key_type&)
+ node_type extract(const key_type& x);
+
+ //! @copydoc ::boost::container::set::swap
+ void swap(multiset& x)
+ BOOST_NOEXCEPT_IF( allocator_traits_type::is_always_equal::value
+ && boost::container::dtl::is_nothrow_swappable<Compare>::value );
+
+ //! @copydoc ::boost::container::set::clear
+ void clear() BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @copydoc ::boost::container::set::key_comp
+ key_compare key_comp() const;
+
+ //! @copydoc ::boost::container::set::value_comp
+ value_compare value_comp() const;
+
+ //! @copydoc ::boost::container::set::find(const key_type& )
+ iterator find(const key_type& x);
+
+ //! @copydoc ::boost::container::set::find(const key_type& ) const
+ const_iterator find(const key_type& x) const;
+
+ //! @copydoc ::boost::container::set::find(const K& )
+ template<typename K>
+ iterator find(const K& x);
+
+ //! @copydoc ::boost::container::set::find(const K& )
+ template<typename K>
+ const_iterator find(const K& x) const;
+
+ //! @copydoc ::boost::container::set::count(const key_type& ) const
+ size_type count(const key_type& x) const;
+
+ //! @copydoc ::boost::container::set::count(const K& ) const
+ template<typename K>
+ size_type count(const K& x) const;
+
+ //! @copydoc ::boost::container::set::lower_bound(const key_type& )
+ iterator lower_bound(const key_type& x);
+
+ //! @copydoc ::boost::container::set::lower_bound(const key_type& ) const
+ const_iterator lower_bound(const key_type& x) const;
+
+ //! @copydoc ::boost::container::set::lower_bound(const K& )
+ template<typename K>
+ iterator lower_bound(const K& x);
+
+ //! @copydoc ::boost::container::set::lower_bound(const K& ) const
+ template<typename K>
+ const_iterator lower_bound(const K& x) const;
+
+ //! @copydoc ::boost::container::set::upper_bound(const key_type& )
+ iterator upper_bound(const key_type& x);
+
+ //! @copydoc ::boost::container::set::upper_bound(const key_type& ) const
+ const_iterator upper_bound(const key_type& x) const;
+
+ //! @copydoc ::boost::container::set::upper_bound(const K& )
+ template<typename K>
+ iterator upper_bound(const K& x);
+
+ //! @copydoc ::boost::container::set::upper_bound(const K& ) const
+ template<typename K>
+ const_iterator upper_bound(const K& x) const;
+
+ //! @copydoc ::boost::container::set::equal_range(const key_type& ) const
+ std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const;
+
+ //! @copydoc ::boost::container::set::equal_range(const key_type& )
+ std::pair<iterator,iterator> equal_range(const key_type& x);
+
+ //! @copydoc ::boost::container::set::equal_range(const K& ) const
+ template<typename K>
+ std::pair<const_iterator, const_iterator> equal_range(const K& x) const;
+
+ //! @copydoc ::boost::container::set::equal_range(const K& )
+ template<typename K>
+ std::pair<iterator,iterator> equal_range(const K& x);
+
+ //! @copydoc ::boost::container::set::rebalance()
+ void rebalance();
+
+ //! <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 multiset& x, const multiset& y);
+
+ //! <b>Effects</b>: Returns true if x and y are unequal
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator!=(const multiset& x, const multiset& y);
+
+ //! <b>Effects</b>: Returns true if x is less than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator<(const multiset& x, const multiset& y);
+
+ //! <b>Effects</b>: Returns true if x is greater than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator>(const multiset& x, const multiset& y);
+
+ //! <b>Effects</b>: Returns true if x is equal or less than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator<=(const multiset& x, const multiset& y);
+
+ //! <b>Effects</b>: Returns true if x is equal or greater than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator>=(const multiset& x, const multiset& y);
+
+ //! <b>Effects</b>: x.swap(y)
+ //!
+ //! <b>Complexity</b>: Constant.
+ friend void swap(multiset& x, multiset& y);
+
+ #endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ private:
+ template <class KeyType>
+ BOOST_CONTAINER_FORCEINLINE iterator priv_insert(BOOST_FWD_REF(KeyType) x)
+ { return this->base_t::insert_equal(::boost::forward<KeyType>(x)); }
+
+ template <class KeyType>
+ BOOST_CONTAINER_FORCEINLINE iterator priv_insert(const_iterator p, BOOST_FWD_REF(KeyType) x)
+ { return this->base_t::insert_equal(p, ::boost::forward<KeyType>(x)); }
+
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+};
+
+#if __cplusplus >= 201703L
+
+template <typename InputIterator>
+multiset(InputIterator, InputIterator) ->
+ multiset<typename iterator_traits<InputIterator>::value_type>;
+
+template <typename InputIterator, typename Allocator>
+multiset(InputIterator, InputIterator, Allocator const&) ->
+ multiset< typename iterator_traits<InputIterator>::value_type
+ , std::less<typename iterator_traits<InputIterator>::value_type>
+ , Allocator>;
+
+template <typename InputIterator, typename Compare>
+multiset(InputIterator, InputIterator, Compare const&) ->
+ multiset<typename iterator_traits<InputIterator>::value_type, Compare>;
+
+template <typename InputIterator, typename Compare, typename Allocator>
+multiset(InputIterator, InputIterator, Compare const&, Allocator const&) ->
+ multiset<typename iterator_traits<InputIterator>::value_type, Compare, Allocator>;
+
+template <typename InputIterator>
+multiset(ordered_range_t, InputIterator, InputIterator) ->
+ multiset<typename iterator_traits<InputIterator>::value_type>;
+
+template <typename InputIterator, typename Allocator>
+multiset(ordered_range_t, InputIterator, InputIterator, Allocator const&) ->
+ multiset< typename iterator_traits<InputIterator>::value_type
+ , std::less<typename iterator_traits<InputIterator>::value_type>
+ , Allocator>;
+
+template <typename InputIterator, typename Compare>
+multiset(ordered_range_t, InputIterator, InputIterator, Compare const&) ->
+ multiset< typename iterator_traits<InputIterator>::value_type, Compare>;
+
+template <typename InputIterator, typename Compare, typename Allocator>
+multiset(ordered_range_t, InputIterator, InputIterator, Compare const&, Allocator const&) ->
+ multiset<typename iterator_traits<InputIterator>::value_type, Compare, Allocator>;
+
+#endif
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+} //namespace container {
+
+//!has_trivial_destructor_after_move<> == true_type
+//!specialization for optimizations
+template <class Key, class Compare, class Allocator, class Options>
+struct has_trivial_destructor_after_move<boost::container::multiset<Key, Compare, Allocator, Options> >
+{
+ 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 {
+
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+}}
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif // BOOST_CONTAINER_SET_HPP
diff --git a/include/boost/container/slist.hpp b/include/boost/container/slist.hpp
new file mode 100644
index 0000000..2769070
--- /dev/null
+++ b/include/boost/container/slist.hpp
@@ -0,0 +1,1714 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2004-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_SLIST_HPP
+#define BOOST_CONTAINER_SLIST_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+
+// container
+#include <boost/container/container_fwd.hpp>
+#include <boost/container/new_allocator.hpp> //new_allocator
+#include <boost/container/throw_exception.hpp>
+// container/detail
+#include <boost/container/detail/algorithm.hpp> //algo_equal(), algo_lexicographical_compare
+#include <boost/container/detail/compare_functors.hpp>
+#include <boost/container/detail/iterator.hpp>
+#include <boost/container/detail/iterators.hpp>
+#include <boost/container/detail/mpl.hpp>
+#include <boost/container/detail/node_alloc_holder.hpp>
+#include <boost/container/detail/type_traits.hpp>
+#include <boost/container/detail/value_functors.hpp>
+// intrusive
+#include <boost/intrusive/pointer_traits.hpp>
+#include <boost/intrusive/slist.hpp>
+// move
+#include <boost/move/iterator.hpp>
+#include <boost/move/traits.hpp>
+#include <boost/move/utility_core.hpp>
+// move/detail
+#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+#include <boost/move/detail/fwd_macros.hpp>
+#endif
+#include <boost/move/detail/move_helpers.hpp>
+// other
+#include <boost/core/no_exceptions_support.hpp>
+// std
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+#include <initializer_list>
+#endif
+
+namespace boost {
+namespace container {
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+template <class T, class Allocator>
+class slist;
+
+namespace dtl {
+
+template<class VoidPointer>
+struct slist_hook
+{
+ typedef typename dtl::bi::make_slist_base_hook
+ <dtl::bi::void_pointer<VoidPointer>, dtl::bi::link_mode<dtl::bi::normal_link> >::type type;
+};
+
+template <class T, class VoidPointer>
+struct slist_node
+ : public slist_hook<VoidPointer>::type
+{
+ private:
+ slist_node();
+
+ public:
+ typedef T value_type;
+ typedef typename slist_hook<VoidPointer>::type hook_type;
+
+ T m_data;
+
+ T &get_data()
+ { return this->m_data; }
+
+ const T &get_data() const
+ { return this->m_data; }
+};
+
+template <class T, class VoidPointer>
+struct iiterator_node_value_type< slist_node<T,VoidPointer> > {
+ typedef T type;
+};
+
+template<class Allocator>
+struct intrusive_slist_type
+{
+ typedef boost::container::allocator_traits<Allocator> allocator_traits_type;
+ typedef typename allocator_traits_type::value_type value_type;
+ typedef typename boost::intrusive::pointer_traits
+ <typename allocator_traits_type::pointer>::template
+ rebind_pointer<void>::type
+ void_pointer;
+ typedef typename dtl::slist_node
+ <value_type, void_pointer> node_type;
+
+ typedef typename dtl::bi::make_slist
+ <node_type
+ ,dtl::bi::base_hook<typename slist_hook<void_pointer>::type>
+ ,dtl::bi::constant_time_size<true>
+ , dtl::bi::size_type
+ <typename allocator_traits_type::size_type>
+ >::type container_type;
+ typedef container_type type ;
+};
+
+} //namespace dtl {
+
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+//! An slist is a singly linked list: a list where each element is linked to the next
+//! element, but not to the previous element. That is, it is a Sequence that
+//! supports forward but not backward traversal, and (amortized) constant time
+//! insertion and removal of elements. Slists, like lists, have the important
+//! property that insertion and splicing do not invalidate iterators to list elements,
+//! and that even removal invalidates only the iterators that point to the elements
+//! that are removed. The ordering of iterators may be changed (that is,
+//! slist<T>::iterator might have a different predecessor or successor after a list
+//! operation than it did before), but the iterators themselves will not be invalidated
+//! or made to point to different elements unless that invalidation or mutation is explicit.
+//!
+//! The main difference between slist and list is that list's iterators are bidirectional
+//! iterators, while slist's iterators are forward iterators. This means that slist is
+//! less versatile than list; frequently, however, bidirectional iterators are
+//! unnecessary. You should usually use slist unless you actually need the extra
+//! functionality of list, because singly linked lists are smaller and faster than double
+//! linked lists.
+//!
+//! Important performance note: like every other Sequence, slist defines the member
+//! functions insert and erase. Using these member functions carelessly, however, can
+//! result in disastrously slow programs. The problem is that insert's first argument is
+//! an iterator p, and that it inserts the new element(s) before p. This means that
+//! insert must find the iterator just before p; this is a constant-time operation
+//! for list, since list has bidirectional iterators, but for slist it must find that
+//! iterator by traversing the list from the beginning up to p. In other words:
+//! insert and erase are slow operations anywhere but near the beginning of the slist.
+//!
+//! Slist provides the member functions insert_after and erase_after, which are constant
+//! time operations: you should always use insert_after and erase_after whenever
+//! possible. If you find that insert_after and erase_after aren't adequate for your
+//! needs, and that you often need to use insert and erase in the middle of the list,
+//! then you should probably use list instead of slist.
+//!
+//! \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 = new_allocator<T> >
+#else
+template <class T, class Allocator>
+#endif
+class slist
+ : protected dtl::node_alloc_holder
+ <Allocator, typename dtl::intrusive_slist_type<Allocator>::type>
+{
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ typedef typename
+ dtl::intrusive_slist_type<Allocator>::type Icont;
+ typedef dtl::node_alloc_holder<Allocator, Icont> AllocHolder;
+ typedef typename AllocHolder::NodePtr NodePtr;
+ typedef typename AllocHolder::NodeAlloc NodeAlloc;
+ typedef typename AllocHolder::ValAlloc ValAlloc;
+ typedef typename AllocHolder::Node Node;
+ typedef dtl::allocator_destroyer<NodeAlloc> Destroyer;
+ typedef typename AllocHolder::alloc_version alloc_version;
+ typedef boost::container::
+ allocator_traits<Allocator> allocator_traits_type;
+ typedef boost::container::equal_to_value<Allocator> equal_to_value_type;
+
+ BOOST_COPYABLE_AND_MOVABLE(slist)
+ typedef dtl::iterator_from_iiterator<typename Icont::iterator, false> iterator_impl;
+ typedef dtl::iterator_from_iiterator<typename Icont::iterator, true > const_iterator_impl;
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ public:
+ //////////////////////////////////////////////
+ //
+ // types
+ //
+ //////////////////////////////////////////////
+
+ typedef 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;
+ typedef typename ::boost::container::allocator_traits<Allocator>::const_reference const_reference;
+ typedef typename ::boost::container::allocator_traits<Allocator>::size_type size_type;
+ typedef typename ::boost::container::allocator_traits<Allocator>::difference_type difference_type;
+ typedef Allocator allocator_type;
+ typedef BOOST_CONTAINER_IMPDEF(NodeAlloc) stored_allocator_type;
+ typedef BOOST_CONTAINER_IMPDEF(iterator_impl) iterator;
+ typedef BOOST_CONTAINER_IMPDEF(const_iterator_impl) const_iterator;
+
+ public:
+
+ //////////////////////////////////////////////
+ //
+ // construct/copy/destroy
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Constructs a list taking the allocator as parameter.
+ //!
+ //! <b>Throws</b>: If allocator_type's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Constant.
+ slist() BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<Allocator>::value)
+ : AllocHolder()
+ {}
+
+ //! <b>Effects</b>: Constructs a list taking the allocator as parameter.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ explicit slist(const allocator_type& a) BOOST_NOEXCEPT_OR_NOTHROW
+ : AllocHolder(a)
+ {}
+
+ //! <b>Effects</b>: Constructs a list
+ //! and inserts n value-initialized value_types.
+ //!
+ //! <b>Throws</b>: If allocator_type's default constructor
+ //! throws or T's default or copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to n.
+ explicit slist(size_type n)
+ : AllocHolder(allocator_type())
+ { this->resize(n); }
+
+ //! <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.
+ slist(size_type n, const allocator_type &a)
+ : AllocHolder(a)
+ { this->resize(n); }
+
+ //! <b>Effects</b>: Constructs a list that will use a copy of allocator a
+ //! and inserts n copies of value.
+ //!
+ //! <b>Throws</b>: If allocator_type's default constructor
+ //! throws or T's default or copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to n.
+ explicit slist(size_type n, const value_type& x, const allocator_type& a = allocator_type())
+ : AllocHolder(a)
+ { this->insert_after(this->cbefore_begin(), n, x); }
+
+ //! <b>Effects</b>: Constructs a list that will use a copy of allocator a
+ //! and inserts a copy of the range [first, last) in the list.
+ //!
+ //! <b>Throws</b>: If allocator_type's default constructor
+ //! throws or T's constructor taking a dereferenced InIt throws.
+ //!
+ //! <b>Complexity</b>: Linear to the range [first, last).
+ template <class InpIt>
+ slist(InpIt first, InpIt last, const allocator_type& a = allocator_type())
+ : AllocHolder(a)
+ { this->insert_after(this->cbefore_begin(), first, last); }
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Constructs a list that will use a copy of allocator a
+ //! and inserts a copy of the range [il.begin(), il.end()) in the list.
+ //!
+ //! <b>Throws</b>: If allocator_type's default constructor
+ //! throws or T's constructor taking a dereferenced std::initializer_list iterator throws.
+ //!
+ //! <b>Complexity</b>: Linear to the range [il.begin(), il.end()).
+ slist(std::initializer_list<value_type> il, const allocator_type& a = allocator_type())
+ : AllocHolder(a)
+ { this->insert_after(this->cbefore_begin(), il.begin(), il.end()); }
+#endif
+
+ //! <b>Effects</b>: Copy constructs a list.
+ //!
+ //! <b>Postcondition</b>: x == *this.
+ //!
+ //! <b>Throws</b>: If allocator_type's default constructor
+ //!
+ //! <b>Complexity</b>: Linear to the elements x contains.
+ slist(const slist& x)
+ : AllocHolder(x)
+ { this->insert_after(this->cbefore_begin(), x.begin(), x.end()); }
+
+ //! <b>Effects</b>: Move constructor. Moves x's resources to *this.
+ //!
+ //! <b>Throws</b>: If allocator_type's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Constant.
+ slist(BOOST_RV_REF(slist) x) BOOST_NOEXCEPT_OR_NOTHROW
+ : AllocHolder(BOOST_MOVE_BASE(AllocHolder, x))
+ {}
+
+ //! <b>Effects</b>: Copy constructs a list using the specified allocator.
+ //!
+ //! <b>Postcondition</b>: x == *this.
+ //!
+ //! <b>Throws</b>: If allocator_type's default constructor
+ //!
+ //! <b>Complexity</b>: Linear to the elements x contains.
+ slist(const slist& x, const allocator_type &a)
+ : AllocHolder(a)
+ { this->insert_after(this->cbefore_begin(), x.begin(), x.end()); }
+
+ //! <b>Effects</b>: Move constructor using the specified allocator.
+ //! Moves x's resources to *this.
+ //!
+ //! <b>Throws</b>: If allocation or value_type's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise.
+ slist(BOOST_RV_REF(slist) x, const allocator_type &a)
+ : AllocHolder(a)
+ {
+ if(this->node_alloc() == x.node_alloc()){
+ this->icont().swap(x.icont());
+ }
+ else{
+ this->insert_after(this->cbefore_begin(), boost::make_move_iterator(x.begin()), boost::make_move_iterator(x.end()));
+ }
+ }
+
+ //! <b>Effects</b>: Destroys the list. All stored values are destroyed
+ //! and used memory is deallocated.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements.
+ ~slist() BOOST_NOEXCEPT_OR_NOTHROW
+ {} //AllocHolder clears the slist
+
+ //! <b>Effects</b>: Makes *this contain the same elements as x.
+ //!
+ //! <b>Postcondition</b>: this->size() == x.size(). *this contains a copy
+ //! of each of x's elements.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in x.
+ slist& operator= (BOOST_COPY_ASSIGN_REF(slist) x)
+ {
+ if (&x != this){
+ NodeAlloc &this_alloc = this->node_alloc();
+ const NodeAlloc &x_alloc = x.node_alloc();
+ dtl::bool_<allocator_traits_type::
+ propagate_on_container_copy_assignment::value> flag;
+ if(flag && this_alloc != x_alloc){
+ this->clear();
+ }
+ this->AllocHolder::copy_assign_alloc(x);
+ this->assign(x.begin(), x.end());
+ }
+ return *this;
+ }
+
+ //! <b>Effects</b>: Makes *this contain the same elements as x.
+ //!
+ //! <b>Postcondition</b>: this->size() == x.size(). *this contains a copy
+ //! of each of x's elements.
+ //!
+ //! <b>Throws</b>: If allocator_traits_type::propagate_on_container_move_assignment
+ //! is false and (allocation throws or value_type's move constructor throws)
+ //!
+ //! <b>Complexity</b>: Constant if allocator_traits_type::
+ //! propagate_on_container_move_assignment is true or
+ //! this->get>allocator() == x.get_allocator(). Linear otherwise.
+ slist& operator=(BOOST_RV_REF(slist) x)
+ 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();
+ NodeAlloc &x_alloc = x.node_alloc();
+ const bool propagate_alloc = allocator_traits_type::
+ propagate_on_container_move_assignment::value;
+ const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
+ //Resources can be transferred if both allocators are
+ //going to be equal after this function (either propagated or already equal)
+ if(propagate_alloc || allocators_equal){
+ //Destroy
+ this->clear();
+ //Move allocator if needed
+ this->AllocHolder::move_assign_alloc(x);
+ //Obtain resources
+ this->icont() = boost::move(x.icont());
+ }
+ //Else do a one by one move
+ else{
+ this->assign( boost::make_move_iterator(x.begin())
+ , boost::make_move_iterator(x.end()));
+ }
+ return *this;
+ }
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Makes *this contain the same elements as in il.
+ //!
+ //! <b>Postcondition</b>: this->size() == il.size(). *this contains a copy
+ //! of each of il's elements.
+ //!
+ //! <b>Throws</b>: If allocator_traits_type::propagate_on_container_move_assignment
+ //! is false and (allocation throws or value_type's move constructor throws)
+ slist& operator=(std::initializer_list<value_type> il)
+ {
+ assign(il.begin(), il.end());
+ return *this;
+ }
+#endif
+
+ //! <b>Effects</b>: Assigns the n copies of val to *this.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to n.
+ void assign(size_type n, const T& val)
+ {
+ typedef constant_iterator<value_type, difference_type> cvalue_iterator;
+ return this->assign(cvalue_iterator(val, n), cvalue_iterator());
+ }
+
+ //! <b>Effects</b>: Assigns the range [first, last) to *this.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or
+ //! T's constructor from dereferencing InpIt throws.
+ //!
+ //! <b>Complexity</b>: Linear to n.
+ template <class InpIt>
+ void assign(InpIt first, InpIt last
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename dtl::disable_if_convertible<InpIt, size_type>::type * = 0
+ #endif
+ )
+ {
+ iterator end_n(this->end());
+ iterator prev(this->before_begin());
+ iterator node(this->begin());
+ while (node != end_n && first != last){
+ *node = *first;
+ prev = node;
+ ++node;
+ ++first;
+ }
+ if (first != last)
+ this->insert_after(prev, first, last);
+ else
+ this->erase_after(prev, end_n);
+ }
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Assigns the range [il.begin(), il.end()) to *this.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or
+ //! T's constructor from dereferencing std::initializer_list iterator throws.
+ //!
+ //! <b>Complexity</b>: Linear to range [il.begin(), il.end()).
+
+ void assign(std::initializer_list<value_type> il)
+ {
+ assign(il.begin(), il.end());
+ }
+#endif
+ //! <b>Effects</b>: Returns a copy of the internal allocator.
+ //!
+ //! <b>Throws</b>: If allocator's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Constant.
+ 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.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->node_alloc(); }
+
+ //! <b>Effects</b>: Returns a reference to the internal allocator.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->node_alloc(); }
+
+ //////////////////////////////////////////////
+ //
+ // iterators
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Returns a non-dereferenceable iterator that,
+ //! when incremented, yields begin(). This iterator may be used
+ //! as the argument to insert_after, erase_after, etc.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ iterator before_begin() BOOST_NOEXCEPT_OR_NOTHROW
+ { return iterator(end()); }
+
+ //! <b>Effects</b>: Returns a non-dereferenceable const_iterator
+ //! that, when incremented, yields begin(). This iterator may be used
+ //! as the argument to insert_after, erase_after, etc.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_iterator before_begin() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->cbefore_begin(); }
+
+ //! <b>Effects</b>: Returns an iterator to the first element contained in the list.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ 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.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->cbegin(); }
+
+ //! <b>Effects</b>: Returns an iterator to the end of the list.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ iterator end() BOOST_NOEXCEPT_OR_NOTHROW
+ { return iterator(this->icont().end()); }
+
+ //! <b>Effects</b>: Returns a const_iterator to the end of the list.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->cend(); }
+
+ //! <b>Effects</b>: Returns a non-dereferenceable const_iterator
+ //! that, when incremented, yields begin(). This iterator may be used
+ //! as the argument to insert_after, erase_after, etc.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_iterator cbefore_begin() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return const_iterator(end()); }
+
+ //! <b>Effects</b>: Returns a const_iterator to the first element contained in the list.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ 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.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return const_iterator(this->non_const_icont().end()); }
+
+ //! <b>Returns</b>: The iterator to the element before i in the sequence.
+ //! Returns the end-iterator, if either i is the begin-iterator or the
+ //! sequence is empty.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements before i.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ iterator previous(iterator p) BOOST_NOEXCEPT_OR_NOTHROW
+ { return iterator(this->icont().previous(p.get())); }
+
+ //! <b>Returns</b>: The const_iterator to the element before i in the sequence.
+ //! Returns the end-const_iterator, if either i is the begin-const_iterator or
+ //! the sequence is empty.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements before i.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ const_iterator previous(const_iterator p)
+ { return const_iterator(this->icont().previous(p.get())); }
+
+ //////////////////////////////////////////////
+ //
+ // capacity
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Returns true if the list contains no elements.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ bool empty() const
+ { return !this->size(); }
+
+ //! <b>Effects</b>: Returns the number of the elements contained in the list.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ size_type size() const
+ { return this->icont().size(); }
+
+ //! <b>Effects</b>: Returns the largest possible size of the list.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ size_type max_size() const
+ { return AllocHolder::max_size(); }
+
+ //! <b>Effects</b>: Inserts or erases elements at the end such that
+ //! the size becomes n. New elements are value initialized.
+ //!
+ //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to the difference between size() and new_size.
+ void resize(size_type new_size)
+ {
+ const_iterator last_pos;
+ if(!priv_try_shrink(new_size, last_pos)){
+ typedef value_init_construct_iterator<value_type, difference_type> value_init_iterator;
+ this->insert_after(last_pos, value_init_iterator(new_size - this->size()), value_init_iterator());
+ }
+ }
+
+ //! <b>Effects</b>: Inserts or erases elements at the end such that
+ //! the size becomes n. New elements are copy constructed from x.
+ //!
+ //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to the difference between size() and new_size.
+ void resize(size_type new_size, const T& x)
+ {
+ const_iterator last_pos;
+ if(!priv_try_shrink(new_size, last_pos)){
+ this->insert_after(last_pos, new_size, x);
+ }
+ }
+
+ //////////////////////////////////////////////
+ //
+ // element access
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Requires</b>: !empty()
+ //!
+ //! <b>Effects</b>: Returns a reference to the first element
+ //! from the beginning of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ reference front()
+ {
+ BOOST_ASSERT(!this->empty());
+ return *this->begin();
+ }
+
+ //! <b>Requires</b>: !empty()
+ //!
+ //! <b>Effects</b>: Returns a const reference to the first element
+ //! from the beginning of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reference front() const
+ {
+ BOOST_ASSERT(!this->empty());
+ return *this->begin();
+ }
+
+ //////////////////////////////////////////////
+ //
+ // modifiers
+ //
+ //////////////////////////////////////////////
+
+ #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... in the front of the list
+ //!
+ //! <b>Returns</b>: A reference to the created object.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or
+ //! T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Amortized constant time.
+ template <class... Args>
+ reference emplace_front(BOOST_FWD_REF(Args)... args)
+ { return *this->emplace_after(this->cbefore_begin(), boost::forward<Args>(args)...); }
+
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... after prev
+ //!
+ //! <b>Throws</b>: If memory allocation throws or
+ //! T's in-place constructor throws.
+ //!
+ //! <b>Complexity</b>: Constant
+ template <class... Args>
+ iterator emplace_after(const_iterator prev, BOOST_FWD_REF(Args)... args)
+ {
+ NodePtr pnode(AllocHolder::create_node(boost::forward<Args>(args)...));
+ return iterator(this->icont().insert_after(prev.get(), *pnode));
+ }
+
+ #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ #define BOOST_CONTAINER_SLIST_EMPLACE_CODE(N) \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ reference emplace_front(BOOST_MOVE_UREF##N)\
+ { return *this->emplace_after(this->cbefore_begin() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);}\
+ \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ iterator emplace_after(const_iterator p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ {\
+ NodePtr pnode (AllocHolder::create_node(BOOST_MOVE_FWD##N));\
+ return iterator(this->icont().insert_after(p.get(), *pnode));\
+ }\
+ //
+ BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SLIST_EMPLACE_CODE)
+ #undef BOOST_CONTAINER_SLIST_EMPLACE_CODE
+
+ #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ //! <b>Effects</b>: Inserts a copy of x at the beginning of the list.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or
+ //! T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Amortized constant time.
+ void push_front(const T &x);
+
+ //! <b>Effects</b>: Constructs a new element in the beginning of the list
+ //! and moves the resources of x to this new element.
+ //!
+ //! <b>Throws</b>: If memory allocation throws.
+ //!
+ //! <b>Complexity</b>: Amortized constant time.
+ void push_front(T &&x);
+ #else
+ BOOST_MOVE_CONVERSION_AWARE_CATCH(push_front, T, void, priv_push_front)
+ #endif
+
+
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ //! <b>Requires</b>: p must be a valid iterator of *this.
+ //!
+ //! <b>Effects</b>: Inserts a copy of the value after prev_p.
+ //!
+ //! <b>Returns</b>: An iterator to the inserted element.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Amortized constant time.
+ //!
+ //! <b>Note</b>: Does not affect the validity of iterators and references of
+ //! previous values.
+ iterator insert_after(const_iterator prev_p, const T &x);
+
+ //! <b>Requires</b>: prev_p must be a valid iterator of *this.
+ //!
+ //! <b>Effects</b>: Inserts a move constructed copy object from the value after the
+ //! element pointed by prev_p.
+ //!
+ //! <b>Returns</b>: An iterator to the inserted element.
+ //!
+ //! <b>Throws</b>: If memory allocation throws.
+ //!
+ //! <b>Complexity</b>: Amortized constant time.
+ //!
+ //! <b>Note</b>: Does not affect the validity of iterators and references of
+ //! previous values.
+ iterator insert_after(const_iterator prev_p, T &&x);
+ #else
+ BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert_after, T, iterator, priv_insert_after, const_iterator, const_iterator)
+ #endif
+
+ //! <b>Requires</b>: prev_p must be a valid iterator of *this.
+ //!
+ //! <b>Effects</b>: Inserts n copies of x after prev_p.
+ //!
+ //! <b>Returns</b>: an iterator to the last inserted element or prev_p if n is 0.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
+ //!
+ //!
+ //! <b>Complexity</b>: Linear to n.
+ //!
+ //! <b>Note</b>: Does not affect the validity of iterators and references of
+ //! previous values.
+ iterator insert_after(const_iterator prev_p, size_type n, const value_type& x)
+ {
+ typedef constant_iterator<value_type, difference_type> cvalue_iterator;
+ return this->insert_after(prev_p, cvalue_iterator(x, n), cvalue_iterator());
+ }
+
+ //! <b>Requires</b>: prev_p must be a valid iterator of *this.
+ //!
+ //! <b>Effects</b>: Inserts the range pointed by [first, last) after prev_p.
+ //!
+ //! <b>Returns</b>: an iterator to the last inserted element or prev_p if first == last.
+ //!
+ //! <b>Throws</b>: If memory allocation throws, T's constructor from a
+ //! dereferenced InpIt throws.
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements inserted.
+ //!
+ //! <b>Note</b>: Does not affect the validity of iterators and references of
+ //! previous values.
+ template <class InpIt>
+ iterator insert_after(const_iterator prev_p, InpIt first, InpIt last
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename dtl::enable_if_c
+ < !dtl::is_convertible<InpIt, size_type>::value
+ && (dtl::is_input_iterator<InpIt>::value
+ || dtl::is_same<alloc_version, version_1>::value
+ )
+ >::type * = 0
+ #endif
+ )
+ {
+ iterator ret_it(prev_p.get());
+ for (; first != last; ++first){
+ ret_it = iterator(this->icont().insert_after(ret_it.get(), *this->create_node_from_it(first)));
+ }
+ return ret_it;
+ }
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Requires</b>: prev_p must be a valid iterator of *this.
+ //!
+ //! <b>Effects</b>: Inserts the range pointed by [il.begin(), il.end()) after prev_p.
+ //!
+ //! <b>Returns</b>: an iterator to the last inserted element or prev_p if il.begin() == il.end().
+ //!
+ //! <b>Throws</b>: If memory allocation throws, T's constructor from a
+ //! dereferenced std::initializer_list iterator throws.
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements inserted.
+ //!
+ //! <b>Note</b>: Does not affect the validity of iterators and references of
+ //! previous values.
+ iterator insert_after(const_iterator prev_p, std::initializer_list<value_type> il)
+ {
+ return insert_after(prev_p, il.begin(), il.end());
+ }
+#endif
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ template <class FwdIt>
+ iterator insert_after(const_iterator prev, FwdIt first, FwdIt last
+ , typename dtl::enable_if_c
+ < !dtl::is_convertible<FwdIt, size_type>::value
+ && !(dtl::is_input_iterator<FwdIt>::value
+ || dtl::is_same<alloc_version, version_1>::value
+ )
+ >::type * = 0
+ )
+ {
+ //Optimized allocation and construction
+ insertion_functor func(this->icont(), prev.get());
+ this->allocate_many_and_construct(first, boost::container::iterator_distance(first, last), func);
+ return iterator(func.inserted_first());
+ }
+ #endif
+
+ //! <b>Effects</b>: Removes the first element from the list.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Amortized constant time.
+ void pop_front()
+ {
+ BOOST_ASSERT(!this->empty());
+ this->icont().pop_front_and_dispose(Destroyer(this->node_alloc()));
+ }
+
+ //! <b>Effects</b>: Erases the element after the element pointed by prev_p
+ //! of the list.
+ //!
+ //! <b>Returns</b>: the first element remaining beyond the removed elements,
+ //! or end() if no such element exists.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Note</b>: Does not invalidate iterators or references to non erased elements.
+ iterator erase_after(const_iterator prev_p)
+ {
+ return iterator(this->icont().erase_after_and_dispose(prev_p.get(), Destroyer(this->node_alloc())));
+ }
+
+ //! <b>Effects</b>: Erases the range (before_first, last) from
+ //! the list.
+ //!
+ //! <b>Returns</b>: the first element remaining beyond the removed elements,
+ //! or end() if no such element exists.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Linear to the number of erased elements.
+ //!
+ //! <b>Note</b>: Does not invalidate iterators or references to non erased elements.
+ iterator erase_after(const_iterator before_first, const_iterator last)
+ {
+ return iterator(this->icont().erase_after_and_dispose(before_first.get(), last.get(), Destroyer(this->node_alloc())));
+ }
+
+ //! <b>Effects</b>: Swaps the contents of *this and x.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements on *this and x.
+ void swap(slist& x)
+ BOOST_NOEXCEPT_IF( allocator_traits_type::propagate_on_container_swap::value
+ || allocator_traits_type::is_always_equal::value)
+ {
+ BOOST_ASSERT(allocator_traits_type::propagate_on_container_swap::value ||
+ allocator_traits_type::is_always_equal::value ||
+ this->get_stored_allocator() == x.get_stored_allocator());
+ AllocHolder::swap(x);
+ }
+
+ //! <b>Effects</b>: Erases all the elements of the list.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the list.
+ void clear()
+ { this->icont().clear_and_dispose(Destroyer(this->node_alloc())); }
+
+ //////////////////////////////////////////////
+ //
+ // slist operations
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Requires</b>: p must point to an element contained
+ //! by the list. x != *this
+ //!
+ //! <b>Effects</b>: Transfers all the elements of list x to this list, after the
+ //! the element pointed by p. No destructors or copy constructors are called.
+ //!
+ //! <b>Throws</b>: std::runtime_error if this' allocator and x's allocator
+ //! are not equal.
+ //!
+ //! <b>Complexity</b>: Linear to the elements in x.
+ //!
+ //! <b>Note</b>: Iterators of values obtained from list x now point to elements of
+ //! this list. Iterators of this list and all the references are not invalidated.
+ void splice_after(const_iterator prev_p, slist& x) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(this != &x);
+ BOOST_ASSERT(this->node_alloc() == x.node_alloc());
+ this->icont().splice_after(prev_p.get(), x.icont());
+ }
+
+ //! <b>Requires</b>: p must point to an element contained
+ //! by the list. x != *this
+ //!
+ //! <b>Effects</b>: Transfers all the elements of list x to this list, after the
+ //! the element pointed by p. No destructors or copy constructors are called.
+ //!
+ //! <b>Throws</b>: std::runtime_error if this' allocator and x's allocator
+ //! are not equal.
+ //!
+ //! <b>Complexity</b>: Linear to the elements in x.
+ //!
+ //! <b>Note</b>: Iterators of values obtained from list x now point to elements of
+ //! this list. Iterators of this list and all the references are not invalidated.
+ void splice_after(const_iterator prev_p, BOOST_RV_REF(slist) x) BOOST_NOEXCEPT_OR_NOTHROW
+ { this->splice_after(prev_p, static_cast<slist&>(x)); }
+
+ //! <b>Requires</b>: prev_p must be a valid iterator of this.
+ //! i must point to an element contained in list x.
+ //! this' allocator and x's allocator shall compare equal.
+ //!
+ //! <b>Effects</b>: Transfers the value pointed by i, from list x to this list,
+ //! after the element pointed by prev_p.
+ //! If prev_p == prev or prev_p == ++prev, this function is a null operation.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
+ //! list. Iterators of this list and all the references are not invalidated.
+ void splice_after(const_iterator prev_p, slist& x, const_iterator prev) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(this->node_alloc() == x.node_alloc());
+ this->icont().splice_after(prev_p.get(), x.icont(), prev.get());
+ }
+
+ //! <b>Requires</b>: prev_p must be a valid iterator of this.
+ //! i must point to an element contained in list x.
+ //! this' allocator and x's allocator shall compare equal.
+ //!
+ //! <b>Effects</b>: Transfers the value pointed by i, from list x to this list,
+ //! after the element pointed by prev_p.
+ //! If prev_p == prev or prev_p == ++prev, this function is a null operation.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
+ //! list. Iterators of this list and all the references are not invalidated.
+ void splice_after(const_iterator prev_p, BOOST_RV_REF(slist) x, const_iterator prev) BOOST_NOEXCEPT_OR_NOTHROW
+ { this->splice_after(prev_p, static_cast<slist&>(x), prev); }
+
+ //! <b>Requires</b>: prev_p must be a valid iterator of this.
+ //! before_first and before_last must be valid iterators of x.
+ //! prev_p must not be contained in [before_first, before_last) range.
+ //! this' allocator and x's allocator shall compare equal.
+ //!
+ //! <b>Effects</b>: Transfers the range [before_first + 1, before_last + 1)
+ //! from list x to this list, after the element pointed by prev_p.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Linear to the number of transferred elements.
+ //!
+ //! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
+ //! list. Iterators of this list and all the references are not invalidated.
+ void splice_after(const_iterator prev_p, slist& x,
+ const_iterator before_first, const_iterator before_last) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(this->node_alloc() == x.node_alloc());
+ this->icont().splice_after
+ (prev_p.get(), x.icont(), before_first.get(), before_last.get());
+ }
+
+ //! <b>Requires</b>: prev_p must be a valid iterator of this.
+ //! before_first and before_last must be valid iterators of x.
+ //! prev_p must not be contained in [before_first, before_last) range.
+ //! this' allocator and x's allocator shall compare equal.
+ //!
+ //! <b>Effects</b>: Transfers the range [before_first + 1, before_last + 1)
+ //! from list x to this list, after the element pointed by prev_p.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Linear to the number of transferred elements.
+ //!
+ //! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
+ //! list. Iterators of this list and all the references are not invalidated.
+ void splice_after(const_iterator prev_p, BOOST_RV_REF(slist) x,
+ const_iterator before_first, const_iterator before_last) BOOST_NOEXCEPT_OR_NOTHROW
+ { this->splice_after(prev_p, static_cast<slist&>(x), before_first, before_last); }
+
+ //! <b>Requires</b>: prev_p must be a valid iterator of this.
+ //! before_first and before_last must be valid iterators of x.
+ //! prev_p must not be contained in [before_first, before_last) range.
+ //! n == distance(before_first, before_last).
+ //! this' allocator and x's allocator shall compare equal.
+ //!
+ //! <b>Effects</b>: Transfers the range [before_first + 1, before_last + 1)
+ //! from list x to this list, after the element pointed by prev_p.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
+ //! list. Iterators of this list and all the references are not invalidated.
+ void splice_after(const_iterator prev_p, slist& x,
+ const_iterator before_first, const_iterator before_last,
+ size_type n) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(this->node_alloc() == x.node_alloc());
+ this->icont().splice_after
+ (prev_p.get(), x.icont(), before_first.get(), before_last.get(), n);
+ }
+
+ //! <b>Requires</b>: prev_p must be a valid iterator of this.
+ //! before_first and before_last must be valid iterators of x.
+ //! prev_p must not be contained in [before_first, before_last) range.
+ //! n == distance(before_first, before_last).
+ //! this' allocator and x's allocator shall compare equal.
+ //!
+ //! <b>Effects</b>: Transfers the range [before_first + 1, before_last + 1)
+ //! from list x to this list, after the element pointed by prev_p.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
+ //! list. Iterators of this list and all the references are not invalidated.
+ void splice_after(const_iterator prev_p, BOOST_RV_REF(slist) x,
+ const_iterator before_first, const_iterator before_last,
+ size_type n) BOOST_NOEXCEPT_OR_NOTHROW
+ { this->splice_after(prev_p, static_cast<slist&>(x), before_first, before_last, n); }
+
+ //! <b>Effects</b>: Removes all the elements that compare equal to value.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Linear time. It performs exactly size() comparisons for equality.
+ //!
+ //! <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_type(value)); }
+
+ //! <b>Effects</b>: Removes all the elements for which a specified
+ //! predicate is satisfied.
+ //!
+ //! <b>Throws</b>: If pred throws.
+ //!
+ //! <b>Complexity</b>: Linear time. It performs exactly size() calls to the predicate.
+ //!
+ //! <b>Note</b>: The relative order of elements that are not removed is unchanged,
+ //! and iterators to elements that are not removed remain valid.
+ template <class Pred>
+ void remove_if(Pred pred)
+ {
+ 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
+ //! elements that are equal from the list.
+ //!
+ //! <b>Throws</b>: If comparison throws.
+ //!
+ //! <b>Complexity</b>: Linear time (size()-1 comparisons equality comparisons).
+ //!
+ //! <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 unique()
+ { this->unique(value_equal_t()); }
+
+ //! <b>Effects</b>: Removes adjacent duplicate elements or adjacent
+ //! elements that satisfy some binary predicate from the list.
+ //!
+ //! <b>Throws</b>: If pred throws.
+ //!
+ //! <b>Complexity</b>: Linear time (size()-1 comparisons calls to pred()).
+ //!
+ //! <b>Note</b>: The relative order of elements that are not removed is unchanged,
+ //! and iterators to elements that are not removed remain valid.
+ template <class Pred>
+ void unique(Pred pred)
+ {
+ typedef value_to_node_compare<Node, Pred> value_to_node_compare_type;
+ this->icont().unique_and_dispose(value_to_node_compare_type(pred), Destroyer(this->node_alloc()));
+ }
+
+ //! <b>Requires</b>: The lists x and *this must be distinct.
+ //!
+ //! <b>Effects</b>: This function removes all of x's elements and inserts them
+ //! in order into *this according to std::less<value_type>. The merge is stable;
+ //! that is, if an element from *this is equivalent to one from x, then the element
+ //! from *this will precede the one from x.
+ //!
+ //! <b>Throws</b>: If comparison throws.
+ //!
+ //! <b>Complexity</b>: This function is linear time: it performs at most
+ //! size() + x.size() - 1 comparisons.
+ void merge(slist & x)
+ { this->merge(x, value_less_t()); }
+
+ //! <b>Requires</b>: The lists x and *this must be distinct.
+ //!
+ //! <b>Effects</b>: This function removes all of x's elements and inserts them
+ //! in order into *this according to std::less<value_type>. The merge is stable;
+ //! that is, if an element from *this is equivalent to one from x, then the element
+ //! from *this will precede the one from x.
+ //!
+ //! <b>Throws</b>: If comparison throws.
+ //!
+ //! <b>Complexity</b>: This function is linear time: it performs at most
+ //! size() + x.size() - 1 comparisons.
+ void merge(BOOST_RV_REF(slist) x)
+ { this->merge(static_cast<slist&>(x)); }
+
+ //! <b>Requires</b>: p must be a comparison function that induces a strict weak
+ //! ordering and both *this and x must be sorted according to that ordering
+ //! The lists x and *this must be distinct.
+ //!
+ //! <b>Effects</b>: This function removes all of x's elements and inserts them
+ //! in order into *this. The merge is stable; that is, if an element from *this is
+ //! equivalent to one from x, then the element from *this will precede the one from x.
+ //!
+ //! <b>Throws</b>: If comp throws.
+ //!
+ //! <b>Complexity</b>: This function is linear time: it performs at most
+ //! size() + x.size() - 1 comparisons.
+ //!
+ //! <b>Note</b>: Iterators and references to *this are not invalidated.
+ template <class StrictWeakOrdering>
+ void merge(slist& x, StrictWeakOrdering comp)
+ {
+ typedef value_to_node_compare<Node, StrictWeakOrdering> value_to_node_compare_type;
+ BOOST_ASSERT(this->node_alloc() == x.node_alloc());
+ this->icont().merge(x.icont(), value_to_node_compare_type(comp));
+ }
+
+ //! <b>Requires</b>: p must be a comparison function that induces a strict weak
+ //! ordering and both *this and x must be sorted according to that ordering
+ //! The lists x and *this must be distinct.
+ //!
+ //! <b>Effects</b>: This function removes all of x's elements and inserts them
+ //! in order into *this. The merge is stable; that is, if an element from *this is
+ //! equivalent to one from x, then the element from *this will precede the one from x.
+ //!
+ //! <b>Throws</b>: If comp throws.
+ //!
+ //! <b>Complexity</b>: This function is linear time: it performs at most
+ //! size() + x.size() - 1 comparisons.
+ //!
+ //! <b>Note</b>: Iterators and references to *this are not invalidated.
+ template <class StrictWeakOrdering>
+ void merge(BOOST_RV_REF(slist) x, StrictWeakOrdering comp)
+ { this->merge(static_cast<slist&>(x), comp); }
+
+ //! <b>Effects</b>: This function sorts the list *this according to std::less<value_type>.
+ //! The sort is stable, that is, the relative order of equivalent elements is preserved.
+ //!
+ //! <b>Throws</b>: If comparison throws.
+ //!
+ //! <b>Notes</b>: Iterators and references are not invalidated.
+ //!
+ //! <b>Complexity</b>: The number of comparisons is approximately N log N, where N
+ //! is the list's size.
+ void sort()
+ { this->sort(value_less_t()); }
+
+ //! <b>Effects</b>: This function sorts the list *this according to std::less<value_type>.
+ //! The sort is stable, that is, the relative order of equivalent elements is preserved.
+ //!
+ //! <b>Throws</b>: If comp throws.
+ //!
+ //! <b>Notes</b>: Iterators and references are not invalidated.
+ //!
+ //! <b>Complexity</b>: The number of comparisons is approximately N log N, where N
+ //! is the list's size.
+ template <class StrictWeakOrdering>
+ void sort(StrictWeakOrdering comp)
+ {
+ typedef value_to_node_compare<Node, StrictWeakOrdering> value_to_node_compare_type;
+ // nothing if the slist has length 0 or 1.
+ if (this->size() < 2)
+ return;
+ this->icont().sort(value_to_node_compare_type(comp));
+ }
+
+ //! <b>Effects</b>: Reverses the order of elements in the list.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: This function is linear time.
+ //!
+ //! <b>Note</b>: Iterators and references are not invalidated
+ void reverse() BOOST_NOEXCEPT_OR_NOTHROW
+ { this->icont().reverse(); }
+
+ //////////////////////////////////////////////
+ //
+ // list compatibility interface
+ //
+ //////////////////////////////////////////////
+
+ #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... before p
+ //!
+ //! <b>Throws</b>: If memory allocation throws or
+ //! T's in-place constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to the elements before p
+ template <class... Args>
+ iterator emplace(const_iterator p, BOOST_FWD_REF(Args)... args)
+ { return this->emplace_after(this->previous(p), boost::forward<Args>(args)...); }
+
+ #else
+
+ #define BOOST_CONTAINER_SLIST_EMPLACE_CODE(N) \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ iterator emplace(const_iterator p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ {\
+ return this->emplace_after(this->previous(p) BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
+ }\
+ //
+ BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SLIST_EMPLACE_CODE)
+ #undef BOOST_CONTAINER_SLIST_EMPLACE_CODE
+
+ #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ //! <b>Requires</b>: p must be a valid iterator of *this.
+ //!
+ //! <b>Effects</b>: Insert a copy of x before p.
+ //!
+ //! <b>Returns</b>: an iterator to the inserted element.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or x's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to the elements before p.
+ iterator insert(const_iterator p, const T &x);
+
+ //! <b>Requires</b>: p must be a valid iterator of *this.
+ //!
+ //! <b>Effects</b>: Insert a new element before p with x's resources.
+ //!
+ //! <b>Returns</b>: an iterator to the inserted element.
+ //!
+ //! <b>Throws</b>: If memory allocation throws.
+ //!
+ //! <b>Complexity</b>: Linear to the elements before p.
+ iterator insert(const_iterator prev_p, T &&x);
+ #else
+ BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator, const_iterator)
+ #endif
+
+ //! <b>Requires</b>: p must be a valid iterator of *this.
+ //!
+ //! <b>Effects</b>: Inserts n copies of x before p.
+ //!
+ //! <b>Returns</b>: an iterator to the first inserted element or p if n == 0.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to n plus linear to the elements before p.
+ iterator insert(const_iterator p, size_type n, const value_type& x)
+ {
+ const_iterator prev(this->previous(p));
+ this->insert_after(prev, n, x);
+ return ++iterator(prev.get());
+ }
+
+ //! <b>Requires</b>: p must be a valid iterator of *this.
+ //!
+ //! <b>Effects</b>: Insert a copy of the [first, last) range before p.
+ //!
+ //! <b>Returns</b>: an iterator to the first inserted element or p if first == last.
+ //!
+ //! <b>Throws</b>: If memory allocation throws, T's constructor from a
+ //! dereferenced InpIt throws.
+ //!
+ //! <b>Complexity</b>: Linear to distance [first, last) plus
+ //! linear to the elements before p.
+ template <class InIter>
+ iterator insert(const_iterator p, InIter first, InIter last)
+ {
+ const_iterator prev(this->previous(p));
+ this->insert_after(prev, first, last);
+ return ++iterator(prev.get());
+ }
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Requires</b>: p must be a valid iterator of *this.
+ //!
+ //! <b>Effects</b>: Insert a copy of the [il.begin(), il.end()) range before p.
+ //!
+ //! <b>Returns</b>: an iterator to the first inserted element or p if il.begin() == il.end().
+ //!
+ //! <b>Throws</b>: If memory allocation throws, T's constructor from a
+ //! dereferenced std::initializer_list iterator throws.
+ //!
+ //! <b>Complexity</b>: Linear to the range [il.begin(), il.end()) plus
+ //! linear to the elements before p.
+ iterator insert(const_iterator p, std::initializer_list<value_type> il)
+ {
+ return insert(p, il.begin(), il.end());
+ }
+#endif
+
+ //! <b>Requires</b>: p must be a valid iterator of *this.
+ //!
+ //! <b>Effects</b>: Erases the element at p.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements before p.
+ iterator erase(const_iterator p) BOOST_NOEXCEPT_OR_NOTHROW
+ { return iterator(this->erase_after(previous(p))); }
+
+ //! <b>Requires</b>: first and last must be valid iterator to elements in *this.
+ //!
+ //! <b>Effects</b>: Erases the elements pointed by [first, last).
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Linear to the distance between first and last plus
+ //! linear to the elements before first.
+ iterator erase(const_iterator first, const_iterator last) BOOST_NOEXCEPT_OR_NOTHROW
+ { return iterator(this->erase_after(previous(first), last)); }
+
+ //! <b>Requires</b>: p must point to an element contained
+ //! by the list. x != *this. this' allocator and x's allocator shall compare equal
+ //!
+ //! <b>Effects</b>: Transfers all the elements of list x to this list, before the
+ //! the element pointed by p. No destructors or copy constructors are called.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Linear in distance(begin(), p), and linear in x.size().
+ //!
+ //! <b>Note</b>: Iterators of values obtained from list x now point to elements of
+ //! this list. Iterators of this list and all the references are not invalidated.
+ void splice(const_iterator p, slist& x) BOOST_NOEXCEPT_OR_NOTHROW
+ { this->splice_after(this->previous(p), x); }
+
+ //! <b>Requires</b>: p must point to an element contained
+ //! by the list. x != *this. this' allocator and x's allocator shall compare equal
+ //!
+ //! <b>Effects</b>: Transfers all the elements of list x to this list, before the
+ //! the element pointed by p. No destructors or copy constructors are called.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Linear in distance(begin(), p), and linear in x.size().
+ //!
+ //! <b>Note</b>: Iterators of values obtained from list x now point to elements of
+ //! this list. Iterators of this list and all the references are not invalidated.
+ void splice(const_iterator p, BOOST_RV_REF(slist) x) BOOST_NOEXCEPT_OR_NOTHROW
+ { this->splice(p, static_cast<slist&>(x)); }
+
+ //! <b>Requires</b>: p must point to an element contained
+ //! by this list. i must point to an element contained in list x.
+ //! this' allocator and x's allocator shall compare equal
+ //!
+ //! <b>Effects</b>: Transfers the value pointed by i, from list x to this list,
+ //! before the element pointed by p. No destructors or copy constructors are called.
+ //! If p == i or p == ++i, this function is a null operation.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Linear in distance(begin(), p), and in distance(x.begin(), i).
+ //!
+ //! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
+ //! list. Iterators of this list and all the references are not invalidated.
+ void splice(const_iterator p, slist& x, const_iterator i) BOOST_NOEXCEPT_OR_NOTHROW
+ { this->splice_after(this->previous(p), x, x.previous(i)); }
+
+ //! <b>Requires</b>: p must point to an element contained
+ //! by this list. i must point to an element contained in list x.
+ //! this' allocator and x's allocator shall compare equal.
+ //!
+ //! <b>Effects</b>: Transfers the value pointed by i, from list x to this list,
+ //! before the element pointed by p. No destructors or copy constructors are called.
+ //! If p == i or p == ++i, this function is a null operation.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Linear in distance(begin(), p), and in distance(x.begin(), i).
+ //!
+ //! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
+ //! list. Iterators of this list and all the references are not invalidated.
+ void splice(const_iterator p, BOOST_RV_REF(slist) x, const_iterator i) BOOST_NOEXCEPT_OR_NOTHROW
+ { this->splice(p, static_cast<slist&>(x), i); }
+
+ //! <b>Requires</b>: p must point to an element contained
+ //! by this list. first and last must point to elements contained in list x.
+ //!
+ //! <b>Effects</b>: Transfers the range pointed by first and last from list x to this list,
+ //! before the element pointed by p. No destructors or copy constructors are called.
+ //! this' allocator and x's allocator shall compare equal.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Linear in distance(begin(), p), in distance(x.begin(), first),
+ //! and in distance(first, last).
+ //!
+ //! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
+ //! list. Iterators of this list and all the references are not invalidated.
+ void splice(const_iterator p, slist& x, const_iterator first, const_iterator last) BOOST_NOEXCEPT_OR_NOTHROW
+ { this->splice_after(this->previous(p), x, x.previous(first), x.previous(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.
+ //! 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 element pointed by p. No destructors or copy constructors are called.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Linear in distance(begin(), p), in distance(x.begin(), first),
+ //! and in distance(first, last).
+ //!
+ //! <b>Note</b>: Iterators of values obtained from list x now point to elements of this
+ //! list. Iterators of this list and all the references are not invalidated.
+ void splice(const_iterator p, BOOST_RV_REF(slist) x, const_iterator first, const_iterator last) BOOST_NOEXCEPT_OR_NOTHROW
+ { this->splice(p, static_cast<slist&>(x), first, last); }
+
+ //! <b>Effects</b>: Returns true if x and y are equal
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator==(const slist& x, const slist& y)
+ { return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin()); }
+
+ //! <b>Effects</b>: Returns true if x and y are unequal
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator!=(const slist& x, const slist& y)
+ { return !(x == y); }
+
+ //! <b>Effects</b>: Returns true if x is less than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator<(const slist& x, const slist& y)
+ { return ::boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
+
+ //! <b>Effects</b>: Returns true if x is greater than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator>(const slist& x, const slist& y)
+ { return y < x; }
+
+ //! <b>Effects</b>: Returns true if x is equal or less than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator<=(const slist& x, const slist& y)
+ { return !(y < x); }
+
+ //! <b>Effects</b>: Returns true if x is equal or greater than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator>=(const slist& x, const slist& y)
+ { return !(x < y); }
+
+ //! <b>Effects</b>: x.swap(y)
+ //!
+ //! <b>Complexity</b>: Constant.
+ friend void swap(slist& x, slist& y)
+ { x.swap(y); }
+
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ private:
+
+ void priv_push_front (const T &x)
+ { this->insert_after(this->cbefore_begin(), x); }
+
+ void priv_push_front (BOOST_RV_REF(T) x)
+ { this->insert_after(this->cbefore_begin(), ::boost::move(x)); }
+
+ bool priv_try_shrink(size_type new_size, const_iterator &last_pos)
+ {
+ typename Icont::iterator end_n(this->icont().end()), cur(this->icont().before_begin()), cur_next;
+ while (++(cur_next = cur) != end_n && new_size > 0){
+ --new_size;
+ cur = cur_next;
+ }
+ last_pos = const_iterator(cur);
+ if (cur_next != end_n){
+ this->erase_after(last_pos, const_iterator(end_n));
+ return true;
+ }
+ else{
+ return false;
+ }
+ }
+
+ template<class U>
+ iterator priv_insert(const_iterator p, BOOST_FWD_REF(U) x)
+ { return this->insert_after(previous(p), ::boost::forward<U>(x)); }
+
+ template<class U>
+ iterator priv_insert_after(const_iterator prev_p, BOOST_FWD_REF(U) x)
+ { return iterator(this->icont().insert_after(prev_p.get(), *this->create_node(::boost::forward<U>(x)))); }
+
+ class insertion_functor;
+ friend class insertion_functor;
+
+ class insertion_functor
+ {
+ Icont &icont_;
+ typedef typename Icont::iterator iiterator;
+ typedef typename Icont::const_iterator iconst_iterator;
+ const iconst_iterator prev_;
+ iiterator ret_;
+
+ public:
+ insertion_functor(Icont &icont, typename Icont::const_iterator prev)
+ : icont_(icont), prev_(prev), ret_(prev.unconst())
+ {}
+
+ void operator()(Node &n)
+ {
+ ret_ = this->icont_.insert_after(prev_, n);
+ }
+
+ iiterator inserted_first() const
+ { return ret_; }
+ };
+
+ //Functors for member algorithm defaults
+ typedef value_less<value_type> value_less_t;
+ typedef value_equal<value_type> value_equal_t;
+
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+};
+
+#if __cplusplus >= 201703L
+
+template <typename InpIt>
+slist(InpIt, InpIt) ->
+ slist<typename iterator_traits<InpIt>::value_type>;
+
+template <typename InpIt, typename Allocator>
+slist(InpIt, InpIt, Allocator const&) ->
+ slist<typename iterator_traits<InpIt>::value_type, Allocator>;
+
+#endif
+
+}}
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+namespace boost {
+
+//!has_trivial_destructor_after_move<> == true_type
+//!specialization for optimizations
+template <class T, class Allocator>
+struct has_trivial_destructor_after_move<boost::container::slist<T, Allocator> >
+{
+ typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer;
+ static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value &&
+ ::boost::has_trivial_destructor_after_move<pointer>::value;
+};
+
+namespace container {
+
+}} //namespace boost{ namespace container {
+
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+// Specialization of insert_iterator so that insertions will be constant
+// time rather than linear time.
+
+#include <boost/move/detail/std_ns_begin.hpp>
+BOOST_CONTAINER_DOC1ST(namespace std {, BOOST_MOVE_STD_NS_BEG)
+
+//! A specialization of insert_iterator
+//! that works with slist
+template <class T, class Allocator>
+class insert_iterator<boost::container::slist<T, Allocator> >
+{
+ private:
+ typedef boost::container::slist<T, Allocator> Container;
+ Container* container;
+ typename Container::iterator iter;
+
+ public:
+ typedef Container container_type;
+ typedef output_iterator_tag iterator_category;
+ typedef void value_type;
+ typedef void difference_type;
+ typedef void pointer;
+ typedef void reference;
+
+ insert_iterator(Container& x,
+ typename Container::iterator i,
+ bool is_previous = false)
+ : container(&x), iter(is_previous ? i : x.previous(i)){ }
+
+ insert_iterator<Container>&
+ operator=(const typename Container::value_type& value)
+ {
+ iter = container->insert_after(iter, value);
+ return *this;
+ }
+ insert_iterator<Container>& operator*(){ return *this; }
+ insert_iterator<Container>& operator++(){ return *this; }
+ insert_iterator<Container>& operator++(int){ return *this; }
+};
+
+BOOST_CONTAINER_DOC1ST( }, BOOST_MOVE_STD_NS_END)
+#include <boost/move/detail/std_ns_end.hpp>
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif // BOOST_CONTAINER_SLIST_HPP
diff --git a/include/boost/container/small_vector.hpp b/include/boost/container/small_vector.hpp
new file mode 100644
index 0000000..70704d6
--- /dev/null
+++ b/include/boost/container/small_vector.hpp
@@ -0,0 +1,631 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_CONTAINER_SMALL_VECTOR_HPP
+#define BOOST_CONTAINER_CONTAINER_SMALL_VECTOR_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+
+// container
+#include <boost/container/container_fwd.hpp>
+#include <boost/container/vector.hpp>
+#include <boost/container/allocator_traits.hpp>
+#include <boost/container/new_allocator.hpp> //new_allocator
+// container/detail
+#include <boost/container/detail/type_traits.hpp>
+#include <boost/container/detail/version_type.hpp>
+
+//move
+#include <boost/move/adl_move_swap.hpp>
+#include <boost/move/iterator.hpp>
+
+//move/detail
+#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+#include <boost/move/detail/fwd_macros.hpp>
+#endif
+
+//std
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+#include <initializer_list> //for std::initializer_list
+#endif
+
+namespace boost {
+namespace container {
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+template <class T, class Allocator = new_allocator<T> >
+class small_vector_base;
+
+#endif
+
+//! A non-standard allocator used to implement `small_vector`.
+//! Users should never use it directly. It is described here
+//! for documentation purposes.
+//!
+//! This allocator inherits from a standard-conforming allocator
+//! and forwards member functions to the standard allocator except
+//! when internal storage is being used as memory source.
+//!
+//! This allocator is a "partially_propagable" allocator and
+//! defines `is_partially_propagable` as true_type.
+//!
+//! A partially propagable allocator means that not all storage
+//! allocatod by an instance of `small_vector_allocator` can be
+//! deallocated by another instance of this type, even if both
+//! instances compare equal or an instance is propagated to another
+//! one using the copy/move constructor or assignment. The storage that
+//! can never be propagated is identified by `storage_is_unpropagable(p)`.
+//!
+//! `boost::container::vector` supports partially propagable allocators
+//! fallbacking to deep copy/swap/move operations when internal storage
+//! is being used to store vector elements.
+//!
+//! `small_vector_allocator` assumes that will be instantiated as
+//! `boost::container::vector< T, small_vector_allocator<Allocator> >`
+//! and internal storage can be obtained downcasting that vector
+//! to `small_vector_base<T>`.
+template<class Allocator>
+class small_vector_allocator
+ : public Allocator
+{
+ typedef unsigned int allocation_type;
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ private:
+
+ BOOST_COPYABLE_AND_MOVABLE(small_vector_allocator)
+
+ BOOST_CONTAINER_FORCEINLINE const Allocator &as_base() const
+ { return static_cast<const Allocator&>(*this); }
+
+ BOOST_CONTAINER_FORCEINLINE Allocator &as_base()
+ { return static_cast<Allocator&>(*this); }
+
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ public:
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ typedef allocator_traits<Allocator> allocator_traits_type;
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ typedef typename allocator_traits<Allocator>::value_type value_type;
+ typedef typename allocator_traits<Allocator>::pointer pointer;
+ typedef typename allocator_traits<Allocator>::const_pointer const_pointer;
+ typedef typename allocator_traits<Allocator>::reference reference;
+ typedef typename allocator_traits<Allocator>::const_reference const_reference;
+ typedef typename allocator_traits<Allocator>::size_type size_type;
+ typedef typename allocator_traits<Allocator>::difference_type difference_type;
+ typedef typename allocator_traits<Allocator>::void_pointer void_pointer;
+ typedef typename allocator_traits<Allocator>::const_void_pointer const_void_pointer;
+
+ typedef typename allocator_traits<Allocator>::propagate_on_container_copy_assignment propagate_on_container_copy_assignment;
+ typedef typename allocator_traits<Allocator>::propagate_on_container_move_assignment propagate_on_container_move_assignment;
+ typedef typename allocator_traits<Allocator>::propagate_on_container_swap propagate_on_container_swap;
+ //! An integral constant with member `value == false`
+ typedef BOOST_CONTAINER_IMPDEF(dtl::bool_<false>) is_always_equal;
+ //! An integral constant with member `value == true`
+ typedef BOOST_CONTAINER_IMPDEF(dtl::bool_<true>) is_partially_propagable;
+
+ BOOST_CONTAINER_DOCIGN(typedef dtl::version_type<small_vector_allocator BOOST_CONTAINER_I 1> version;)
+
+ //!Obtains an small_vector_allocator that allocates
+ //!objects of type T2
+ template<class T2>
+ struct rebind
+ {
+ typedef typename allocator_traits<Allocator>::template rebind_alloc<T2>::type other;
+ };
+
+ #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ //!Constructor from arbitrary arguments
+ template<class ...Args>
+ BOOST_CONTAINER_FORCEINLINE explicit small_vector_allocator(BOOST_FWD_REF(Args) ...args)
+ : Allocator(::boost::forward<Args>(args)...)
+ {}
+ #else
+ #define BOOST_CONTAINER_SMALL_VECTOR_ALLOCATOR_CTOR_CODE(N) \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ BOOST_CONTAINER_FORCEINLINE explicit small_vector_allocator(BOOST_MOVE_UREF##N)\
+ : Allocator(BOOST_MOVE_FWD##N)\
+ {}\
+ //
+ BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SMALL_VECTOR_ALLOCATOR_CTOR_CODE)
+ #undef BOOST_CONTAINER_SMALL_VECTOR_ALLOCATOR_CTOR_CODE
+ #endif
+
+ //!Constructor from other small_vector_allocator.
+ //!Never throws
+ BOOST_CONTAINER_FORCEINLINE small_vector_allocator
+ (const small_vector_allocator &other) BOOST_NOEXCEPT_OR_NOTHROW
+ : Allocator(other.as_base())
+ {}
+
+ //!Move constructor from small_vector_allocator.
+ //!Never throws
+ BOOST_CONTAINER_FORCEINLINE small_vector_allocator
+ (BOOST_RV_REF(small_vector_allocator) other) BOOST_NOEXCEPT_OR_NOTHROW
+ : Allocator(::boost::move(other.as_base()))
+ {}
+
+ //!Constructor from related small_vector_allocator.
+ //!Never throws
+ template<class OtherAllocator>
+ BOOST_CONTAINER_FORCEINLINE small_vector_allocator
+ (const small_vector_allocator<OtherAllocator> &other) BOOST_NOEXCEPT_OR_NOTHROW
+ : Allocator(other.as_base())
+ {}
+
+ //!Move constructor from related small_vector_allocator.
+ //!Never throws
+ template<class OtherAllocator>
+ BOOST_CONTAINER_FORCEINLINE small_vector_allocator
+ (BOOST_RV_REF(small_vector_allocator<OtherAllocator>) other) BOOST_NOEXCEPT_OR_NOTHROW
+ : Allocator(::boost::move(other.as_base()))
+ {}
+
+ //!Assignment from other small_vector_allocator.
+ //!Never throws
+ BOOST_CONTAINER_FORCEINLINE small_vector_allocator &
+ operator=(BOOST_COPY_ASSIGN_REF(small_vector_allocator) other) BOOST_NOEXCEPT_OR_NOTHROW
+ { return static_cast<small_vector_allocator&>(this->Allocator::operator=(other.as_base())); }
+
+ //!Move constructor from other small_vector_allocator.
+ //!Never throws
+ BOOST_CONTAINER_FORCEINLINE small_vector_allocator &
+ operator=(BOOST_RV_REF(small_vector_allocator) other) BOOST_NOEXCEPT_OR_NOTHROW
+ { return static_cast<small_vector_allocator&>(this->Allocator::operator=(::boost::move(other.as_base()))); }
+
+ //!Assignment from related small_vector_allocator.
+ //!Never throws
+ template<class OtherAllocator>
+ BOOST_CONTAINER_FORCEINLINE small_vector_allocator &
+ operator=(BOOST_COPY_ASSIGN_REF(small_vector_allocator<OtherAllocator>) other) BOOST_NOEXCEPT_OR_NOTHROW
+ { return static_cast<small_vector_allocator&>(this->Allocator::operator=(other.as_base())); }
+
+ //!Move assignment from related small_vector_allocator.
+ //!Never throws
+ template<class OtherAllocator>
+ BOOST_CONTAINER_FORCEINLINE small_vector_allocator &
+ operator=(BOOST_RV_REF(small_vector_allocator<OtherAllocator>) other) BOOST_NOEXCEPT_OR_NOTHROW
+ { return static_cast<small_vector_allocator&>(this->Allocator::operator=(::boost::move(other.as_base()))); }
+
+ //!Allocates storage from the standard-conforming allocator
+ BOOST_CONTAINER_FORCEINLINE pointer allocate(size_type count, const_void_pointer hint = const_void_pointer())
+ { return allocator_traits_type::allocate(this->as_base(), count, hint); }
+
+ //!Deallocates previously allocated memory.
+ //!Never throws
+ void deallocate(pointer ptr, size_type n) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ if(!this->is_internal_storage(ptr))
+ allocator_traits_type::deallocate(this->as_base(), ptr, n);
+ }
+
+ //!Returns the maximum number of elements that could be allocated.
+ //!Never throws
+ BOOST_CONTAINER_FORCEINLINE size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return allocator_traits_type::max_size(this->as_base()); }
+
+ small_vector_allocator select_on_container_copy_construction() const
+ { return small_vector_allocator(allocator_traits_type::select_on_container_copy_construction(this->as_base())); }
+
+ bool storage_is_unpropagable(pointer p) const
+ { return this->is_internal_storage(p) || allocator_traits_type::storage_is_unpropagable(this->as_base(), p); }
+
+ //!Swaps two allocators, does nothing
+ //!because this small_vector_allocator is stateless
+ BOOST_CONTAINER_FORCEINLINE friend void swap(small_vector_allocator &l, small_vector_allocator &r) BOOST_NOEXCEPT_OR_NOTHROW
+ { boost::adl_move_swap(l.as_base(), r.as_base()); }
+
+ //!An small_vector_allocator always compares to true, as memory allocated with one
+ //!instance can be deallocated by another instance (except for unpropagable storage)
+ BOOST_CONTAINER_FORCEINLINE friend bool operator==(const small_vector_allocator &l, const small_vector_allocator &r) BOOST_NOEXCEPT_OR_NOTHROW
+ { return allocator_traits_type::equal(l.as_base(), r.as_base()); }
+
+ //!An small_vector_allocator always compares to false, as memory allocated with one
+ //!instance can be deallocated by another instance
+ BOOST_CONTAINER_FORCEINLINE friend bool operator!=(const small_vector_allocator &l, const small_vector_allocator &r) BOOST_NOEXCEPT_OR_NOTHROW
+ { return !(l == r); }
+
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ /*
+ //!An advanced function that offers in-place expansion shrink to fit and new allocation
+ //!capabilities. Memory allocated with this function can only be deallocated with deallocate()
+ //!or deallocate_many().
+ //!This function is available only with Version == 2
+ pointer allocation_command(allocation_type command,
+ size_type limit_size,
+ size_type &prefer_in_recvd_out_size,
+ pointer &reuse)
+ { return allocator_traits_type::allocation_command(command, limit_size, prefer_in_recvd_out_size, reuse); }
+
+ //!Returns maximum the number of objects the previously allocated memory
+ //!pointed by p can hold.
+ //!Memory must not have been allocated with
+ //!allocate_one or allocate_individual.
+ //!This function is available only with Version == 2
+ size_type size(pointer p) const BOOST_NOEXCEPT_OR_NOTHROW
+ { return allocator_traits_type::size(p); }
+ */
+ private:
+ /*
+ //!Allocates just one object. Memory allocated with this function
+ //!must be deallocated only with deallocate_one().
+ //!Throws bad_alloc if there is no enough memory
+ //!This function is available only with Version == 2
+ using Allocator::allocate_one;
+ using Allocator::allocate_individual;
+ using Allocator::deallocate_one;
+ using Allocator::deallocate_individual;
+ using Allocator::allocate_many;
+ using Allocator::deallocate_many;*/
+
+ BOOST_CONTAINER_FORCEINLINE bool is_internal_storage(pointer p) const
+ { return this->internal_storage() == p; }
+
+ pointer internal_storage() const
+ {
+ typedef typename Allocator::value_type value_type;
+ typedef typename allocator_traits_type::size_type size_type;
+ typedef vector_alloc_holder< small_vector_allocator<Allocator>, size_type > vector_alloc_holder_t;
+ typedef vector<value_type, small_vector_allocator<Allocator> > vector_base;
+ typedef small_vector_base<value_type, Allocator> derived_type;
+ //
+ const vector_alloc_holder_t &v_holder = static_cast<const vector_alloc_holder_t &>(*this);
+ const vector_base &v_base = reinterpret_cast<const vector_base &>(v_holder);
+ const derived_type &d_base = static_cast<const derived_type &>(v_base);
+ return d_base.internal_storage();
+ }
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+};
+
+//! This class consists of common code from all small_vector<T, N> types that don't depend on the
+//! "N" template parameter. This class is non-copyable and non-destructible, so this class typically
+//! used as reference argument to functions that read or write small vectors. Since `small_vector<T, N>`
+//! derives from `small_vector_base<T>`, the conversion to `small_vector_base` is implicit
+//! <pre>
+//!
+//! //Clients can pass any small_vector<Foo, N>.
+//! void read_any_small_vector_of_foo(const small_vector_base<Foo> &in_parameter);
+//!
+//! void modify_any_small_vector_of_foo(small_vector_base<Foo> &in_out_parameter);
+//!
+//! void some_function()
+//! {
+//!
+//! small_vector<Foo, 8> myvector;
+//!
+//! read_any_small_vector_of_foo(myvector); // Reads myvector
+//!
+//! modify_any_small_vector_of_foo(myvector); // Modifies myvector
+//!
+//! }
+//! </pre>
+//!
+//! All `boost::container:vector` member functions are inherited. See `vector` documentation for details.
+//!
+template <class T, class SecondaryAllocator>
+class small_vector_base
+ : public vector<T, small_vector_allocator<SecondaryAllocator> >
+{
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ public:
+ //Make it public as it will be inherited by small_vector and container
+ //must have this public member
+ typedef typename allocator_traits<SecondaryAllocator>::pointer pointer;
+
+ private:
+ BOOST_COPYABLE_AND_MOVABLE(small_vector_base)
+
+ friend class small_vector_allocator<SecondaryAllocator>;
+
+ pointer internal_storage() const BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ return boost::intrusive::pointer_traits<pointer>::pointer_to
+ (*const_cast<T*>(static_cast<const T*>(static_cast<const void*>(m_storage_start.data))));
+ }
+
+ typedef vector<T, small_vector_allocator<SecondaryAllocator> > base_type;
+ base_type &as_base() { return static_cast<base_type&>(*this); }
+ const base_type &as_base() const { return static_cast<const base_type&>(*this); }
+
+ public:
+ typedef typename dtl::aligned_storage
+ <sizeof(T), dtl::alignment_of<T>::value>::type storage_type;
+ typedef small_vector_allocator<SecondaryAllocator> allocator_type;
+
+ protected:
+
+ BOOST_CONTAINER_FORCEINLINE explicit small_vector_base(initial_capacity_t, std::size_t initial_capacity)
+ : base_type(initial_capacity_t(), this->internal_storage(), initial_capacity)
+ {}
+
+ template<class AllocFwd>
+ BOOST_CONTAINER_FORCEINLINE explicit small_vector_base(initial_capacity_t, std::size_t capacity, BOOST_FWD_REF(AllocFwd) a)
+ : base_type(initial_capacity_t(), this->internal_storage(), capacity, ::boost::forward<AllocFwd>(a))
+ {}
+
+ //~small_vector_base(){}
+
+ private:
+ //The only member
+ storage_type m_storage_start;
+
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ public:
+ BOOST_CONTAINER_FORCEINLINE small_vector_base& operator=(BOOST_COPY_ASSIGN_REF(small_vector_base) other)
+ { return static_cast<small_vector_base&>(this->base_type::operator=(static_cast<base_type const&>(other))); }
+
+ BOOST_CONTAINER_FORCEINLINE small_vector_base& operator=(BOOST_RV_REF(small_vector_base) other)
+ { return static_cast<small_vector_base&>(this->base_type::operator=(BOOST_MOVE_BASE(base_type, other))); }
+
+ BOOST_CONTAINER_FORCEINLINE void swap(small_vector_base &other)
+ { return this->base_type::swap(other); }
+
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ protected:
+ void move_construct_impl(base_type &x, const allocator_type &a)
+ {
+ if(base_type::is_propagable_from(x.get_stored_allocator(), x.data(), a, true)){
+ this->steal_resources(x);
+ }
+ else{
+ this->assign( boost::make_move_iterator(boost::movelib::iterator_to_raw_pointer(x.begin()))
+ , boost::make_move_iterator(boost::movelib::iterator_to_raw_pointer(x.end ()))
+ );
+ }
+ }
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+};
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+/////////////////////////////////////////////////////
+//
+// small_vector_storage_calculator
+//
+/////////////////////////////////////////////////////
+template<std::size_t Needed, std::size_t Hdr, std::size_t SSize, bool NeedsZero = (0u == Needed || Needed <= Hdr)>
+struct small_vector_storage_calculator_helper
+{
+ static const std::size_t value = (Needed - Hdr - 1u)/SSize + 1u;
+};
+
+template<std::size_t Needed, std::size_t Hdr, std::size_t SSize>
+struct small_vector_storage_calculator_helper<Needed, Hdr, SSize, true>
+{
+ static const std::size_t value = 0u;
+};
+
+template<class Storage, class Allocator, class T, std::size_t N>
+struct small_vector_storage_calculator
+{
+ typedef small_vector_base<T, Allocator> svh_type;
+ typedef vector<T, small_vector_allocator<Allocator> > svhb_type;
+ static const std::size_t s_align = dtl::alignment_of<Storage>::value;
+ static const std::size_t s_size = sizeof(Storage);
+ static const std::size_t svh_sizeof = sizeof(svh_type);
+ static const std::size_t svhb_sizeof = sizeof(svhb_type);
+ static const std::size_t s_start = ((svhb_sizeof-1)/s_align+1)*s_align;
+ static const std::size_t header_bytes = svh_sizeof-s_start;
+ static const std::size_t needed_bytes = sizeof(T)*N;
+ static const std::size_t needed_extra_storages =
+ small_vector_storage_calculator_helper<needed_bytes, header_bytes, s_size>::value;
+};
+
+/////////////////////////////////////////////////////
+//
+// small_vector_storage_definer
+//
+/////////////////////////////////////////////////////
+template<class Storage, std::size_t N>
+struct small_vector_storage
+{
+ Storage m_rest_of_storage[N];
+};
+
+template<class Storage>
+struct small_vector_storage<Storage, 0>
+{};
+
+template<class Allocator, std::size_t N>
+struct small_vector_storage_definer
+{
+ typedef typename Allocator::value_type value_type;
+ typedef typename small_vector_base<value_type, Allocator>::storage_type storage_type;
+ static const std::size_t needed_extra_storages =
+ small_vector_storage_calculator<storage_type, Allocator, value_type, N>::needed_extra_storages;
+ typedef small_vector_storage<storage_type, needed_extra_storages> type;
+};
+
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+//! small_vector is a vector-like container optimized for the case when it contains few elements.
+//! It contains some preallocated elements in-place, which can avoid the use of dynamic storage allocation
+//! when the actual number of elements is below that preallocated threshold.
+//!
+//! `small_vector<T, N, Allocator>` is convertible to `small_vector_base<T, Allocator>` that is independent
+//! from the preallocated element capacity, so client code does not need to be templated on that N argument.
+//!
+//! All `boost::container::vector` member functions are inherited. See `vector` documentation for details.
+//!
+//! \tparam T The type of object that is stored in the small_vector
+//! \tparam N The number of preallocated elements stored inside small_vector. It shall be less than Allocator::max_size();
+//! \tparam Allocator The allocator used for memory management when the number of elements exceeds N.
+template <class T, std::size_t N, class Allocator BOOST_CONTAINER_DOCONLY(= new_allocator<T>) >
+class small_vector : public small_vector_base<T, Allocator>
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ , private small_vector_storage_definer<Allocator, N>::type
+ #endif
+{
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ typedef small_vector_base<T, Allocator> base_type;
+ typedef typename small_vector_storage_definer<Allocator, N>::type remaining_storage_holder;
+
+ BOOST_COPYABLE_AND_MOVABLE(small_vector)
+
+ typedef allocator_traits<typename base_type::allocator_type> allocator_traits_type;
+
+ public:
+ typedef small_vector_storage_calculator< typename small_vector_base<T, Allocator>
+ ::storage_type, Allocator, T, N> storage_test;
+
+ static const std::size_t needed_extra_storages = storage_test::needed_extra_storages;
+ static const std::size_t needed_bytes = storage_test::needed_bytes;
+ static const std::size_t header_bytes = storage_test::header_bytes;
+ static const std::size_t s_start = storage_test::s_start;
+
+ typedef typename base_type::allocator_type allocator_type;
+ typedef typename base_type::size_type size_type;
+ typedef typename base_type::value_type value_type;
+
+ BOOST_CONTAINER_FORCEINLINE static std::size_t internal_capacity()
+ { return (sizeof(small_vector) - storage_test::s_start)/sizeof(T); }
+
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ //! @brief The capacity/max size of the container
+ static const size_type static_capacity = N;
+
+ public:
+ BOOST_CONTAINER_FORCEINLINE small_vector()
+ BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<Allocator>::value)
+ : base_type(initial_capacity_t(), internal_capacity())
+ {}
+
+ BOOST_CONTAINER_FORCEINLINE explicit small_vector(const allocator_type &a)
+ : base_type(initial_capacity_t(), internal_capacity(), a)
+ {}
+
+ BOOST_CONTAINER_FORCEINLINE explicit small_vector(size_type n)
+ : base_type(initial_capacity_t(), internal_capacity())
+ { this->resize(n); }
+
+ BOOST_CONTAINER_FORCEINLINE small_vector(size_type n, const allocator_type &a)
+ : base_type(initial_capacity_t(), internal_capacity(), a)
+ { this->resize(n); }
+
+ BOOST_CONTAINER_FORCEINLINE small_vector(size_type n, default_init_t)
+ : base_type(initial_capacity_t(), internal_capacity())
+ { this->resize(n, default_init_t()); }
+
+ BOOST_CONTAINER_FORCEINLINE small_vector(size_type n, default_init_t, const allocator_type &a)
+ : base_type(initial_capacity_t(), internal_capacity(), a)
+ { this->resize(n, default_init_t()); }
+
+ BOOST_CONTAINER_FORCEINLINE small_vector(size_type n, const value_type &v)
+ : base_type(initial_capacity_t(), internal_capacity())
+ { this->resize(n, v); }
+
+ BOOST_CONTAINER_FORCEINLINE small_vector(size_type n, const value_type &v, const allocator_type &a)
+ : base_type(initial_capacity_t(), internal_capacity(), a)
+ { this->resize(n, v); }
+
+ template <class InIt>
+ BOOST_CONTAINER_FORCEINLINE small_vector(InIt first, InIt last
+ BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_c
+ < dtl::is_convertible<InIt BOOST_MOVE_I size_type>::value
+ BOOST_MOVE_I dtl::nat >::type * = 0)
+ )
+ : base_type(initial_capacity_t(), internal_capacity())
+ { this->assign(first, last); }
+
+ template <class InIt>
+ BOOST_CONTAINER_FORCEINLINE small_vector(InIt first, InIt last, const allocator_type& a
+ BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_c
+ < dtl::is_convertible<InIt BOOST_MOVE_I size_type>::value
+ BOOST_MOVE_I dtl::nat >::type * = 0)
+ )
+ : base_type(initial_capacity_t(), internal_capacity(), a)
+ { this->assign(first, last); }
+
+ BOOST_CONTAINER_FORCEINLINE small_vector(const small_vector &other)
+ : base_type( initial_capacity_t(), internal_capacity()
+ , allocator_traits_type::select_on_container_copy_construction(other.get_stored_allocator()))
+ { this->assign(other.cbegin(), other.cend()); }
+
+ BOOST_CONTAINER_FORCEINLINE small_vector(const small_vector &other, const allocator_type &a)
+ : base_type(initial_capacity_t(), internal_capacity(), a)
+ { this->assign(other.cbegin(), other.cend()); }
+
+ BOOST_CONTAINER_FORCEINLINE explicit small_vector(const base_type &other)
+ : base_type( initial_capacity_t(), internal_capacity()
+ , allocator_traits_type::select_on_container_copy_construction(other.get_stored_allocator()))
+ { this->assign(other.cbegin(), other.cend()); }
+
+ BOOST_CONTAINER_FORCEINLINE explicit small_vector(BOOST_RV_REF(base_type) other)
+ : base_type(initial_capacity_t(), internal_capacity(), ::boost::move(other.get_stored_allocator()))
+ { this->move_construct_impl(other, other.get_stored_allocator()); }
+
+ BOOST_CONTAINER_FORCEINLINE small_vector(BOOST_RV_REF(small_vector) other)
+ : base_type(initial_capacity_t(), internal_capacity(), ::boost::move(other.get_stored_allocator()))
+ { this->move_construct_impl(other, other.get_stored_allocator()); }
+
+ BOOST_CONTAINER_FORCEINLINE small_vector(BOOST_RV_REF(small_vector) other, const allocator_type &a)
+ : base_type(initial_capacity_t(), internal_capacity(), a)
+ { this->move_construct_impl(other, a); }
+
+ #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ BOOST_CONTAINER_FORCEINLINE small_vector(std::initializer_list<value_type> il, const allocator_type& a = allocator_type())
+ : base_type(initial_capacity_t(), internal_capacity(), a)
+ {
+ this->assign(il.begin(), il.end());
+ }
+ #endif
+
+ BOOST_CONTAINER_FORCEINLINE small_vector& operator=(BOOST_COPY_ASSIGN_REF(small_vector) other)
+ { return static_cast<small_vector&>(this->base_type::operator=(static_cast<base_type const&>(other))); }
+
+ BOOST_CONTAINER_FORCEINLINE small_vector& operator=(BOOST_RV_REF(small_vector) other)
+ { return static_cast<small_vector&>(this->base_type::operator=(BOOST_MOVE_BASE(base_type, other))); }
+
+ BOOST_CONTAINER_FORCEINLINE small_vector& operator=(const base_type &other)
+ { return static_cast<small_vector&>(this->base_type::operator=(other)); }
+
+ BOOST_CONTAINER_FORCEINLINE small_vector& operator=(BOOST_RV_REF(base_type) other)
+ { return static_cast<small_vector&>(this->base_type::operator=(boost::move(other))); }
+
+ BOOST_CONTAINER_FORCEINLINE void swap(small_vector &other)
+ { return this->base_type::swap(other); }
+};
+
+}}
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+/*
+namespace boost {
+
+//!has_trivial_destructor_after_move<> == true_type
+//!specialization for optimizations
+template <class T, class Allocator>
+struct has_trivial_destructor_after_move<boost::container::vector<T, Allocator> >
+{
+ typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer;
+ static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value &&
+ ::boost::has_trivial_destructor_after_move<pointer>::value;
+};
+
+}
+*/
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif // #ifndef BOOST_CONTAINER_CONTAINER_SMALL_VECTOR_HPP
diff --git a/include/boost/container/stable_vector.hpp b/include/boost/container/stable_vector.hpp
new file mode 100644
index 0000000..41f45df
--- /dev/null
+++ b/include/boost/container/stable_vector.hpp
@@ -0,0 +1,2124 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2008-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.
+//
+//////////////////////////////////////////////////////////////////////////////
+// Stable vector.
+//
+// Copyright 2008 Joaquin M Lopez Munoz.
+// 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)
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_STABLE_VECTOR_HPP
+#define BOOST_CONTAINER_STABLE_VECTOR_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+
+// container
+#include <boost/container/allocator_traits.hpp>
+#include <boost/container/container_fwd.hpp>
+#include <boost/container/new_allocator.hpp> //new_allocator
+#include <boost/container/throw_exception.hpp>
+// container/detail
+#include <boost/container/detail/addressof.hpp>
+#include <boost/container/detail/algorithm.hpp> //algo_equal(), algo_lexicographical_compare
+#include <boost/container/detail/alloc_helpers.hpp>
+#include <boost/container/detail/allocator_version_traits.hpp>
+#include <boost/container/detail/construct_in_place.hpp>
+#include <boost/container/detail/iterator.hpp>
+#include <boost/container/detail/iterators.hpp>
+#include <boost/container/detail/placement_new.hpp>
+#include <boost/move/detail/to_raw_pointer.hpp>
+#include <boost/container/detail/type_traits.hpp>
+// intrusive
+#include <boost/intrusive/pointer_traits.hpp>
+// intrusive/detail
+#include <boost/intrusive/detail/minimal_pair_header.hpp> //pair
+// move
+#include <boost/move/utility_core.hpp>
+#include <boost/move/iterator.hpp>
+#include <boost/move/adl_move_swap.hpp>
+// move/detail
+#include <boost/move/detail/move_helpers.hpp>
+// other
+#include <boost/assert.hpp>
+#include <boost/core/no_exceptions_support.hpp>
+// std
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+#include <initializer_list>
+#endif
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ #include <boost/container/vector.hpp>
+ //#define STABLE_VECTOR_ENABLE_INVARIANT_CHECKING
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+namespace boost {
+namespace container {
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+namespace stable_vector_detail{
+
+template <class C>
+class clear_on_destroy
+{
+ public:
+ clear_on_destroy(C &c)
+ : c_(c), do_clear_(true)
+ {}
+
+ void release()
+ { do_clear_ = false; }
+
+ ~clear_on_destroy()
+ {
+ if(do_clear_){
+ c_.clear();
+ c_.priv_clear_pool();
+ }
+ }
+
+ private:
+ clear_on_destroy(const clear_on_destroy &);
+ clear_on_destroy &operator=(const clear_on_destroy &);
+ C &c_;
+ bool do_clear_;
+};
+
+template<typename Pointer>
+struct node;
+
+template<class VoidPtr>
+struct node_base
+{
+ private:
+ typedef typename boost::intrusive::
+ pointer_traits<VoidPtr> void_ptr_traits;
+ typedef typename void_ptr_traits::
+ template rebind_pointer
+ <node_base>::type node_base_ptr;
+ typedef typename void_ptr_traits::
+ template rebind_pointer
+ <node_base_ptr>::type node_base_ptr_ptr;
+
+ public:
+ node_base(const node_base_ptr_ptr &n)
+ : up(n)
+ {}
+
+ node_base()
+ : up()
+ {}
+
+ node_base_ptr_ptr up;
+};
+
+template<typename Pointer>
+struct node
+ : public node_base
+ <typename ::boost::intrusive::pointer_traits<Pointer>::template
+ rebind_pointer<void>::type
+ >
+{
+ private:
+ node();
+
+ public:
+ typename ::boost::intrusive::pointer_traits<Pointer>::element_type value;
+};
+
+template<class VoidPtr, class VoidAllocator>
+struct index_traits
+{
+ typedef boost::intrusive::
+ pointer_traits
+ <VoidPtr> void_ptr_traits;
+ typedef stable_vector_detail::
+ node_base<VoidPtr> node_base_type;
+ typedef typename void_ptr_traits::template
+ rebind_pointer<node_base_type>::type node_base_ptr;
+ typedef typename void_ptr_traits::template
+ rebind_pointer<node_base_ptr>::type node_base_ptr_ptr;
+ typedef boost::intrusive::
+ pointer_traits<node_base_ptr> node_base_ptr_traits;
+ typedef boost::intrusive::
+ pointer_traits<node_base_ptr_ptr> node_base_ptr_ptr_traits;
+ typedef typename allocator_traits<VoidAllocator>::
+ template portable_rebind_alloc
+ <node_base_ptr>::type node_base_ptr_allocator;
+ typedef ::boost::container::vector
+ <node_base_ptr, node_base_ptr_allocator> index_type;
+ typedef typename index_type::iterator index_iterator;
+ typedef typename index_type::const_iterator const_index_iterator;
+ typedef typename index_type::size_type size_type;
+
+ static const size_type ExtraPointers = 3;
+ //Stable vector stores metadata at the end of the index (node_base_ptr vector) with additional 3 pointers:
+ // back() is this->index.back() - ExtraPointers;
+ // end node index is *(this->index.end() - 3)
+ // Node cache first is *(this->index.end() - 2);
+ // Node cache last is this->index.back();
+
+ static node_base_ptr_ptr ptr_to_node_base_ptr(node_base_ptr &n)
+ { return node_base_ptr_ptr_traits::pointer_to(n); }
+
+ static void fix_up_pointers(index_iterator first, index_iterator last)
+ {
+ while(first != last){
+ typedef typename index_type::reference node_base_ptr_ref;
+ node_base_ptr_ref nbp = *first;
+ nbp->up = index_traits::ptr_to_node_base_ptr(nbp);
+ ++first;
+ }
+ }
+
+ static index_iterator get_fix_up_end(index_type &index)
+ { return index.end() - (ExtraPointers - 1); }
+
+ static void fix_up_pointers_from(index_type & index, index_iterator first)
+ { index_traits::fix_up_pointers(first, index_traits::get_fix_up_end(index)); }
+
+ static void readjust_end_node(index_type &index, node_base_type &end_node)
+ {
+ if(!index.empty()){
+ index_iterator end_node_it(index_traits::get_fix_up_end(index));
+ node_base_ptr &end_node_idx_ref = *(--end_node_it);
+ end_node_idx_ref = node_base_ptr_traits::pointer_to(end_node);
+ end_node.up = node_base_ptr_ptr_traits::pointer_to(end_node_idx_ref);
+ }
+ else{
+ end_node.up = node_base_ptr_ptr();
+ }
+ }
+
+ static void initialize_end_node(index_type &index, node_base_type &end_node, const size_type index_capacity_if_empty)
+ {
+ if(index.empty()){
+ index.reserve(index_capacity_if_empty + ExtraPointers);
+ index.resize(ExtraPointers);
+ node_base_ptr &end_node_ref = *index.data();
+ end_node_ref = node_base_ptr_traits::pointer_to(end_node);
+ end_node.up = index_traits::ptr_to_node_base_ptr(end_node_ref);
+ }
+ }
+
+ #ifdef STABLE_VECTOR_ENABLE_INVARIANT_CHECKING
+ static bool invariants(index_type &index)
+ {
+ for( index_iterator it = index.begin()
+ , it_end = index_traits::get_fix_up_end(index)
+ ; it != it_end
+ ; ++it){
+ if((*it)->up != index_traits::ptr_to_node_base_ptr(*it)){
+ return false;
+ }
+ }
+ return true;
+ }
+ #endif //STABLE_VECTOR_ENABLE_INVARIANT_CHECKING
+};
+
+} //namespace stable_vector_detail
+
+template<typename Pointer, bool IsConst>
+class stable_vector_iterator
+{
+ typedef boost::intrusive::pointer_traits<Pointer> non_const_ptr_traits;
+ public:
+ typedef std::random_access_iterator_tag iterator_category;
+ typedef typename non_const_ptr_traits::element_type value_type;
+ typedef typename non_const_ptr_traits::difference_type difference_type;
+ typedef typename ::boost::container::dtl::if_c
+ < IsConst
+ , typename non_const_ptr_traits::template
+ rebind_pointer<const value_type>::type
+ , Pointer
+ >::type pointer;
+ typedef boost::intrusive::pointer_traits<pointer> ptr_traits;
+ typedef typename ptr_traits::reference reference;
+
+ private:
+ typedef typename non_const_ptr_traits::template
+ rebind_pointer<void>::type void_ptr;
+ typedef stable_vector_detail::node<Pointer> node_type;
+ typedef stable_vector_detail::node_base<void_ptr> node_base_type;
+ typedef typename non_const_ptr_traits::template
+ rebind_pointer<node_type>::type node_ptr;
+ typedef boost::intrusive::
+ pointer_traits<node_ptr> node_ptr_traits;
+ typedef typename non_const_ptr_traits::template
+ rebind_pointer<node_base_type>::type node_base_ptr;
+ typedef typename non_const_ptr_traits::template
+ rebind_pointer<node_base_ptr>::type node_base_ptr_ptr;
+
+ node_base_ptr m_pn;
+
+ public:
+
+ explicit stable_vector_iterator(node_base_ptr p) BOOST_NOEXCEPT_OR_NOTHROW
+ : m_pn(p)
+ {}
+
+ stable_vector_iterator() BOOST_NOEXCEPT_OR_NOTHROW
+ : m_pn() //Value initialization to achieve "null iterators" (N3644)
+ {}
+
+ stable_vector_iterator(stable_vector_iterator<Pointer, false> const& other) BOOST_NOEXCEPT_OR_NOTHROW
+ : m_pn(other.node_pointer())
+ {}
+
+ node_ptr node_pointer() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return node_ptr_traits::static_cast_from(m_pn); }
+
+ public:
+ //Pointer like operators
+ reference operator*() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return node_pointer()->value; }
+
+ pointer operator->() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return ptr_traits::pointer_to(this->operator*()); }
+
+ //Increment / Decrement
+ stable_vector_iterator& operator++() BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ node_base_ptr_ptr p(this->m_pn->up);
+ this->m_pn = *(++p);
+ return *this;
+ }
+
+ stable_vector_iterator operator++(int) BOOST_NOEXCEPT_OR_NOTHROW
+ { stable_vector_iterator tmp(*this); ++*this; return stable_vector_iterator(tmp); }
+
+ stable_vector_iterator& operator--() BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ node_base_ptr_ptr p(this->m_pn->up);
+ this->m_pn = *(--p);
+ return *this;
+ }
+
+ stable_vector_iterator operator--(int) BOOST_NOEXCEPT_OR_NOTHROW
+ { stable_vector_iterator tmp(*this); --*this; return stable_vector_iterator(tmp); }
+
+ reference operator[](difference_type off) const BOOST_NOEXCEPT_OR_NOTHROW
+ { return node_ptr_traits::static_cast_from(this->m_pn->up[off])->value; }
+
+ stable_vector_iterator& operator+=(difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ if(off) this->m_pn = this->m_pn->up[off];
+ return *this;
+ }
+
+ friend stable_vector_iterator operator+(const stable_vector_iterator &left, difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ stable_vector_iterator tmp(left);
+ tmp += off;
+ return tmp;
+ }
+
+ friend stable_vector_iterator operator+(difference_type off, const stable_vector_iterator& right) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ stable_vector_iterator tmp(right);
+ tmp += off;
+ return tmp;
+ }
+
+ stable_vector_iterator& operator-=(difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
+ { *this += -off; return *this; }
+
+ friend stable_vector_iterator operator-(const stable_vector_iterator &left, difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ stable_vector_iterator tmp(left);
+ tmp -= off;
+ return tmp;
+ }
+
+ friend difference_type operator-(const stable_vector_iterator &left, const stable_vector_iterator &right) BOOST_NOEXCEPT_OR_NOTHROW
+ { return left.m_pn->up - right.m_pn->up; }
+
+ //Comparison operators
+ friend bool operator== (const stable_vector_iterator& l, const stable_vector_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
+ { return l.m_pn == r.m_pn; }
+
+ friend bool operator!= (const stable_vector_iterator& l, const stable_vector_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
+ { return l.m_pn != r.m_pn; }
+
+ friend bool operator< (const stable_vector_iterator& l, const stable_vector_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
+ { return l.m_pn->up < r.m_pn->up; }
+
+ friend bool operator<= (const stable_vector_iterator& l, const stable_vector_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
+ { return l.m_pn->up <= r.m_pn->up; }
+
+ friend bool operator> (const stable_vector_iterator& l, const stable_vector_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
+ { return l.m_pn->up > r.m_pn->up; }
+
+ friend bool operator>= (const stable_vector_iterator& l, const stable_vector_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
+ { return l.m_pn->up >= r.m_pn->up; }
+};
+
+ #if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING)
+
+ #define STABLE_VECTOR_CHECK_INVARIANT \
+ invariant_checker BOOST_JOIN(check_invariant_,__LINE__)(*this); \
+ BOOST_JOIN(check_invariant_,__LINE__).touch();
+
+ #else //STABLE_VECTOR_ENABLE_INVARIANT_CHECKING
+
+ #define STABLE_VECTOR_CHECK_INVARIANT
+
+ #endif //#if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING)
+
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+//! Originally developed by Joaquin M. Lopez Munoz, stable_vector is a std::vector
+//! drop-in replacement implemented as a node container, offering iterator and reference
+//! stability.
+//!
+//! Here are the details taken from the author's blog
+//! (<a href="http://bannalia.blogspot.com/2008/09/introducing-stablevector.html" >
+//! Introducing stable_vector</a>):
+//!
+//! We present stable_vector, a fully STL-compliant stable container that provides
+//! most of the features of std::vector except element contiguity.
+//!
+//! General properties: stable_vector satisfies all the requirements of a container,
+//! a reversible container and a sequence and provides all the optional operations
+//! present in std::vector. Like std::vector, iterators are random access.
+//! stable_vector does not provide element contiguity; in exchange for this absence,
+//! the container is stable, i.e. references and iterators to an element of a stable_vector
+//! remain valid as long as the element is not erased, and an iterator that has been
+//! assigned the return value of end() always remain valid until the destruction of
+//! the associated stable_vector.
+//!
+//! Operation complexity: The big-O complexities of stable_vector operations match
+//! exactly those of std::vector. In general, insertion/deletion is constant time at
+//! the end of the sequence and linear elsewhere. Unlike std::vector, stable_vector
+//! does not internally perform any value_type destruction, copy or assignment
+//! operations other than those exactly corresponding to the insertion of new
+//! elements or deletion of stored elements, which can sometimes compensate in terms
+//! of performance for the extra burden of doing more pointer manipulation and an
+//! additional allocation per element.
+//!
+//! Exception safety: As stable_vector does not internally copy elements around, some
+//! operations provide stronger exception safety guarantees than in std::vector.
+//!
+//! \tparam T The type of object that is stored in the stable_vector
+//! \tparam Allocator The allocator used for all internal memory management
+#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
+template <class T, class Allocator = new_allocator<T> >
+#else
+template <class T, class Allocator>
+#endif
+class stable_vector
+{
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ typedef allocator_traits<Allocator> allocator_traits_type;
+ typedef boost::intrusive::
+ pointer_traits
+ <typename allocator_traits_type::pointer> ptr_traits;
+ typedef typename ptr_traits::
+ template rebind_pointer<void>::type void_ptr;
+ typedef typename allocator_traits_type::
+ template portable_rebind_alloc
+ <void>::type void_allocator_type;
+ typedef stable_vector_detail::index_traits
+ <void_ptr, void_allocator_type> index_traits_type;
+ typedef typename index_traits_type::node_base_type node_base_type;
+ typedef typename index_traits_type::node_base_ptr node_base_ptr;
+ typedef typename index_traits_type::
+ node_base_ptr_ptr node_base_ptr_ptr;
+ typedef typename index_traits_type::
+ node_base_ptr_traits node_base_ptr_traits;
+ typedef typename index_traits_type::
+ node_base_ptr_ptr_traits node_base_ptr_ptr_traits;
+ typedef typename index_traits_type::index_type index_type;
+ typedef typename index_traits_type::index_iterator index_iterator;
+ typedef typename index_traits_type::
+ const_index_iterator const_index_iterator;
+ typedef stable_vector_detail::node
+ <typename ptr_traits::pointer> node_type;
+ typedef typename ptr_traits::template
+ rebind_pointer<node_type>::type node_ptr;
+ typedef boost::intrusive::
+ pointer_traits<node_ptr> node_ptr_traits;
+ typedef typename ptr_traits::template
+ rebind_pointer<const node_type>::type const_node_ptr;
+ typedef boost::intrusive::
+ pointer_traits<const_node_ptr> const_node_ptr_traits;
+ typedef typename node_ptr_traits::reference node_reference;
+ typedef typename const_node_ptr_traits::reference const_node_reference;
+
+ typedef ::boost::container::dtl::integral_constant
+ <unsigned, boost::container::dtl::
+ version<Allocator>::value> alloc_version;
+ typedef typename allocator_traits_type::
+ template portable_rebind_alloc
+ <node_type>::type node_allocator_type;
+
+ typedef ::boost::container::dtl::
+ allocator_version_traits<node_allocator_type> allocator_version_traits_t;
+ typedef typename allocator_version_traits_t::multiallocation_chain multiallocation_chain;
+
+ node_ptr allocate_one()
+ { return allocator_version_traits_t::allocate_one(this->priv_node_alloc()); }
+
+ void deallocate_one(const node_ptr &p)
+ { allocator_version_traits_t::deallocate_one(this->priv_node_alloc(), p); }
+
+ void allocate_individual(typename allocator_traits_type::size_type n, multiallocation_chain &m)
+ { allocator_version_traits_t::allocate_individual(this->priv_node_alloc(), n, m); }
+
+ void deallocate_individual(multiallocation_chain &holder)
+ { allocator_version_traits_t::deallocate_individual(this->priv_node_alloc(), holder); }
+
+ friend class stable_vector_detail::clear_on_destroy<stable_vector>;
+ typedef stable_vector_iterator
+ < typename allocator_traits<Allocator>::pointer
+ , false> iterator_impl;
+ typedef stable_vector_iterator
+ < typename allocator_traits<Allocator>::pointer
+ , true> const_iterator_impl;
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ public:
+
+ //////////////////////////////////////////////
+ //
+ // types
+ //
+ //////////////////////////////////////////////
+ typedef 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;
+ typedef typename ::boost::container::allocator_traits<Allocator>::const_reference const_reference;
+ typedef typename ::boost::container::allocator_traits<Allocator>::size_type size_type;
+ typedef typename ::boost::container::allocator_traits<Allocator>::difference_type difference_type;
+ typedef Allocator allocator_type;
+ typedef node_allocator_type stored_allocator_type;
+ typedef BOOST_CONTAINER_IMPDEF(iterator_impl) iterator;
+ typedef BOOST_CONTAINER_IMPDEF(const_iterator_impl) const_iterator;
+ typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<iterator>) reverse_iterator;
+ typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<const_iterator>) const_reverse_iterator;
+
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ private:
+ BOOST_COPYABLE_AND_MOVABLE(stable_vector)
+ static const size_type ExtraPointers = index_traits_type::ExtraPointers;
+
+ class insert_rollback;
+ friend class insert_rollback;
+
+ class push_back_rollback;
+ friend class push_back_rollback;
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ public:
+ //////////////////////////////////////////////
+ //
+ // construct/copy/destroy
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Default constructs a stable_vector.
+ //!
+ //! <b>Throws</b>: If allocator_type's default constructor throws.
+ //!
+ //! <b>Complexity</b>: Constant.
+ stable_vector() BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<Allocator>::value)
+ : internal_data(), index()
+ {
+ STABLE_VECTOR_CHECK_INVARIANT;
+ }
+
+ //! <b>Effects</b>: Constructs a stable_vector taking the allocator as parameter.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ explicit stable_vector(const allocator_type& al) BOOST_NOEXCEPT_OR_NOTHROW
+ : internal_data(al), index(al)
+ {
+ STABLE_VECTOR_CHECK_INVARIANT;
+ }
+
+ //! <b>Effects</b>: Constructs a stable_vector
+ //! and inserts n value initialized values.
+ //!
+ //! <b>Throws</b>: If allocator_type's default constructor
+ //! throws or T's default or copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to n.
+ explicit stable_vector(size_type n)
+ : internal_data(), index()
+ {
+ stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
+ this->resize(n);
+ STABLE_VECTOR_CHECK_INVARIANT;
+ cod.release();
+ }
+
+ //! <b>Effects</b>: Constructs a stable_vector
+ //! and inserts n default initialized values.
+ //!
+ //! <b>Throws</b>: If allocator_type's default constructor
+ //! throws or T's default or copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to n.
+ //!
+ //! <b>Note</b>: Non-standard extension
+ stable_vector(size_type n, default_init_t)
+ : internal_data(), index()
+ {
+ stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
+ this->resize(n, default_init);
+ STABLE_VECTOR_CHECK_INVARIANT;
+ cod.release();
+ }
+
+ //! <b>Effects</b>: Constructs a stable_vector that will use a copy of allocator a
+ //! and inserts n value initialized values.
+ //!
+ //! <b>Throws</b>: If allocator_type's default constructor
+ //! throws or T's default or copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to n.
+ explicit stable_vector(size_type n, const allocator_type &a)
+ : internal_data(), index(a)
+ {
+ stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
+ this->resize(n);
+ STABLE_VECTOR_CHECK_INVARIANT;
+ cod.release();
+ }
+
+ //! <b>Effects</b>: Constructs a stable_vector that will use a copy of allocator a
+ //! and inserts n default initialized values.
+ //!
+ //! <b>Throws</b>: If allocator_type's default constructor
+ //! throws or T's default or copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to n.
+ //!
+ //! <b>Note</b>: Non-standard extension
+ stable_vector(size_type n, default_init_t, const allocator_type &a)
+ : internal_data(), index(a)
+ {
+ stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
+ this->resize(n, default_init);
+ STABLE_VECTOR_CHECK_INVARIANT;
+ cod.release();
+ }
+
+ //! <b>Effects</b>: Constructs a stable_vector that will use a copy of allocator a
+ //! and inserts n copies of value.
+ //!
+ //! <b>Throws</b>: If allocator_type's default constructor
+ //! throws or T's default or copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to n.
+ stable_vector(size_type n, const T& t, const allocator_type& al = allocator_type())
+ : internal_data(al), index(al)
+ {
+ stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
+ this->insert(this->cend(), n, t);
+ STABLE_VECTOR_CHECK_INVARIANT;
+ cod.release();
+ }
+
+ //! <b>Effects</b>: Constructs a stable_vector that will use a copy of allocator a
+ //! and inserts a copy of the range [first, last) in the stable_vector.
+ //!
+ //! <b>Throws</b>: If allocator_type's default constructor
+ //! throws or T's constructor taking a dereferenced InIt throws.
+ //!
+ //! <b>Complexity</b>: Linear to the range [first, last).
+ template <class InputIterator>
+ stable_vector(InputIterator first,InputIterator last, const allocator_type& al = allocator_type())
+ : internal_data(al), index(al)
+ {
+ stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
+ this->insert(this->cend(), first, last);
+ STABLE_VECTOR_CHECK_INVARIANT;
+ cod.release();
+ }
+
+ //! <b>Effects</b>: Copy constructs a stable_vector.
+ //!
+ //! <b>Postcondition</b>: x == *this.
+ //!
+ //! <b>Complexity</b>: Linear to the elements x contains.
+ stable_vector(const stable_vector& x)
+ : internal_data(allocator_traits<node_allocator_type>::
+ select_on_container_copy_construction(x.priv_node_alloc()))
+ , index(allocator_traits<allocator_type>::
+ select_on_container_copy_construction(x.index.get_stored_allocator()))
+ {
+ stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
+ this->insert(this->cend(), x.begin(), x.end());
+ STABLE_VECTOR_CHECK_INVARIANT;
+ cod.release();
+ }
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Constructs a stable_vector that will use a copy of allocator a
+ //! and inserts a copy of the range [il.begin(), il.last()) in the stable_vector
+ //!
+ //! <b>Throws</b>: If allocator_type's default constructor
+ //! throws or T's constructor taking a dereferenced initializer_list iterator throws.
+ //!
+ //! <b>Complexity</b>: Linear to the range [il.begin(), il.end()).
+ stable_vector(std::initializer_list<value_type> il, const allocator_type& l = allocator_type())
+ : internal_data(l), index(l)
+ {
+ stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
+ insert(cend(), il.begin(), il.end());
+ STABLE_VECTOR_CHECK_INVARIANT;
+ cod.release();
+ }
+#endif
+
+ //! <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.
+ stable_vector(BOOST_RV_REF(stable_vector) x) BOOST_NOEXCEPT_OR_NOTHROW
+ : internal_data(boost::move(x.priv_node_alloc())), index(boost::move(x.index))
+ {
+ this->priv_swap_members(x);
+ }
+
+ //! <b>Effects</b>: Copy constructs a stable_vector using the specified allocator.
+ //!
+ //! <b>Postcondition</b>: x == *this.
+ //!
+ //! <b>Complexity</b>: Linear to the elements x contains.
+ stable_vector(const stable_vector& x, const allocator_type &a)
+ : internal_data(a), index(a)
+ {
+ stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
+ this->insert(this->cend(), x.begin(), x.end());
+ STABLE_VECTOR_CHECK_INVARIANT;
+ cod.release();
+ }
+
+ //! <b>Effects</b>: Move constructor using the specified allocator.
+ //! Moves x's resources to *this.
+ //!
+ //! <b>Throws</b>: If allocator_type's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise
+ stable_vector(BOOST_RV_REF(stable_vector) x, const allocator_type &a)
+ : internal_data(a), index(a)
+ {
+ if(this->priv_node_alloc() == x.priv_node_alloc()){
+ this->index.swap(x.index);
+ this->priv_swap_members(x);
+ }
+ else{
+ stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
+ this->insert(this->cend(), boost::make_move_iterator(x.begin()), boost::make_move_iterator(x.end()));
+ STABLE_VECTOR_CHECK_INVARIANT;
+ cod.release();
+ }
+ }
+
+ //! <b>Effects</b>: Destroys the stable_vector. All stored values are destroyed
+ //! and used memory is deallocated.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements.
+ ~stable_vector()
+ {
+ this->clear();
+ this->priv_clear_pool();
+ }
+
+ //! <b>Effects</b>: Makes *this contain the same elements as x.
+ //!
+ //! <b>Postcondition</b>: this->size() == x.size(). *this contains a copy
+ //! of each of x's elements.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in x.
+ stable_vector& operator=(BOOST_COPY_ASSIGN_REF(stable_vector) x)
+ {
+ STABLE_VECTOR_CHECK_INVARIANT;
+ if (&x != this){
+ node_allocator_type &this_alloc = this->priv_node_alloc();
+ const node_allocator_type &x_alloc = x.priv_node_alloc();
+ dtl::bool_<allocator_traits_type::
+ propagate_on_container_copy_assignment::value> flag;
+ if(flag && this_alloc != x_alloc){
+ this->clear();
+ this->shrink_to_fit();
+ }
+ dtl::assign_alloc(this->priv_node_alloc(), x.priv_node_alloc(), flag);
+ dtl::assign_alloc(this->index.get_stored_allocator(), x.index.get_stored_allocator(), flag);
+ this->assign(x.begin(), x.end());
+ }
+ return *this;
+ }
+
+ //! <b>Effects</b>: Move assignment. All x's values are transferred to *this.
+ //!
+ //! <b>Postcondition</b>: x.empty(). *this contains a the elements x had
+ //! before the function.
+ //!
+ //! <b>Throws</b>: If allocator_traits_type::propagate_on_container_move_assignment
+ //! is false and (allocation throws or T's move constructor throws)
+ //!
+ //! <b>Complexity</b>: Constant if allocator_traits_type::
+ //! propagate_on_container_move_assignment is true or
+ //! this->get>allocator() == x.get_allocator(). Linear otherwise.
+ stable_vector& operator=(BOOST_RV_REF(stable_vector) x)
+ BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value
+ || allocator_traits_type::is_always_equal::value)
+ {
+ //for move constructor, no aliasing (&x != this) is assummed.
+ BOOST_ASSERT(this != &x);
+ node_allocator_type &this_alloc = this->priv_node_alloc();
+ node_allocator_type &x_alloc = x.priv_node_alloc();
+ const bool propagate_alloc = allocator_traits_type::
+ propagate_on_container_move_assignment::value;
+ dtl::bool_<propagate_alloc> flag;
+ const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
+ //Resources can be transferred if both allocators are
+ //going to be equal after this function (either propagated or already equal)
+ if(propagate_alloc || allocators_equal){
+ STABLE_VECTOR_CHECK_INVARIANT
+ //Destroy objects but retain memory in case x reuses it in the future
+ this->clear();
+ //Move allocator if needed
+ dtl::move_alloc(this_alloc, x_alloc, flag);
+ //Take resources
+ this->index.swap(x.index);
+ this->priv_swap_members(x);
+ }
+ //Else do a one by one move
+ else{
+ this->assign( boost::make_move_iterator(x.begin())
+ , boost::make_move_iterator(x.end()));
+ }
+ return *this;
+ }
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Make *this container contains elements from il.
+ //!
+ //! <b>Complexity</b>: Linear to the range [il.begin(), il.end()).
+ stable_vector& operator=(std::initializer_list<value_type> il)
+ {
+ STABLE_VECTOR_CHECK_INVARIANT;
+ assign(il.begin(), il.end());
+ return *this;
+ }
+#endif
+
+ //! <b>Effects</b>: Assigns the n copies of val to *this.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to n.
+ void assign(size_type n, const T& t)
+ {
+ typedef constant_iterator<value_type, difference_type> cvalue_iterator;
+ this->assign(cvalue_iterator(t, n), cvalue_iterator());
+ }
+
+ //! <b>Effects</b>: Assigns the the range [first, last) to *this.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or
+ //! T's constructor from dereferencing InpIt throws.
+ //!
+ //! <b>Complexity</b>: Linear to n.
+ template<typename InputIterator>
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ typename dtl::disable_if_convertible<InputIterator, size_type>::type
+ #else
+ void
+ #endif
+ assign(InputIterator first,InputIterator last)
+ {
+ STABLE_VECTOR_CHECK_INVARIANT;
+ iterator first1 = this->begin();
+ iterator last1 = this->end();
+ for ( ; first1 != last1 && first != last; ++first1, ++first)
+ *first1 = *first;
+ if (first == last){
+ this->erase(first1, last1);
+ }
+ else{
+ this->insert(last1, first, last);
+ }
+ }
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Assigns the the range [il.begin(), il.end()) to *this.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or
+ //! T's constructor from dereferencing initializer_list iterator throws.
+ //!
+ void assign(std::initializer_list<value_type> il)
+ {
+ STABLE_VECTOR_CHECK_INVARIANT;
+ assign(il.begin(), il.end());
+ }
+#endif
+
+ //! <b>Effects</b>: Returns a copy of the internal allocator.
+ //!
+ //! <b>Throws</b>: If allocator's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Constant.
+ allocator_type get_allocator() const
+ { return this->priv_node_alloc(); }
+
+ //! <b>Effects</b>: Returns a reference to the internal allocator.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->priv_node_alloc(); }
+
+ //! <b>Effects</b>: Returns a reference to the internal allocator.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->priv_node_alloc(); }
+
+ //////////////////////////////////////////////
+ //
+ // iterators
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Returns an iterator to the first element contained in the stable_vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ iterator begin() BOOST_NOEXCEPT_OR_NOTHROW
+ { return (this->index.empty()) ? this->end(): iterator(node_ptr_traits::static_cast_from(this->index.front())); }
+
+ //! <b>Effects</b>: Returns a const_iterator to the first element contained in the stable_vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return (this->index.empty()) ? this->cend() : const_iterator(node_ptr_traits::static_cast_from(this->index.front())) ; }
+
+ //! <b>Effects</b>: Returns an iterator to the end of the stable_vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ iterator end() BOOST_NOEXCEPT_OR_NOTHROW
+ { return iterator(this->priv_get_end_node()); }
+
+ //! <b>Effects</b>: Returns a const_iterator to the end of the stable_vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return const_iterator(this->priv_get_end_node()); }
+
+ //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
+ //! of the reversed stable_vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW
+ { return reverse_iterator(this->end()); }
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
+ //! of the reversed stable_vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return const_reverse_iterator(this->end()); }
+
+ //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
+ //! of the reversed stable_vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW
+ { return reverse_iterator(this->begin()); }
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
+ //! of the reversed stable_vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return const_reverse_iterator(this->begin()); }
+
+ //! <b>Effects</b>: Returns a const_iterator to the first element contained in the stable_vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->begin(); }
+
+ //! <b>Effects</b>: Returns a const_iterator to the end of the stable_vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->end(); }
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
+ //! of the reversed stable_vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->rbegin(); }
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
+ //! of the reversed stable_vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reverse_iterator crend()const BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->rend(); }
+
+ //////////////////////////////////////////////
+ //
+ // capacity
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Returns true if the stable_vector contains no elements.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ bool empty() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->index.size() <= ExtraPointers; }
+
+ //! <b>Effects</b>: Returns the number of the elements contained in the stable_vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ size_type size() const BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ const size_type index_size = this->index.size();
+ return (index_size - ExtraPointers) & (size_type(0u) -size_type(index_size != 0));
+ }
+
+ //! <b>Effects</b>: Returns the largest possible size of the stable_vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->index.max_size() - ExtraPointers; }
+
+ //! <b>Effects</b>: Inserts or erases elements at the end such that
+ //! the size becomes n. New elements are value initialized.
+ //!
+ //! <b>Throws</b>: If memory allocation throws, or T's value initialization throws.
+ //!
+ //! <b>Complexity</b>: Linear to the difference between size() and new_size.
+ void resize(size_type n)
+ {
+ typedef value_init_construct_iterator<value_type, difference_type> value_init_iterator;
+ STABLE_VECTOR_CHECK_INVARIANT;
+ if(n > this->size())
+ this->insert(this->cend(), value_init_iterator(n - this->size()), value_init_iterator());
+ else if(n < this->size())
+ this->erase(this->cbegin() + n, this->cend());
+ }
+
+ //! <b>Effects</b>: Inserts or erases elements at the end such that
+ //! the size becomes n. New elements are default initialized.
+ //!
+ //! <b>Throws</b>: If memory allocation throws, or T's default initialization throws.
+ //!
+ //! <b>Complexity</b>: Linear to the difference between size() and new_size.
+ //!
+ //! <b>Note</b>: Non-standard extension
+ void resize(size_type n, default_init_t)
+ {
+ typedef default_init_construct_iterator<value_type, difference_type> default_init_iterator;
+ STABLE_VECTOR_CHECK_INVARIANT;
+ if(n > this->size())
+ this->insert(this->cend(), default_init_iterator(n - this->size()), default_init_iterator());
+ else if(n < this->size())
+ this->erase(this->cbegin() + n, this->cend());
+ }
+
+ //! <b>Effects</b>: Inserts or erases elements at the end such that
+ //! the size becomes n. New elements are copy constructed from x.
+ //!
+ //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to the difference between size() and new_size.
+ void resize(size_type n, const T& t)
+ {
+ STABLE_VECTOR_CHECK_INVARIANT;
+ if(n > this->size())
+ this->insert(this->cend(), n - this->size(), t);
+ else if(n < this->size())
+ this->erase(this->cbegin() + n, this->cend());
+ }
+
+ //! <b>Effects</b>: Number of elements for which memory has been allocated.
+ //! capacity() is always greater than or equal to size().
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ const size_type index_size = this->index.size();
+ BOOST_ASSERT(!index_size || index_size >= ExtraPointers);
+ const size_type node_extra_capacity = this->internal_data.pool_size;
+ //Pool count must be less than index capacity, as index is a vector
+ BOOST_ASSERT(node_extra_capacity <= (this->index.capacity()- index_size));
+ const size_type index_offset =
+ (node_extra_capacity - ExtraPointers) & (size_type(0u) - size_type(index_size != 0));
+ return index_size + index_offset;
+ }
+
+ //! <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.
+ //! If the request is successful, then capacity() is greater than or equal to
+ //! n; otherwise, capacity() is unchanged. In either case, size() is unchanged.
+ //!
+ //! <b>Throws</b>: If memory allocation allocation throws.
+ void reserve(size_type n)
+ {
+ STABLE_VECTOR_CHECK_INVARIANT;
+ if(n > this->max_size()){
+ throw_length_error("stable_vector::reserve max_size() exceeded");
+ }
+
+ size_type sz = this->size();
+ size_type old_capacity = this->capacity();
+ if(n > old_capacity){
+ index_traits_type::initialize_end_node(this->index, this->internal_data.end_node, n);
+ const void * old_ptr = &index[0];
+ this->index.reserve(n + ExtraPointers);
+ bool realloced = &index[0] != old_ptr;
+ //Fix the pointers for the newly allocated buffer
+ if(realloced){
+ index_traits_type::fix_up_pointers_from(this->index, this->index.begin());
+ }
+ //Now fill pool if data is not enough
+ if((n - sz) > this->internal_data.pool_size){
+ this->priv_increase_pool((n - sz) - this->internal_data.pool_size);
+ }
+ }
+ }
+
+ //! <b>Effects</b>: Tries to deallocate the excess of memory created
+ //! with previous allocations. The size of the stable_vector is unchanged
+ //!
+ //! <b>Throws</b>: If memory allocation throws.
+ //!
+ //! <b>Complexity</b>: Linear to size().
+ void shrink_to_fit()
+ {
+ if(this->capacity()){
+ //First empty allocated node pool
+ this->priv_clear_pool();
+ //If empty completely destroy the index, let's recover default-constructed state
+ if(this->empty()){
+ this->index.clear();
+ this->index.shrink_to_fit();
+ this->internal_data.end_node.up = node_base_ptr_ptr();
+ }
+ //Otherwise, try to shrink-to-fit the index and readjust pointers if necessary
+ else{
+ const void* old_ptr = &index[0];
+ this->index.shrink_to_fit();
+ bool realloced = &index[0] != old_ptr;
+ //Fix the pointers for the newly allocated buffer
+ if(realloced){
+ index_traits_type::fix_up_pointers_from(this->index, this->index.begin());
+ }
+ }
+ }
+ }
+
+ //////////////////////////////////////////////
+ //
+ // element access
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Requires</b>: !empty()
+ //!
+ //! <b>Effects</b>: Returns a reference to the first
+ //! element of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ reference front() BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(!this->empty());
+ return static_cast<node_reference>(*this->index.front()).value;
+ }
+
+ //! <b>Requires</b>: !empty()
+ //!
+ //! <b>Effects</b>: Returns a const reference to the first
+ //! element of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reference front() const BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(!this->empty());
+ return static_cast<const_node_reference>(*this->index.front()).value;
+ }
+
+ //! <b>Requires</b>: !empty()
+ //!
+ //! <b>Effects</b>: Returns a reference to the last
+ //! element of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ reference back() BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(!this->empty());
+ return static_cast<node_reference>(*this->index[this->size()-1u]).value;
+ }
+
+ //! <b>Requires</b>: !empty()
+ //!
+ //! <b>Effects</b>: Returns a const reference to the last
+ //! element of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reference back() const BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(!this->empty());
+ return static_cast<const_node_reference>(*this->index[this->size()-1u]).value;
+ }
+
+ //! <b>Requires</b>: size() > n.
+ //!
+ //! <b>Effects</b>: Returns a reference to the nth element
+ //! from the beginning of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ reference operator[](size_type n) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(this->size() > n);
+ return static_cast<node_reference>(*this->index[n]).value;
+ }
+
+ //! <b>Requires</b>: size() > n.
+ //!
+ //! <b>Effects</b>: Returns a const reference to the nth element
+ //! from the beginning of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reference operator[](size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(this->size() > n);
+ return static_cast<const_node_reference>(*this->index[n]).value;
+ }
+
+ //! <b>Requires</b>: size() >= n.
+ //!
+ //! <b>Effects</b>: Returns an iterator to the nth element
+ //! from the beginning of the container. Returns end()
+ //! if n == size().
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Note</b>: Non-standard extension
+ iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(this->size() >= n);
+ return (this->index.empty()) ? this->end() : iterator(node_ptr_traits::static_cast_from(this->index[n]));
+ }
+
+ //! <b>Requires</b>: size() >= n.
+ //!
+ //! <b>Effects</b>: Returns a const_iterator to the nth element
+ //! from the beginning of the container. Returns end()
+ //! if n == size().
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Note</b>: Non-standard extension
+ const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(this->size() >= n);
+ return (this->index.empty()) ? this->cend() : iterator(node_ptr_traits::static_cast_from(this->index[n]));
+ }
+
+ //! <b>Requires</b>: 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(iterator p) BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->priv_index_of(p.node_pointer()); }
+
+ //! <b>Requires</b>: begin() <= p <= end().
+ //!
+ //! <b>Effects</b>: Returns the index of the element pointed by p
+ //! and size() if p == end().
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Note</b>: Non-standard extension
+ size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->priv_index_of(p.node_pointer()); }
+
+ //! <b>Requires</b>: size() > n.
+ //!
+ //! <b>Effects</b>: Returns a reference to the nth element
+ //! from the beginning of the container.
+ //!
+ //! <b>Throws</b>: std::range_error if n >= size()
+ //!
+ //! <b>Complexity</b>: Constant.
+ reference at(size_type n)
+ {
+ if(n >= this->size()){
+ throw_out_of_range("vector::at invalid subscript");
+ }
+ return operator[](n);
+ }
+
+ //! <b>Requires</b>: size() > n.
+ //!
+ //! <b>Effects</b>: Returns a const reference to the nth element
+ //! from the beginning of the container.
+ //!
+ //! <b>Throws</b>: std::range_error if n >= size()
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reference at(size_type n)const
+ {
+ if(n >= this->size()){
+ throw_out_of_range("vector::at invalid subscript");
+ }
+ return operator[](n);
+ }
+
+ //////////////////////////////////////////////
+ //
+ // modifiers
+ //
+ //////////////////////////////////////////////
+
+ #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... in the end of the stable_vector.
+ //!
+ //! <b>Returns</b>: A reference to the created object.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or the in-place constructor throws.
+ //!
+ //! <b>Complexity</b>: Amortized constant time.
+ template<class ...Args>
+ reference emplace_back(Args &&...args)
+ {
+ typedef emplace_functor<Args...> EmplaceFunctor;
+ typedef emplace_iterator<value_type, EmplaceFunctor, difference_type> EmplaceIterator;
+ EmplaceFunctor &&ef = EmplaceFunctor(boost::forward<Args>(args)...);
+ return *this->insert(this->cend(), EmplaceIterator(ef), EmplaceIterator());
+ }
+
+ //! <b>Requires</b>: p must be a valid iterator of *this.
+ //!
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... before p
+ //!
+ //! <b>Throws</b>: If memory allocation throws or the in-place constructor throws.
+ //!
+ //! <b>Complexity</b>: If p is end(), amortized constant time
+ //! Linear time otherwise.
+ template<class ...Args>
+ iterator emplace(const_iterator p, Args && ...args)
+ {
+ BOOST_ASSERT(this->priv_in_range_or_end(p));
+ size_type pos_n = p - cbegin();
+ typedef emplace_functor<Args...> EmplaceFunctor;
+ typedef emplace_iterator<value_type, EmplaceFunctor, difference_type> EmplaceIterator;
+ EmplaceFunctor &&ef = EmplaceFunctor(boost::forward<Args>(args)...);
+ this->insert(p, EmplaceIterator(ef), EmplaceIterator());
+ return iterator(this->begin() + pos_n);
+ }
+
+ #else
+
+ #define BOOST_CONTAINER_STABLE_VECTOR_EMPLACE_CODE(N) \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ reference emplace_back(BOOST_MOVE_UREF##N)\
+ {\
+ typedef emplace_functor##N\
+ BOOST_MOVE_LT##N BOOST_MOVE_TARG##N BOOST_MOVE_GT##N EmplaceFunctor;\
+ typedef emplace_iterator<value_type, EmplaceFunctor, difference_type> EmplaceIterator;\
+ EmplaceFunctor ef BOOST_MOVE_LP##N BOOST_MOVE_FWD##N BOOST_MOVE_RP##N;\
+ return *this->insert(this->cend() , EmplaceIterator(ef), EmplaceIterator());\
+ }\
+ \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ iterator emplace(const_iterator p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ {\
+ BOOST_ASSERT(this->priv_in_range_or_end(p));\
+ typedef emplace_functor##N\
+ BOOST_MOVE_LT##N BOOST_MOVE_TARG##N BOOST_MOVE_GT##N EmplaceFunctor;\
+ typedef emplace_iterator<value_type, EmplaceFunctor, difference_type> EmplaceIterator;\
+ EmplaceFunctor ef BOOST_MOVE_LP##N BOOST_MOVE_FWD##N BOOST_MOVE_RP##N;\
+ const size_type pos_n = p - this->cbegin();\
+ this->insert(p, EmplaceIterator(ef), EmplaceIterator());\
+ return this->begin() += pos_n;\
+ }\
+ //
+ BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_STABLE_VECTOR_EMPLACE_CODE)
+ #undef BOOST_CONTAINER_STABLE_VECTOR_EMPLACE_CODE
+
+ #endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ //! <b>Effects</b>: Inserts a copy of x at the end of the stable_vector.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or
+ //! T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Amortized constant time.
+ void push_back(const T &x);
+
+ //! <b>Effects</b>: Constructs a new element in the end of the stable_vector
+ //! and moves the resources of x to this new element.
+ //!
+ //! <b>Throws</b>: If memory allocation throws.
+ //!
+ //! <b>Complexity</b>: Amortized constant time.
+ void push_back(T &&x);
+ #else
+ BOOST_MOVE_CONVERSION_AWARE_CATCH(push_back, T, void, priv_push_back)
+ #endif
+
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ //! <b>Requires</b>: p must be a valid iterator of *this.
+ //!
+ //! <b>Effects</b>: Insert a copy of x before p.
+ //!
+ //! <b>Returns</b>: An iterator to the inserted element.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or x's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: If p is end(), amortized constant time
+ //! Linear time otherwise.
+ iterator insert(const_iterator p, const T &x);
+
+ //! <b>Requires</b>: p must be a valid iterator of *this.
+ //!
+ //! <b>Effects</b>: Insert a new element before p with x's resources.
+ //!
+ //! <b>Returns</b>: an iterator to the inserted element.
+ //!
+ //! <b>Throws</b>: If memory allocation throws.
+ //!
+ //! <b>Complexity</b>: If p is end(), amortized constant time
+ //! Linear time otherwise.
+ iterator insert(const_iterator p, T &&x);
+ #else
+ BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator, const_iterator)
+ #endif
+
+ //! <b>Requires</b>: p must be a valid iterator of *this.
+ //!
+ //! <b>Effects</b>: Insert n copies of x before p.
+ //!
+ //! <b>Returns</b>: an iterator to the first inserted element or p if n is 0.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to n.
+ iterator insert(const_iterator p, size_type n, const T& t)
+ {
+ BOOST_ASSERT(this->priv_in_range_or_end(p));
+ STABLE_VECTOR_CHECK_INVARIANT;
+ typedef constant_iterator<value_type, difference_type> cvalue_iterator;
+ return this->insert(p, cvalue_iterator(t, n), cvalue_iterator());
+ }
+
+ //! <b>Requires</b>: p must be a valid iterator of *this.
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Requires</b>: p must be a valid iterator of *this.
+ //!
+ //! <b>Effects</b>: Insert a copy of the [il.begin(), il.end()) range before p.
+ //!
+ //! <b>Returns</b>: an iterator to the first inserted element or p if first == last.
+ //!
+ //! <b>Complexity</b>: Linear to distance [il.begin(), il.end()).
+ iterator insert(const_iterator p, std::initializer_list<value_type> il)
+ {
+ //Position checks done by insert()
+ STABLE_VECTOR_CHECK_INVARIANT;
+ return insert(p, il.begin(), il.end());
+ }
+#endif
+
+ //! <b>Requires</b>: pos must be a valid iterator of *this.
+ //!
+ //! <b>Effects</b>: Insert a copy of the [first, last) range before p.
+ //!
+ //! <b>Returns</b>: an iterator to the first inserted element or p if first == last.
+ //!
+ //! <b>Throws</b>: If memory allocation throws, T's constructor from a
+ //! dereferenced InpIt throws or T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to distance [first, last).
+ template <class InputIterator>
+ iterator insert(const_iterator p, InputIterator first, InputIterator last
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ //Put this as argument instead of the return type as old GCC's like 3.4
+ //detect this and the next disable_if_or as overloads
+ , typename dtl::disable_if_or
+ < void
+ , dtl::is_convertible<InputIterator, size_type>
+ , dtl::is_not_input_iterator<InputIterator>
+ >::type* = 0
+ #endif
+ )
+ {
+ BOOST_ASSERT(this->priv_in_range_or_end(p));
+ STABLE_VECTOR_CHECK_INVARIANT;
+ const size_type pos_n = p - this->cbegin();
+ for(; first != last; ++first){
+ this->emplace(p, *first);
+ }
+ return this->begin() + pos_n;
+ }
+
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ template <class FwdIt>
+ typename dtl::disable_if_or
+ < iterator
+ , dtl::is_convertible<FwdIt, size_type>
+ , dtl::is_input_iterator<FwdIt>
+ >::type
+ insert(const_iterator p, FwdIt first, FwdIt last)
+ {
+ BOOST_ASSERT(this->priv_in_range_or_end(p));
+ const size_type num_new = static_cast<size_type>(boost::container::iterator_distance(first, last));
+ const size_type idx = static_cast<size_type>(p - this->cbegin());
+ if(num_new){
+ //Fills the node pool and inserts num_new null pointers in idx.
+ //If a new buffer was needed fixes up pointers up to idx so
+ //past-new nodes are not aligned until the end of this function
+ //or in a rollback in case of exception
+ index_iterator it_past_newly_constructed(this->priv_insert_forward_non_templated(idx, num_new));
+ const index_iterator it_past_new(it_past_newly_constructed + num_new);
+ {
+ //Prepare rollback
+ insert_rollback rollback(*this, it_past_newly_constructed, it_past_new);
+ while(first != last){
+ const node_ptr n = this->priv_get_from_pool();
+ BOOST_ASSERT(!!n);
+ //Put it in the index so rollback can return it in pool if construct_in_place throws
+ *it_past_newly_constructed = n;
+ //Constructs and fixes up pointers This can throw
+ this->priv_build_node_from_it(n, it_past_newly_constructed, first);
+ ++first;
+ ++it_past_newly_constructed;
+ }
+ //rollback.~insert_rollback() called in case of exception
+ }
+ //Fix up pointers for past-new nodes (new nodes were fixed during construction) and
+ //nodes before insertion p in priv_insert_forward_non_templated(...)
+ index_traits_type::fix_up_pointers_from(this->index, it_past_newly_constructed);
+ }
+ return this->begin() + idx;
+ }
+ #endif
+
+ //! <b>Effects</b>: Removes the last element from the stable_vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant time.
+ void pop_back() BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(!this->empty());
+ this->erase(--this->cend());
+ }
+
+ //! <b>Effects</b>: Erases the element at p.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Linear to the elements between p and the
+ //! last element. Constant if p is the last element.
+ iterator erase(const_iterator p) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(this->priv_in_range(p));
+ STABLE_VECTOR_CHECK_INVARIANT;
+ const size_type d = p - this->cbegin();
+ index_iterator it = this->index.begin() + d;
+ this->priv_delete_node(p.node_pointer());
+ it = this->index.erase(it);
+ index_traits_type::fix_up_pointers_from(this->index, it);
+ return iterator(node_ptr_traits::static_cast_from(*it));
+ }
+
+ //! <b>Effects</b>: Erases the elements pointed by [first, last).
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Linear to the distance between first and last
+ //! plus linear to the elements between p and the last element.
+ iterator erase(const_iterator first, const_iterator last) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(first == last ||
+ (first < last && this->priv_in_range(first) && this->priv_in_range_or_end(last)));
+ STABLE_VECTOR_CHECK_INVARIANT;
+ const const_iterator cbeg(this->cbegin());
+ const size_type d1 = static_cast<size_type>(first - cbeg),
+ d2 = static_cast<size_type>(last - cbeg);
+ size_type d_dif = d2 - d1;
+ if(d_dif){
+ multiallocation_chain holder;
+ const index_iterator it1(this->index.begin() + d1);
+ const index_iterator it2(it1 + d_dif);
+ index_iterator it(it1);
+ while(d_dif--){
+ node_base_ptr &nb = *it;
+ ++it;
+ node_type &n = *node_ptr_traits::static_cast_from(nb);
+ this->priv_destroy_node(n);
+ holder.push_back(node_ptr_traits::pointer_to(n));
+ }
+ this->priv_put_in_pool(holder);
+ const index_iterator e = this->index.erase(it1, it2);
+ index_traits_type::fix_up_pointers_from(this->index, e);
+ }
+ return iterator(last.node_pointer());
+ }
+
+ //! <b>Effects</b>: Swaps the contents of *this and x.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ void swap(stable_vector & x)
+ BOOST_NOEXCEPT_IF( allocator_traits_type::propagate_on_container_swap::value
+ || allocator_traits_type::is_always_equal::value)
+ {
+ BOOST_ASSERT(allocator_traits_type::propagate_on_container_swap::value ||
+ allocator_traits_type::is_always_equal::value ||
+ this->get_stored_allocator() == x.get_stored_allocator());
+ STABLE_VECTOR_CHECK_INVARIANT;
+ dtl::bool_<allocator_traits_type::propagate_on_container_swap::value> flag;
+ dtl::swap_alloc(this->priv_node_alloc(), x.priv_node_alloc(), flag);
+ //vector's allocator is swapped here
+ this->index.swap(x.index);
+ this->priv_swap_members(x);
+ }
+
+ //! <b>Effects</b>: Erases all the elements of the stable_vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the stable_vector.
+ void clear() BOOST_NOEXCEPT_OR_NOTHROW
+ { this->erase(this->cbegin(),this->cend()); }
+
+ //! <b>Effects</b>: Returns true if x and y are equal
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator==(const stable_vector& x, const stable_vector& y)
+ { return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin()); }
+
+ //! <b>Effects</b>: Returns true if x and y are unequal
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator!=(const stable_vector& x, const stable_vector& y)
+ { return !(x == y); }
+
+ //! <b>Effects</b>: Returns true if x is less than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator<(const stable_vector& x, const stable_vector& y)
+ { return ::boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
+
+ //! <b>Effects</b>: Returns true if x is greater than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator>(const stable_vector& x, const stable_vector& y)
+ { return y < x; }
+
+ //! <b>Effects</b>: Returns true if x is equal or less than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator<=(const stable_vector& x, const stable_vector& y)
+ { return !(y < x); }
+
+ //! <b>Effects</b>: Returns true if x is equal or greater than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator>=(const stable_vector& x, const stable_vector& y)
+ { return !(x < y); }
+
+ //! <b>Effects</b>: x.swap(y)
+ //!
+ //! <b>Complexity</b>: Constant.
+ friend void swap(stable_vector& x, stable_vector& y)
+ { x.swap(y); }
+
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ private:
+
+ bool priv_in_range(const_iterator pos) const
+ {
+ return (this->begin() <= pos) && (pos < this->end());
+ }
+
+ bool priv_in_range_or_end(const_iterator pos) const
+ {
+ return (this->begin() <= pos) && (pos <= this->end());
+ }
+
+ size_type priv_index_of(node_ptr p) const
+ {
+ //Check range
+ BOOST_ASSERT(this->index.empty() || (this->index.data() <= p->up));
+ BOOST_ASSERT(this->index.empty() || p->up <= (this->index.data() + this->index.size()));
+ return this->index.empty() ? 0 : p->up - this->index.data();
+ }
+
+ class insert_rollback
+ {
+ public:
+
+ insert_rollback(stable_vector &sv, index_iterator &it_past_constructed, const index_iterator &it_past_new)
+ : m_sv(sv), m_it_past_constructed(it_past_constructed), m_it_past_new(it_past_new)
+ {}
+
+ ~insert_rollback()
+ {
+ if(m_it_past_constructed != m_it_past_new){
+ m_sv.priv_put_in_pool(node_ptr_traits::static_cast_from(*m_it_past_constructed));
+ index_iterator e = m_sv.index.erase(m_it_past_constructed, m_it_past_new);
+ index_traits_type::fix_up_pointers_from(m_sv.index, e);
+ }
+ }
+
+ private:
+ stable_vector &m_sv;
+ index_iterator &m_it_past_constructed;
+ const index_iterator &m_it_past_new;
+ };
+
+ class push_back_rollback
+ {
+ public:
+ push_back_rollback(stable_vector &sv, const node_ptr &p)
+ : m_sv(sv), m_p(p)
+ {}
+
+ ~push_back_rollback()
+ {
+ if(m_p){
+ m_sv.priv_put_in_pool(m_p);
+ }
+ }
+
+ void release()
+ { m_p = node_ptr(); }
+
+ private:
+ stable_vector &m_sv;
+ node_ptr m_p;
+ };
+
+ index_iterator priv_insert_forward_non_templated(size_type idx, size_type num_new)
+ {
+ index_traits_type::initialize_end_node(this->index, this->internal_data.end_node, num_new);
+
+ //Now try to fill the pool with new data
+ if(this->internal_data.pool_size < num_new){
+ this->priv_increase_pool(num_new - this->internal_data.pool_size);
+ }
+
+ //Now try to make room in the vector
+ const node_base_ptr_ptr old_buffer = this->index.data();
+ this->index.insert(this->index.begin() + idx, num_new, node_ptr());
+ bool new_buffer = this->index.data() != old_buffer;
+
+ //Fix the pointers for the newly allocated buffer
+ const index_iterator index_beg = this->index.begin();
+ if(new_buffer){
+ index_traits_type::fix_up_pointers(index_beg, index_beg + idx);
+ }
+ return index_beg + idx;
+ }
+
+ bool priv_capacity_bigger_than_size() const
+ {
+ return this->index.capacity() > this->index.size() &&
+ this->internal_data.pool_size > 0;
+ }
+
+ template <class U>
+ void priv_push_back(BOOST_MOVE_CATCH_FWD(U) x)
+ {
+ if(BOOST_LIKELY(this->priv_capacity_bigger_than_size())){
+ //Enough memory in the pool and in the index
+ const node_ptr p = this->priv_get_from_pool();
+ BOOST_ASSERT(!!p);
+ {
+ push_back_rollback rollback(*this, p);
+ //This might throw
+ this->priv_build_node_from_convertible(p, ::boost::forward<U>(x));
+ rollback.release();
+ }
+ //This can't throw as there is room for a new elements in the index
+ index_iterator new_index = this->index.insert(this->index.end() - ExtraPointers, p);
+ index_traits_type::fix_up_pointers_from(this->index, new_index);
+ }
+ else{
+ this->insert(this->cend(), ::boost::forward<U>(x));
+ }
+ }
+
+ iterator priv_insert(const_iterator p, const value_type &t)
+ {
+ BOOST_ASSERT(this->priv_in_range_or_end(p));
+ typedef constant_iterator<value_type, difference_type> cvalue_iterator;
+ return this->insert(p, cvalue_iterator(t, 1), cvalue_iterator());
+ }
+
+ iterator priv_insert(const_iterator p, BOOST_RV_REF(T) x)
+ {
+ BOOST_ASSERT(this->priv_in_range_or_end(p));
+ typedef repeat_iterator<T, difference_type> repeat_it;
+ typedef boost::move_iterator<repeat_it> repeat_move_it;
+ //Just call more general insert(p, size, value) and return iterator
+ return this->insert(p, repeat_move_it(repeat_it(x, 1)), repeat_move_it(repeat_it()));
+ }
+
+ void priv_clear_pool()
+ {
+ if(!this->index.empty() && this->index.back()){
+ node_base_ptr &pool_first_ref = *(this->index.end() - 2);
+ node_base_ptr &pool_last_ref = this->index.back();
+
+ multiallocation_chain holder;
+ holder.incorporate_after( holder.before_begin()
+ , node_ptr_traits::static_cast_from(pool_first_ref)
+ , node_ptr_traits::static_cast_from(pool_last_ref)
+ , internal_data.pool_size);
+ this->deallocate_individual(holder);
+ pool_first_ref = pool_last_ref = 0;
+ this->internal_data.pool_size = 0;
+ }
+ }
+
+ void priv_increase_pool(size_type n)
+ {
+ node_base_ptr &pool_first_ref = *(this->index.end() - 2);
+ node_base_ptr &pool_last_ref = this->index.back();
+ multiallocation_chain holder;
+ holder.incorporate_after( holder.before_begin()
+ , node_ptr_traits::static_cast_from(pool_first_ref)
+ , node_ptr_traits::static_cast_from(pool_last_ref)
+ , internal_data.pool_size);
+ multiallocation_chain m;
+ this->allocate_individual(n, m);
+ holder.splice_after(holder.before_begin(), m, m.before_begin(), m.last(), n);
+ this->internal_data.pool_size += n;
+ std::pair<node_ptr, node_ptr> data(holder.extract_data());
+ pool_first_ref = data.first;
+ pool_last_ref = data.second;
+ }
+
+ void priv_put_in_pool(const node_ptr &p)
+ {
+ node_base_ptr &pool_first_ref = *(this->index.end()-2);
+ node_base_ptr &pool_last_ref = this->index.back();
+ multiallocation_chain holder;
+ holder.incorporate_after( holder.before_begin()
+ , node_ptr_traits::static_cast_from(pool_first_ref)
+ , node_ptr_traits::static_cast_from(pool_last_ref)
+ , internal_data.pool_size);
+ holder.push_front(p);
+ ++this->internal_data.pool_size;
+ std::pair<node_ptr, node_ptr> ret(holder.extract_data());
+ pool_first_ref = ret.first;
+ pool_last_ref = ret.second;
+ }
+
+ void priv_put_in_pool(multiallocation_chain &ch)
+ {
+ node_base_ptr &pool_first_ref = *(this->index.end()-(ExtraPointers-1));
+ node_base_ptr &pool_last_ref = this->index.back();
+ ch.incorporate_after( ch.before_begin()
+ , node_ptr_traits::static_cast_from(pool_first_ref)
+ , node_ptr_traits::static_cast_from(pool_last_ref)
+ , internal_data.pool_size);
+ this->internal_data.pool_size = ch.size();
+ const std::pair<node_ptr, node_ptr> ret(ch.extract_data());
+ pool_first_ref = ret.first;
+ pool_last_ref = ret.second;
+ }
+
+ node_ptr priv_get_from_pool()
+ {
+ //Precondition: index is not empty
+ BOOST_ASSERT(!this->index.empty());
+ node_base_ptr &pool_first_ref = *(this->index.end() - (ExtraPointers-1));
+ node_base_ptr &pool_last_ref = this->index.back();
+ multiallocation_chain holder;
+ holder.incorporate_after( holder.before_begin()
+ , node_ptr_traits::static_cast_from(pool_first_ref)
+ , node_ptr_traits::static_cast_from(pool_last_ref)
+ , internal_data.pool_size);
+ node_ptr ret = holder.pop_front();
+ --this->internal_data.pool_size;
+ if(!internal_data.pool_size){
+ pool_first_ref = pool_last_ref = node_ptr();
+ }
+ else{
+ const std::pair<node_ptr, node_ptr> data(holder.extract_data());
+ pool_first_ref = data.first;
+ pool_last_ref = data.second;
+ }
+ return ret;
+ }
+
+ node_base_ptr priv_get_end_node() const
+ { return node_base_ptr_traits::pointer_to(const_cast<node_base_type&>(this->internal_data.end_node)); }
+
+ void priv_destroy_node(const node_type &n)
+ {
+ allocator_traits<node_allocator_type>::
+ destroy(this->priv_node_alloc(), dtl::addressof(n.value));
+ static_cast<const node_base_type*>(&n)->~node_base_type();
+ }
+
+ void priv_delete_node(const node_ptr &n)
+ {
+ this->priv_destroy_node(*n);
+ this->priv_put_in_pool(n);
+ }
+
+ template<class Iterator>
+ void priv_build_node_from_it(const node_ptr &p, const index_iterator &up_index, const Iterator &it)
+ {
+ //This can throw
+ boost::container::construct_in_place
+ ( this->priv_node_alloc()
+ , dtl::addressof(p->value)
+ , it);
+ //This does not throw
+ ::new(static_cast<node_base_type*>(boost::movelib::to_raw_pointer(p)), boost_container_new_t())
+ node_base_type(index_traits_type::ptr_to_node_base_ptr(*up_index));
+ }
+
+ template<class ValueConvertible>
+ void priv_build_node_from_convertible(const node_ptr &p, BOOST_FWD_REF(ValueConvertible) value_convertible)
+ {
+ //This can throw
+ boost::container::allocator_traits<node_allocator_type>::construct
+ ( this->priv_node_alloc()
+ , dtl::addressof(p->value)
+ , ::boost::forward<ValueConvertible>(value_convertible));
+ //This does not throw
+ ::new(static_cast<node_base_type*>(boost::movelib::to_raw_pointer(p)), boost_container_new_t()) node_base_type;
+ }
+
+ void priv_swap_members(stable_vector &x)
+ {
+ boost::adl_move_swap(this->internal_data.pool_size, x.internal_data.pool_size);
+ index_traits_type::readjust_end_node(this->index, this->internal_data.end_node);
+ index_traits_type::readjust_end_node(x.index, x.internal_data.end_node);
+ }
+
+ #if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING)
+ bool priv_invariant()const
+ {
+ index_type & index_ref = const_cast<index_type&>(this->index);
+
+ const size_type index_size = this->index.size();
+ if(!index_size)
+ return !this->capacity() && !this->size();
+
+ if(index_size < ExtraPointers)
+ return false;
+
+ const size_type bucket_extra_capacity = this->index.capacity()- index_size;
+ const size_type node_extra_capacity = this->internal_data.pool_size;
+ if(bucket_extra_capacity < node_extra_capacity){
+ return false;
+ }
+
+ if(this->priv_get_end_node() != *(index.end() - ExtraPointers)){
+ return false;
+ }
+
+ if(!index_traits_type::invariants(index_ref)){
+ return false;
+ }
+
+ size_type n = this->capacity() - this->size();
+ node_base_ptr &pool_first_ref = *(index_ref.end() - (ExtraPointers-1));
+ node_base_ptr &pool_last_ref = index_ref.back();
+ multiallocation_chain holder;
+ holder.incorporate_after( holder.before_begin()
+ , node_ptr_traits::static_cast_from(pool_first_ref)
+ , node_ptr_traits::static_cast_from(pool_last_ref)
+ , internal_data.pool_size);
+ typename multiallocation_chain::iterator beg(holder.begin()), end(holder.end());
+ size_type num_pool = 0;
+ while(beg != end){
+ ++num_pool;
+ ++beg;
+ }
+ return n >= num_pool && num_pool == internal_data.pool_size;
+ }
+
+ class invariant_checker
+ {
+ invariant_checker(const invariant_checker &);
+ invariant_checker & operator=(const invariant_checker &);
+ const stable_vector* p;
+
+ public:
+ invariant_checker(const stable_vector& v):p(&v){}
+ ~invariant_checker(){BOOST_ASSERT(p->priv_invariant());}
+ void touch(){}
+ };
+ #endif
+
+ class ebo_holder
+ : public node_allocator_type
+ {
+ private:
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(ebo_holder)
+
+ public:
+ template<class AllocatorRLValue>
+ explicit ebo_holder(BOOST_FWD_REF(AllocatorRLValue) a)
+ : node_allocator_type(boost::forward<AllocatorRLValue>(a))
+ , pool_size(0)
+ , end_node()
+ {}
+
+ ebo_holder()
+ : node_allocator_type()
+ , pool_size(0)
+ , end_node()
+ {}
+
+ size_type pool_size;
+ node_base_type end_node;
+ } internal_data;
+
+ node_allocator_type &priv_node_alloc() { return internal_data; }
+ const node_allocator_type &priv_node_alloc() const { return internal_data; }
+
+ index_type index;
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+};
+
+#if __cplusplus >= 201703L
+
+template <typename InputIterator>
+stable_vector(InputIterator, InputIterator) ->
+ stable_vector<typename iterator_traits<InputIterator>::value_type>;
+
+template <typename InputIterator, typename Allocator>
+stable_vector(InputIterator, InputIterator, Allocator const&) ->
+ stable_vector<typename iterator_traits<InputIterator>::value_type, Allocator>;
+
+#endif
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+#undef STABLE_VECTOR_CHECK_INVARIANT
+
+} //namespace container {
+
+//!has_trivial_destructor_after_move<> == true_type
+//!specialization for optimizations
+template <class T, class Allocator>
+struct has_trivial_destructor_after_move<boost::container::stable_vector<T, Allocator> >
+{
+ typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer;
+ static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value &&
+ ::boost::has_trivial_destructor_after_move<pointer>::value;
+};
+
+namespace container {
+
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+}} //namespace boost{ namespace container {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //BOOST_CONTAINER_STABLE_VECTOR_HPP
diff --git a/include/boost/container/static_vector.hpp b/include/boost/container/static_vector.hpp
new file mode 100644
index 0000000..b40d5c3
--- /dev/null
+++ b/include/boost/container/static_vector.hpp
@@ -0,0 +1,1242 @@
+// Boost.Container static_vector
+//
+// Copyright (c) 2012-2013 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2011-2013 Andrew Hundt.
+// Copyright (c) 2013-2014 Ion Gaztanaga
+//
+// Use, modification and distribution is subject to 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)
+
+#ifndef BOOST_CONTAINER_STATIC_VECTOR_HPP
+#define BOOST_CONTAINER_STATIC_VECTOR_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+#include <boost/container/detail/type_traits.hpp>
+#include <boost/container/vector.hpp>
+
+#include <cstddef>
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+#include <initializer_list>
+#endif
+
+namespace boost { namespace container {
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+namespace dtl {
+
+template<class T, std::size_t N>
+class static_storage_allocator
+{
+ public:
+ typedef T value_type;
+
+ BOOST_CONTAINER_FORCEINLINE static_storage_allocator() BOOST_NOEXCEPT_OR_NOTHROW
+ {}
+
+ BOOST_CONTAINER_FORCEINLINE static_storage_allocator(const static_storage_allocator &) BOOST_NOEXCEPT_OR_NOTHROW
+ {}
+
+ BOOST_CONTAINER_FORCEINLINE static_storage_allocator & operator=(const static_storage_allocator &) BOOST_NOEXCEPT_OR_NOTHROW
+ { return *this; }
+
+ BOOST_CONTAINER_FORCEINLINE T* internal_storage() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return const_cast<T*>(static_cast<const T*>(static_cast<const void*>(storage.data))); }
+
+ BOOST_CONTAINER_FORCEINLINE T* internal_storage() BOOST_NOEXCEPT_OR_NOTHROW
+ { return static_cast<T*>(static_cast<void*>(storage.data)); }
+
+ static const std::size_t internal_capacity = N;
+
+ std::size_t max_size() const
+ { return N; }
+
+ typedef boost::container::dtl::version_type<static_storage_allocator, 0> version;
+
+ BOOST_CONTAINER_FORCEINLINE friend bool operator==(const static_storage_allocator &, const static_storage_allocator &) BOOST_NOEXCEPT_OR_NOTHROW
+ { return false; }
+
+ BOOST_CONTAINER_FORCEINLINE friend bool operator!=(const static_storage_allocator &, const static_storage_allocator &) BOOST_NOEXCEPT_OR_NOTHROW
+ { return true; }
+
+ private:
+ typename aligned_storage<sizeof(T)*N, alignment_of<T>::value>::type storage;
+};
+
+} //namespace dtl {
+
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+//!
+//!@brief A variable-size array container with fixed capacity.
+//!
+//!static_vector is a sequence container like boost::container::vector with contiguous storage that can
+//!change in size, along with the static allocation, low overhead, and fixed capacity of boost::array.
+//!
+//!A static_vector is a sequence that supports random access to elements, constant time insertion and
+//!removal of elements at the end, and linear time insertion and removal of elements at the beginning or
+//!in the middle. The number of elements in a static_vector may vary dynamically up to a fixed capacity
+//!because elements are stored within the object itself similarly to an array. However, objects are
+//!initialized as they are inserted into static_vector unlike C arrays or std::array which must construct
+//!all elements on instantiation. The behavior of static_vector enables the use of statically allocated
+//!elements in cases with complex object lifetime requirements that would otherwise not be trivially
+//!possible.
+//!
+//!@par Error Handling
+//! Insertion beyond the capacity result in throwing std::bad_alloc() if exceptions are enabled or
+//! calling throw_bad_alloc() if not enabled.
+//!
+//! std::out_of_range is thrown if out of bound access is performed in <code>at()</code> if exceptions are
+//! enabled, throw_out_of_range() if not enabled.
+//!
+//!@tparam Value The type of element that will be stored.
+//!@tparam Capacity The maximum number of elements static_vector can store, fixed at compile time.
+template <typename Value, std::size_t Capacity>
+class static_vector
+ : public vector<Value, dtl::static_storage_allocator<Value, Capacity> >
+{
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ typedef vector<Value, dtl::static_storage_allocator<Value, Capacity> > base_t;
+
+ BOOST_COPYABLE_AND_MOVABLE(static_vector)
+
+ template<class U, std::size_t OtherCapacity>
+ friend class static_vector;
+
+ public:
+ typedef dtl::static_storage_allocator<Value, Capacity> allocator_type;
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+public:
+ //! @brief The type of elements stored in the container.
+ typedef typename base_t::value_type value_type;
+ //! @brief The unsigned integral type used by the container.
+ typedef typename base_t::size_type size_type;
+ //! @brief The pointers difference type.
+ typedef typename base_t::difference_type difference_type;
+ //! @brief The pointer type.
+ typedef typename base_t::pointer pointer;
+ //! @brief The const pointer type.
+ typedef typename base_t::const_pointer const_pointer;
+ //! @brief The value reference type.
+ typedef typename base_t::reference reference;
+ //! @brief The value const reference type.
+ typedef typename base_t::const_reference const_reference;
+ //! @brief The iterator type.
+ typedef typename base_t::iterator iterator;
+ //! @brief The const iterator type.
+ typedef typename base_t::const_iterator const_iterator;
+ //! @brief The reverse iterator type.
+ typedef typename base_t::reverse_iterator reverse_iterator;
+ //! @brief The const reverse iterator.
+ typedef typename base_t::const_reverse_iterator const_reverse_iterator;
+
+ //! @brief The capacity/max size of the container
+ static const size_type static_capacity = Capacity;
+
+ //! @brief Constructs an empty static_vector.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ BOOST_CONTAINER_FORCEINLINE static_vector() BOOST_NOEXCEPT_OR_NOTHROW
+ : base_t()
+ {}
+
+ //! @pre <tt>count <= capacity()</tt>
+ //!
+ //! @brief Constructs a static_vector containing count value initialized values.
+ //!
+ //! @param count The number of values which will be contained in the container.
+ //!
+ //! @par Throws
+ //! If Value's value initialization throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ BOOST_CONTAINER_FORCEINLINE explicit static_vector(size_type count)
+ : base_t(count)
+ {}
+
+ //! @pre <tt>count <= capacity()</tt>
+ //!
+ //! @brief Constructs a static_vector containing count default initialized values.
+ //!
+ //! @param count The number of values which will be contained in the container.
+ //!
+ //! @par Throws
+ //! If Value's default initialization throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ //!
+ //! @par Note
+ //! Non-standard extension
+ BOOST_CONTAINER_FORCEINLINE static_vector(size_type count, default_init_t)
+ : base_t(count, default_init_t())
+ {}
+
+ //! @pre <tt>count <= capacity()</tt>
+ //!
+ //! @brief Constructs a static_vector containing count copies of value.
+ //!
+ //! @param count The number of copies of a values that will be contained in the container.
+ //! @param value The value which will be used to copy construct values.
+ //!
+ //! @par Throws
+ //! If Value's copy constructor throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ BOOST_CONTAINER_FORCEINLINE static_vector(size_type count, value_type const& value)
+ : base_t(count, value)
+ {}
+
+ //! @pre
+ //! @li <tt>distance(first, last) <= capacity()</tt>
+ //! @li Iterator must meet the \c ForwardTraversalIterator concept.
+ //!
+ //! @brief Constructs a static_vector containing copy of a range <tt>[first, last)</tt>.
+ //!
+ //! @param first The iterator to the first element in range.
+ //! @param last The iterator to the one after the last element in range.
+ //!
+ //! @par Throws
+ //! If Value's constructor taking a dereferenced Iterator throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ template <typename Iterator>
+ BOOST_CONTAINER_FORCEINLINE static_vector(Iterator first, Iterator last)
+ : base_t(first, last)
+ {}
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! @pre
+ //! @li <tt>distance(il.begin(), il.end()) <= capacity()</tt>
+ //!
+ //! @brief Constructs a static_vector containing copy of a range <tt>[il.begin(), il.end())</tt>.
+ //!
+ //! @param il std::initializer_list with values to initialize vector.
+ //!
+ //! @par Throws
+ //! If Value's constructor taking a dereferenced std::initializer_list throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ BOOST_CONTAINER_FORCEINLINE static_vector(std::initializer_list<value_type> il)
+ : base_t(il)
+ {}
+#endif
+
+ //! @brief Constructs a copy of other static_vector.
+ //!
+ //! @param other The static_vector which content will be copied to this one.
+ //!
+ //! @par Throws
+ //! If Value's copy constructor throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ BOOST_CONTAINER_FORCEINLINE static_vector(static_vector const& other)
+ : base_t(other)
+ {}
+
+ BOOST_CONTAINER_FORCEINLINE static_vector(static_vector const& other, const allocator_type &)
+ : base_t(other)
+ {}
+
+ BOOST_CONTAINER_FORCEINLINE static_vector(BOOST_RV_REF(static_vector) other, const allocator_type &)
+ BOOST_NOEXCEPT_IF(boost::container::dtl::is_nothrow_move_constructible<value_type>::value)
+ : base_t(BOOST_MOVE_BASE(base_t, other))
+ {}
+
+ BOOST_CONTAINER_FORCEINLINE explicit static_vector(const allocator_type &)
+ : base_t()
+ {}
+
+ //! @pre <tt>other.size() <= capacity()</tt>.
+ //!
+ //! @brief Constructs a copy of other static_vector.
+ //!
+ //! @param other The static_vector which content will be copied to this one.
+ //!
+ //! @par Throws
+ //! If Value's copy constructor throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ template <std::size_t C>
+ BOOST_CONTAINER_FORCEINLINE static_vector(static_vector<value_type, C> const& other)
+ : base_t(other)
+ {}
+
+ //! @brief Move constructor. Moves Values stored in the other static_vector to this one.
+ //!
+ //! @param other The static_vector which content will be moved to this one.
+ //!
+ //! @par Throws
+ //! @li If \c has_nothrow_move<Value>::value is \c true and Value's move constructor throws.
+ //! @li If \c has_nothrow_move<Value>::value is \c false and Value's copy constructor throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ BOOST_CONTAINER_FORCEINLINE static_vector(BOOST_RV_REF(static_vector) other)
+ BOOST_NOEXCEPT_IF(boost::container::dtl::is_nothrow_move_constructible<value_type>::value)
+ : base_t(BOOST_MOVE_BASE(base_t, other))
+ {}
+
+ //! @pre <tt>other.size() <= capacity()</tt>
+ //!
+ //! @brief Move constructor. Moves Values stored in the other static_vector to this one.
+ //!
+ //! @param other The static_vector which content will be moved to this one.
+ //!
+ //! @par Throws
+ //! @li If \c has_nothrow_move<Value>::value is \c true and Value's move constructor throws.
+ //! @li If \c has_nothrow_move<Value>::value is \c false and Value's copy constructor throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ template <std::size_t C>
+ BOOST_CONTAINER_FORCEINLINE static_vector(BOOST_RV_REF_BEG static_vector<value_type, C> BOOST_RV_REF_END other)
+ : base_t(BOOST_MOVE_BASE(typename static_vector<value_type BOOST_MOVE_I C>::base_t, other))
+ {}
+
+ //! @brief Copy assigns Values stored in the other static_vector to this one.
+ //!
+ //! @param other The static_vector which content will be copied to this one.
+ //!
+ //! @par Throws
+ //! If Value's copy constructor or copy assignment throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ BOOST_CONTAINER_FORCEINLINE static_vector & operator=(BOOST_COPY_ASSIGN_REF(static_vector) other)
+ {
+ return static_cast<static_vector&>(base_t::operator=(static_cast<base_t const&>(other)));
+ }
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! @brief Copy assigns Values stored in std::initializer_list to *this.
+ //!
+ //! @param il The std::initializer_list which content will be copied to this one.
+ //!
+ //! @par Throws
+ //! If Value's copy constructor or copy assignment throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ BOOST_CONTAINER_FORCEINLINE static_vector & operator=(std::initializer_list<value_type> il)
+ { return static_cast<static_vector&>(base_t::operator=(il)); }
+#endif
+
+ //! @pre <tt>other.size() <= capacity()</tt>
+ //!
+ //! @brief Copy assigns Values stored in the other static_vector to this one.
+ //!
+ //! @param other The static_vector which content will be copied to this one.
+ //!
+ //! @par Throws
+ //! If Value's copy constructor or copy assignment throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ template <std::size_t C>
+ BOOST_CONTAINER_FORCEINLINE static_vector & operator=(static_vector<value_type, C> const& other)
+ {
+ return static_cast<static_vector&>(base_t::operator=
+ (static_cast<typename static_vector<value_type, C>::base_t const&>(other)));
+ }
+
+ //! @brief Move assignment. Moves Values stored in the other static_vector to this one.
+ //!
+ //! @param other The static_vector which content will be moved to this one.
+ //!
+ //! @par Throws
+ //! @li If \c has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws.
+ //! @li If \c has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ BOOST_CONTAINER_FORCEINLINE static_vector & operator=(BOOST_RV_REF(static_vector) other)
+ {
+ return static_cast<static_vector&>(base_t::operator=(BOOST_MOVE_BASE(base_t, other)));
+ }
+
+ //! @pre <tt>other.size() <= capacity()</tt>
+ //!
+ //! @brief Move assignment. Moves Values stored in the other static_vector to this one.
+ //!
+ //! @param other The static_vector which content will be moved to this one.
+ //!
+ //! @par Throws
+ //! @li If \c has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws.
+ //! @li If \c has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ template <std::size_t C>
+ BOOST_CONTAINER_FORCEINLINE static_vector & operator=(BOOST_RV_REF_BEG static_vector<value_type, C> BOOST_RV_REF_END other)
+ {
+ return static_cast<static_vector&>(base_t::operator=
+ (BOOST_MOVE_BASE(typename static_vector<value_type BOOST_MOVE_I C>::base_t, other)));
+ }
+
+#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ //! @brief Destructor. Destroys Values stored in this container.
+ //!
+ //! @par Throws
+ //! Nothing
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ ~static_vector();
+
+ //! @brief Swaps contents of the other static_vector and this one.
+ //!
+ //! @param other The static_vector which content will be swapped with this one's content.
+ //!
+ //! @par Throws
+ //! @li If \c has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws,
+ //! @li If \c has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws,
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ void swap(static_vector & other);
+
+ //! @pre <tt>other.size() <= capacity() && size() <= other.capacity()</tt>
+ //!
+ //! @brief Swaps contents of the other static_vector and this one.
+ //!
+ //! @param other The static_vector which content will be swapped with this one's content.
+ //!
+ //! @par Throws
+ //! @li If \c has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws,
+ //! @li If \c has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws,
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ template <std::size_t C>
+ void swap(static_vector<value_type, C> & other);
+
+ //! @pre <tt>count <= capacity()</tt>
+ //!
+ //! @brief Inserts or erases elements at the end such that
+ //! the size becomes count. New elements are value initialized.
+ //!
+ //! @param count The number of elements which will be stored in the container.
+ //!
+ //! @par Throws
+ //! If Value's value initialization throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ void resize(size_type count);
+
+ //! @pre <tt>count <= capacity()</tt>
+ //!
+ //! @brief Inserts or erases elements at the end such that
+ //! the size becomes count. New elements are default initialized.
+ //!
+ //! @param count The number of elements which will be stored in the container.
+ //!
+ //! @par Throws
+ //! If Value's default initialization throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ //!
+ //! @par Note
+ //! Non-standard extension
+ void resize(size_type count, default_init_t);
+
+ //! @pre <tt>count <= capacity()</tt>
+ //!
+ //! @brief Inserts or erases elements at the end such that
+ //! the size becomes count. New elements are copy constructed from value.
+ //!
+ //! @param count The number of elements which will be stored in the container.
+ //! @param value The value used to copy construct the new element.
+ //!
+ //! @par Throws
+ //! If Value's copy constructor throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ void resize(size_type count, value_type const& value);
+
+ //! @pre <tt>count <= capacity()</tt>
+ //!
+ //! @brief This call has no effect because the Capacity of this container is constant.
+ //!
+ //! @param count The number of elements which the container should be able to contain.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ void reserve(size_type count) BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @pre <tt>size() < capacity()</tt>
+ //!
+ //! @brief Adds a copy of value at the end.
+ //!
+ //! @param value The value used to copy construct the new element.
+ //!
+ //! @par Throws
+ //! If Value's copy constructor throws.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ void push_back(value_type const& value);
+
+ //! @pre <tt>size() < capacity()</tt>
+ //!
+ //! @brief Moves value to the end.
+ //!
+ //! @param value The value to move construct the new element.
+ //!
+ //! @par Throws
+ //! If Value's move constructor throws.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ void push_back(BOOST_RV_REF(value_type) value);
+
+ //! @pre <tt>!empty()</tt>
+ //!
+ //! @brief Destroys last value and decreases the size.
+ //!
+ //! @par Throws
+ //! Nothing by default.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ void pop_back();
+
+ //! @pre
+ //! @li \c p must be a valid iterator of \c *this in range <tt>[begin(), end()]</tt>.
+ //! @li <tt>size() < capacity()</tt>
+ //!
+ //! @brief Inserts a copy of element at p.
+ //!
+ //! @param p The position at which the new value will be inserted.
+ //! @param value The value used to copy construct the new element.
+ //!
+ //! @par Throws
+ //! @li If Value's copy constructor or copy assignment throws
+ //! @li If Value's move constructor or move assignment throws.
+ //!
+ //! @par Complexity
+ //! Constant or linear.
+ iterator insert(const_iterator p, value_type const& value);
+
+ //! @pre
+ //! @li \c p must be a valid iterator of \c *this in range <tt>[begin(), end()]</tt>.
+ //! @li <tt>size() < capacity()</tt>
+ //!
+ //! @brief Inserts a move-constructed element at p.
+ //!
+ //! @param p The position at which the new value will be inserted.
+ //! @param value The value used to move construct the new element.
+ //!
+ //! @par Throws
+ //! If Value's move constructor or move assignment throws.
+ //!
+ //! @par Complexity
+ //! Constant or linear.
+ iterator insert(const_iterator p, BOOST_RV_REF(value_type) value);
+
+ //! @pre
+ //! @li \c p must be a valid iterator of \c *this in range <tt>[begin(), end()]</tt>.
+ //! @li <tt>size() + count <= capacity()</tt>
+ //!
+ //! @brief Inserts a count copies of value at p.
+ //!
+ //! @param p The position at which new elements will be inserted.
+ //! @param count The number of new elements which will be inserted.
+ //! @param value The value used to copy construct new elements.
+ //!
+ //! @par Throws
+ //! @li If Value's copy constructor or copy assignment throws.
+ //! @li If Value's move constructor or move assignment throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ iterator insert(const_iterator p, size_type count, value_type const& value);
+
+ //! @pre
+ //! @li \c p must be a valid iterator of \c *this in range <tt>[begin(), end()]</tt>.
+ //! @li <tt>distance(first, last) <= capacity()</tt>
+ //! @li \c Iterator must meet the \c ForwardTraversalIterator concept.
+ //!
+ //! @brief Inserts a copy of a range <tt>[first, last)</tt> at p.
+ //!
+ //! @param p The position at which new elements will be inserted.
+ //! @param first The iterator to the first element of a range used to construct new elements.
+ //! @param last The iterator to the one after the last element of a range used to construct new elements.
+ //!
+ //! @par Throws
+ //! @li If Value's constructor and assignment taking a dereferenced \c Iterator.
+ //! @li If Value's move constructor or move assignment throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ template <typename Iterator>
+ iterator insert(const_iterator p, Iterator first, Iterator last);
+
+ //! @pre
+ //! @li \c p must be a valid iterator of \c *this in range <tt>[begin(), end()]</tt>.
+ //! @li <tt>distance(il.begin(), il.end()) <= capacity()</tt>
+ //!
+ //! @brief Inserts a copy of a range <tt>[il.begin(), il.end())</tt> at p.
+ //!
+ //! @param p The position at which new elements will be inserted.
+ //! @param il The std::initializer_list which contains elements that will be inserted.
+ //!
+ //! @par Throws
+ //! @li If Value's constructor and assignment taking a dereferenced std::initializer_list iterator.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ iterator insert(const_iterator p, std::initializer_list<value_type> il);
+
+ //! @pre \c p must be a valid iterator of \c *this in range <tt>[begin(), end())</tt>
+ //!
+ //! @brief Erases Value from p.
+ //!
+ //! @param p The position of the element which will be erased from the container.
+ //!
+ //! @par Throws
+ //! If Value's move assignment throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ iterator erase(const_iterator p);
+
+ //! @pre
+ //! @li \c first and \c last must define a valid range
+ //! @li iterators must be in range <tt>[begin(), end()]</tt>
+ //!
+ //! @brief Erases Values from a range <tt>[first, last)</tt>.
+ //!
+ //! @param first The position of the first element of a range which will be erased from the container.
+ //! @param last The position of the one after the last element of a range which will be erased from the container.
+ //!
+ //! @par Throws
+ //! If Value's move assignment throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ iterator erase(const_iterator first, const_iterator last);
+
+ //! @pre <tt>distance(first, last) <= capacity()</tt>
+ //!
+ //! @brief Assigns a range <tt>[first, last)</tt> of Values to this container.
+ //!
+ //! @param first The iterator to the first element of a range used to construct new content of this container.
+ //! @param last The iterator to the one after the last element of a range used to construct new content of this container.
+ //!
+ //! @par Throws
+ //! If Value's copy constructor or copy assignment throws,
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ template <typename Iterator>
+ void assign(Iterator first, Iterator last);
+
+ //! @pre <tt>distance(il.begin(), il.end()) <= capacity()</tt>
+ //!
+ //! @brief Assigns a range <tt>[il.begin(), il.end())</tt> of Values to this container.
+ //!
+ //! @param il std::initializer_list with values used to construct new content of this container.
+ //!
+ //! @par Throws
+ //! If Value's copy constructor or copy assignment throws,
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ void assign(std::initializer_list<value_type> il);
+
+ //! @pre <tt>count <= capacity()</tt>
+ //!
+ //! @brief Assigns a count copies of value to this container.
+ //!
+ //! @param count The new number of elements which will be container in the container.
+ //! @param value The value which will be used to copy construct the new content.
+ //!
+ //! @par Throws
+ //! If Value's copy constructor or copy assignment throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ void assign(size_type count, value_type const& value);
+
+ //! @pre <tt>size() < capacity()</tt>
+ //!
+ //! @brief Inserts a Value constructed with
+ //! \c std::forward<Args>(args)... in the end of the container.
+ //!
+ //! @return A reference to the created object.
+ //!
+ //! @param args The arguments of the constructor of the new element which will be created at the end of the container.
+ //!
+ //! @par Throws
+ //! If in-place constructor throws or Value's move constructor throws.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ template<class ...Args>
+ reference emplace_back(Args &&...args);
+
+ //! @pre
+ //! @li \c p must be a valid iterator of \c *this in range <tt>[begin(), end()]</tt>
+ //! @li <tt>size() < capacity()</tt>
+ //!
+ //! @brief Inserts a Value constructed with
+ //! \c std::forward<Args>(args)... before p
+ //!
+ //! @param p The position at which new elements will be inserted.
+ //! @param args The arguments of the constructor of the new element.
+ //!
+ //! @par Throws
+ //! If in-place constructor throws or if Value's move constructor or move assignment throws.
+ //!
+ //! @par Complexity
+ //! Constant or linear.
+ template<class ...Args>
+ iterator emplace(const_iterator p, Args &&...args);
+
+ //! @brief Removes all elements from the container.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ void clear() BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @pre <tt>i < size()</tt>
+ //!
+ //! @brief Returns reference to the i-th element.
+ //!
+ //! @param i The element's index.
+ //!
+ //! @return reference to the i-th element
+ //! from the beginning of the container.
+ //!
+ //! @par Throws
+ //! \c std::out_of_range exception by default.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ reference at(size_type i);
+
+ //! @pre <tt>i < size()</tt>
+ //!
+ //! @brief Returns const reference to the i-th element.
+ //!
+ //! @param i The element's index.
+ //!
+ //! @return const reference to the i-th element
+ //! from the beginning of the container.
+ //!
+ //! @par Throws
+ //! \c std::out_of_range exception by default.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_reference at(size_type i) const;
+
+ //! @pre <tt>i < size()</tt>
+ //!
+ //! @brief Returns reference to the i-th element.
+ //!
+ //! @param i The element's index.
+ //!
+ //! @return reference to the i-th element
+ //! from the beginning of the container.
+ //!
+ //! @par Throws
+ //! Nothing by default.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ reference operator[](size_type i);
+
+ //! @pre <tt>i < size()</tt>
+ //!
+ //! @brief Returns const reference to the i-th element.
+ //!
+ //! @param i The element's index.
+ //!
+ //! @return const reference to the i-th element
+ //! from the beginning of the container.
+ //!
+ //! @par Throws
+ //! Nothing by default.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_reference operator[](size_type i) const;
+
+ //! @pre <tt>i =< size()</tt>
+ //!
+ //! @brief Returns a iterator to the i-th element.
+ //!
+ //! @param i The element's index.
+ //!
+ //! @return a iterator to the i-th element.
+ //!
+ //! @par Throws
+ //! Nothing by default.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ iterator nth(size_type i);
+
+ //! @pre <tt>i =< size()</tt>
+ //!
+ //! @brief Returns a const_iterator to the i-th element.
+ //!
+ //! @param i The element's index.
+ //!
+ //! @return a const_iterator to the i-th element.
+ //!
+ //! @par Throws
+ //! Nothing by default.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_iterator nth(size_type i) const;
+
+ //! @pre <tt>begin() <= p <= end()</tt>
+ //!
+ //! @brief Returns the index of the element pointed by p.
+ //!
+ //! @param p An iterator to the element.
+ //!
+ //! @return The index of the element pointed by p.
+ //!
+ //! @par Throws
+ //! Nothing by default.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ size_type index_of(iterator p);
+
+ //! @pre <tt>begin() <= p <= end()</tt>
+ //!
+ //! @brief Returns the index of the element pointed by p.
+ //!
+ //! @param p A const_iterator to the element.
+ //!
+ //! @return a const_iterator to the i-th element.
+ //!
+ //! @par Throws
+ //! Nothing by default.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ size_type index_of(const_iterator p) const;
+
+ //! @pre \c !empty()
+ //!
+ //! @brief Returns reference to the first element.
+ //!
+ //! @return reference to the first element
+ //! from the beginning of the container.
+ //!
+ //! @par Throws
+ //! Nothing by default.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ reference front();
+
+ //! @pre \c !empty()
+ //!
+ //! @brief Returns const reference to the first element.
+ //!
+ //! @return const reference to the first element
+ //! from the beginning of the container.
+ //!
+ //! @par Throws
+ //! Nothing by default.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_reference front() const;
+
+ //! @pre \c !empty()
+ //!
+ //! @brief Returns reference to the last element.
+ //!
+ //! @return reference to the last element
+ //! from the beginning of the container.
+ //!
+ //! @par Throws
+ //! Nothing by default.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ reference back();
+
+ //! @pre \c !empty()
+ //!
+ //! @brief Returns const reference to the first element.
+ //!
+ //! @return const reference to the last element
+ //! from the beginning of the container.
+ //!
+ //! @par Throws
+ //! Nothing by default.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_reference back() const;
+
+ //! @brief Pointer such that <tt>[data(), data() + size())</tt> is a valid range.
+ //! For a non-empty vector <tt>data() == &front()</tt>.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ Value * data() BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @brief Const pointer such that <tt>[data(), data() + size())</tt> is a valid range.
+ //! For a non-empty vector <tt>data() == &front()</tt>.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const Value * data() const BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @brief Returns iterator to the first element.
+ //!
+ //! @return iterator to the first element contained in the vector.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ iterator begin() BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @brief Returns const iterator to the first element.
+ //!
+ //! @return const_iterator to the first element contained in the vector.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @brief Returns const iterator to the first element.
+ //!
+ //! @return const_iterator to the first element contained in the vector.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @brief Returns iterator to the one after the last element.
+ //!
+ //! @return iterator pointing to the one after the last element contained in the vector.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ iterator end() BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @brief Returns const iterator to the one after the last element.
+ //!
+ //! @return const_iterator pointing to the one after the last element contained in the vector.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @brief Returns const iterator to the one after the last element.
+ //!
+ //! @return const_iterator pointing to the one after the last element contained in the vector.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @brief Returns reverse iterator to the first element of the reversed container.
+ //!
+ //! @return reverse_iterator pointing to the beginning
+ //! of the reversed static_vector.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @brief Returns const reverse iterator to the first element of the reversed container.
+ //!
+ //! @return const_reverse_iterator pointing to the beginning
+ //! of the reversed static_vector.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @brief Returns const reverse iterator to the first element of the reversed container.
+ //!
+ //! @return const_reverse_iterator pointing to the beginning
+ //! of the reversed static_vector.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @brief Returns reverse iterator to the one after the last element of the reversed container.
+ //!
+ //! @return reverse_iterator pointing to the one after the last element
+ //! of the reversed static_vector.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @brief Returns const reverse iterator to the one after the last element of the reversed container.
+ //!
+ //! @return const_reverse_iterator pointing to the one after the last element
+ //! of the reversed static_vector.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @brief Returns const reverse iterator to the one after the last element of the reversed container.
+ //!
+ //! @return const_reverse_iterator pointing to the one after the last element
+ //! of the reversed static_vector.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @brief Returns container's capacity.
+ //!
+ //! @return container's capacity.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ static size_type capacity() BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @brief Returns container's capacity.
+ //!
+ //! @return container's capacity.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ static size_type max_size() BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @brief Returns the number of stored elements.
+ //!
+ //! @return Number of elements contained in the container.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ size_type size() const BOOST_NOEXCEPT_OR_NOTHROW;
+
+ //! @brief Queries if the container contains elements.
+ //!
+ //! @return true if the number of elements contained in the
+ //! container is equal to 0.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ bool empty() const BOOST_NOEXCEPT_OR_NOTHROW;
+#else
+
+ BOOST_CONTAINER_FORCEINLINE friend void swap(static_vector &x, static_vector &y)
+ {
+ x.swap(y);
+ }
+
+#endif // BOOST_CONTAINER_DOXYGEN_INVOKED
+
+};
+
+#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+//! @brief Checks if contents of two static_vectors are equal.
+//!
+//! @ingroup static_vector_non_member
+//!
+//! @param x The first static_vector.
+//! @param y The second static_vector.
+//!
+//! @return \c true if containers have the same size and elements in both containers are equal.
+//!
+//! @par Complexity
+//! Linear O(N).
+template<typename V, std::size_t C1, std::size_t C2>
+bool operator== (static_vector<V, C1> const& x, static_vector<V, C2> const& y);
+
+//! @brief Checks if contents of two static_vectors are not equal.
+//!
+//! @ingroup static_vector_non_member
+//!
+//! @param x The first static_vector.
+//! @param y The second static_vector.
+//!
+//! @return \c true if containers have different size or elements in both containers are not equal.
+//!
+//! @par Complexity
+//! Linear O(N).
+template<typename V, std::size_t C1, std::size_t C2>
+bool operator!= (static_vector<V, C1> const& x, static_vector<V, C2> const& y);
+
+//! @brief Lexicographically compares static_vectors.
+//!
+//! @ingroup static_vector_non_member
+//!
+//! @param x The first static_vector.
+//! @param y The second static_vector.
+//!
+//! @return \c true if x compares lexicographically less than y.
+//!
+//! @par Complexity
+//! Linear O(N).
+template<typename V, std::size_t C1, std::size_t C2>
+bool operator< (static_vector<V, C1> const& x, static_vector<V, C2> const& y);
+
+//! @brief Lexicographically compares static_vectors.
+//!
+//! @ingroup static_vector_non_member
+//!
+//! @param x The first static_vector.
+//! @param y The second static_vector.
+//!
+//! @return \c true if y compares lexicographically less than x.
+//!
+//! @par Complexity
+//! Linear O(N).
+template<typename V, std::size_t C1, std::size_t C2>
+bool operator> (static_vector<V, C1> const& x, static_vector<V, C2> const& y);
+
+//! @brief Lexicographically compares static_vectors.
+//!
+//! @ingroup static_vector_non_member
+//!
+//! @param x The first static_vector.
+//! @param y The second static_vector.
+//!
+//! @return \c true if y don't compare lexicographically less than x.
+//!
+//! @par Complexity
+//! Linear O(N).
+template<typename V, std::size_t C1, std::size_t C2>
+bool operator<= (static_vector<V, C1> const& x, static_vector<V, C2> const& y);
+
+//! @brief Lexicographically compares static_vectors.
+//!
+//! @ingroup static_vector_non_member
+//!
+//! @param x The first static_vector.
+//! @param y The second static_vector.
+//!
+//! @return \c true if x don't compare lexicographically less than y.
+//!
+//! @par Complexity
+//! Linear O(N).
+template<typename V, std::size_t C1, std::size_t C2>
+bool operator>= (static_vector<V, C1> const& x, static_vector<V, C2> const& y);
+
+//! @brief Swaps contents of two static_vectors.
+//!
+//! This function calls static_vector::swap().
+//!
+//! @ingroup static_vector_non_member
+//!
+//! @param x The first static_vector.
+//! @param y The second static_vector.
+//!
+//! @par Complexity
+//! Linear O(N).
+template<typename V, std::size_t C1, std::size_t C2>
+inline void swap(static_vector<V, C1> & x, static_vector<V, C2> & y);
+
+#else
+
+template<typename V, std::size_t C1, std::size_t C2>
+inline void swap(static_vector<V, C1> & x, static_vector<V, C2> & y
+ , typename dtl::enable_if_c< C1 != C2>::type * = 0)
+{
+ x.swap(y);
+}
+
+#endif // BOOST_CONTAINER_DOXYGEN_INVOKED
+
+}} // namespace boost::container
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif // BOOST_CONTAINER_STATIC_VECTOR_HPP
diff --git a/include/boost/container/string.hpp b/include/boost/container/string.hpp
new file mode 100644
index 0000000..6c0cc96
--- /dev/null
+++ b/include/boost/container/string.hpp
@@ -0,0 +1,3459 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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 http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_STRING_HPP
+#define BOOST_CONTAINER_STRING_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/container_fwd.hpp>
+// container
+#include <boost/container/allocator_traits.hpp>
+#include <boost/container/new_allocator.hpp> //new_allocator
+#include <boost/container/throw_exception.hpp>
+// container/detail
+#include <boost/container/detail/alloc_helpers.hpp>
+#include <boost/container/detail/allocator_version_traits.hpp>
+#include <boost/container/detail/allocation_type.hpp>
+#include <boost/container/detail/iterator.hpp>
+#include <boost/container/detail/iterators.hpp>
+#include <boost/container/detail/min_max.hpp>
+#include <boost/container/detail/mpl.hpp>
+#include <boost/container/detail/next_capacity.hpp>
+#include <boost/move/detail/to_raw_pointer.hpp>
+#include <boost/container/detail/version_type.hpp>
+#include <boost/container/detail/type_traits.hpp>
+#include <boost/container/detail/minimal_char_traits_header.hpp>
+#include <boost/container/detail/algorithm.hpp>
+
+#include <boost/intrusive/pointer_traits.hpp>
+
+#include <boost/move/utility_core.hpp>
+#include <boost/move/adl_move_swap.hpp>
+#include <boost/move/traits.hpp>
+
+#include <boost/static_assert.hpp>
+#include <boost/core/no_exceptions_support.hpp>
+#include <boost/functional/hash.hpp>
+
+#include <algorithm>
+#include <iosfwd>
+#include <istream>
+#include <ostream>
+#include <ios>
+#include <locale>
+#include <cstddef>
+#include <climits>
+
+//std
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+#include <initializer_list> //for std::initializer_list
+#endif
+
+
+namespace boost {
+namespace container {
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+namespace dtl {
+// ------------------------------------------------------------
+// Class basic_string_base.
+
+// basic_string_base is a helper class that makes it it easier to write
+// an exception-safe version of basic_string. The constructor allocates,
+// but does not initialize, a block of memory. The destructor
+// deallocates, but does not destroy elements within, a block of
+// memory. The destructor assumes that the memory either is the internal buffer,
+// or else points to a block of memory that was allocated using string_base's
+// allocator and whose size is this->m_storage.
+template <class Allocator>
+class basic_string_base
+{
+ basic_string_base & operator=(const basic_string_base &);
+ basic_string_base(const basic_string_base &);
+
+ typedef allocator_traits<Allocator> allocator_traits_type;
+ public:
+ typedef Allocator allocator_type;
+ typedef allocator_type stored_allocator_type;
+ typedef typename allocator_traits_type::pointer pointer;
+ typedef typename allocator_traits_type::value_type value_type;
+ typedef typename allocator_traits_type::size_type size_type;
+ typedef ::boost::intrusive::pointer_traits<pointer> pointer_traits;
+
+ basic_string_base()
+ : members_()
+ { init(); }
+
+ explicit basic_string_base(const allocator_type& a)
+ : members_(a)
+ { init(); }
+
+ explicit basic_string_base(BOOST_RV_REF(allocator_type) a)
+ : members_(boost::move(a))
+ { this->init(); }
+
+ basic_string_base(const allocator_type& a, size_type n)
+ : members_(a)
+ {
+ this->init();
+ this->allocate_initial_block(n);
+ }
+
+ explicit basic_string_base(size_type n)
+ : members_()
+ {
+ this->init();
+ this->allocate_initial_block(n);
+ }
+
+ ~basic_string_base()
+ {
+ if(!this->is_short()){
+ this->deallocate(this->priv_long_addr(), this->priv_long_storage());
+ }
+ }
+
+ private:
+
+ //This is the structure controlling a long string
+ struct long_t
+ {
+ size_type is_short : 1;
+ size_type length : (sizeof(size_type)*CHAR_BIT - 1);
+ size_type storage;
+ pointer start;
+
+ long_t()
+ {}
+
+ long_t(const long_t &other)
+ {
+ this->is_short = false;
+ length = other.length;
+ storage = other.storage;
+ start = other.start;
+ }
+
+ long_t &operator= (const long_t &other)
+ {
+ length = other.length;
+ storage = other.storage;
+ start = other.start;
+ return *this;
+ }
+ };
+
+ //This type is the first part of the structure controlling a short string
+ //The "data" member stores
+ struct short_header
+ {
+ unsigned char is_short : 1;
+ unsigned char length : (CHAR_BIT - 1);
+ };
+
+ //This type has the same alignment and size as long_t but it's POD
+ //so, unlike long_t, it can be placed in a union
+
+ typedef typename dtl::aligned_storage
+ <sizeof(long_t), dtl::alignment_of<long_t>::value>::type long_raw_t;
+
+ protected:
+ static const size_type MinInternalBufferChars = 8;
+ static const size_type AlignmentOfValueType =
+ alignment_of<value_type>::value;
+ static const size_type ShortDataOffset = ((sizeof(short_header)-1)/AlignmentOfValueType+1)*AlignmentOfValueType;
+ static const size_type ZeroCostInternalBufferChars =
+ (sizeof(long_t) - ShortDataOffset)/sizeof(value_type);
+ static const size_type UnalignedFinalInternalBufferChars =
+ (ZeroCostInternalBufferChars > MinInternalBufferChars) ?
+ ZeroCostInternalBufferChars : MinInternalBufferChars;
+
+ struct short_t
+ {
+ short_header h;
+ value_type data[UnalignedFinalInternalBufferChars];
+ };
+
+ union repr_t
+ {
+ long_raw_t r;
+ short_t s;
+
+ const short_t &short_repr() const
+ { return s; }
+
+ const long_t &long_repr() const
+ { return *static_cast<const long_t*>(static_cast<const void*>(r.data)); }
+
+ short_t &short_repr()
+ { return s; }
+
+ long_t &long_repr()
+ { return *static_cast<long_t*>(static_cast<void*>(&r)); }
+ };
+
+ struct members_holder
+ : public Allocator
+ {
+ members_holder()
+ : Allocator()
+ {}
+
+ template<class AllocatorConvertible>
+ explicit members_holder(BOOST_FWD_REF(AllocatorConvertible) a)
+ : Allocator(boost::forward<AllocatorConvertible>(a))
+ {}
+
+ repr_t m_repr;
+ } members_;
+
+ const Allocator &alloc() const
+ { return members_; }
+
+ Allocator &alloc()
+ { return members_; }
+
+ static const size_type InternalBufferChars = (sizeof(repr_t) - ShortDataOffset)/sizeof(value_type);
+
+ private:
+
+ static const size_type MinAllocation = InternalBufferChars*2;
+
+ protected:
+ bool is_short() const
+ {
+ //Access and copy (to avoid UB) the first byte of the union to know if the
+ //active representation is short or long
+ short_header hdr;
+ BOOST_STATIC_ASSERT((sizeof(short_header) == 1));
+ *(unsigned char*)&hdr = *(unsigned char*)&this->members_.m_repr;
+ return hdr.is_short != 0;
+ }
+
+ void is_short(bool yes)
+ {
+ const bool was_short = this->is_short();
+ if(yes && !was_short){
+ allocator_traits_type::destroy
+ ( this->alloc()
+ , static_cast<long_t*>(static_cast<void*>(&this->members_.m_repr.r))
+ );
+ this->members_.m_repr.s.h.is_short = true;
+ }
+ else if(!yes && was_short){
+ allocator_traits_type::construct
+ ( this->alloc()
+ , static_cast<long_t*>(static_cast<void*>(&this->members_.m_repr.r))
+ );
+ this->members_.m_repr.s.h.is_short = false;
+ }
+ }
+
+ private:
+ void init()
+ {
+ this->members_.m_repr.s.h.is_short = 1;
+ this->members_.m_repr.s.h.length = 0;
+ }
+
+ protected:
+
+ typedef dtl::integral_constant<unsigned,
+ boost::container::dtl::version<Allocator>::value> alloc_version;
+
+ pointer allocation_command(allocation_type command,
+ size_type limit_size,
+ size_type &prefer_in_recvd_out_size,
+ pointer &reuse)
+ {
+ if(this->is_short() && (command & (expand_fwd | expand_bwd)) ){
+ reuse = 0;
+ command &= ~(expand_fwd | expand_bwd);
+ }
+ return dtl::allocator_version_traits<Allocator>::allocation_command
+ (this->alloc(), command, limit_size, prefer_in_recvd_out_size, reuse);
+ }
+
+ size_type next_capacity(size_type additional_objects) const
+ {
+ return growth_factor_100()
+ ( this->priv_storage(), additional_objects, allocator_traits_type::max_size(this->alloc()));
+ }
+
+ void deallocate(pointer p, size_type n)
+ {
+ if (p && (n > InternalBufferChars))
+ this->alloc().deallocate(p, n);
+ }
+
+ void construct(pointer p, const value_type &value = value_type())
+ {
+ allocator_traits_type::construct
+ ( this->alloc()
+ , boost::movelib::to_raw_pointer(p)
+ , value
+ );
+ }
+
+ void destroy(pointer p, size_type n)
+ {
+ value_type *raw_p = boost::movelib::to_raw_pointer(p);
+ for(; n--; ++raw_p){
+ allocator_traits_type::destroy( this->alloc(), raw_p);
+ }
+ }
+
+ void destroy(pointer p)
+ {
+ allocator_traits_type::destroy
+ ( this->alloc()
+ , boost::movelib::to_raw_pointer(p)
+ );
+ }
+
+ void allocate_initial_block(size_type n)
+ {
+ if (n <= this->max_size()) {
+ if(n > InternalBufferChars){
+ size_type new_cap = this->next_capacity(n);
+ pointer reuse = 0;
+ pointer p = this->allocation_command(allocate_new, n, new_cap, reuse);
+ this->is_short(false);
+ this->priv_long_addr(p);
+ this->priv_long_size(0);
+ this->priv_storage(new_cap);
+ }
+ }
+ else{
+ throw_length_error("basic_string::allocate_initial_block max_size() exceeded");
+ }
+ }
+
+ void deallocate_block()
+ { this->deallocate(this->priv_addr(), this->priv_storage()); }
+
+ size_type max_size() const
+ { return allocator_traits_type::max_size(this->alloc()) - 1; }
+
+ protected:
+ size_type priv_capacity() const
+ { return this->priv_storage() - 1; }
+
+ pointer priv_short_addr() const
+ { return pointer_traits::pointer_to(const_cast<value_type&>(this->members_.m_repr.short_repr().data[0])); }
+
+ pointer priv_long_addr() const
+ { return this->members_.m_repr.long_repr().start; }
+
+ pointer priv_addr() const
+ {
+ return this->is_short()
+ ? priv_short_addr()
+ : priv_long_addr()
+ ;
+ }
+
+ pointer priv_end_addr() const
+ {
+ return this->is_short()
+ ? this->priv_short_addr() + this->priv_short_size()
+ : this->priv_long_addr() + this->priv_long_size()
+ ;
+ }
+
+ void priv_long_addr(pointer addr)
+ { this->members_.m_repr.long_repr().start = addr; }
+
+ size_type priv_storage() const
+ { return this->is_short() ? priv_short_storage() : priv_long_storage(); }
+
+ size_type priv_short_storage() const
+ { return InternalBufferChars; }
+
+ size_type priv_long_storage() const
+ { return this->members_.m_repr.long_repr().storage; }
+
+ void priv_storage(size_type storage)
+ {
+ if(!this->is_short())
+ this->priv_long_storage(storage);
+ }
+
+ void priv_long_storage(size_type storage)
+ {
+ this->members_.m_repr.long_repr().storage = storage;
+ }
+
+ size_type priv_size() const
+ { return this->is_short() ? this->priv_short_size() : this->priv_long_size(); }
+
+ size_type priv_short_size() const
+ { return this->members_.m_repr.short_repr().h.length; }
+
+ size_type priv_long_size() const
+ { return this->members_.m_repr.long_repr().length; }
+
+ void priv_size(size_type sz)
+ {
+ if(this->is_short())
+ this->priv_short_size(sz);
+ else
+ this->priv_long_size(sz);
+ }
+
+ void priv_short_size(size_type sz)
+ {
+ this->members_.m_repr.s.h.length = (unsigned char)sz;
+ }
+
+ void priv_long_size(size_type sz)
+ {
+ this->members_.m_repr.long_repr().length = sz;
+ }
+
+ void swap_data(basic_string_base& other)
+ {
+ if(this->is_short()){
+ if(other.is_short()){
+ repr_t tmp(this->members_.m_repr);
+ this->members_.m_repr = other.members_.m_repr;
+ other.members_.m_repr = tmp;
+ }
+ else{
+ short_t short_backup(this->members_.m_repr.short_repr());
+ this->members_.m_repr.short_repr().~short_t();
+ ::new(&this->members_.m_repr.long_repr()) long_t(other.members_.m_repr.long_repr());
+ other.members_.m_repr.long_repr().~long_t();
+ ::new(&other.members_.m_repr.short_repr()) short_t(short_backup);
+ }
+ }
+ else{
+ if(other.is_short()){
+ short_t short_backup(other.members_.m_repr.short_repr());
+ other.members_.m_repr.short_repr().~short_t();
+ ::new(&other.members_.m_repr.long_repr()) long_t(this->members_.m_repr.long_repr());
+ this->members_.m_repr.long_repr().~long_t();
+ ::new(&this->members_.m_repr.short_repr()) short_t(short_backup);
+ }
+ else{
+ boost::adl_move_swap(this->members_.m_repr.long_repr(), other.members_.m_repr.long_repr());
+ }
+ }
+ }
+};
+
+} //namespace dtl {
+
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+//! The basic_string class represents a Sequence of characters. It contains all the
+//! usual operations of a Sequence, and, additionally, it contains standard string
+//! operations such as search and concatenation.
+//!
+//! The basic_string class is parameterized by character type, and by that type's
+//! Character Traits.
+//!
+//! This class has performance characteristics very much like vector<>, meaning,
+//! for example, that it does not perform reference-count or copy-on-write, and that
+//! concatenation of two strings is an O(N) operation.
+//!
+//! Some of basic_string's member functions use an unusual method of specifying positions
+//! and ranges. In addition to the conventional method using iterators, many of
+//! basic_string's member functions use a single value pos of type size_type to represent a
+//! position (in which case the position is begin() + pos, and many of basic_string's
+//! member functions use two values, pos and n, to represent a range. In that case pos is
+//! the beginning of the range and n is its size. That is, the range is
+//! [begin() + pos, begin() + pos + n).
+//!
+//! Note that the C++ standard does not specify the complexity of basic_string operations.
+//! In this implementation, basic_string has performance characteristics very similar to
+//! those of vector: access to a single character is O(1), while copy and concatenation
+//! are O(N).
+//!
+//! In this implementation, begin(),
+//! end(), rbegin(), rend(), operator[], c_str(), and data() do not invalidate iterators.
+//! In this implementation, iterators are only invalidated by member functions that
+//! explicitly change the string's contents.
+//!
+//! \tparam CharT The type of character it contains.
+//! \tparam Traits The Character Traits type, which encapsulates basic character operations
+//! \tparam Allocator The allocator, used for internal memory management.
+#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
+template <class CharT, class Traits = std::char_traits<CharT>, class Allocator = new_allocator<CharT> >
+#else
+template <class CharT, class Traits, class Allocator>
+#endif
+class basic_string
+ : private dtl::basic_string_base<Allocator>
+{
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ private:
+ typedef allocator_traits<Allocator> allocator_traits_type;
+ BOOST_COPYABLE_AND_MOVABLE(basic_string)
+ typedef dtl::basic_string_base<Allocator> base_t;
+ static const typename base_t::size_type InternalBufferChars = base_t::InternalBufferChars;
+
+ protected:
+ // Allocator helper class to use a char_traits as a function object.
+
+ template <class Tr>
+ struct Eq_traits
+ {
+ //Compatibility with std::binary_function
+ typedef typename Tr::char_type first_argument_type;
+ typedef typename Tr::char_type second_argument_type;
+ typedef bool result_type;
+
+ bool operator()(const first_argument_type& x, const second_argument_type& y) const
+ { return Tr::eq(x, y); }
+ };
+
+ template <class Tr>
+ struct Not_within_traits
+ {
+ typedef typename Tr::char_type argument_type;
+ typedef bool result_type;
+
+ typedef const typename Tr::char_type* Pointer;
+ const Pointer m_first;
+ const Pointer m_last;
+
+ Not_within_traits(Pointer f, Pointer l)
+ : m_first(f), m_last(l) {}
+
+ bool operator()(const typename Tr::char_type& x) const
+ {
+ return boost::container::find_if(m_first, m_last,
+ boost::container::bind1st(Eq_traits<Tr>(), x)) == m_last;
+ }
+ };
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ public:
+ //////////////////////////////////////////////
+ //
+ // types
+ //
+ //////////////////////////////////////////////
+ typedef Traits traits_type;
+ typedef CharT 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;
+ typedef typename ::boost::container::allocator_traits<Allocator>::const_reference const_reference;
+ typedef typename ::boost::container::allocator_traits<Allocator>::size_type size_type;
+ typedef typename ::boost::container::allocator_traits<Allocator>::difference_type difference_type;
+ typedef Allocator allocator_type;
+ typedef BOOST_CONTAINER_IMPDEF(allocator_type) stored_allocator_type;
+ typedef BOOST_CONTAINER_IMPDEF(pointer) iterator;
+ typedef BOOST_CONTAINER_IMPDEF(const_pointer) const_iterator;
+ typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<iterator>) reverse_iterator;
+ typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<const_iterator>) const_reverse_iterator;
+ static const size_type npos = size_type(-1);
+
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ private:
+ typedef constant_iterator<CharT, difference_type> cvalue_iterator;
+ typedef typename base_t::alloc_version alloc_version;
+ typedef ::boost::intrusive::pointer_traits<pointer> pointer_traits;
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ public: // Constructor, destructor, assignment.
+ //////////////////////////////////////////////
+ //
+ // construct/copy/destroy
+ //
+ //////////////////////////////////////////////
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ struct reserve_t {};
+
+ basic_string(reserve_t, size_type n,
+ const allocator_type& a = allocator_type())
+ //Select allocator as in copy constructor as reserve_t-based constructors
+ //are two step copies optimized for capacity
+ : base_t( allocator_traits_type::select_on_container_copy_construction(a)
+ , n + 1)
+ { this->priv_terminate_string(); }
+
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ //! <b>Effects</b>: Default constructs a basic_string.
+ //!
+ //! <b>Throws</b>: If allocator_type's default constructor throws.
+ basic_string() BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<Allocator>::value)
+ : base_t()
+ { this->priv_terminate_string(); }
+
+
+ //! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter.
+ //!
+ //! <b>Throws</b>: Nothing
+ explicit basic_string(const allocator_type& a) BOOST_NOEXCEPT_OR_NOTHROW
+ : base_t(a)
+ { this->priv_terminate_string(); }
+
+ //! <b>Effects</b>: Copy constructs a basic_string.
+ //!
+ //! <b>Postcondition</b>: x == *this.
+ //!
+ //! <b>Throws</b>: If allocator_type's default constructor or allocation throws.
+ basic_string(const basic_string& s)
+ : base_t(allocator_traits_type::select_on_container_copy_construction(s.alloc()))
+ {
+ this->priv_terminate_string();
+ this->assign(s.begin(), s.end());
+ }
+
+ //! <b>Effects</b>: Same as basic_string(sv.data(), sv.size(), a).
+ //!
+ //! <b>Throws</b>: If allocator_type's default constructor or allocation throws.
+ template<template <class, class> class BasicStringView>
+ explicit basic_string(BasicStringView<CharT, Traits> sv, const Allocator& a = Allocator())
+ : base_t(allocator_traits_type::select_on_container_copy_construction(a))
+ {
+ this->priv_terminate_string();
+ this->assign(sv);
+ }
+
+ //! <b>Effects</b>: Move constructor. Moves s's resources to *this.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ basic_string(BOOST_RV_REF(basic_string) s) BOOST_NOEXCEPT_OR_NOTHROW
+ : base_t(boost::move(s.alloc()))
+ {
+ if(s.alloc() == this->alloc()){
+ this->swap_data(s);
+ }
+ else{
+ this->assign(s.begin(), s.end());
+ }
+ }
+
+ //! <b>Effects</b>: Copy constructs a basic_string using the specified allocator.
+ //!
+ //! <b>Postcondition</b>: x == *this.
+ //!
+ //! <b>Throws</b>: If allocation throws.
+ basic_string(const basic_string& s, const allocator_type &a)
+ : base_t(a)
+ {
+ this->priv_terminate_string();
+ this->assign(s.begin(), s.end());
+ }
+
+ //! <b>Effects</b>: Move constructor using the specified allocator.
+ //! Moves s's resources to *this.
+ //!
+ //! <b>Throws</b>: If allocation throws.
+ //!
+ //! <b>Complexity</b>: Constant if a == s.get_allocator(), linear otherwise.
+ basic_string(BOOST_RV_REF(basic_string) s, const allocator_type &a)
+ : base_t(a)
+ {
+ this->priv_terminate_string();
+ if(a == this->alloc()){
+ this->swap_data(s);
+ }
+ else{
+ this->assign(s.begin(), s.end());
+ }
+ }
+
+ //! <b>Effects</b>: Constructs a basic_string with a default-constructed allocator,
+ //! and is initialized by a specific number of characters of the s string.
+ basic_string(const basic_string& s, size_type pos, size_type n = npos)
+ : base_t()
+ {
+ this->priv_terminate_string();
+ if (pos > s.size())
+ throw_out_of_range("basic_string::basic_string out of range position");
+ else
+ this->assign
+ (s.begin() + pos, s.begin() + pos + dtl::min_value(n, s.size() - pos));
+ }
+
+ //! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter,
+ //! and is initialized by a specific number of characters of the s string.
+ basic_string(const basic_string& s, size_type pos, size_type n, const allocator_type& a)
+ : base_t(a)
+ {
+ this->priv_terminate_string();
+ if (pos > s.size())
+ throw_out_of_range("basic_string::basic_string out of range position");
+ else
+ this->assign
+ (s.begin() + pos, s.begin() + pos + dtl::min_value(n, s.size() - pos));
+ }
+
+ //! <b>Effects</b>: Constructs a basic_string taking a default-constructed allocator,
+ //! and is initialized by a specific number of characters of the s c-string.
+ basic_string(const CharT* s, size_type n)
+ : base_t()
+ {
+ this->priv_terminate_string();
+ this->assign(s, s + n);
+ }
+
+ //! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter,
+ //! and is initialized by a specific number of characters of the s c-string.
+ basic_string(const CharT* s, size_type n, const allocator_type& a)
+ : base_t(a)
+ {
+ this->priv_terminate_string();
+ this->assign(s, s + n);
+ }
+
+ //! <b>Effects</b>: Constructs a basic_string with a default-constructed allocator,
+ //! and is initialized by the null-terminated s c-string.
+ basic_string(const CharT* s)
+ : base_t()
+ {
+ this->priv_terminate_string();
+ this->assign(s, s + Traits::length(s));
+ }
+
+ //! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter,
+ //! and is initialized by the null-terminated s c-string.
+ basic_string(const CharT* s, const allocator_type& a)
+ : base_t(a)
+ {
+ this->priv_terminate_string();
+ this->assign(s, s + Traits::length(s));
+ }
+
+
+ //! <b>Effects</b>: Constructs a basic_string with a default-constructed allocator,
+ //! and is initialized by n copies of c.
+ basic_string(size_type n, CharT c)
+ : base_t()
+ {
+ this->priv_terminate_string();
+ this->assign(n, c);
+ }
+
+ //! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter,
+ //! and is initialized by n copies of c.
+ basic_string(size_type n, CharT c, const allocator_type& a)
+ : base_t(a)
+ {
+ this->priv_terminate_string();
+ this->assign(n, c);
+ }
+
+ //! <b>Effects</b>: Constructs a basic_string with a default-constructed allocator,
+ //! and is initialized by n default-initialized characters.
+ basic_string(size_type n, default_init_t)
+ : base_t(n + 1)
+ {
+ this->priv_size(n);
+ this->priv_terminate_string();
+ }
+
+ //! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter,
+ //! and is initialized by n default-initialized characters.
+ basic_string(size_type n, default_init_t, const allocator_type& a)
+ : base_t(a, n + 1)
+ {
+ this->priv_size(n);
+ this->priv_terminate_string();
+ }
+
+ //! <b>Effects</b>: Constructs a basic_string with a default-constructed allocator,
+ //! and a range of iterators.
+ template <class InputIterator>
+ basic_string(InputIterator f, InputIterator l)
+ : base_t()
+ {
+ this->priv_terminate_string();
+ this->assign(f, l);
+ }
+
+ //! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter,
+ //! and a range of iterators.
+ template <class InputIterator>
+ basic_string(InputIterator f, InputIterator l, const allocator_type& a)
+ : base_t(a)
+ {
+ this->priv_terminate_string();
+ this->assign(f, l);
+ }
+
+ #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Same as basic_string(il.begin(), il.end(), a).
+ //!
+ basic_string(std::initializer_list<value_type> il, const allocator_type& a = allocator_type())
+ : base_t(a)
+ {
+ this->priv_terminate_string();
+ this->assign(il.begin(), il.end());
+ }
+ #endif
+
+ //! <b>Effects</b>: Destroys the basic_string. All used memory is deallocated.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ ~basic_string() BOOST_NOEXCEPT_OR_NOTHROW
+ {}
+
+ //! <b>Effects</b>: Copy constructs a string.
+ //!
+ //! <b>Postcondition</b>: x == *this.
+ //!
+ //! <b>Complexity</b>: Linear to the elements x contains.
+ basic_string& operator=(BOOST_COPY_ASSIGN_REF(basic_string) x)
+ {
+ if (&x != this){
+ allocator_type &this_alloc = this->alloc();
+ const allocator_type &x_alloc = x.alloc();
+ dtl::bool_<allocator_traits_type::
+ propagate_on_container_copy_assignment::value> flag;
+ if(flag && this_alloc != x_alloc){
+ if(!this->is_short()){
+ this->deallocate_block();
+ this->is_short(true);
+ Traits::assign(*this->priv_addr(), CharT(0));
+ this->priv_short_size(0);
+ }
+ }
+ dtl::assign_alloc(this->alloc(), x.alloc(), flag);
+ this->assign(x.begin(), x.end());
+ }
+ return *this;
+ }
+
+ //! <b>Effects</b>: Move constructor. Moves x's resources to *this.
+ //!
+ //! <b>Throws</b>: If allocator_traits_type::propagate_on_container_move_assignment
+ //! is false and allocation throws
+ //!
+ //! <b>Complexity</b>: Constant if allocator_traits_type::
+ //! propagate_on_container_move_assignment is true or
+ //! this->get>allocator() == x.get_allocator(). Linear otherwise.
+ basic_string& operator=(BOOST_RV_REF(basic_string) x)
+ BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value
+ || allocator_traits_type::is_always_equal::value)
+ {
+ //for move constructor, no aliasing (&x != this) is assummed.
+ BOOST_ASSERT(this != &x);
+ allocator_type &this_alloc = this->alloc();
+ allocator_type &x_alloc = x.alloc();
+ const bool propagate_alloc = allocator_traits_type::
+ propagate_on_container_move_assignment::value;
+ dtl::bool_<propagate_alloc> flag;
+ const bool allocators_equal = this_alloc == x_alloc; (void)allocators_equal;
+ //Resources can be transferred if both allocators are
+ //going to be equal after this function (either propagated or already equal)
+ if(propagate_alloc || allocators_equal){
+ //Destroy objects but retain memory in case x reuses it in the future
+ this->clear();
+ //Move allocator if needed
+ dtl::move_alloc(this_alloc, x_alloc, flag);
+ //Nothrow swap
+ this->swap_data(x);
+ }
+ //Else do a one by one move
+ else{
+ this->assign( x.begin(), x.end());
+ }
+ return *this;
+ }
+
+ //! <b>Effects</b>: Assignment from a null-terminated c-string.
+ //!
+ basic_string& operator=(const CharT* s)
+ { return this->assign(s, s + Traits::length(s)); }
+
+ //! <b>Effects</b>: Returns *this = basic_string(1, c).
+ //!
+ basic_string& operator=(CharT c)
+ { return this->assign(static_cast<size_type>(1), c); }
+
+ //! <b>Effects</b>: Equivalent to return assign(sv).
+ //!
+ template<template <class, class> class BasicStringView>
+ basic_string& operator=(BasicStringView<CharT, Traits> sv)
+ { return this->assign(sv.data(), sv.size()); }
+
+ #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Returns *this = basic_string(il);
+ //!
+ basic_string& operator=(std::initializer_list<CharT> il)
+ {
+ return this->assign(il.begin(), il.end());
+ }
+ #endif
+
+ //! <b>Effects</b>: Returns a copy of the internal allocator.
+ //!
+ //! <b>Throws</b>: If allocator's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Constant.
+ allocator_type get_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->alloc(); }
+
+ //! <b>Effects</b>: Returns a reference to the internal allocator.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->alloc(); }
+
+ //! <b>Effects</b>: Returns a reference to the internal allocator.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->alloc(); }
+
+ //////////////////////////////////////////////
+ //
+ // iterators
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Returns an iterator to the first element contained in the vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ iterator begin() BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->priv_addr(); }
+
+ //! <b>Effects</b>: Returns a const_iterator to the first element contained in the vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->priv_addr(); }
+
+ //! <b>Effects</b>: Returns an iterator to the end of the vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ iterator end() BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->priv_end_addr(); }
+
+ //! <b>Effects</b>: Returns a const_iterator to the end of the vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->priv_end_addr(); }
+
+ //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
+ //! of the reversed vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW
+ { return reverse_iterator(this->priv_end_addr()); }
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
+ //! of the reversed vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->crbegin(); }
+
+ //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
+ //! of the reversed vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW
+ { return reverse_iterator(this->priv_addr()); }
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
+ //! of the reversed vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->crend(); }
+
+ //! <b>Effects</b>: Returns a const_iterator to the first element contained in the vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->priv_addr(); }
+
+ //! <b>Effects</b>: Returns a const_iterator to the end of the vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->priv_end_addr(); }
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
+ //! of the reversed vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return const_reverse_iterator(this->priv_end_addr()); }
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
+ //! of the reversed vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return const_reverse_iterator(this->priv_addr()); }
+
+ //////////////////////////////////////////////
+ //
+ // capacity
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Returns true if the vector contains no elements.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ bool empty() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return !this->priv_size(); }
+
+ //! <b>Effects</b>: Returns the number of the elements contained in the vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ size_type size() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->priv_size(); }
+
+ //! <b>Effects</b>: Returns the number of the elements contained in the vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ size_type length() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->size(); }
+
+ //! <b>Effects</b>: Returns the largest possible size of the vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return base_t::max_size(); }
+
+ //! <b>Effects</b>: Inserts or erases elements at the end such that
+ //! the size becomes n. New elements are copy constructed from x.
+ //!
+ //! <b>Throws</b>: If memory allocation throws
+ //!
+ //! <b>Complexity</b>: Linear to the difference between size() and new_size.
+ void resize(size_type n, CharT c)
+ {
+ if (n <= this->size())
+ this->erase(this->begin() + n, this->end());
+ else
+ this->append(n - this->size(), c);
+ }
+
+ //! <b>Effects</b>: Inserts or erases elements at the end such that
+ //! the size becomes n. New elements are value initialized.
+ //!
+ //! <b>Throws</b>: If memory allocation throws
+ //!
+ //! <b>Complexity</b>: Linear to the difference between size() and new_size.
+ void resize(size_type n)
+ { resize(n, CharT()); }
+
+
+ //! <b>Effects</b>: Inserts or erases elements at the end such that
+ //! the size becomes n. New elements are uninitialized.
+ //!
+ //! <b>Throws</b>: If memory allocation throws
+ //!
+ //! <b>Complexity</b>: Linear to the difference between size() and new_size.
+ //!
+ //! <b>Note</b>: Non-standard extension
+ void resize(size_type n, default_init_t)
+ {
+ if (n <= this->size())
+ this->erase(this->begin() + n, this->end());
+ else{
+ this->priv_reserve(n, false);
+ this->priv_size(n);
+ this->priv_terminate_string();
+ }
+ }
+
+ //! <b>Effects</b>: Number of elements for which memory has been allocated.
+ //! capacity() is always greater than or equal to size().
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->priv_capacity(); }
+
+ //! <b>Effects</b>: If n is less than or equal to capacity(), this call has no
+ //! effect. Otherwise, it is a request for allocation of additional memory.
+ //! If the request is successful, then capacity() is greater than or equal to
+ //! n; otherwise, capacity() is unchanged. In either case, size() is unchanged.
+ //!
+ //! <b>Throws</b>: If memory allocation allocation throws
+ void reserve(size_type res_arg)
+ { this->priv_reserve(res_arg); }
+
+ //! <b>Effects</b>: Tries to deallocate the excess of memory created
+ //! with previous allocations. The size of the string is unchanged
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Linear to size().
+ void shrink_to_fit()
+ {
+ //Check if shrinking is possible
+ if(this->priv_storage() > InternalBufferChars){
+ //Check if we should pass from dynamically allocated buffer
+ //to the internal storage
+ if(this->priv_size() < InternalBufferChars){
+ //Dynamically allocated buffer attributes
+ pointer long_addr = this->priv_long_addr();
+ size_type long_storage = this->priv_long_storage();
+ size_type long_size = this->priv_long_size();
+ //Shrink from allocated buffer to the internal one, including trailing null
+ Traits::copy( boost::movelib::to_raw_pointer(this->priv_short_addr())
+ , boost::movelib::to_raw_pointer(long_addr)
+ , long_size+1);
+ this->is_short(true);
+ this->alloc().deallocate(long_addr, long_storage);
+ }
+ else{
+ //Shrinking in dynamic buffer
+ this->priv_shrink_to_fit_dynamic_buffer(alloc_version());
+ }
+ }
+ }
+
+ //////////////////////////////////////////////
+ //
+ // element access
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Requires</b>: !empty()
+ //!
+ //! <b>Effects</b>: Returns a reference to the first
+ //! element of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ reference front() BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(!this->empty());
+ return *this->priv_addr();
+ }
+
+ //! <b>Requires</b>: !empty()
+ //!
+ //! <b>Effects</b>: Returns a const reference to the first
+ //! element of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reference front() const BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(!this->empty());
+ return *this->priv_addr();
+ }
+
+ //! <b>Requires</b>: !empty()
+ //!
+ //! <b>Effects</b>: Returns a reference to the last
+ //! element of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ reference back() BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(!this->empty());
+ return *(this->priv_addr() + (this->size() - 1u) );
+ }
+
+ //! <b>Requires</b>: !empty()
+ //!
+ //! <b>Effects</b>: Returns a const reference to the last
+ //! element of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reference back() const BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(!this->empty());
+ return *(this->priv_addr() + (this->size() - 1u) );
+ }
+
+ //! <b>Requires</b>: size() > n.
+ //!
+ //! <b>Effects</b>: Returns a reference to the nth element
+ //! from the beginning of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ reference operator[](size_type n) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(this->size() > n);
+ return *(this->priv_addr() + n);
+ }
+
+ //! <b>Requires</b>: size() > n.
+ //!
+ //! <b>Effects</b>: Returns a const reference to the nth element
+ //! from the beginning of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reference operator[](size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(this->size() > n);
+ return *(this->priv_addr() + n);
+ }
+
+ //! <b>Requires</b>: size() > n.
+ //!
+ //! <b>Effects</b>: Returns a reference to the nth element
+ //! from the beginning of the container.
+ //!
+ //! <b>Throws</b>: std::range_error if n >= size()
+ //!
+ //! <b>Complexity</b>: Constant.
+ reference at(size_type n)
+ {
+ if (n >= this->size())
+ throw_out_of_range("basic_string::at invalid subscript");
+ return *(this->priv_addr() + n);
+ }
+
+ //! <b>Requires</b>: size() > n.
+ //!
+ //! <b>Effects</b>: Returns a const reference to the nth element
+ //! from the beginning of the container.
+ //!
+ //! <b>Throws</b>: std::range_error if n >= size()
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reference at(size_type n) const {
+ if (n >= this->size())
+ throw_out_of_range("basic_string::at invalid subscript");
+ return *(this->priv_addr() + n);
+ }
+
+ //////////////////////////////////////////////
+ //
+ // modifiers
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Calls append(str.data, str.size()).
+ //!
+ //! <b>Returns</b>: *this
+ basic_string& operator+=(const basic_string& s)
+ { return this->append(s); }
+
+ //! <b>Effects</b>: Same as `return append(sv)`.
+ //!
+ template<template<class, class> class BasicStringView>
+ basic_string& operator+=(BasicStringView<CharT, Traits> sv)
+ {
+ return this->append(sv);
+ }
+
+ //! <b>Effects</b>: Calls append(s).
+ //!
+ //! <b>Returns</b>: *this
+ basic_string& operator+=(const CharT* s)
+ { return this->append(s); }
+
+ //! <b>Effects</b>: Calls append(1, c).
+ //!
+ //! <b>Returns</b>: *this
+ basic_string& operator+=(CharT c)
+ { this->push_back(c); return *this; }
+
+ #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Returns append(il)
+ //!
+ basic_string& operator+=(std::initializer_list<CharT> il)
+ {
+ return this->append(il);
+ }
+ #endif
+
+ //! <b>Effects</b>: Calls append(str.data(), str.size()).
+ //!
+ //! <b>Returns</b>: *this
+ basic_string& append(const basic_string& s)
+ { return this->append(s.begin(), s.end()); }
+
+ //! <b>Effects</b>: Same as return append(sv.data(), sv.size()).
+ //!
+ template<template<class, class> class BasicStringView>
+ basic_string& append(BasicStringView<CharT, Traits> sv)
+ { return this->append(sv.data(), sv.size()); }
+
+ //! <b>Requires</b>: pos <= str.size()
+ //!
+ //! <b>Effects</b>: Determines the effective length rlen of the string to append
+ //! as the smaller of n and str.size() - pos and calls append(str.data() + pos, rlen).
+ //!
+ //! <b>Throws</b>: If memory allocation throws and out_of_range if pos > str.size()
+ //!
+ //! <b>Returns</b>: *this
+ basic_string& append(const basic_string& s, size_type pos, size_type n = npos)
+ {
+ if (pos > s.size())
+ throw_out_of_range("basic_string::append out of range position");
+ return this->append(s.begin() + pos,
+ s.begin() + pos + dtl::min_value(n, s.size() - pos));
+ }
+
+ //! <b>Requires</b>: s points to an array of at least n elements of CharT.
+ //!
+ //! <b>Effects</b>: The function replaces the string controlled by *this with
+ //! a string of length size() + n whose irst size() elements are a copy of the
+ //! original string controlled by *this and whose remaining
+ //! elements are a copy of the initial n elements of s.
+ //!
+ //! <b>Throws</b>: If memory allocation throws length_error if size() + n > max_size().
+ //!
+ //! <b>Returns</b>: *this
+ basic_string& append(const CharT* s, size_type n)
+ { return this->append(s, s + n); }
+
+ //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
+ //!
+ //! <b>Effects</b>: Calls append(s, traits::length(s)).
+ //!
+ //! <b>Returns</b>: *this
+ basic_string& append(const CharT* s)
+ { return this->append(s, s + Traits::length(s)); }
+
+ //! <b>Effects</b>: Equivalent to append(basic_string(n, c)).
+ //!
+ //! <b>Returns</b>: *this
+ basic_string& append(size_type n, CharT c)
+ { return this->append(cvalue_iterator(c, n), cvalue_iterator()); }
+
+ //! <b>Requires</b>: [first,last) is a valid range.
+ //!
+ //! <b>Effects</b>: Equivalent to append(basic_string(first, last)).
+ //!
+ //! <b>Returns</b>: *this
+ template <class InputIter>
+ basic_string& append(InputIter first, InputIter last)
+ { this->insert(this->end(), first, last); return *this; }
+
+ #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Returns append(il.begin(), il.size()).
+ //!
+ basic_string& append(std::initializer_list<CharT> il)
+ {
+ return this->append(il.begin(), il.size());
+ }
+ #endif
+
+ //! <b>Effects</b>: Equivalent to append(static_cast<size_type>(1), c).
+ //!
+ void push_back(CharT c)
+ {
+ const size_type old_size = this->priv_size();
+ if (old_size < this->capacity()){
+ const pointer addr = this->priv_addr();
+ this->priv_construct_null(addr + old_size + 1);
+ Traits::assign(addr[old_size], c);
+ this->priv_size(old_size+1);
+ }
+ else{
+ //No enough memory, insert a new object at the end
+ this->append(size_type(1), c);
+ }
+ }
+
+ //! <b>Effects</b>: Equivalent to assign(str, 0, npos).
+ //!
+ //! <b>Returns</b>: *this
+ basic_string& assign(const basic_string& s)
+ { return this->operator=(s); }
+
+ //! <b>Effects</b>: Equivalent to return assign(sv.data(), sv.size()).
+ //!
+ //! <b>Returns</b>: *this
+ template<template <class, class> class BasicStringView>
+ basic_string& assign(BasicStringView<CharT, Traits> sv)
+ { return this->operator=(sv); }
+
+ //! <b>Effects</b>: The function replaces the string controlled by *this
+ //! with a string of length str.size() whose elements are a copy of the string
+ //! controlled by str. Leaves str in a valid but unspecified state.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Returns</b>: *this
+ basic_string& assign(BOOST_RV_REF(basic_string) ms) BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->swap_data(ms), *this; }
+
+ //! <b>Requires</b>: pos <= str.size()
+ //!
+ //! <b>Effects</b>: Determines the effective length rlen of the string to assign as
+ //! the smaller of n and str.size() - pos and calls assign(str.data() + pos rlen).
+ //!
+ //! <b>Throws</b>: If memory allocation throws or out_of_range if pos > str.size().
+ //!
+ //! <b>Returns</b>: *this
+ basic_string& assign(const basic_string& s, size_type pos, size_type n)
+ {
+ if (pos > s.size())
+ throw_out_of_range("basic_string::assign out of range position");
+ return this->assign(s.begin() + pos,
+ s.begin() + pos + dtl::min_value(n, s.size() - pos));
+ }
+
+ //! <b>Requires</b>: s points to an array of at least n elements of CharT.
+ //!
+ //! <b>Effects</b>: Replaces the string controlled by *this with a string of
+ //! length n whose elements are a copy of those pointed to by s.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or length_error if n > max_size().
+ //!
+ //! <b>Returns</b>: *this
+ basic_string& assign(const CharT* s, size_type n)
+ { return this->assign(s, s + n); }
+
+ //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
+ //!
+ //! <b>Effects</b>: Calls assign(s, traits::length(s)).
+ //!
+ //! <b>Returns</b>: *this
+ basic_string& assign(const CharT* s)
+ { return this->assign(s, s + Traits::length(s)); }
+
+ //! <b>Effects</b>: Equivalent to assign(basic_string(n, c)).
+ //!
+ //! <b>Returns</b>: *this
+ basic_string& assign(size_type n, CharT c)
+ { return this->assign(cvalue_iterator(c, n), cvalue_iterator()); }
+
+ //! <b>Effects</b>: Equivalent to assign(basic_string(first, last)).
+ //!
+ //! <b>Returns</b>: *this
+ basic_string& assign(const CharT* first, const CharT* last)
+ {
+ size_type n = static_cast<size_type>(last - first);
+ this->reserve(n);
+ CharT* ptr = boost::movelib::to_raw_pointer(this->priv_addr());
+ Traits::copy(ptr, first, n);
+ this->priv_construct_null(ptr + n);
+ this->priv_size(n);
+ return *this;
+ }
+
+ //! <b>Effects</b>: Equivalent to assign(basic_string(first, last)).
+ //!
+ //! <b>Returns</b>: *this
+ template <class InputIter>
+ basic_string& assign(InputIter first, InputIter last
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename dtl::disable_if_convertible<InputIter, size_type>::type * = 0
+ #endif
+ )
+ {
+ size_type cur = 0;
+ const pointer addr = this->priv_addr();
+ CharT *ptr = boost::movelib::to_raw_pointer(addr);
+ const size_type old_size = this->priv_size();
+ while (first != last && cur != old_size) {
+ Traits::assign(*ptr, *first);
+ ++first;
+ ++cur;
+ ++ptr;
+ }
+ if (first == last)
+ this->erase(addr + cur, addr + old_size);
+ else
+ this->append(first, last);
+ return *this;
+ }
+
+ #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Returns assign(il.begin(), il.size()).
+ //!
+ basic_string& assign(std::initializer_list<CharT> il)
+ {
+ return this->assign(il.begin(), il.size());
+ }
+ #endif
+
+ //! <b>Requires</b>: pos <= size().
+ //!
+ //! <b>Effects</b>: Calls insert(pos, str.data(), str.size()).
+ //!
+ //! <b>Throws</b>: If memory allocation throws or out_of_range if pos > size().
+ //!
+ //! <b>Returns</b>: *this
+ basic_string& insert(size_type pos, const basic_string& s)
+ {
+ const size_type sz = this->size();
+ if (pos > sz)
+ throw_out_of_range("basic_string::insert out of range position");
+ if (sz > this->max_size() - s.size())
+ throw_length_error("basic_string::insert max_size() exceeded");
+ this->insert(this->priv_addr() + pos, s.begin(), s.end());
+ return *this;
+ }
+
+ //! <b>Requires</b>: pos1 <= size() and pos2 <= str.size()
+ //!
+ //! <b>Effects</b>: Determines the effective length rlen of the string to insert as
+ //! the smaller of n and str.size() - pos2 and calls insert(pos1, str.data() + pos2, rlen).
+ //!
+ //! <b>Throws</b>: If memory allocation throws or out_of_range if pos1 > size() or pos2 > str.size().
+ //!
+ //! <b>Returns</b>: *this
+ basic_string& insert(size_type pos1, const basic_string& s, size_type pos2, size_type n = npos)
+ {
+ const size_type sz = this->size();
+ const size_type str_size = s.size();
+ if (pos1 > sz || pos2 > str_size)
+ throw_out_of_range("basic_string::insert out of range position");
+ size_type len = dtl::min_value(n, str_size - pos2);
+ if (sz > this->max_size() - len)
+ throw_length_error("basic_string::insert max_size() exceeded");
+ const CharT *beg_ptr = boost::movelib::to_raw_pointer(s.begin()) + pos2;
+ const CharT *end_ptr = beg_ptr + len;
+ this->insert(this->priv_addr() + pos1, beg_ptr, end_ptr);
+ return *this;
+ }
+
+ //! <b>Requires</b>: s points to an array of at least n elements of CharT and pos <= size().
+ //!
+ //! <b>Effects</b>: Replaces the string controlled by *this with a string of length size() + n
+ //! whose first pos elements are a copy of the initial elements of the original string
+ //! controlled by *this and whose next n elements are a copy of the elements in s and whose
+ //! remaining elements are a copy of the remaining elements of the original string controlled by *this.
+ //!
+ //! <b>Throws</b>: If memory allocation throws, out_of_range if pos > size() or
+ //! length_error if size() + n > max_size().
+ //!
+ //! <b>Returns</b>: *this
+ basic_string& insert(size_type pos, const CharT* s, size_type n)
+ {
+ if (pos > this->size())
+ throw_out_of_range("basic_string::insert out of range position");
+ if (this->size() > this->max_size() - n)
+ throw_length_error("basic_string::insert max_size() exceeded");
+ this->insert(this->priv_addr() + pos, s, s + n);
+ return *this;
+ }
+
+ //! <b>Requires</b>: pos <= size() and s points to an array of at least traits::length(s) + 1 elements of CharT
+ //!
+ //! <b>Effects</b>: Calls insert(pos, s, traits::length(s)).
+ //!
+ //! <b>Throws</b>: If memory allocation throws, out_of_range if pos > size()
+ //! length_error if size() > max_size() - Traits::length(s)
+ //!
+ //! <b>Returns</b>: *this
+ basic_string& insert(size_type pos, const CharT* s)
+ {
+ if (pos > this->size())
+ throw_out_of_range("basic_string::insert out of range position");
+ size_type len = Traits::length(s);
+ if (this->size() > this->max_size() - len)
+ throw_length_error("basic_string::insert max_size() exceeded");
+ this->insert(this->priv_addr() + pos, s, s + len);
+ return *this;
+ }
+
+ //! <b>Effects</b>: Equivalent to insert(pos, basic_string(n, c)).
+ //!
+ //! <b>Throws</b>: If memory allocation throws, out_of_range if pos > size()
+ //! length_error if size() > max_size() - n
+ //!
+ //! <b>Returns</b>: *this
+ basic_string& insert(size_type pos, size_type n, CharT c)
+ {
+ if (pos > this->size())
+ throw_out_of_range("basic_string::insert out of range position");
+ if (this->size() > this->max_size() - n)
+ throw_length_error("basic_string::insert max_size() exceeded");
+ this->insert(const_iterator(this->priv_addr() + pos), n, c);
+ return *this;
+ }
+
+ //! <b>Effects</b>: Same as `return insert(pos, sv.data(), sv.size())`.
+ //!
+ template<template<class, class> class BasicStringView>
+ basic_string& insert(size_type pos, BasicStringView<CharT, Traits> sv)
+ { return this->insert(pos, sv.data(), sv.size()); }
+
+ //! <b>Requires</b>: p is a valid iterator on *this.
+ //!
+ //! <b>Effects</b>: inserts a copy of c before the character referred to by p.
+ //!
+ //! <b>Returns</b>: An iterator which refers to the copy of the inserted character.
+ iterator insert(const_iterator p, CharT c)
+ {
+ size_type new_offset = p - this->priv_addr();
+ this->insert(p, cvalue_iterator(c, 1), cvalue_iterator());
+ return this->priv_addr() + new_offset;
+ }
+
+ //! <b>Requires</b>: p is a valid iterator on *this.
+ //!
+ //! <b>Effects</b>: Inserts n copies of c before the character referred to by p.
+ //!
+ //! <b>Returns</b>: an iterator to the first inserted element or p if n is 0.
+ iterator insert(const_iterator p, size_type n, CharT c)
+ { return this->insert(p, cvalue_iterator(c, n), cvalue_iterator()); }
+
+ //! <b>Requires</b>: p is a valid iterator on *this. [first,last) is a valid range.
+ //!
+ //! <b>Effects</b>: Equivalent to insert(p - begin(), basic_string(first, last)).
+ //!
+ //! <b>Returns</b>: an iterator to the first inserted element or p if first == last.
+ template <class InputIter>
+ iterator insert(const_iterator p, InputIter first, InputIter last
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename dtl::disable_if_or
+ < void
+ , dtl::is_convertible<InputIter, size_type>
+ , dtl::is_not_input_iterator<InputIter>
+ >::type * = 0
+ #endif
+ )
+ {
+ const size_type n_pos = p - this->cbegin();
+ for ( ; first != last; ++first, ++p) {
+ p = this->insert(p, *first);
+ }
+ return this->begin() + n_pos;
+ }
+
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ template <class ForwardIter>
+ iterator insert(const_iterator p, ForwardIter first, ForwardIter last
+ , typename dtl::disable_if_or
+ < void
+ , dtl::is_convertible<ForwardIter, size_type>
+ , dtl::is_input_iterator<ForwardIter>
+ >::type * = 0
+ )
+ {
+ const size_type n_pos = p - this->cbegin();
+ if (first != last) {
+ const size_type n = boost::container::iterator_distance(first, last);
+ const size_type old_size = this->priv_size();
+ const size_type remaining = this->capacity() - old_size;
+ const pointer old_start = this->priv_addr();
+ bool enough_capacity = false;
+ size_type new_cap = 0;
+
+ //Check if we have enough capacity
+ pointer hint = pointer();
+ pointer allocation_ret = pointer();
+ if (remaining >= n){
+ enough_capacity = true;
+ }
+ else {
+ //Otherwise expand current buffer or allocate new storage
+ new_cap = this->next_capacity(n);
+ hint = old_start;
+ allocation_ret = this->allocation_command
+ (allocate_new | expand_fwd | expand_bwd, old_size + n + 1, new_cap, hint);
+
+ //Check forward expansion
+ if(old_start == allocation_ret){
+ enough_capacity = true;
+ this->priv_storage(new_cap);
+ }
+ }
+
+ //Reuse same buffer
+ if(enough_capacity){
+ const size_type elems_after = old_size - (p - old_start);
+ const size_type old_length = old_size;
+ if (elems_after >= n) {
+ const pointer pointer_past_last = old_start + old_size + 1;
+ priv_uninitialized_copy(old_start + (old_size - n + 1),
+ pointer_past_last, pointer_past_last);
+
+ this->priv_size(old_size+n);
+ Traits::move(const_cast<CharT*>(boost::movelib::to_raw_pointer(p + n)),
+ boost::movelib::to_raw_pointer(p),
+ (elems_after - n) + 1);
+ this->priv_copy(first, last, const_cast<CharT*>(boost::movelib::to_raw_pointer(p)));
+ }
+ else {
+ ForwardIter mid = first;
+ boost::container::iterator_advance(mid, elems_after + 1);
+
+ priv_uninitialized_copy(mid, last, old_start + old_size + 1);
+ const size_type newer_size = old_size + (n - elems_after);
+ this->priv_size(newer_size);
+ priv_uninitialized_copy
+ (p, const_iterator(old_start + old_length + 1),
+ old_start + newer_size);
+ this->priv_size(newer_size + elems_after);
+ this->priv_copy(first, mid, const_cast<CharT*>(boost::movelib::to_raw_pointer(p)));
+ }
+ }
+ else{
+ pointer new_start = allocation_ret;
+ if(!hint){
+ //Copy data to new buffer
+ size_type new_length = 0;
+ //This can't throw, since characters are POD
+ new_length += priv_uninitialized_copy
+ (const_iterator(old_start), p, new_start);
+ new_length += priv_uninitialized_copy
+ (first, last, new_start + new_length);
+ new_length += priv_uninitialized_copy
+ (p, const_iterator(old_start + old_size),
+ new_start + new_length);
+ this->priv_construct_null(new_start + new_length);
+
+ this->deallocate_block();
+ this->is_short(false);
+ this->priv_long_addr(new_start);
+ this->priv_long_size(new_length);
+ this->priv_long_storage(new_cap);
+ }
+ else{
+ //value_type is POD, so backwards expansion is much easier
+ //than with vector<T>
+ value_type * const oldbuf = boost::movelib::to_raw_pointer(old_start);
+ value_type * const newbuf = boost::movelib::to_raw_pointer(new_start);
+ const value_type *const pos = boost::movelib::to_raw_pointer(p);
+ const size_type before = pos - oldbuf;
+
+ //First move old data
+ Traits::move(newbuf, oldbuf, before);
+ Traits::move(newbuf + before + n, pos, old_size - before);
+ //Now initialize the new data
+ priv_uninitialized_copy(first, last, new_start + before);
+ this->priv_construct_null(new_start + (old_size + n));
+ this->is_short(false);
+ this->priv_long_addr(new_start);
+ this->priv_long_size(old_size + n);
+ this->priv_long_storage(new_cap);
+ }
+ }
+ }
+ return this->begin() + n_pos;
+ }
+ #endif
+
+ #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: As if by insert(p, il.begin(), il.end()).
+ //!
+ //! <b>Returns</b>: An iterator which refers to the copy of the first inserted
+ //! character, or p if i1 is empty.
+ iterator insert(const_iterator p, std::initializer_list<CharT> il)
+ {
+ return this->insert(p, il.begin(), il.end());
+ }
+ #endif
+
+ //! <b>Effects</b>: Removes the last element from the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant time.
+ void pop_back() BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(!this->empty());
+ iterator p = this->end();
+ this->erase(--p);
+ }
+
+ //! <b>Requires</b>: pos <= size()
+ //!
+ //! <b>Effects</b>: Determines the effective length xlen of the string to be removed as the smaller of n and size() - pos.
+ //! The function then replaces the string controlled by *this with a string of length size() - xlen
+ //! whose first pos elements are a copy of the initial elements of the original string controlled by *this,
+ //! and whose remaining elements are a copy of the elements of the original string controlled by *this
+ //! beginning at position pos + xlen.
+ //!
+ //! <b>Throws</b>: out_of_range if pos > size().
+ //!
+ //! <b>Returns</b>: *this
+ basic_string& erase(size_type pos = 0, size_type n = npos)
+ {
+ if (pos > this->size())
+ throw_out_of_range("basic_string::erase out of range position");
+ const pointer addr = this->priv_addr();
+ erase(addr + pos, addr + pos + dtl::min_value(n, this->size() - pos));
+ return *this;
+ }
+
+ //! <b>Effects</b>: Removes the character referred to by p.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Returns</b>: An iterator which points to the element immediately following p prior to the element being
+ //! erased. If no such element exists, end() is returned.
+ iterator erase(const_iterator p) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ // The move includes the terminating null.
+ CharT * const ptr = const_cast<CharT*>(boost::movelib::to_raw_pointer(p));
+ const size_type old_size = this->priv_size();
+ Traits::move(ptr,
+ boost::movelib::to_raw_pointer(p + 1),
+ old_size - (p - this->priv_addr()));
+ this->priv_size(old_size-1);
+ return iterator(ptr);
+ }
+
+ //! <b>Requires</b>: first and last are valid iterators on *this, defining a range [first,last).
+ //!
+ //! <b>Effects</b>: Removes the characters in the range [first,last).
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Returns</b>: An iterator which points to the element pointed to by last prior to
+ //! the other elements being erased. If no such element exists, end() is returned.
+ iterator erase(const_iterator first, const_iterator last) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ CharT * f = const_cast<CharT*>(boost::movelib::to_raw_pointer(first));
+ if (first != last) { // The move includes the terminating null.
+ const size_type num_erased = last - first;
+ const size_type old_size = this->priv_size();
+ Traits::move(f,
+ boost::movelib::to_raw_pointer(last),
+ (old_size + 1)-(last - this->priv_addr()));
+ const size_type new_length = old_size - num_erased;
+ this->priv_size(new_length);
+ }
+ return iterator(f);
+ }
+
+ //! <b>Effects</b>: Erases all the elements of the vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the vector.
+ void clear() BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ if (!this->empty()) {
+ Traits::assign(*this->priv_addr(), CharT(0));
+ this->priv_size(0);
+ }
+ }
+
+ //! <b>Requires</b>: pos1 <= size().
+ //!
+ //! <b>Effects</b>: Calls replace(pos1, n1, str.data(), str.size()).
+ //!
+ //! <b>Throws</b>: if memory allocation throws or out_of_range if pos1 > size().
+ //!
+ //! <b>Returns</b>: *this
+ basic_string& replace(size_type pos1, size_type n1, const basic_string& str)
+ {
+ if (pos1 > this->size())
+ throw_out_of_range("basic_string::replace out of range position");
+ const size_type len = dtl::min_value(n1, this->size() - pos1);
+ if (this->size() - len >= this->max_size() - str.size())
+ throw_length_error("basic_string::replace max_size() exceeded");
+ const pointer addr = this->priv_addr();
+ return this->replace( const_iterator(addr + pos1)
+ , const_iterator(addr + pos1 + len)
+ , str.begin(), str.end());
+ }
+
+ //! <b>Effects</b>: Calls `return replace(pos1, n1, sv.data(), sv.size());`.
+ //!
+ template<template<class, class> class BasicStringView>
+ basic_string& replace(size_type pos1, size_type n1, BasicStringView<CharT, Traits> sv)
+ {
+ return this->replace(pos1, n1, sv.data(), sv.size());
+ }
+
+ //! <b>Requires</b>: pos1 <= size() and pos2 <= str.size().
+ //!
+ //! <b>Effects</b>: Determines the effective length rlen of the string to be
+ //! inserted as the smaller of n2 and str.size() - pos2 and calls
+ //! replace(pos1, n1, str.data() + pos2, rlen).
+ //!
+ //! <b>Throws</b>: if memory allocation throws, out_of_range if pos1 > size() or pos2 > str.size().
+ //!
+ //! <b>Returns</b>: *this
+ basic_string& replace(size_type pos1, size_type n1,
+ const basic_string& str, size_type pos2, size_type n2 = npos)
+ {
+ if (pos2 > str.size())
+ throw_out_of_range("basic_string::replace out of range position");
+ return this->replace(pos1, n1, str.data()+pos2, dtl::min_value(n2, str.size() - pos2));
+ }
+
+ //! <b>Throws</b>: out_of_range if pos1 > size() or pos2 > sv.size().
+ //!
+ //! <b>Effects</b>: Determines the effective length rlen of the string to be inserted as the
+ //! smaller of n2 and sv.size() - pos2 and calls `replace(pos1, n1, sv.data() + pos2, rlen)`.
+ //!
+ //! <b>Returns</b>: *this.
+ template<template<class, class> class BasicStringView>
+ basic_string& replace(size_type pos1, size_type n1, BasicStringView<CharT, Traits> sv,
+ size_type pos2, size_type n2 = npos)
+ {
+ if (pos2 > sv.size())
+ throw_out_of_range("basic_string::replace out of range position");
+ return this->replace(pos1, n1, sv.data()+pos2, dtl::min_value(n2, sv.size() - pos2));
+ }
+
+ //! <b>Requires</b>: pos1 <= size() and s points to an array of at least n2 elements of CharT.
+ //!
+ //! <b>Effects</b>: Determines the effective length xlen of the string to be removed as the
+ //! smaller of n1 and size() - pos1. If size() - xlen >= max_size() - n2 throws length_error.
+ //! Otherwise, the function replaces the string controlled by *this with a string of
+ //! length size() - xlen + n2 whose first pos1 elements are a copy of the initial elements
+ //! of the original string controlled by *this, whose next n2 elements are a copy of the
+ //! initial n2 elements of s, and whose remaining elements are a copy of the elements of
+ //! the original string controlled by *this beginning at position pos + xlen.
+ //!
+ //! <b>Throws</b>: if memory allocation throws, out_of_range if pos1 > size() or length_error
+ //! if the length of the resulting string would exceed max_size()
+ //!
+ //! <b>Returns</b>: *this
+ basic_string& replace(size_type pos1, size_type n1, const CharT* s, size_type n2)
+ {
+ if (pos1 > this->size())
+ throw_out_of_range("basic_string::replace out of range position");
+ const size_type len = dtl::min_value(n1, this->size() - pos1);
+ const size_type max_size = this->max_size();
+ if (n2 > max_size || (this->size() - len) >= (max_size - n2))
+ throw_length_error("basic_string::replace max_size() exceeded");
+ const pointer addr = this->priv_addr() + pos1;
+ return this->replace(addr, addr + len, s, s + n2);
+ }
+
+ //! <b>Requires</b>: pos1 <= size() and s points to an array of at least n2 elements of CharT.
+ //!
+ //! <b>Effects</b>: Determines the effective length xlen of the string to be removed as the smaller
+ //! of n1 and size() - pos1. If size() - xlen >= max_size() - n2 throws length_error. Otherwise,
+ //! the function replaces the string controlled by *this with a string of length size() - xlen + n2
+ //! whose first pos1 elements are a copy of the initial elements of the original string controlled
+ //! by *this, whose next n2 elements are a copy of the initial n2 elements of s, and whose
+ //! remaining elements are a copy of the elements of the original string controlled by *this
+ //! beginning at position pos + xlen.
+ //!
+ //! <b>Throws</b>: if memory allocation throws, out_of_range if pos1 > size() or length_error
+ //! if the length of the resulting string would exceed max_size()
+ //!
+ //! <b>Returns</b>: *this
+ basic_string& replace(size_type pos, size_type n1, const CharT* s)
+ {
+ return this->replace(pos, n1, s, Traits::length(s));
+ }
+
+ //! <b>Requires</b>: pos1 <= size().
+ //!
+ //! <b>Effects</b>: Equivalent to replace(pos1, n1, basic_string(n2, c)).
+ //!
+ //! <b>Throws</b>: if memory allocation throws, out_of_range if pos1 > size() or length_error
+ //! if the length of the resulting string would exceed max_size()
+ //!
+ //! <b>Returns</b>: *this
+ basic_string& replace(size_type pos1, size_type n1, size_type n2, CharT c)
+ {
+ if (pos1 > this->size())
+ throw_out_of_range("basic_string::replace out of range position");
+ const size_type len = dtl::min_value(n1, this->size() - pos1);
+ if (n2 > this->max_size() || this->size() - len >= this->max_size() - n2)
+ throw_length_error("basic_string::replace max_size() exceeded");
+ const pointer addr = this->priv_addr();
+ return this->replace(addr + pos1, addr + pos1 + len, n2, c);
+ }
+
+ //! <b>Requires</b>: [begin(),i1) and [i1,i2) are valid ranges.
+ //!
+ //! <b>Effects</b>: Calls replace(i1 - begin(), i2 - i1, str).
+ //!
+ //! <b>Throws</b>: if memory allocation throws
+ //!
+ //! <b>Returns</b>: *this
+ basic_string& replace(const_iterator i1, const_iterator i2, const basic_string& str)
+ { return this->replace(i1, i2, str.data(), str.data()+str.size()); }
+
+ //! <b>Requires</b>: [begin(),i1) and [i1,i2) are valid ranges and
+ //! s points to an array of at least n elements
+ //!
+ //! <b>Effects</b>: Calls replace(i1 - begin(), i2 - i1, s, n).
+ //!
+ //! <b>Throws</b>: if memory allocation throws
+ //!
+ //! <b>Returns</b>: *this
+ basic_string& replace(const_iterator i1, const_iterator i2, const CharT* s, size_type n)
+ { return this->replace(i1, i2, s, s + n); }
+
+ //! <b>Requires</b>: [begin(),i1) and [i1,i2) are valid ranges and s points to an
+ //! array of at least traits::length(s) + 1 elements of CharT.
+ //!
+ //! <b>Effects</b>: Calls replace(i1 - begin(), i2 - i1, s, traits::length(s)).
+ //!
+ //! <b>Throws</b>: if memory allocation throws
+ //!
+ //! <b>Returns</b>: *this
+ basic_string& replace(const_iterator i1, const_iterator i2, const CharT* s)
+ { return this->replace(i1, i2, s, s + Traits::length(s)); }
+
+ //! <b>Requires</b>: [begin(),i1) and [i1,i2) are valid ranges.
+ //!
+ //! <b>Effects</b>: Calls replace(i1 - begin(), i2 - i1, basic_string(n, c)).
+ //!
+ //! <b>Throws</b>: if memory allocation throws
+ //!
+ //! <b>Returns</b>: *this
+ basic_string& replace(const_iterator i1, const_iterator i2, size_type n, CharT c)
+ {
+ const size_type len = static_cast<size_type>(i2 - i1);
+ if (len >= n) {
+ Traits::assign(const_cast<CharT*>(boost::movelib::to_raw_pointer(i1)), n, c);
+ erase(i1 + n, i2);
+ }
+ else {
+ Traits::assign(const_cast<CharT*>(boost::movelib::to_raw_pointer(i1)), len, c);
+ insert(i2, n - len, c);
+ }
+ return *this;
+ }
+
+ //! <b>Requires</b>: [begin(),i1), [i1,i2) and [j1,j2) are valid ranges.
+ //!
+ //! <b>Effects</b>: Calls replace(i1 - begin(), i2 - i1, basic_string(j1, j2)).
+ //!
+ //! <b>Throws</b>: if memory allocation throws
+ //!
+ //! <b>Returns</b>: *this
+ template <class InputIter>
+ basic_string& replace(const_iterator i1, const_iterator i2, InputIter j1, InputIter j2
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename dtl::disable_if_or
+ < void
+ , dtl::is_convertible<InputIter, size_type>
+ , dtl::is_input_iterator<InputIter>
+ >::type * = 0
+ #endif
+ )
+ {
+ for ( ; i1 != i2 && j1 != j2; ++i1, ++j1){
+ Traits::assign(*const_cast<CharT*>(boost::movelib::to_raw_pointer(i1)), *j1);
+ }
+
+ if (j1 == j2)
+ this->erase(i1, i2);
+ else
+ this->insert(i2, j1, j2);
+ return *this;
+ }
+
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ template <class ForwardIter>
+ basic_string& replace(const_iterator i1, const_iterator i2, ForwardIter j1, ForwardIter j2
+ , typename dtl::disable_if_or
+ < void
+ , dtl::is_convertible<ForwardIter, size_type>
+ , dtl::is_not_input_iterator<ForwardIter>
+ >::type * = 0
+ )
+ {
+ difference_type n = boost::container::iterator_distance(j1, j2);
+ const difference_type len = i2 - i1;
+ if (len >= n) {
+ this->priv_copy(j1, j2, const_cast<CharT*>(boost::movelib::to_raw_pointer(i1)));
+ this->erase(i1 + n, i2);
+ }
+ else {
+ ForwardIter m = j1;
+ boost::container::iterator_advance(m, len);
+ this->priv_copy(j1, m, const_cast<CharT*>(boost::movelib::to_raw_pointer(i1)));
+ this->insert(i2, m, j2);
+ }
+ return *this;
+ }
+ #endif
+
+ //! <b>Requires</b>: [begin(), i1) and [i1, i2) are valid ranges.
+ //!
+ //! <b>Effects</b>: Calls `replace(i1 - begin(), i2 - i1, sv).`.
+ //!
+ //! <b>Returns</b>: *this.
+ template<template <class, class> class BasicStringView>
+ basic_string& replace(const_iterator i1, const_iterator i2, BasicStringView<CharT, Traits> sv)
+ {
+ return this->replace( static_cast<size_type>(i1 - this->cbegin())
+ , static_cast<size_type>(i2 - i1), sv);
+ }
+
+ #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Requires</b>: [begin(), i1) and [i1, i2) are valid ranges.
+ //!
+ //! <b>Effects</b>: Calls replace(i1 - begin(), i2 - i1, il.begin(), il.size()).
+ //!
+ //! <b>Returns</b>: *this.
+ basic_string& replace(const_iterator i1, const_iterator i2, std::initializer_list<CharT> il)
+ {
+ return this->replace( static_cast<size_type>(i1 - this->cbegin())
+ , static_cast<size_type>(i2 - i1)
+ , il.begin(), il.size());
+ }
+ #endif
+
+ //! <b>Requires</b>: pos <= size()
+ //!
+ //! <b>Effects</b>: Determines the effective length rlen of the string to copy as the
+ //! smaller of n and size() - pos. s shall designate an array of at least rlen elements.
+ //! The function then replaces the string designated by s with a string of length rlen
+ //! whose elements are a copy of the string controlled by *this beginning at position pos.
+ //! The function does not append a null object to the string designated by s.
+ //!
+ //! <b>Throws</b>: if memory allocation throws, out_of_range if pos > size().
+ //!
+ //! <b>Returns</b>: rlen
+ size_type copy(CharT* s, size_type n, size_type pos = 0) const
+ {
+ if (pos > this->size())
+ throw_out_of_range("basic_string::copy out of range position");
+ const size_type len = dtl::min_value(n, this->size() - pos);
+ Traits::copy(s, boost::movelib::to_raw_pointer(this->priv_addr() + pos), len);
+ return len;
+ }
+
+ //! <b>Effects</b>: *this contains the same sequence of characters that was in s,
+ //! s contains the same sequence of characters that was in *this.
+ //!
+ //! <b>Throws</b>: Nothing
+ void swap(basic_string& x)
+ BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_swap::value
+ || allocator_traits_type::is_always_equal::value)
+ {
+ this->base_t::swap_data(x);
+ dtl::bool_<allocator_traits_type::propagate_on_container_swap::value> flag;
+ dtl::swap_alloc(this->alloc(), x.alloc(), flag);
+ }
+
+ //////////////////////////////////////////////
+ //
+ // data access
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Requires</b>: The program shall not alter any of the values stored in the character array.
+ //!
+ //! <b>Returns</b>: A pointer p such that p + i == &operator[](i) for each i in [0,size()].
+ //!
+ //! <b>Complexity</b>: constant time.
+ const CharT* c_str() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return boost::movelib::to_raw_pointer(this->priv_addr()); }
+
+ //! <b>Requires</b>: The program shall not alter any of the values stored in the character array.
+ //!
+ //! <b>Returns</b>: A pointer p such that p + i == &operator[](i) for each i in [0,size()].
+ //!
+ //! <b>Complexity</b>: constant time.
+ const CharT* data() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return boost::movelib::to_raw_pointer(this->priv_addr()); }
+
+ //! <b>Returns</b>: A pointer p such that p + i == &operator[](i) for each i in [0,size()].
+ //!
+ //! <b>Complexity</b>: constant time.
+ CharT* data() BOOST_NOEXCEPT_OR_NOTHROW
+ { return boost::movelib::to_raw_pointer(this->priv_addr()); }
+
+ #ifndef BOOST_CONTAINER_TEMPLATED_CONVERSION_OPERATOR_BROKEN
+ //! <b>Returns</b>: a string_view to the characters in the string.
+ //!
+ //! <b>Complexity</b>: constant time.
+ template<template <class, class> class BasicStringView>
+ operator BasicStringView<CharT, Traits>() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->to_view< BasicStringView<CharT, Traits> >(); }
+ #endif
+
+ //! <b>Returns</b>: a string_view to the characters in the string.
+ //!
+ //! <b>Complexity</b>: constant time.
+ //!
+ //! <b>Note</b>: This function is available to write portable code for compilers
+ //! that don't support templated conversion operators.
+ template<class BasicStringView>
+ BasicStringView to_view() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return BasicStringView(this->data(), this->size()); }
+
+ //////////////////////////////////////////////
+ //
+ // string operations
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Determines the lowest position xpos, if possible, such that both
+ //! of the following conditions hold:
+ //! 1) pos <= xpos and xpos + str.size() <= size();
+ //! 2) traits::eq(at(xpos+I), str.at(I)) for all elements I of the string controlled by str.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
+ size_type find(const basic_string& s, size_type pos = 0) const
+ { return find(s.c_str(), pos, s.size()); }
+
+ //! <b>Effects</b>: Determines the lowest position xpos, if possible, such that both
+ //! of the following conditions hold:
+ //! 1) pos <= xpos and xpos + sv.size() <= size();
+ //! 2) traits::eq(at(xpos+I), sv.at(I)) for all elements I of the string controlled by sv.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
+ template<template <class, class> class BasicStringView>
+ size_type find(BasicStringView<CharT, Traits> sv, size_type pos = 0) const
+ { return find(sv.data(), pos, sv.size()); }
+
+ //! <b>Requires</b>: s points to an array of at least n elements of CharT.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Returns</b>: find(basic_string<CharT,traits,Allocator>(s,n),pos).
+ size_type find(const CharT* s, size_type pos, size_type n) const
+ {
+ if (pos + n > this->size())
+ return npos;
+ else {
+ const pointer addr = this->priv_addr();
+ pointer finish = addr + this->priv_size();
+ const const_iterator result =
+ boost::container::search(boost::movelib::to_raw_pointer(addr + pos),
+ boost::movelib::to_raw_pointer(finish),
+ s, s + n, Eq_traits<Traits>());
+ return result != finish ? result - begin() : npos;
+ }
+ }
+
+ //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Returns</b>: find(basic_string(s), pos).
+ size_type find(const CharT* s, size_type pos = 0) const
+ { return this->find(s, pos, Traits::length(s)); }
+
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Returns</b>: find(basic_string<CharT,traits,Allocator>(1,c), pos).
+ size_type find(CharT c, size_type pos = 0) const
+ {
+ const size_type sz = this->size();
+ if (pos >= sz)
+ return npos;
+ else {
+ const pointer addr = this->priv_addr();
+ pointer finish = addr + sz;
+ const const_iterator result =
+ boost::container::find_if(addr + pos, finish,
+ boost::container::bind2nd(Eq_traits<Traits>(), c));
+ return result != finish ? result - begin() : npos;
+ }
+ }
+
+ //! <b>Effects</b>: Determines the highest position xpos, if possible, such
+ //! that both of the following conditions obtain:
+ //! a) xpos <= pos and xpos + str.size() <= size();
+ //! b) traits::eq(at(xpos+I), str.at(I)) for all elements I of the string controlled by str.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
+ size_type rfind(const basic_string& str, size_type pos = npos) const
+ { return rfind(str.c_str(), pos, str.size()); }
+
+ //! <b>Effects</b>: Determines the highest position xpos, if possible, such
+ //! that both of the following conditions obtain:
+ //! a) xpos <= pos and xpos + sv.size() <= size();
+ //! b) traits::eq(at(xpos+I), sv.at(I)) for all elements I of the string controlled by sv.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
+ template<template <class, class> class BasicStringView>
+ size_type rfind(BasicStringView<CharT, Traits> sv, size_type pos = npos) const
+ { return rfind(sv.data(), pos, sv.size()); }
+
+ //! <b>Requires</b>: s points to an array of at least n elements of CharT.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Returns</b>: rfind(basic_string(s, n), pos).
+ size_type rfind(const CharT* s, size_type pos, size_type n) const
+ {
+ const size_type len = this->size();
+
+ if (n > len)
+ return npos;
+ else if (n == 0)
+ return dtl::min_value(len, pos);
+ else {
+ const const_iterator last = begin() + dtl::min_value(len - n, pos) + n;
+ const const_iterator result = find_end(begin(), last,
+ s, s + n,
+ Eq_traits<Traits>());
+ return result != last ? result - begin() : npos;
+ }
+ }
+
+ //! <b>Requires</b>: pos <= size() and s points to an array of at least
+ //! traits::length(s) + 1 elements of CharT.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Returns</b>: rfind(basic_string(s), pos).
+ size_type rfind(const CharT* s, size_type pos = npos) const
+ { return rfind(s, pos, Traits::length(s)); }
+
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Returns</b>: rfind(basic_string<CharT,traits,Allocator>(1,c),pos).
+ size_type rfind(CharT c, size_type pos = npos) const
+ {
+ const size_type len = this->size();
+
+ if (len < 1)
+ return npos;
+ else {
+ const const_iterator last = begin() + dtl::min_value(len - 1, pos) + 1;
+ const_reverse_iterator rresult =
+ boost::container::find_if(const_reverse_iterator(last), rend(),
+ boost::container::bind2nd(Eq_traits<Traits>(), c));
+ return rresult != rend() ? (rresult.base() - 1) - begin() : npos;
+ }
+ }
+
+ //! <b>Effects</b>: Determines the lowest position xpos, if possible, such that both of the
+ //! following conditions obtain: a) pos <= xpos and xpos < size();
+ //! b) traits::eq(at(xpos), str.at(I)) for some element I of the string controlled by str.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
+ size_type find_first_of(const basic_string& str, size_type pos = 0) const
+ { return this->find_first_of(str.c_str(), pos, str.size()); }
+
+ //! <b>Effects</b>: Determines the lowest position xpos, if possible, such that both of the
+ //! following conditions obtain: a) pos <= xpos and xpos < size();
+ //! b) traits::eq(at(xpos), sv.at(I)) for some element I of the string controlled by sv.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
+ template<template <class, class> class BasicStringView>
+ size_type find_first_of(BasicStringView<CharT, Traits> sv, size_type pos = 0) const
+ { return this->find_first_of(sv.data(), pos, sv.size()); }
+
+ //! <b>Requires</b>: s points to an array of at least n elements of CharT.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Returns</b>: find_first_of(basic_string(s, n), pos).
+ size_type find_first_of(const CharT* s, size_type pos, size_type n) const
+ {
+ const size_type sz = this->size();
+ if (pos >= sz)
+ return npos;
+ else {
+ const pointer addr = this->priv_addr();
+ pointer finish = addr + sz;
+ const_iterator result = boost::container::find_first_of
+ (addr + pos, finish, s, s + n, Eq_traits<Traits>());
+ return result != finish ? result - this->begin() : npos;
+ }
+ }
+
+ //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Returns</b>: find_first_of(basic_string(s), pos).
+ size_type find_first_of(const CharT* s, size_type pos = 0) const
+ { return this->find_first_of(s, pos, Traits::length(s)); }
+
+ //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Returns</b>: find_first_of(basic_string<CharT,traits,Allocator>(1,c), pos).
+ size_type find_first_of(CharT c, size_type pos = 0) const
+ { return this->find(c, pos); }
+
+ //! <b>Effects</b>: Determines the highest position xpos, if possible, such that both of
+ //! the following conditions obtain: a) xpos <= pos and xpos < size(); b)
+ //! traits::eq(at(xpos), str.at(I)) for some element I of the string controlled by str.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
+ size_type find_last_of(const basic_string& str, size_type pos = npos) const
+ { return this->find_last_of(str.c_str(), pos, str.size()); }
+
+ //! <b>Effects</b>: Determines the highest position xpos, if possible, such that both of
+ //! the following conditions obtain: a) xpos <= pos and xpos < size(); b)
+ //! traits::eq(at(xpos), str.at(I)) for some element I of the string controlled by str.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
+ template<template <class, class> class BasicStringView>
+ size_type find_last_of(BasicStringView<CharT, Traits> sv, size_type pos = npos) const
+ { return this->find_last_of(sv.data(), pos, sv.size()); }
+
+ //! <b>Requires</b>: s points to an array of at least n elements of CharT.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Returns</b>: find_last_of(basic_string(s, n), pos).
+ size_type find_last_of(const CharT* s, size_type pos, size_type n) const
+ {
+ const size_type len = this->size();
+
+ if (len < 1)
+ return npos;
+ else {
+ const pointer addr = this->priv_addr();
+ const const_iterator last = addr + dtl::min_value(len - 1, pos) + 1;
+ const const_reverse_iterator rresult =
+ boost::container::find_first_of(const_reverse_iterator(last), rend(),
+ s, s + n, Eq_traits<Traits>());
+ return rresult != rend() ? (rresult.base() - 1) - addr : npos;
+ }
+ }
+
+ //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Returns</b>: find_last_of(basic_string<CharT,traits,Allocator>(1,c),pos).
+ size_type find_last_of(const CharT* s, size_type pos = npos) const
+ { return find_last_of(s, pos, Traits::length(s)); }
+
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Returns</b>: find_last_of(basic_string(s), pos).
+ size_type find_last_of(CharT c, size_type pos = npos) const
+ { return rfind(c, pos); }
+
+ //! <b>Effects</b>: Determines the lowest position xpos, if possible, such that
+ //! both of the following conditions obtain:
+ //! a) pos <= xpos and xpos < size(); b) traits::eq(at(xpos), str.at(I)) for no
+ //! element I of the string controlled by str.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
+ size_type find_first_not_of(const basic_string& str, size_type pos = 0) const
+ { return find_first_not_of(str.c_str(), pos, str.size()); }
+
+ //! <b>Effects</b>: Determines the lowest position xpos, if possible, such that
+ //! both of the following conditions obtain:
+ //! a) pos <= xpos and xpos < size(); b) traits::eq(at(xpos), sv.at(I)) for no
+ //! element I of the string controlled by sv.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
+ template<template <class, class> class BasicStringView>
+ size_type find_first_not_of(BasicStringView<CharT, Traits> sv, size_type pos = 0) const
+ { return find_first_not_of(sv.data(), pos, sv.size()); }
+
+ //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Returns</b>: find_first_not_of(basic_string(s, n), pos).
+ size_type find_first_not_of(const CharT* s, size_type pos, size_type n) const
+ {
+ if (pos > this->size())
+ return npos;
+ else {
+ const pointer addr = this->priv_addr();
+ const pointer finish = addr + this->priv_size();
+ const const_iterator result = boost::container::find_if
+ (addr + pos, finish, Not_within_traits<Traits>(s, s + n));
+ return result != finish ? result - addr : npos;
+ }
+ }
+
+ //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Returns</b>: find_first_not_of(basic_string(s), pos).
+ size_type find_first_not_of(const CharT* s, size_type pos = 0) const
+ { return find_first_not_of(s, pos, Traits::length(s)); }
+
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Returns</b>: find_first_not_of(basic_string(1, c), pos).
+ size_type find_first_not_of(CharT c, size_type pos = 0) const
+ {
+ if (pos > this->size())
+ return npos;
+ else {
+ const pointer addr = this->priv_addr();
+ const pointer finish = addr + this->priv_size();
+ const const_iterator result
+ = boost::container::find_if(addr + pos, finish,
+ boost::container::not1(boost::container::bind2nd(Eq_traits<Traits>(), c)));
+ return result != finish ? result - begin() : npos;
+ }
+ }
+
+ //! <b>Effects</b>: Determines the highest position xpos, if possible, such that
+ //! both of the following conditions obtain: a) xpos <= pos and xpos < size();
+ //! b) traits::eq(at(xpos), str.at(I)) for no element I of the string controlled by str.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
+ size_type find_last_not_of(const basic_string& str, size_type pos = npos) const
+ { return find_last_not_of(str.c_str(), pos, str.size()); }
+
+ //! <b>Effects</b>: Determines the highest position xpos, if possible, such that
+ //! both of the following conditions obtain: a) xpos <= pos and xpos < size();
+ //! b) traits::eq(at(xpos), sv.at(I)) for no element I of the string controlled by sv.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Returns</b>: xpos if the function can determine such a value for xpos. Otherwise, returns npos.
+ template<template <class, class> class BasicStringView>
+ size_type find_last_not_of(BasicStringView<CharT, Traits> sv, size_type pos = npos) const
+ { return find_last_not_of(sv.data(), pos, sv.size()); }
+
+ //! <b>Requires</b>: s points to an array of at least n elements of CharT.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Returns</b>: find_last_not_of(basic_string(s, n), pos).
+ size_type find_last_not_of(const CharT* s, size_type pos, size_type n) const
+ {
+ const size_type len = this->size();
+
+ if (len < 1)
+ return npos;
+ else {
+ const const_iterator last = begin() + dtl::min_value(len - 1, pos) + 1;
+ const const_reverse_iterator rresult =
+ boost::container::find_if(const_reverse_iterator(last), rend(),
+ Not_within_traits<Traits>(s, s + n));
+ return rresult != rend() ? (rresult.base() - 1) - begin() : npos;
+ }
+ }
+
+ //! <b>Requires</b>: s points to an array of at least traits::length(s) + 1 elements of CharT.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Returns</b>: find_last_not_of(basic_string(s), pos).
+ size_type find_last_not_of(const CharT* s, size_type pos = npos) const
+ { return find_last_not_of(s, pos, Traits::length(s)); }
+
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Returns</b>: find_last_not_of(basic_string(1, c), pos).
+ size_type find_last_not_of(CharT c, size_type pos = npos) const
+ {
+ const size_type len = this->size();
+
+ if (len < 1)
+ return npos;
+ else {
+ const const_iterator last = begin() + dtl::min_value(len - 1, pos) + 1;
+ const const_reverse_iterator rresult =
+ boost::container::find_if(const_reverse_iterator(last), rend(),
+ boost::container::not1(boost::container::bind2nd(Eq_traits<Traits>(), c)));
+ return rresult != rend() ? (rresult.base() - 1) - begin() : npos;
+ }
+ }
+
+ //! <b>Requires</b>: Requires: pos <= size()
+ //!
+ //! <b>Effects</b>: Determines the effective length rlen of the string to copy as
+ //! the smaller of n and size() - pos.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or out_of_range if pos > size().
+ //!
+ //! <b>Returns</b>: basic_string<CharT,traits,Allocator>(data()+pos,rlen).
+ basic_string substr(size_type pos = 0, size_type n = npos) const
+ {
+ if (pos > this->size())
+ throw_out_of_range("basic_string::substr out of range position");
+ const pointer addr = this->priv_addr();
+ return basic_string(addr + pos,
+ addr + pos + dtl::min_value(n, size() - pos), this->alloc());
+ }
+
+ //! <b>Effects</b>: Determines the effective length rlen of the string to compare as
+ //! the smaller of size() and str.size(). The function then compares the two strings by
+ //! calling traits::compare(data(), str.data(), rlen).
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Returns</b>: The nonzero result if the result of the comparison is nonzero.
+ //! Otherwise, returns a value < 0 if size() < str.size(), a 0 value if size() == str.size(),
+ //! and value > 0 if size() > str.size()
+ int compare(const basic_string& str) const
+ {
+ const pointer addr = this->priv_addr();
+ const pointer str_addr = str.priv_addr();
+ return s_compare(addr, addr + this->priv_size(), str_addr, str_addr + str.priv_size());
+ }
+
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Returns</b>: compare(basic_string(sv)).
+ template<template <class, class> class BasicStringView>
+ int compare(BasicStringView<CharT,Traits> sv) const
+ {
+ const pointer addr = this->priv_addr();
+ return s_compare(addr, addr + this->priv_size(), sv.data(), sv.data() + sv.size());
+ }
+
+ //! <b>Requires</b>: pos1 <= size()
+ //!
+ //! <b>Effects</b>: Determines the effective length rlen of the string to compare as
+ //! the smaller of (this->size() - pos1), n1 and str.size(). The function then compares the two strings by
+ //! calling traits::compare(data()+pos1, str.data(), rlen).
+ //!
+ //! <b>Throws</b>: out_of_range if pos1 > size()
+ //!
+ //! <b>Returns</b>:basic_string(*this,pos1,n1).compare(str).
+ int compare(size_type pos1, size_type n1, const basic_string& str) const
+ {
+ if (pos1 > this->size())
+ throw_out_of_range("basic_string::compare out of range position");
+ const pointer addr = this->priv_addr();
+ const pointer str_addr = str.priv_addr();
+ return s_compare(addr + pos1,
+ addr + pos1 + dtl::min_value(n1, this->size() - pos1),
+ str_addr, str_addr + str.priv_size());
+ }
+
+ //! <b>Requires</b>: pos1 <= size()
+ //!
+ //! <b>Throws</b>: out_of_range if pos1 > size()
+ //!
+ //! <b>Returns</b>:basic_string(*this,pos1,n1).compare(sv).
+ template<template <class, class> class BasicStringView>
+ int compare(size_type pos1, size_type n1, BasicStringView<CharT,Traits> sv) const
+ {
+ if (pos1 > this->size())
+ throw_out_of_range("basic_string::compare out of range position");
+ const pointer addr = this->priv_addr() + pos1;
+ const CharT* str_addr = sv.data();
+ return s_compare(addr, addr + dtl::min_value(n1, this->size() - pos1),
+ str_addr, str_addr + sv.size());
+ }
+
+ //! <b>Requires</b>: pos1 <= size() and pos2 <= str.size()
+ //!
+ //! <b>Effects</b>: Determines the effective length rlen of the string to copy as
+ //! the smaller of
+ //!
+ //! <b>Throws</b>: out_of_range if pos1 > size() or pos2 > str.size()
+ //!
+ //! <b>Returns</b>: basic_string(*this, pos1, n1).compare(basic_string(str, pos2, n2)).
+ int compare(size_type pos1, size_type n1, const basic_string& str, size_type pos2, size_type n2 = npos) const
+ {
+ if (pos1 > this->size() || pos2 > str.size())
+ throw_out_of_range("basic_string::compare out of range position");
+ const pointer addr = this->priv_addr() + pos1;
+ const pointer str_addr = str.priv_addr() + pos2;
+ return s_compare(addr, addr + dtl::min_value(n1, this->size() - pos1),
+ str_addr, str_addr + dtl::min_value(n2, str.size() - pos2));
+ }
+
+ //! <b>Requires</b>: pos1 <= size() and pos2 <= str.size()
+ //!
+ //! <b>Effects</b>: Determines the effective length rlen of the string to copy as
+ //! the smaller of
+ //!
+ //! <b>Throws</b>: out_of_range if pos1 > size() or pos2 > sv.size()
+ //!
+ //! <b>Returns</b>: basic_string(*this, pos1, n1).compare(BasicStringView<CharT, Traits>(sv, pos2, n2)).
+ template<template <class, class> class BasicStringView>
+ int compare(size_type pos1, size_type n1, BasicStringView<CharT,Traits> sv, size_type pos2, size_type n2) const
+ {
+ if (pos1 > this->size() || pos2 > sv.size())
+ throw_out_of_range("basic_string::compare out of range position");
+ const pointer addr = this->priv_addr() + pos1;
+ const CharT * str_addr = sv.data() + pos2;
+ return s_compare(addr, addr + dtl::min_value(n1, this->size() - pos1),
+ str_addr, str_addr + dtl::min_value(n2, sv.size() - pos2));
+ }
+
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Returns</b>: compare(basic_string(s)).
+ int compare(const CharT* s) const
+ {
+ const pointer addr = this->priv_addr();
+ return s_compare(addr, addr + this->priv_size(), s, s + Traits::length(s));
+ }
+
+ //! <b>Requires</b>: pos1 > size() and s points to an array of at least n2 elements of CharT.
+ //!
+ //! <b>Throws</b>: out_of_range if pos1 > size()
+ //!
+ //! <b>Returns</b>: basic_string(*this, pos, n1).compare(basic_string(s, n2)).
+ int compare(size_type pos1, size_type n1, const CharT* s, size_type n2) const
+ {
+ if (pos1 > this->size())
+ throw_out_of_range("basic_string::compare out of range position");
+ const pointer addr = this->priv_addr();
+ return s_compare( addr + pos1,
+ addr + pos1 + dtl::min_value(n1, this->size() - pos1),
+ s, s + n2);
+ }
+
+ //! <b>Requires</b>: pos1 > size() and s points to an array of at least traits::length(s) + 1 elements of CharT.
+ //!
+ //! <b>Throws</b>: out_of_range if pos1 > size()
+ //!
+ //! <b>Returns</b>: basic_string(*this, pos, n1).compare(basic_string(s, n2)).
+ int compare(size_type pos1, size_type n1, const CharT* s) const
+ { return this->compare(pos1, n1, s, Traits::length(s)); }
+
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ private:
+ void priv_reserve(size_type res_arg, const bool null_terminate = true)
+ {
+ if (res_arg > this->max_size()){
+ throw_length_error("basic_string::reserve max_size() exceeded");
+ }
+
+ if (this->capacity() < res_arg){
+ size_type n = dtl::max_value(res_arg, this->size()) + 1;
+ size_type new_cap = this->next_capacity(n);
+ pointer reuse = 0;
+ pointer new_start = this->allocation_command(allocate_new, n, new_cap, reuse);
+ size_type new_length = 0;
+
+ const pointer addr = this->priv_addr();
+ new_length += priv_uninitialized_copy
+ (addr, addr + this->priv_size(), new_start);
+ if(null_terminate){
+ this->priv_construct_null(new_start + new_length);
+ }
+ this->deallocate_block();
+ this->is_short(false);
+ this->priv_long_addr(new_start);
+ this->priv_long_size(new_length);
+ this->priv_storage(new_cap);
+ }
+ }
+
+ template<class It1, class It2>
+ static int s_compare(It1 f1, It1 l1, It2 f2, It2 l2)
+ {
+ const difference_type n1 = l1 - f1;
+ const difference_type n2 = l2 - f2;
+ const int cmp = Traits::compare(boost::movelib::to_raw_pointer(f1),
+ boost::movelib::to_raw_pointer(f2),
+ dtl::min_value(n1, n2));
+ return cmp != 0 ? cmp : (n1 < n2 ? -1 : (n1 > n2 ? 1 : 0));
+ }
+
+ template<class AllocVersion>
+ void priv_shrink_to_fit_dynamic_buffer
+ ( AllocVersion
+ , typename dtl::enable_if<dtl::is_same<AllocVersion, version_1> >::type* = 0)
+ {
+ //Allocate a new buffer.
+ size_type real_cap = 0;
+ const pointer long_addr = this->priv_long_addr();
+ const size_type long_size = this->priv_long_size();
+ const size_type long_storage = this->priv_long_storage();
+ //We can make this nothrow as chars are always NoThrowCopyables
+ BOOST_TRY{
+ pointer reuse = 0;
+ real_cap = long_size+1;
+ const pointer ret = this->allocation_command(allocate_new, long_size+1, real_cap, reuse);
+ //Copy and update
+ Traits::copy( boost::movelib::to_raw_pointer(ret)
+ , boost::movelib::to_raw_pointer(this->priv_long_addr())
+ , long_size+1);
+ this->priv_long_addr(ret);
+ this->priv_storage(real_cap);
+ //And release old buffer
+ this->alloc().deallocate(long_addr, long_storage);
+ }
+ BOOST_CATCH(...){
+ return;
+ }
+ BOOST_CATCH_END
+ }
+
+ template<class AllocVersion>
+ void priv_shrink_to_fit_dynamic_buffer
+ ( AllocVersion
+ , typename dtl::enable_if<dtl::is_same<AllocVersion, version_2> >::type* = 0)
+ {
+ size_type received_size = this->priv_long_size()+1;
+ pointer hint = this->priv_long_addr();
+ if(this->alloc().allocation_command
+ ( shrink_in_place | nothrow_allocation, this->priv_long_storage(), received_size, hint)){
+ this->priv_storage(received_size);
+ }
+ }
+
+ void priv_construct_null(pointer p)
+ { this->construct(p, CharT(0)); }
+
+ // Helper functions used by constructors. It is a severe error for
+ // any of them to be called anywhere except from within constructors.
+ void priv_terminate_string()
+ { this->priv_construct_null(this->priv_end_addr()); }
+
+ template<class FwdIt, class Count> inline
+ void priv_uninitialized_fill_n(FwdIt first, Count count, const CharT val)
+ {
+ //Save initial position
+ FwdIt init = first;
+
+ BOOST_TRY{
+ //Construct objects
+ for (; count--; ++first){
+ this->construct(first, val);
+ }
+ }
+ BOOST_CATCH(...){
+ //Call destructors
+ for (; init != first; ++init){
+ this->destroy(init);
+ }
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ }
+
+ template<class InpIt, class FwdIt> inline
+ size_type priv_uninitialized_copy(InpIt first, InpIt last, FwdIt dest)
+ {
+ //Save initial destination position
+ FwdIt dest_init = dest;
+ size_type constructed = 0;
+
+ BOOST_TRY{
+ //Try to build objects
+ for (; first != last; ++dest, ++first, ++constructed){
+ this->construct(dest, *first);
+ }
+ }
+ BOOST_CATCH(...){
+ //Call destructors
+ for (; constructed--; ++dest_init){
+ this->destroy(dest_init);
+ }
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ return (constructed);
+ }
+
+ template <class InputIterator, class OutIterator>
+ void priv_copy(InputIterator first, InputIterator last, OutIterator result)
+ {
+ for ( ; first != last; ++first, ++result)
+ Traits::assign(*result, *first);
+ }
+
+ void priv_copy(const CharT* first, const CharT* last, CharT* result)
+ { Traits::copy(result, first, last - first); }
+
+ template <class Integer>
+ basic_string& priv_replace_dispatch(const_iterator first, const_iterator last,
+ Integer n, Integer x,
+ dtl::true_)
+ { return this->replace(first, last, (size_type) n, (CharT) x); }
+
+ template <class InputIter>
+ basic_string& priv_replace_dispatch(const_iterator first, const_iterator last,
+ InputIter f, InputIter l,
+ dtl::false_)
+ {
+ typedef typename boost::container::iterator_traits<InputIter>::iterator_category Category;
+ return this->priv_replace(first, last, f, l, Category());
+ }
+
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+};
+
+#if __cplusplus >= 201703L
+
+template <typename InputIterator>
+basic_string(InputIterator, InputIterator) ->
+ basic_string<typename iterator_traits<InputIterator>::value_type>;
+
+template <typename InputIterator, typename Allocator>
+basic_string(InputIterator, InputIterator, Allocator const&) ->
+ basic_string<typename iterator_traits<InputIterator>::value_type, Allocator>;
+
+#endif
+
+#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+//!Typedef for a basic_string of
+//!narrow characters
+typedef basic_string
+ <char
+ ,std::char_traits<char>
+ ,new_allocator<char> >
+string;
+
+//!Typedef for a basic_string of
+//!narrow characters
+typedef basic_string
+ <wchar_t
+ ,std::char_traits<wchar_t>
+ ,new_allocator<wchar_t> >
+wstring;
+
+#else
+
+template <class CharT, class Traits, class Allocator>
+const typename basic_string<CharT,Traits,Allocator>::size_type
+ basic_string<CharT,Traits,Allocator>::npos;
+
+template<class S>
+struct is_string
+{
+ static const bool value = false;
+};
+
+template<class C, class T, class A>
+struct is_string< basic_string<C, T, A> >
+{
+ static const bool value = true;
+};
+
+#endif
+
+// ------------------------------------------------------------
+// Non-member functions.
+
+// Operator+
+
+template <class CharT, class Traits, class Allocator> inline
+ basic_string<CharT,Traits,Allocator>
+ operator+(const basic_string<CharT,Traits,Allocator>& x
+ ,const basic_string<CharT,Traits,Allocator>& y)
+{
+ typedef basic_string<CharT,Traits,Allocator> str_t;
+ typedef typename str_t::reserve_t reserve_t;
+ reserve_t reserve;
+ str_t result(reserve, x.size() + y.size(), x.get_stored_allocator());
+ result.append(x);
+ result.append(y);
+ return result;
+}
+
+template <class CharT, class Traits, class Allocator> inline
+ basic_string<CharT, Traits, Allocator> operator+
+ ( BOOST_RV_REF_BEG basic_string<CharT, Traits, Allocator> BOOST_RV_REF_END x
+ , BOOST_RV_REF_BEG basic_string<CharT, Traits, Allocator> BOOST_RV_REF_END y)
+{
+ x += y;
+ return boost::move(x);
+}
+
+template <class CharT, class Traits, class Allocator> inline
+ basic_string<CharT, Traits, Allocator> operator+
+ ( BOOST_RV_REF_BEG basic_string<CharT, Traits, Allocator> BOOST_RV_REF_END x
+ , const basic_string<CharT,Traits,Allocator>& y)
+{
+ x += y;
+ return boost::move(x);
+}
+
+template <class CharT, class Traits, class Allocator> inline
+ basic_string<CharT, Traits, Allocator> operator+
+ (const basic_string<CharT,Traits,Allocator>& x
+ ,BOOST_RV_REF_BEG basic_string<CharT, Traits, Allocator> BOOST_RV_REF_END y)
+{
+ y.insert(y.begin(), x.begin(), x.end());
+ return boost::move(y);
+}
+
+template <class CharT, class Traits, class Allocator> inline
+ basic_string<CharT, Traits, Allocator> operator+
+ (const CharT* s, basic_string<CharT, Traits, Allocator> y)
+{
+ y.insert(y.begin(), s, s + Traits::length(s));
+ return y;
+}
+
+template <class CharT, class Traits, class Allocator> inline
+ basic_string<CharT,Traits,Allocator> operator+
+ (basic_string<CharT,Traits,Allocator> x, const CharT* s)
+{
+ x += s;
+ return x;
+}
+
+template <class CharT, class Traits, class Allocator> inline
+ basic_string<CharT,Traits,Allocator> operator+
+ (CharT c, basic_string<CharT,Traits,Allocator> y)
+{
+ y.insert(y.begin(), c);
+ return y;
+}
+
+template <class CharT, class Traits, class Allocator> inline
+ basic_string<CharT,Traits,Allocator> operator+
+ (basic_string<CharT,Traits,Allocator> x, const CharT c)
+{
+ x += c;
+ return x;
+}
+
+// Operator== and operator!=
+
+template <class CharT, class Traits, class Allocator>
+inline bool
+operator==(const basic_string<CharT,Traits,Allocator>& x, const basic_string<CharT,Traits,Allocator>& y)
+{
+ return x.size() == y.size() &&
+ Traits::compare(x.data(), y.data(), x.size()) == 0;
+}
+
+template <class CharT, class Traits, class Allocator>
+inline bool
+operator==(const CharT* s, const basic_string<CharT,Traits,Allocator>& y)
+{
+ typename basic_string<CharT,Traits,Allocator>::size_type n = Traits::length(s);
+ return n == y.size() && Traits::compare(s, y.data(), n) == 0;
+}
+
+template <class CharT, class Traits, class Allocator>
+inline bool
+operator==(const basic_string<CharT,Traits,Allocator>& x, const CharT* s)
+{
+ typename basic_string<CharT,Traits,Allocator>::size_type n = Traits::length(s);
+ return x.size() == n && Traits::compare(x.data(), s, n) == 0;
+}
+
+template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
+inline
+ BOOST_CONTAINER_DOC1ST( bool,
+ typename dtl::disable_if
+ <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
+ operator==( BasicStringView<CharT,Traits> x, const basic_string<CharT,Traits,Allocator>& y)
+{
+ return x.size() == y.size() &&
+ Traits::compare(x.data(), y.data(), x.size()) == 0;
+}
+
+template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
+inline
+ BOOST_CONTAINER_DOC1ST( bool,
+ typename dtl::disable_if
+ <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
+ operator==( const basic_string<CharT,Traits,Allocator>& x, BasicStringView<CharT,Traits> y)
+{
+ return x.size() == y.size() &&
+ Traits::compare(x.data(), y.data(), x.size()) == 0;
+}
+
+template <class CharT, class Traits, class Allocator>
+inline bool
+operator!=(const basic_string<CharT,Traits,Allocator>& x, const basic_string<CharT,Traits,Allocator>& y)
+ { return !(x == y); }
+
+template <class CharT, class Traits, class Allocator>
+inline bool
+operator!=(const CharT* s, const basic_string<CharT,Traits,Allocator>& y)
+ { return !(s == y); }
+
+template <class CharT, class Traits, class Allocator>
+inline bool
+operator!=(const basic_string<CharT,Traits,Allocator>& x, const CharT* s)
+ { return !(x == s); }
+
+
+template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
+inline
+ BOOST_CONTAINER_DOC1ST( bool,
+ typename dtl::disable_if
+ <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
+operator!=( BasicStringView<CharT,Traits> x, const basic_string<CharT,Traits,Allocator>& y)
+ { return !(x == y); }
+
+template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
+inline
+ BOOST_CONTAINER_DOC1ST( bool,
+ typename dtl::disable_if
+ <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
+operator!=( const basic_string<CharT,Traits,Allocator>& x, BasicStringView<CharT,Traits> y)
+ { return !(x == y); }
+
+// Operator< (and also >, <=, and >=).
+template <class CharT, class Traits, class Allocator>
+inline bool
+operator<(const basic_string<CharT,Traits,Allocator>& x, const basic_string<CharT,Traits,Allocator>& y)
+{
+ return x.compare(y) < 0;
+}
+
+template <class CharT, class Traits, class Allocator>
+inline bool
+operator<(const CharT* s, const basic_string<CharT,Traits,Allocator>& y)
+{
+ return y.compare(s) > 0;
+}
+
+template <class CharT, class Traits, class Allocator>
+inline bool
+operator<(const basic_string<CharT,Traits,Allocator>& x, const CharT* s)
+{
+ return x.compare(s) < 0;
+}
+
+template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
+inline
+ BOOST_CONTAINER_DOC1ST( bool,
+ typename dtl::disable_if
+ <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
+operator<( BasicStringView<CharT,Traits> x, const basic_string<CharT,Traits,Allocator>& y)
+ { return y.compare(x) > 0; }
+
+template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
+inline
+ BOOST_CONTAINER_DOC1ST( bool,
+ typename dtl::disable_if
+ <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
+operator<( const basic_string<CharT,Traits,Allocator>& x, BasicStringView<CharT,Traits> y)
+ { return x.compare(y) < 0; }
+
+template <class CharT, class Traits, class Allocator>
+inline bool
+operator>(const basic_string<CharT,Traits,Allocator>& x, const basic_string<CharT,Traits,Allocator>& y) {
+ return y < x;
+}
+
+template <class CharT, class Traits, class Allocator>
+inline bool
+operator>(const CharT* s, const basic_string<CharT,Traits,Allocator>& y) {
+ return y < s;
+}
+
+template <class CharT, class Traits, class Allocator>
+inline bool
+operator>(const basic_string<CharT,Traits,Allocator>& x, const CharT* s)
+{
+ return s < x;
+}
+
+template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
+inline
+ BOOST_CONTAINER_DOC1ST( bool,
+ typename dtl::disable_if
+ <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
+operator>( BasicStringView<CharT,Traits> x, const basic_string<CharT,Traits,Allocator>& y)
+ { return y < x; }
+
+template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
+inline
+ BOOST_CONTAINER_DOC1ST( bool,
+ typename dtl::disable_if
+ <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
+operator>( const basic_string<CharT,Traits,Allocator>& x, BasicStringView<CharT,Traits> y)
+ { return y < x; }
+
+template <class CharT, class Traits, class Allocator>
+inline bool
+operator<=(const basic_string<CharT,Traits,Allocator>& x, const basic_string<CharT,Traits,Allocator>& y)
+{
+ return !(y < x);
+}
+
+template <class CharT, class Traits, class Allocator>
+inline bool
+operator<=(const CharT* s, const basic_string<CharT,Traits,Allocator>& y)
+ { return !(y < s); }
+
+template <class CharT, class Traits, class Allocator>
+inline bool
+operator<=(const basic_string<CharT,Traits,Allocator>& x, const CharT* s)
+ { return !(s < x); }
+
+
+template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
+inline
+ BOOST_CONTAINER_DOC1ST( bool,
+ typename dtl::disable_if
+ <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
+operator<=( BasicStringView<CharT,Traits> x, const basic_string<CharT,Traits,Allocator>& y)
+ { return !(y < x); }
+
+template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
+inline
+ BOOST_CONTAINER_DOC1ST( bool,
+ typename dtl::disable_if
+ <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
+operator<=( const basic_string<CharT,Traits,Allocator>& x, BasicStringView<CharT,Traits> y)
+ { return !(y < x); }
+
+template <class CharT, class Traits, class Allocator>
+inline bool
+operator>=(const basic_string<CharT,Traits,Allocator>& x,
+ const basic_string<CharT,Traits,Allocator>& y)
+ { return !(x < y); }
+
+template <class CharT, class Traits, class Allocator>
+inline bool
+operator>=(const CharT* s, const basic_string<CharT,Traits,Allocator>& y)
+ { return !(s < y); }
+
+template <class CharT, class Traits, class Allocator>
+inline bool
+operator>=(const basic_string<CharT,Traits,Allocator>& x, const CharT* s)
+ { return !(x < s); }
+
+template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
+inline
+ BOOST_CONTAINER_DOC1ST( bool,
+ typename dtl::disable_if
+ <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
+operator>=( BasicStringView<CharT,Traits> x, const basic_string<CharT,Traits,Allocator>& y)
+ { return !(x < y); }
+
+template <class CharT, class Traits, class Allocator, template <class, class> class BasicStringView>
+inline
+ BOOST_CONTAINER_DOC1ST( bool,
+ typename dtl::disable_if
+ <is_string< BasicStringView<CharT BOOST_MOVE_I Traits> > BOOST_MOVE_I bool >::type)
+operator>=( const basic_string<CharT,Traits,Allocator>& x, BasicStringView<CharT,Traits> y)
+ { return !(x < y); }
+
+// Swap.
+template <class CharT, class Traits, class Allocator>
+inline void swap(basic_string<CharT,Traits,Allocator>& x, basic_string<CharT,Traits,Allocator>& y)
+{ x.swap(y); }
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+// I/O.
+namespace dtl {
+
+template <class CharT, class Traits>
+inline bool
+string_fill(std::basic_ostream<CharT, Traits>& os,
+ std::basic_streambuf<CharT, Traits>* buf,
+ std::size_t n)
+{
+ CharT f = os.fill();
+ std::size_t i;
+ bool ok = true;
+
+ for (i = 0; i < n; i++)
+ ok = ok && !Traits::eq_int_type(buf->sputc(f), Traits::eof());
+ return ok;
+}
+
+} //namespace dtl {
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+template <class CharT, class Traits, class Allocator>
+std::basic_ostream<CharT, Traits>&
+operator<<(std::basic_ostream<CharT, Traits>& os, const basic_string<CharT,Traits,Allocator>& s)
+{
+ typename std::basic_ostream<CharT, Traits>::sentry sentry(os);
+ bool ok = false;
+
+ if (sentry) {
+ ok = true;
+ typename basic_string<CharT,Traits,Allocator>::size_type n = s.size();
+ typename basic_string<CharT,Traits,Allocator>::size_type pad_len = 0;
+ const bool left = (os.flags() & std::ios::left) != 0;
+ const std::size_t w = os.width(0);
+ std::basic_streambuf<CharT, Traits>* buf = os.rdbuf();
+
+ if (w != 0 && n < w)
+ pad_len = w - n;
+
+ if (!left)
+ ok = dtl::string_fill(os, buf, pad_len);
+
+ ok = ok &&
+ buf->sputn(s.data(), std::streamsize(n)) == std::streamsize(n);
+
+ if (left)
+ ok = ok && dtl::string_fill(os, buf, pad_len);
+ }
+
+ if (!ok)
+ os.setstate(std::ios_base::failbit);
+
+ return os;
+}
+
+
+template <class CharT, class Traits, class Allocator>
+std::basic_istream<CharT, Traits>&
+operator>>(std::basic_istream<CharT, Traits>& is, basic_string<CharT,Traits,Allocator>& s)
+{
+ typename std::basic_istream<CharT, Traits>::sentry sentry(is);
+
+ if (sentry) {
+ std::basic_streambuf<CharT, Traits>* buf = is.rdbuf();
+ const std::ctype<CharT>& ctype = std::use_facet<std::ctype<CharT> >(is.getloc());
+
+ s.clear();
+ std::size_t n = is.width(0);
+ if (n == 0)
+ n = static_cast<std::size_t>(-1);
+ else
+ s.reserve(n);
+
+ while (n-- > 0) {
+ typename Traits::int_type c1 = buf->sbumpc();
+
+ if (Traits::eq_int_type(c1, Traits::eof())) {
+ is.setstate(std::ios_base::eofbit);
+ break;
+ }
+ else {
+ CharT c = Traits::to_char_type(c1);
+
+ if (ctype.is(std::ctype<CharT>::space, c)) {
+ if (Traits::eq_int_type(buf->sputbackc(c), Traits::eof()))
+ is.setstate(std::ios_base::failbit);
+ break;
+ }
+ else
+ s.push_back(c);
+ }
+ }
+
+ // If we have read no characters, then set failbit.
+ if (s.size() == 0)
+ is.setstate(std::ios_base::failbit);
+ }
+ else
+ is.setstate(std::ios_base::failbit);
+
+ return is;
+}
+
+template <class CharT, class Traits, class Allocator>
+std::basic_istream<CharT, Traits>&
+getline(std::istream& is, basic_string<CharT,Traits,Allocator>& s,CharT delim)
+{
+ typename basic_string<CharT,Traits,Allocator>::size_type nread = 0;
+ typename std::basic_istream<CharT, Traits>::sentry sentry(is, true);
+ if (sentry) {
+ std::basic_streambuf<CharT, Traits>* buf = is.rdbuf();
+ s.clear();
+
+ while (nread < s.max_size()) {
+ int c1 = buf->sbumpc();
+ if (Traits::eq_int_type(c1, Traits::eof())) {
+ is.setstate(std::ios_base::eofbit);
+ break;
+ }
+ else {
+ ++nread;
+ CharT c = Traits::to_char_type(c1);
+ if (!Traits::eq(c, delim))
+ s.push_back(c);
+ else
+ break; // Character is extracted but not appended.
+ }
+ }
+ }
+ if (nread == 0 || nread >= s.max_size())
+ is.setstate(std::ios_base::failbit);
+
+ return is;
+}
+
+template <class CharT, class Traits, class Allocator>
+inline std::basic_istream<CharT, Traits>&
+getline(std::basic_istream<CharT, Traits>& is, basic_string<CharT,Traits,Allocator>& s)
+{
+ return getline(is, s, '\n');
+}
+
+template <class Ch, class Allocator>
+inline std::size_t hash_value(basic_string<Ch, std::char_traits<Ch>, Allocator> const& v)
+{
+ return hash_range(v.begin(), v.end());
+}
+
+}}
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+namespace boost {
+
+//!has_trivial_destructor_after_move<> == true_type
+//!specialization for optimizations
+template <class C, class T, class Allocator>
+struct has_trivial_destructor_after_move<boost::container::basic_string<C, T, Allocator> >
+{
+ typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer;
+ static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value &&
+ ::boost::has_trivial_destructor_after_move<pointer>::value;
+};
+
+}
+
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif // BOOST_CONTAINER_STRING_HPP
diff --git a/include/boost/container/throw_exception.hpp b/include/boost/container/throw_exception.hpp
new file mode 100644
index 0000000..1b6eec1
--- /dev/null
+++ b/include/boost/container/throw_exception.hpp
@@ -0,0 +1,181 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2012-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_THROW_EXCEPTION_HPP
+#define BOOST_CONTAINER_THROW_EXCEPTION_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>
+
+#ifndef BOOST_NO_EXCEPTIONS
+ #include <stdexcept> //for std exception types
+ #include <string> //for implicit std::string conversion
+ #include <new> //for std::bad_alloc
+#else
+ #include <boost/assert.hpp>
+ #include <cstdlib> //for std::abort
+#endif
+
+namespace boost {
+namespace container {
+
+#if defined(BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS)
+ //The user must provide definitions for the following functions
+
+ void throw_bad_alloc();
+
+ void throw_out_of_range(const char* str);
+
+ void throw_length_error(const char* str);
+
+ void throw_logic_error(const char* str);
+
+ void throw_runtime_error(const char* str);
+
+#elif defined(BOOST_NO_EXCEPTIONS)
+
+ inline void throw_bad_alloc()
+ {
+ const char msg[] = "boost::container bad_alloc thrown";
+ (void)msg;
+ BOOST_ASSERT(!msg);
+ std::abort();
+ }
+
+ inline void throw_out_of_range(const char* str)
+ {
+ const char msg[] = "boost::container out_of_range thrown";
+ (void)msg; (void)str;
+ BOOST_ASSERT_MSG(!msg, str);
+ std::abort();
+ }
+
+ inline void throw_length_error(const char* str)
+ {
+ const char msg[] = "boost::container length_error thrown";
+ (void)msg; (void)str;
+ BOOST_ASSERT_MSG(!msg, str);
+ std::abort();
+ }
+
+ inline void throw_logic_error(const char* str)
+ {
+ const char msg[] = "boost::container logic_error thrown";
+ (void)msg; (void)str;
+ BOOST_ASSERT_MSG(!msg, str);
+ std::abort();
+ }
+
+ inline void throw_runtime_error(const char* str)
+ {
+ const char msg[] = "boost::container runtime_error thrown";
+ (void)msg; (void)str;
+ BOOST_ASSERT_MSG(!msg, str);
+ std::abort();
+ }
+
+#else //defined(BOOST_NO_EXCEPTIONS)
+
+ //! Exception callback called by Boost.Container when fails to allocate the requested storage space.
+ //! <ul>
+ //! <li>If BOOST_NO_EXCEPTIONS is NOT defined <code>std::bad_alloc()</code> is thrown.</li>
+ //!
+ //! <li>If BOOST_NO_EXCEPTIONS is defined and BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS
+ //! is NOT defined <code>BOOST_ASSERT(!"boost::container bad_alloc thrown")</code> is called
+ //! and <code>std::abort()</code> if the former returns.</li>
+ //!
+ //! <li>If BOOST_NO_EXCEPTIONS and BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS are defined
+ //! the user must provide an implementation and the function should not return.</li>
+ //! </ul>
+ inline void throw_bad_alloc()
+ {
+ throw std::bad_alloc();
+ }
+
+ //! Exception callback called by Boost.Container to signal arguments out of range.
+ //! <ul>
+ //! <li>If BOOST_NO_EXCEPTIONS is NOT defined <code>std::out_of_range(str)</code> is thrown.</li>
+ //!
+ //! <li>If BOOST_NO_EXCEPTIONS is defined and BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS
+ //! is NOT defined <code>BOOST_ASSERT_MSG(!"boost::container out_of_range thrown", str)</code> is called
+ //! and <code>std::abort()</code> if the former returns.</li>
+ //!
+ //! <li>If BOOST_NO_EXCEPTIONS and BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS are defined
+ //! the user must provide an implementation and the function should not return.</li>
+ //! </ul>
+ inline void throw_out_of_range(const char* str)
+ {
+ throw std::out_of_range(str);
+ }
+
+ //! Exception callback called by Boost.Container to signal errors resizing.
+ //! <ul>
+ //! <li>If BOOST_NO_EXCEPTIONS is NOT defined <code>std::length_error(str)</code> is thrown.</li>
+ //!
+ //! <li>If BOOST_NO_EXCEPTIONS is defined and BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS
+ //! is NOT defined <code>BOOST_ASSERT_MSG(!"boost::container length_error thrown", str)</code> is called
+ //! and <code>std::abort()</code> if the former returns.</li>
+ //!
+ //! <li>If BOOST_NO_EXCEPTIONS and BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS are defined
+ //! the user must provide an implementation and the function should not return.</li>
+ //! </ul>
+ inline void throw_length_error(const char* str)
+ {
+ throw std::length_error(str);
+ }
+
+ //! Exception callback called by Boost.Container to report errors in the internal logical
+ //! of the program, such as violation of logical preconditions or class invariants.
+ //! <ul>
+ //! <li>If BOOST_NO_EXCEPTIONS is NOT defined <code>std::logic_error(str)</code> is thrown.</li>
+ //!
+ //! <li>If BOOST_NO_EXCEPTIONS is defined and BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS
+ //! is NOT defined <code>BOOST_ASSERT_MSG(!"boost::container logic_error thrown", str)</code> is called
+ //! and <code>std::abort()</code> if the former returns.</li>
+ //!
+ //! <li>If BOOST_NO_EXCEPTIONS and BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS are defined
+ //! the user must provide an implementation and the function should not return.</li>
+ //! </ul>
+ inline void throw_logic_error(const char* str)
+ {
+ throw std::logic_error(str);
+ }
+
+ //! Exception callback called by Boost.Container to report errors that can only be detected during runtime.
+ //! <ul>
+ //! <li>If BOOST_NO_EXCEPTIONS is NOT defined <code>std::runtime_error(str)</code> is thrown.</li>
+ //!
+ //! <li>If BOOST_NO_EXCEPTIONS is defined and BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS
+ //! is NOT defined <code>BOOST_ASSERT_MSG(!"boost::container runtime_error thrown", str)</code> is called
+ //! and <code>std::abort()</code> if the former returns.</li>
+ //!
+ //! <li>If BOOST_NO_EXCEPTIONS and BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS are defined
+ //! the user must provide an implementation and the function should not return.</li>
+ //! </ul>
+ inline void throw_runtime_error(const char* str)
+ {
+ throw std::runtime_error(str);
+ }
+
+#endif
+
+}} //namespace boost { namespace container {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_CONTAINER_THROW_EXCEPTION_HPP
diff --git a/include/boost/container/uses_allocator.hpp b/include/boost/container/uses_allocator.hpp
new file mode 100644
index 0000000..e0e3518
--- /dev/null
+++ b/include/boost/container/uses_allocator.hpp
@@ -0,0 +1,169 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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_USES_ALLOCATOR_HPP
+#define BOOST_CONTAINER_USES_ALLOCATOR_HPP
+
+#include <boost/container/uses_allocator_fwd.hpp>
+#include <boost/container/detail/type_traits.hpp>
+
+namespace boost {
+namespace container {
+
+//! <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 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
+//! ill-formed.
+//!
+//! <code>
+//! template <class T, class Allocator = allocator<T> >
+//! class Z {
+//! public:
+//! typedef Allocator allocator_type;
+//!
+//! // Default constructor with optional allocator suffix
+//! Z(const allocator_type& a = allocator_type());
+//!
+//! // Copy constructor and allocator-extended copy constructor
+//! Z(const Z& zz);
+//! Z(const Z& zz, const allocator_type& a);
+//! };
+//!
+//! // Specialize trait for class template Z
+//! template <class T, class Allocator = allocator<T> >
+//! struct constructible_with_allocator_suffix<Z<T,Allocator> >
+//! { static const bool value = true; };
+//! </code>
+//!
+//! <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.
+//!
+//! In conforming C++11 compilers or compilers supporting SFINAE expressions
+//! (when BOOST_NO_SFINAE_EXPR is NOT defined), this trait is ignored and C++11 rules will be used
+//! to detect if a type should be constructed with suffix or prefix allocator arguments.
+template <class T>
+struct constructible_with_allocator_suffix
+{ static const bool value = false; };
+
+//! <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>: 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
+//! a constructor, then the program is ill-formed.
+//!
+//! <code>
+//! template <class T, class Allocator = allocator<T> >
+//! class Y {
+//! public:
+//! typedef Allocator allocator_type;
+//!
+//! // Default constructor with and allocator-extended default constructor
+//! Y();
+//! Y(allocator_arg_t, const allocator_type& a);
+//!
+//! // Copy constructor and allocator-extended copy constructor
+//! Y(const Y& yy);
+//! Y(allocator_arg_t, const allocator_type& a, const Y& yy);
+//!
+//! // Variadic constructor and allocator-extended variadic constructor
+//! template<class ...Args> Y(Args&& args...);
+//! template<class ...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> >
+//! { static const bool value = true; };
+//!
+//! </code>
+//!
+//! <b>Note</b>: This trait is a workaround inspired by "N2554: The Scoped Allocator 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.
+//!
+//! In conforming C++11 compilers or compilers supporting SFINAE expressions
+//! (when BOOST_NO_SFINAE_EXPR is NOT defined), this trait is ignored and C++11 rules will be used
+//! to detect if a type should be constructed with suffix or prefix allocator arguments.
+template <class T>
+struct constructible_with_allocator_prefix
+{ static const bool value = false; };
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+namespace dtl {
+
+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 Allocator.
+ private:
+ typedef char yes_type;
+ struct no_type{ char dummy[2]; };
+
+ // Match this function if T::allocator_type exists and is
+ // implicitly convertible from Allocator
+ template <class U>
+ static yes_type test(typename U::allocator_type);
+
+ // Match this function if T::allocator_type exists and it's type is `erased_type`.
+ template <class U, class V>
+ static typename dtl::enable_if
+ < dtl::is_same<typename U::allocator_type, erased_type>
+ , yes_type
+ >::type test(const V&);
+
+ // Match this function if TypeT::allocator_type does not exist or is
+ // not convertible from Allocator.
+ template <typename U>
+ static no_type test(...);
+ static Allocator alloc; // Declared but not defined
+
+ public:
+ static const bool value = sizeof(test<T>(alloc)) == sizeof(yes_type);
+};
+
+} //namespace dtl {
+
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+//! <b>Remark</b>: Automatically detects whether T has a nested allocator_type that is convertible from
+//! 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 where either:
+//! the first argument of a constructor has type allocator_arg_t and the second argument has type Alloc or
+//! the last argument of a constructor has type Alloc.
+//!
+//! <b>Result</b>: uses_allocator<T, Allocator>::value== true if a type T::allocator_type
+//! exists and either is_convertible<Alloc, T::allocator_type>::value != false or T::allocator_type
+//! is an alias `erased_type`. False otherwise.
+template <typename T, typename Allocator>
+struct uses_allocator
+ : dtl::uses_allocator_imp<T, Allocator>
+{};
+
+}} //namespace boost::container
+
+#endif //BOOST_CONTAINER_USES_ALLOCATOR_HPP
diff --git a/include/boost/container/uses_allocator_fwd.hpp b/include/boost/container/uses_allocator_fwd.hpp
new file mode 100644
index 0000000..42a5b90
--- /dev/null
+++ b/include/boost/container/uses_allocator_fwd.hpp
@@ -0,0 +1,73 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_USES_ALLOCATOR_FWD_HPP
+#define BOOST_CONTAINER_USES_ALLOCATOR_FWD_HPP
+
+#include <boost/container/detail/workaround.hpp>
+#include <boost/container/detail/std_fwd.hpp>
+
+//! \file
+//! This header forward declares boost::container::constructible_with_allocator_prefix,
+//! boost::container::constructible_with_allocator_suffix and
+//! boost::container::uses_allocator. Also defines the following types:
+
+namespace boost {
+namespace container {
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ template <int Dummy = 0>
+ struct std_allocator_arg_holder
+ {
+ static ::std::allocator_arg_t *dummy;
+ };
+
+ template <int Dummy> //Silence null-reference compiler warnings
+ ::std::allocator_arg_t *std_allocator_arg_holder<Dummy>::dummy = reinterpret_cast< ::std::allocator_arg_t * >(0x1234);
+
+typedef const std::allocator_arg_t & allocator_arg_t;
+
+#else
+
+//! 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 Allocator requirements
+typedef unspecified allocator_arg_t;
+
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+//! The `erased_type` struct is an empty struct that serves as a placeholder for a type
+//! T in situations where the actual type T is determined at runtime. For example,
+//! the nested type, `allocator_type`, is an alias for `erased_type` in classes that
+//! use type-erased allocators.
+struct erased_type {};
+
+//! A instance of type
+//! allocator_arg_t
+static allocator_arg_t allocator_arg = BOOST_CONTAINER_DOC1ST(unspecified, *std_allocator_arg_holder<>::dummy);
+
+// @cond
+
+template <class T>
+struct constructible_with_allocator_suffix;
+
+template <class T>
+struct constructible_with_allocator_prefix;
+
+template <typename T, typename Allocator>
+struct uses_allocator;
+
+// @endcond
+
+}} // namespace boost { namespace container {
+
+#endif //BOOST_CONTAINER_USES_ALLOCATOR_HPP
diff --git a/include/boost/container/vector.hpp b/include/boost/container/vector.hpp
new file mode 100644
index 0000000..c3baebc
--- /dev/null
+++ b/include/boost/container/vector.hpp
@@ -0,0 +1,3392 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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 http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_CONTAINER_VECTOR_HPP
+#define BOOST_CONTAINER_CONTAINER_VECTOR_HPP
+
+#ifndef BOOST_CONFIG_HPP
+# include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+
+// container
+#include <boost/container/container_fwd.hpp>
+#include <boost/container/allocator_traits.hpp>
+#include <boost/container/new_allocator.hpp> //new_allocator
+#include <boost/container/throw_exception.hpp>
+#include <boost/container/options.hpp>
+// container detail
+#include <boost/container/detail/advanced_insert_int.hpp>
+#include <boost/container/detail/algorithm.hpp> //equal()
+#include <boost/container/detail/alloc_helpers.hpp>
+#include <boost/container/detail/allocation_type.hpp>
+#include <boost/container/detail/copy_move_algo.hpp>
+#include <boost/container/detail/destroyers.hpp>
+#include <boost/container/detail/iterator.hpp>
+#include <boost/container/detail/iterators.hpp>
+#include <boost/move/detail/iterator_to_raw_pointer.hpp>
+#include <boost/container/detail/mpl.hpp>
+#include <boost/container/detail/next_capacity.hpp>
+#include <boost/container/detail/value_functors.hpp>
+#include <boost/move/detail/to_raw_pointer.hpp>
+#include <boost/container/detail/type_traits.hpp>
+#include <boost/container/detail/version_type.hpp>
+// intrusive
+#include <boost/intrusive/pointer_traits.hpp>
+// move
+#include <boost/move/adl_move_swap.hpp>
+#include <boost/move/iterator.hpp>
+#include <boost/move/traits.hpp>
+#include <boost/move/utility_core.hpp>
+// move/detail
+#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+#include <boost/move/detail/fwd_macros.hpp>
+#endif
+#include <boost/move/detail/move_helpers.hpp>
+// move/algo
+#include <boost/move/algo/adaptive_merge.hpp>
+#include <boost/move/algo/unique.hpp>
+#include <boost/move/algo/predicate.hpp>
+#include <boost/move/algo/detail/set_difference.hpp>
+// other
+#include <boost/core/no_exceptions_support.hpp>
+#include <boost/assert.hpp>
+#include <boost/cstdint.hpp>
+
+//std
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+#include <initializer_list> //for std::initializer_list
+#endif
+
+namespace boost {
+namespace container {
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+
+template <class Pointer, bool IsConst>
+class vec_iterator
+{
+ public:
+ typedef std::random_access_iterator_tag iterator_category;
+ typedef typename boost::intrusive::pointer_traits<Pointer>::element_type value_type;
+ typedef typename boost::intrusive::pointer_traits<Pointer>::difference_type difference_type;
+ typedef typename dtl::if_c
+ < IsConst
+ , typename boost::intrusive::pointer_traits<Pointer>::template
+ rebind_pointer<const value_type>::type
+ , Pointer
+ >::type pointer;
+ typedef typename boost::intrusive::pointer_traits<pointer> ptr_traits;
+ typedef typename ptr_traits::reference reference;
+
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ private:
+ Pointer m_ptr;
+
+ public:
+ BOOST_CONTAINER_FORCEINLINE const Pointer &get_ptr() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return m_ptr; }
+
+ BOOST_CONTAINER_FORCEINLINE Pointer &get_ptr() BOOST_NOEXCEPT_OR_NOTHROW
+ { return m_ptr; }
+
+ BOOST_CONTAINER_FORCEINLINE explicit vec_iterator(Pointer ptr) BOOST_NOEXCEPT_OR_NOTHROW
+ : m_ptr(ptr)
+ {}
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ public:
+
+ //Constructors
+ BOOST_CONTAINER_FORCEINLINE vec_iterator() BOOST_NOEXCEPT_OR_NOTHROW
+ : m_ptr() //Value initialization to achieve "null iterators" (N3644)
+ {}
+
+ BOOST_CONTAINER_FORCEINLINE vec_iterator(vec_iterator<Pointer, false> const& other) BOOST_NOEXCEPT_OR_NOTHROW
+ : m_ptr(other.get_ptr())
+ {}
+
+ //Pointer like operators
+ BOOST_CONTAINER_FORCEINLINE reference operator*() const BOOST_NOEXCEPT_OR_NOTHROW
+ { BOOST_ASSERT(!!m_ptr); return *m_ptr; }
+
+ BOOST_CONTAINER_FORCEINLINE pointer operator->() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return m_ptr; }
+
+ BOOST_CONTAINER_FORCEINLINE reference operator[](difference_type off) const BOOST_NOEXCEPT_OR_NOTHROW
+ { BOOST_ASSERT(!!m_ptr); return m_ptr[off]; }
+
+ //Increment / Decrement
+ BOOST_CONTAINER_FORCEINLINE vec_iterator& operator++() BOOST_NOEXCEPT_OR_NOTHROW
+ { BOOST_ASSERT(!!m_ptr); ++m_ptr; return *this; }
+
+ BOOST_CONTAINER_FORCEINLINE vec_iterator operator++(int) BOOST_NOEXCEPT_OR_NOTHROW
+ { BOOST_ASSERT(!!m_ptr); return vec_iterator(m_ptr++); }
+
+ BOOST_CONTAINER_FORCEINLINE vec_iterator& operator--() BOOST_NOEXCEPT_OR_NOTHROW
+ { BOOST_ASSERT(!!m_ptr); --m_ptr; return *this; }
+
+ BOOST_CONTAINER_FORCEINLINE vec_iterator operator--(int) BOOST_NOEXCEPT_OR_NOTHROW
+ { BOOST_ASSERT(!!m_ptr); return vec_iterator(m_ptr--); }
+
+ //Arithmetic
+ BOOST_CONTAINER_FORCEINLINE vec_iterator& operator+=(difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
+ { BOOST_ASSERT(!!m_ptr); m_ptr += off; return *this; }
+
+ BOOST_CONTAINER_FORCEINLINE vec_iterator& operator-=(difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
+ { BOOST_ASSERT(!!m_ptr); m_ptr -= off; return *this; }
+
+ BOOST_CONTAINER_FORCEINLINE friend vec_iterator operator+(const vec_iterator &x, difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
+ { BOOST_ASSERT(!!x.m_ptr); return vec_iterator(x.m_ptr+off); }
+
+ BOOST_CONTAINER_FORCEINLINE friend vec_iterator operator+(difference_type off, vec_iterator right) BOOST_NOEXCEPT_OR_NOTHROW
+ { BOOST_ASSERT(!!right.m_ptr); right.m_ptr += off; return right; }
+
+ BOOST_CONTAINER_FORCEINLINE friend vec_iterator operator-(vec_iterator left, difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
+ { BOOST_ASSERT(!!left.m_ptr); left.m_ptr -= off; return left; }
+
+ BOOST_CONTAINER_FORCEINLINE friend difference_type operator-(const vec_iterator &left, const vec_iterator& right) BOOST_NOEXCEPT_OR_NOTHROW
+ { return left.m_ptr - right.m_ptr; }
+
+ //Comparison operators
+ BOOST_CONTAINER_FORCEINLINE friend bool operator== (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
+ { return l.m_ptr == r.m_ptr; }
+
+ BOOST_CONTAINER_FORCEINLINE friend bool operator!= (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
+ { return l.m_ptr != r.m_ptr; }
+
+ BOOST_CONTAINER_FORCEINLINE friend bool operator< (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
+ { return l.m_ptr < r.m_ptr; }
+
+ BOOST_CONTAINER_FORCEINLINE friend bool operator<= (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
+ { return l.m_ptr <= r.m_ptr; }
+
+ BOOST_CONTAINER_FORCEINLINE friend bool operator> (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
+ { return l.m_ptr > r.m_ptr; }
+
+ BOOST_CONTAINER_FORCEINLINE friend bool operator>= (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
+ { return l.m_ptr >= r.m_ptr; }
+};
+
+template<class BiDirPosConstIt, class BiDirValueIt>
+struct vector_insert_ordered_cursor
+{
+ typedef typename iterator_traits<BiDirPosConstIt>::value_type size_type;
+ typedef typename iterator_traits<BiDirValueIt>::reference reference;
+
+ BOOST_CONTAINER_FORCEINLINE vector_insert_ordered_cursor(BiDirPosConstIt posit, BiDirValueIt valueit)
+ : last_position_it(posit), last_value_it(valueit)
+ {}
+
+ void operator --()
+ {
+ --last_value_it;
+ --last_position_it;
+ while(this->get_pos() == size_type(-1)){
+ --last_value_it;
+ --last_position_it;
+ }
+ }
+
+ BOOST_CONTAINER_FORCEINLINE size_type get_pos() const
+ { return *last_position_it; }
+
+ BOOST_CONTAINER_FORCEINLINE reference get_val()
+ { return *last_value_it; }
+
+ BiDirPosConstIt last_position_it;
+ BiDirValueIt last_value_it;
+};
+
+struct initial_capacity_t{};
+
+template<class Pointer, bool IsConst>
+BOOST_CONTAINER_FORCEINLINE const Pointer &vector_iterator_get_ptr(const vec_iterator<Pointer, IsConst> &it) BOOST_NOEXCEPT_OR_NOTHROW
+{ return it.get_ptr(); }
+
+template<class Pointer, bool IsConst>
+BOOST_CONTAINER_FORCEINLINE Pointer &get_ptr(vec_iterator<Pointer, IsConst> &it) BOOST_NOEXCEPT_OR_NOTHROW
+{ return it.get_ptr(); }
+
+struct vector_uninitialized_size_t {};
+static const vector_uninitialized_size_t vector_uninitialized_size = vector_uninitialized_size_t();
+
+template <class T>
+struct vector_value_traits_base
+{
+ static const bool trivial_dctr = dtl::is_trivially_destructible<T>::value;
+ static const bool trivial_dctr_after_move = has_trivial_destructor_after_move<T>::value;
+ static const bool trivial_copy = dtl::is_trivially_copy_constructible<T>::value;
+ static const bool nothrow_copy = dtl::is_nothrow_copy_constructible<T>::value || trivial_copy;
+ static const bool trivial_assign = dtl::is_trivially_copy_assignable<T>::value;
+ static const bool nothrow_assign = dtl::is_nothrow_copy_assignable<T>::value || trivial_assign;
+};
+
+
+template <class Allocator>
+struct vector_value_traits
+ : public vector_value_traits_base<typename Allocator::value_type>
+{
+ typedef vector_value_traits_base<typename Allocator::value_type> base_t;
+ //This is the anti-exception array destructor
+ //to deallocate values already constructed
+ typedef typename dtl::if_c
+ <base_t::trivial_dctr
+ ,dtl::null_scoped_destructor_n<Allocator>
+ ,dtl::scoped_destructor_n<Allocator>
+ >::type ArrayDestructor;
+ //This is the anti-exception array deallocator
+ typedef dtl::scoped_array_deallocator<Allocator> ArrayDeallocator;
+};
+
+//!This struct deallocates and allocated memory
+template < class Allocator
+ , class StoredSizeType
+ , class AllocatorVersion = typename dtl::version<Allocator>::type
+ >
+struct vector_alloc_holder
+ : public Allocator
+{
+ private:
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(vector_alloc_holder)
+
+ public:
+ typedef Allocator allocator_type;
+ typedef StoredSizeType stored_size_type;
+ typedef boost::container::allocator_traits<Allocator> allocator_traits_type;
+ typedef typename allocator_traits_type::pointer pointer;
+ typedef typename allocator_traits_type::size_type size_type;
+ typedef typename allocator_traits_type::value_type value_type;
+
+ static bool is_propagable_from(const allocator_type &from_alloc, pointer p, const allocator_type &to_alloc, bool const propagate_allocator)
+ {
+ (void)propagate_allocator; (void)p; (void)to_alloc; (void)from_alloc;
+ const bool all_storage_propagable = !allocator_traits_type::is_partially_propagable::value ||
+ !allocator_traits_type::storage_is_unpropagable(from_alloc, p);
+ return all_storage_propagable && (propagate_allocator || allocator_traits_type::equal(from_alloc, to_alloc));
+ }
+
+ static bool are_swap_propagable(const allocator_type &l_a, pointer l_p, const allocator_type &r_a, pointer r_p, bool const propagate_allocator)
+ {
+ (void)propagate_allocator; (void)l_p; (void)r_p; (void)l_a; (void)r_a;
+ const bool all_storage_propagable = !allocator_traits_type::is_partially_propagable::value ||
+ !(allocator_traits_type::storage_is_unpropagable(l_a, l_p) || allocator_traits_type::storage_is_unpropagable(r_a, r_p));
+ return all_storage_propagable && (propagate_allocator || allocator_traits_type::equal(l_a, r_a));
+ }
+
+ //Constructor, does not throw
+ vector_alloc_holder()
+ BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<Allocator>::value)
+ : Allocator(), m_start(), m_size(), m_capacity()
+ {}
+
+ //Constructor, does not throw
+ template<class AllocConvertible>
+ explicit vector_alloc_holder(BOOST_FWD_REF(AllocConvertible) a) BOOST_NOEXCEPT_OR_NOTHROW
+ : Allocator(boost::forward<AllocConvertible>(a)), m_start(), m_size(), m_capacity()
+ {}
+
+ //Constructor, does not throw
+ template<class AllocConvertible>
+ vector_alloc_holder(vector_uninitialized_size_t, BOOST_FWD_REF(AllocConvertible) a, size_type initial_size)
+ : Allocator(boost::forward<AllocConvertible>(a))
+ , m_start()
+ //Size is initialized here so vector should only call uninitialized_xxx after this
+ , m_size(static_cast<stored_size_type>(initial_size))
+ , m_capacity()
+ {
+ if(initial_size){
+ pointer reuse = pointer();
+ size_type final_cap = initial_size;
+ m_start = this->allocation_command(allocate_new, initial_size, final_cap, reuse);
+ m_capacity = static_cast<stored_size_type>(final_cap);
+ }
+ }
+
+ //Constructor, does not throw
+ vector_alloc_holder(vector_uninitialized_size_t, size_type initial_size)
+ : Allocator()
+ , m_start()
+ //Size is initialized here so vector should only call uninitialized_xxx after this
+ , m_size(static_cast<stored_size_type>(initial_size))
+ , m_capacity()
+ {
+ if(initial_size){
+ pointer reuse = pointer();
+ size_type final_cap = initial_size;
+ m_start = this->allocation_command(allocate_new, initial_size, final_cap, reuse);
+ m_capacity = static_cast<stored_size_type>(final_cap);
+ }
+ }
+
+ vector_alloc_holder(BOOST_RV_REF(vector_alloc_holder) holder) BOOST_NOEXCEPT_OR_NOTHROW
+ : Allocator(BOOST_MOVE_BASE(Allocator, holder))
+ , m_start(holder.m_start)
+ , m_size(holder.m_size)
+ , m_capacity(holder.m_capacity)
+ {
+ holder.m_start = pointer();
+ holder.m_size = holder.m_capacity = 0;
+ }
+
+ vector_alloc_holder(initial_capacity_t, pointer p, size_type capacity, BOOST_RV_REF(vector_alloc_holder) holder)
+ : Allocator(BOOST_MOVE_BASE(Allocator, holder))
+ , m_start(p)
+ , m_size(holder.m_size)
+ , m_capacity(static_cast<stored_size_type>(capacity))
+ {
+ allocator_type &this_alloc = this->alloc();
+ allocator_type &x_alloc = holder.alloc();
+ if(this->is_propagable_from(x_alloc, holder.start(), this_alloc, true)){
+ if(this->m_capacity){
+ this->deallocate(this->m_start, this->m_capacity);
+ }
+ m_start = holder.m_start;
+ m_capacity = holder.m_capacity;
+ holder.m_start = pointer();
+ holder.m_capacity = holder.m_size = 0;
+ }
+ else if(this->m_capacity < holder.m_size){
+ size_type const n = holder.m_size;
+ pointer reuse = pointer();
+ size_type final_cap = n;
+ m_start = this->allocation_command(allocate_new, n, final_cap, reuse);
+ m_capacity = static_cast<stored_size_type>(final_cap);
+ #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
+ this->num_alloc += n != 0;
+ #endif
+ }
+ }
+
+ vector_alloc_holder(initial_capacity_t, pointer p, size_type n)
+ BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<Allocator>::value)
+ : Allocator()
+ , m_start(p)
+ , m_size()
+ //n is guaranteed to fit into stored_size_type
+ , m_capacity(static_cast<stored_size_type>(n))
+ {}
+
+ template<class AllocFwd>
+ vector_alloc_holder(initial_capacity_t, pointer p, size_type n, BOOST_FWD_REF(AllocFwd) a)
+ : Allocator(::boost::forward<AllocFwd>(a))
+ , m_start(p)
+ , m_size()
+ , m_capacity(n)
+ {}
+
+ BOOST_CONTAINER_FORCEINLINE ~vector_alloc_holder() BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ if(this->m_capacity){
+ this->deallocate(this->m_start, this->m_capacity);
+ }
+ }
+
+ BOOST_CONTAINER_FORCEINLINE pointer allocation_command(boost::container::allocation_type command,
+ size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse)
+ {
+ typedef typename dtl::version<Allocator>::type alloc_version;
+ return this->priv_allocation_command(alloc_version(), command, limit_size, prefer_in_recvd_out_size, reuse);
+ }
+
+ BOOST_CONTAINER_FORCEINLINE pointer allocate(size_type n)
+ {
+ const size_type max_alloc = allocator_traits_type::max_size(this->alloc());
+ const size_type max = max_alloc <= stored_size_type(-1) ? max_alloc : stored_size_type(-1);
+ if ( max < n )
+ boost::container::throw_length_error("get_next_capacity, allocator's max size reached");
+
+ return allocator_traits_type::allocate(this->alloc(), n);
+ }
+
+ BOOST_CONTAINER_FORCEINLINE void deallocate(const pointer &p, size_type n)
+ {
+ allocator_traits_type::deallocate(this->alloc(), p, n);
+ }
+
+ bool try_expand_fwd(size_type at_least)
+ {
+ //There is not enough memory, try to expand the old one
+ const size_type new_cap = this->capacity() + at_least;
+ size_type real_cap = new_cap;
+ pointer reuse = this->start();
+ bool const success = !!this->allocation_command(expand_fwd, new_cap, real_cap, reuse);
+ //Check for forward expansion
+ if(success){
+ #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
+ ++this->num_expand_fwd;
+ #endif
+ this->capacity(real_cap);
+ }
+ return success;
+ }
+
+ template<class GrowthFactorType>
+ size_type next_capacity(size_type additional_objects) const
+ {
+ BOOST_ASSERT(additional_objects > size_type(this->m_capacity - this->m_size));
+ size_type max = allocator_traits_type::max_size(this->alloc());
+ (clamp_by_stored_size_type)(max, stored_size_type());
+ const size_type remaining_cap = max - size_type(this->m_capacity);
+ const size_type min_additional_cap = additional_objects - size_type(this->m_capacity - this->m_size);
+
+ if ( remaining_cap < min_additional_cap )
+ boost::container::throw_length_error("get_next_capacity, allocator's max size reached");
+
+ return GrowthFactorType()( size_type(this->m_capacity), min_additional_cap, max);
+ }
+
+ pointer m_start;
+ stored_size_type m_size;
+ stored_size_type m_capacity;
+
+ void swap_resources(vector_alloc_holder &x) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ boost::adl_move_swap(this->m_start, x.m_start);
+ boost::adl_move_swap(this->m_size, x.m_size);
+ boost::adl_move_swap(this->m_capacity, x.m_capacity);
+ }
+
+ void steal_resources(vector_alloc_holder &x) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ this->m_start = x.m_start;
+ this->m_size = x.m_size;
+ this->m_capacity = x.m_capacity;
+ x.m_start = pointer();
+ x.m_size = x.m_capacity = 0;
+ }
+
+ BOOST_CONTAINER_FORCEINLINE Allocator &alloc() BOOST_NOEXCEPT_OR_NOTHROW
+ { return *this; }
+
+ BOOST_CONTAINER_FORCEINLINE const Allocator &alloc() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return *this; }
+
+ BOOST_CONTAINER_FORCEINLINE const pointer &start() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return m_start; }
+ BOOST_CONTAINER_FORCEINLINE size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return m_capacity; }
+ BOOST_CONTAINER_FORCEINLINE void start(const pointer &p) BOOST_NOEXCEPT_OR_NOTHROW
+ { m_start = p; }
+ BOOST_CONTAINER_FORCEINLINE void capacity(const size_type &c) BOOST_NOEXCEPT_OR_NOTHROW
+ { BOOST_ASSERT( c <= stored_size_type(-1)); m_capacity = c; }
+
+ private:
+ void priv_first_allocation(size_type cap)
+ {
+ if(cap){
+ pointer reuse = pointer();
+ m_start = this->allocation_command(allocate_new, cap, cap, reuse);
+ m_capacity = cap;
+ #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
+ ++this->num_alloc;
+ #endif
+ }
+ }
+
+ BOOST_CONTAINER_FORCEINLINE static void clamp_by_stored_size_type(size_type &, size_type)
+ {}
+
+ template<class SomeStoredSizeType>
+ BOOST_CONTAINER_FORCEINLINE static void clamp_by_stored_size_type(size_type &s, SomeStoredSizeType)
+ {
+ if (s >= SomeStoredSizeType(-1) )
+ s = SomeStoredSizeType(-1);
+ }
+
+ BOOST_CONTAINER_FORCEINLINE pointer priv_allocation_command(version_1, boost::container::allocation_type command,
+ size_type limit_size,
+ size_type &prefer_in_recvd_out_size,
+ pointer &reuse)
+ {
+ (void)command;
+ BOOST_ASSERT( (command & allocate_new));
+ BOOST_ASSERT(!(command & nothrow_allocation));
+ //First detect overflow on smaller stored_size_types
+ if (limit_size > stored_size_type(-1)){
+ boost::container::throw_length_error("get_next_capacity, allocator's max size reached");
+ }
+ (clamp_by_stored_size_type)(prefer_in_recvd_out_size, stored_size_type());
+ pointer const p = this->allocate(prefer_in_recvd_out_size);
+ reuse = pointer();
+ return p;
+ }
+
+ pointer priv_allocation_command(version_2, boost::container::allocation_type command,
+ size_type limit_size,
+ size_type &prefer_in_recvd_out_size,
+ pointer &reuse)
+ {
+ //First detect overflow on smaller stored_size_types
+ if (limit_size > stored_size_type(-1)){
+ boost::container::throw_length_error("get_next_capacity, allocator's max size reached");
+ }
+ (clamp_by_stored_size_type)(prefer_in_recvd_out_size, stored_size_type());
+ //Allocate memory
+ pointer p = this->alloc().allocation_command(command, limit_size, prefer_in_recvd_out_size, reuse);
+ //If after allocation prefer_in_recvd_out_size is not representable by stored_size_type, truncate it.
+ (clamp_by_stored_size_type)(prefer_in_recvd_out_size, stored_size_type());
+ return p;
+ }
+};
+
+//!This struct deallocates and allocated memory
+template <class Allocator, class StoredSizeType>
+struct vector_alloc_holder<Allocator, StoredSizeType, version_0>
+ : public Allocator
+{
+ private:
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(vector_alloc_holder)
+
+ public:
+ typedef boost::container::allocator_traits<Allocator> allocator_traits_type;
+ typedef typename allocator_traits_type::pointer pointer;
+ typedef typename allocator_traits_type::size_type size_type;
+ typedef typename allocator_traits_type::value_type value_type;
+ typedef StoredSizeType stored_size_type;
+
+ template <class OtherAllocator, class OtherStoredSizeType, class OtherAllocatorVersion>
+ friend struct vector_alloc_holder;
+
+ //Constructor, does not throw
+ vector_alloc_holder()
+ BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<Allocator>::value)
+ : Allocator(), m_size()
+ {}
+
+ //Constructor, does not throw
+ template<class AllocConvertible>
+ explicit vector_alloc_holder(BOOST_FWD_REF(AllocConvertible) a) BOOST_NOEXCEPT_OR_NOTHROW
+ : Allocator(boost::forward<AllocConvertible>(a)), m_size()
+ {}
+
+ //Constructor, does not throw
+ template<class AllocConvertible>
+ vector_alloc_holder(vector_uninitialized_size_t, BOOST_FWD_REF(AllocConvertible) a, size_type initial_size)
+ : Allocator(boost::forward<AllocConvertible>(a))
+ , m_size(initial_size) //Size is initialized here...
+ {
+ //... and capacity here, so vector, must call uninitialized_xxx in the derived constructor
+ this->priv_first_allocation(initial_size);
+ }
+
+ //Constructor, does not throw
+ vector_alloc_holder(vector_uninitialized_size_t, size_type initial_size)
+ : Allocator()
+ , m_size(initial_size) //Size is initialized here...
+ {
+ //... and capacity here, so vector, must call uninitialized_xxx in the derived constructor
+ this->priv_first_allocation(initial_size);
+ }
+
+ vector_alloc_holder(BOOST_RV_REF(vector_alloc_holder) holder)
+ : Allocator(BOOST_MOVE_BASE(Allocator, holder))
+ , m_size(holder.m_size) //Size is initialized here so vector should only call uninitialized_xxx after this
+ {
+ ::boost::container::uninitialized_move_alloc_n
+ (this->alloc(), boost::movelib::to_raw_pointer(holder.start()), m_size, boost::movelib::to_raw_pointer(this->start()));
+ }
+
+ template<class OtherAllocator, class OtherStoredSizeType, class OtherAllocatorVersion>
+ vector_alloc_holder(BOOST_RV_REF_BEG vector_alloc_holder<OtherAllocator, OtherStoredSizeType, OtherAllocatorVersion> BOOST_RV_REF_END holder)
+ : Allocator()
+ , m_size(holder.m_size) //Initialize it to m_size as first_allocation can only succeed or abort
+ {
+ //Different allocator type so we must check we have enough storage
+ const size_type n = holder.m_size;
+ this->priv_first_allocation(n);
+ ::boost::container::uninitialized_move_alloc_n
+ (this->alloc(), boost::movelib::to_raw_pointer(holder.start()), n, boost::movelib::to_raw_pointer(this->start()));
+ }
+
+ BOOST_CONTAINER_FORCEINLINE void priv_first_allocation(size_type cap)
+ {
+ if(cap > Allocator::internal_capacity){
+ throw_bad_alloc();
+ }
+ }
+
+ BOOST_CONTAINER_FORCEINLINE void deep_swap(vector_alloc_holder &x)
+ {
+ this->priv_deep_swap(x);
+ }
+
+ template<class OtherAllocator, class OtherStoredSizeType, class OtherAllocatorVersion>
+ void deep_swap(vector_alloc_holder<OtherAllocator, OtherStoredSizeType, OtherAllocatorVersion> &x)
+ {
+ if(this->m_size > OtherAllocator::internal_capacity || x.m_size > Allocator::internal_capacity){
+ throw_bad_alloc();
+ }
+ this->priv_deep_swap(x);
+ }
+
+ BOOST_CONTAINER_FORCEINLINE void swap_resources(vector_alloc_holder &) BOOST_NOEXCEPT_OR_NOTHROW
+ { //Containers with version 0 allocators can't be moved without moving elements one by one
+ throw_bad_alloc();
+ }
+
+
+ BOOST_CONTAINER_FORCEINLINE void steal_resources(vector_alloc_holder &)
+ { //Containers with version 0 allocators can't be moved without moving elements one by one
+ throw_bad_alloc();
+ }
+
+ BOOST_CONTAINER_FORCEINLINE Allocator &alloc() BOOST_NOEXCEPT_OR_NOTHROW
+ { return *this; }
+
+ BOOST_CONTAINER_FORCEINLINE const Allocator &alloc() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return *this; }
+
+ BOOST_CONTAINER_FORCEINLINE bool try_expand_fwd(size_type at_least)
+ { return !at_least; }
+
+ BOOST_CONTAINER_FORCEINLINE pointer start() const BOOST_NOEXCEPT_OR_NOTHROW { return Allocator::internal_storage(); }
+ BOOST_CONTAINER_FORCEINLINE size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW { return Allocator::internal_capacity; }
+ stored_size_type m_size;
+
+ private:
+
+ template<class OtherAllocator, class OtherStoredSizeType, class OtherAllocatorVersion>
+ void priv_deep_swap(vector_alloc_holder<OtherAllocator, OtherStoredSizeType, OtherAllocatorVersion> &x)
+ {
+ const size_type MaxTmpStorage = sizeof(value_type)*Allocator::internal_capacity;
+ value_type *const first_this = boost::movelib::to_raw_pointer(this->start());
+ value_type *const first_x = boost::movelib::to_raw_pointer(x.start());
+
+ if(this->m_size < x.m_size){
+ boost::container::deep_swap_alloc_n<MaxTmpStorage>(this->alloc(), first_this, this->m_size, first_x, x.m_size);
+ }
+ else{
+ boost::container::deep_swap_alloc_n<MaxTmpStorage>(this->alloc(), first_x, x.m_size, first_this, this->m_size);
+ }
+ boost::adl_move_swap(this->m_size, x.m_size);
+ }
+};
+
+struct growth_factor_60;
+
+template<class T, class Default>
+struct default_if_void
+{
+ typedef T type;
+};
+
+template<class Default>
+struct default_if_void<void, Default>
+{
+ typedef Default type;
+};
+
+template<class Options, class AllocatorSizeType>
+struct get_vector_opt
+{
+ typedef vector_opt< typename default_if_void<typename Options::growth_factor_type, growth_factor_60>::type
+ , typename default_if_void<typename Options::stored_size_type, AllocatorSizeType>::type
+ > type;
+};
+
+template<class AllocatorSizeType>
+struct get_vector_opt<void, AllocatorSizeType>
+{
+ typedef vector_opt<growth_factor_60, AllocatorSizeType> type;
+};
+
+
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+//! A vector is a sequence that supports random access to elements, constant
+//! time insertion and removal of elements at the end, and linear time insertion
+//! and removal of elements at the beginning or in the middle. The number of
+//! elements in a vector may vary dynamically; memory management is automatic.
+//!
+//! \tparam T The type of object that is stored in the vector
+//! \tparam Allocator The allocator used for all internal memory management
+//! \tparam Options A type produced from \c boost::container::vector_options.
+template <class T, class Allocator BOOST_CONTAINER_DOCONLY(= new_allocator<T>), class Options BOOST_CONTAINER_DOCONLY(= void) >
+class vector
+{
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ typedef typename boost::container::allocator_traits<Allocator>::size_type alloc_size_type;
+ typedef typename get_vector_opt<Options, alloc_size_type>::type options_type;
+ typedef typename options_type::growth_factor_type growth_factor_type;
+ typedef typename options_type::stored_size_type stored_size_type;
+ typedef value_less<T> value_less_t;
+
+ //If provided the stored_size option must specify a type that is equal or a type that is smaller.
+ BOOST_STATIC_ASSERT( (sizeof(stored_size_type) < sizeof(alloc_size_type) ||
+ dtl::is_same<stored_size_type, alloc_size_type>::value) );
+
+ typedef typename dtl::version<Allocator>::type alloc_version;
+ typedef boost::container::vector_alloc_holder<Allocator, stored_size_type> alloc_holder_t;
+ alloc_holder_t m_holder;
+ typedef allocator_traits<Allocator> allocator_traits_type;
+ template <class U, class UAllocator, class UOptions>
+ friend class vector;
+
+ typedef typename allocator_traits_type::pointer pointer_impl;
+ typedef vec_iterator<pointer_impl, false> iterator_impl;
+ typedef vec_iterator<pointer_impl, true > const_iterator_impl;
+
+ protected:
+ static bool is_propagable_from(const Allocator &from_alloc, pointer_impl p, const Allocator &to_alloc, bool const propagate_allocator)
+ { return alloc_holder_t::is_propagable_from(from_alloc, p, to_alloc, propagate_allocator); }
+
+ static bool are_swap_propagable( const Allocator &l_a, pointer_impl l_p
+ , const Allocator &r_a, pointer_impl r_p, bool const propagate_allocator)
+ { return alloc_holder_t::are_swap_propagable(l_a, l_p, r_a, r_p, propagate_allocator); }
+
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ public:
+ //////////////////////////////////////////////
+ //
+ // types
+ //
+ //////////////////////////////////////////////
+
+ typedef 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;
+ typedef typename ::boost::container::allocator_traits<Allocator>::const_reference const_reference;
+ typedef typename ::boost::container::allocator_traits<Allocator>::size_type size_type;
+ typedef typename ::boost::container::allocator_traits<Allocator>::difference_type difference_type;
+ typedef Allocator allocator_type;
+ typedef Allocator stored_allocator_type;
+ typedef BOOST_CONTAINER_IMPDEF(iterator_impl) iterator;
+ typedef BOOST_CONTAINER_IMPDEF(const_iterator_impl) const_iterator;
+ typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<iterator>) reverse_iterator;
+ typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<const_iterator>) const_reverse_iterator;
+
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ private:
+ BOOST_COPYABLE_AND_MOVABLE(vector)
+ typedef vector_value_traits<Allocator> value_traits;
+ typedef constant_iterator<T, difference_type> cvalue_iterator;
+
+ protected:
+
+ BOOST_CONTAINER_FORCEINLINE void steal_resources(vector &x)
+ { return this->m_holder.steal_resources(x.m_holder); }
+
+ template<class AllocFwd>
+ BOOST_CONTAINER_FORCEINLINE vector(initial_capacity_t, pointer initial_memory, size_type capacity, BOOST_FWD_REF(AllocFwd) a)
+ : m_holder(initial_capacity_t(), initial_memory, capacity, ::boost::forward<AllocFwd>(a))
+ {}
+
+ BOOST_CONTAINER_FORCEINLINE vector(initial_capacity_t, pointer initial_memory, size_type capacity)
+ : m_holder(initial_capacity_t(), initial_memory, capacity)
+ {}
+
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ public:
+ //////////////////////////////////////////////
+ //
+ // construct/copy/destroy
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Constructs a vector taking the allocator as parameter.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ vector() BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<Allocator>::value)
+ : m_holder()
+ {}
+
+ //! <b>Effects</b>: Constructs a vector taking the allocator as parameter.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ explicit vector(const allocator_type& a) BOOST_NOEXCEPT_OR_NOTHROW
+ : m_holder(a)
+ {}
+
+ //! <b>Effects</b>: Constructs a vector and inserts n value initialized values.
+ //!
+ //! <b>Throws</b>: If allocator_type's allocation
+ //! throws or T's value initialization throws.
+ //!
+ //! <b>Complexity</b>: Linear to n.
+ explicit vector(size_type n)
+ : m_holder(vector_uninitialized_size, n)
+ {
+ #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
+ this->num_alloc += n != 0;
+ #endif
+ boost::container::uninitialized_value_init_alloc_n
+ (this->m_holder.alloc(), n, this->priv_raw_begin());
+ }
+
+ //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
+ //! and inserts n value initialized values.
+ //!
+ //! <b>Throws</b>: If allocator_type's allocation
+ //! throws or T's value initialization throws.
+ //!
+ //! <b>Complexity</b>: Linear to n.
+ explicit vector(size_type n, const allocator_type &a)
+ : m_holder(vector_uninitialized_size, a, n)
+ {
+ #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
+ this->num_alloc += n != 0;
+ #endif
+ boost::container::uninitialized_value_init_alloc_n
+ (this->m_holder.alloc(), n, this->priv_raw_begin());
+ }
+
+ //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
+ //! and inserts n default initialized values.
+ //!
+ //! <b>Throws</b>: If allocator_type's allocation
+ //! throws or T's default initialization throws.
+ //!
+ //! <b>Complexity</b>: Linear to n.
+ //!
+ //! <b>Note</b>: Non-standard extension
+ vector(size_type n, default_init_t)
+ : m_holder(vector_uninitialized_size, n)
+ {
+ #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
+ this->num_alloc += n != 0;
+ #endif
+ boost::container::uninitialized_default_init_alloc_n
+ (this->m_holder.alloc(), n, this->priv_raw_begin());
+ }
+
+ //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
+ //! and inserts n default initialized values.
+ //!
+ //! <b>Throws</b>: If allocator_type's allocation
+ //! throws or T's default initialization throws.
+ //!
+ //! <b>Complexity</b>: Linear to n.
+ //!
+ //! <b>Note</b>: Non-standard extension
+ vector(size_type n, default_init_t, const allocator_type &a)
+ : m_holder(vector_uninitialized_size, a, n)
+ {
+ #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
+ this->num_alloc += n != 0;
+ #endif
+ boost::container::uninitialized_default_init_alloc_n
+ (this->m_holder.alloc(), n, this->priv_raw_begin());
+ }
+
+ //! <b>Effects</b>: Constructs a vector
+ //! and inserts n copies of value.
+ //!
+ //! <b>Throws</b>: If allocator_type's allocation
+ //! throws or T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to n.
+ vector(size_type n, const T& value)
+ : m_holder(vector_uninitialized_size, n)
+ {
+ #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
+ this->num_alloc += n != 0;
+ #endif
+ boost::container::uninitialized_fill_alloc_n
+ (this->m_holder.alloc(), value, n, this->priv_raw_begin());
+ }
+
+ //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
+ //! and inserts n copies of value.
+ //!
+ //! <b>Throws</b>: If allocation
+ //! throws or T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to n.
+ vector(size_type n, const T& value, const allocator_type& a)
+ : m_holder(vector_uninitialized_size, a, n)
+ {
+ #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
+ this->num_alloc += n != 0;
+ #endif
+ boost::container::uninitialized_fill_alloc_n
+ (this->m_holder.alloc(), value, n, this->priv_raw_begin());
+ }
+
+ //! <b>Effects</b>: Constructs a vector
+ //! and inserts a copy of the range [first, last) in the vector.
+ //!
+ //! <b>Throws</b>: If allocator_type's allocation
+ //! throws or T's constructor taking a dereferenced InIt throws.
+ //!
+ //! <b>Complexity</b>: Linear to the range [first, last).
+// template <class InIt>
+// vector(InIt first, InIt last
+// BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_c
+// < dtl::is_convertible<InIt BOOST_MOVE_I size_type>::value
+// BOOST_MOVE_I dtl::nat >::type * = 0)
+// ) -> vector<typename iterator_traits<InIt>::value_type, new_allocator<typename iterator_traits<InIt>::value_type>>;
+ template <class InIt>
+ vector(InIt first, InIt last
+ BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_c
+ < dtl::is_convertible<InIt BOOST_MOVE_I size_type>::value
+ BOOST_MOVE_I dtl::nat >::type * = 0)
+ )
+ : m_holder()
+ { this->assign(first, last); }
+
+ //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
+ //! and inserts a copy of the range [first, last) in the vector.
+ //!
+ //! <b>Throws</b>: If allocator_type's allocation
+ //! throws or T's constructor taking a dereferenced InIt throws.
+ //!
+ //! <b>Complexity</b>: Linear to the range [first, last).
+// template <class InIt>
+// vector(InIt first, InIt last, const allocator_type& a
+// BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_c
+// < dtl::is_convertible<InIt BOOST_MOVE_I size_type>::value
+// BOOST_MOVE_I dtl::nat >::type * = 0)
+// ) -> vector<typename iterator_traits<InIt>::value_type, new_allocator<typename iterator_traits<InIt>::value_type>>;
+ template <class InIt>
+ vector(InIt first, InIt last, const allocator_type& a
+ BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_c
+ < dtl::is_convertible<InIt BOOST_MOVE_I size_type>::value
+ BOOST_MOVE_I dtl::nat >::type * = 0)
+ )
+ : m_holder(a)
+ { this->assign(first, last); }
+
+ //! <b>Effects</b>: Copy constructs a vector.
+ //!
+ //! <b>Postcondition</b>: x == *this.
+ //!
+ //! <b>Throws</b>: If allocator_type's allocation
+ //! throws or T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to the elements x contains.
+ vector(const vector &x)
+ : m_holder( vector_uninitialized_size
+ , allocator_traits_type::select_on_container_copy_construction(x.m_holder.alloc())
+ , x.size())
+ {
+ #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
+ this->num_alloc += x.size() != 0;
+ #endif
+ ::boost::container::uninitialized_copy_alloc_n
+ ( this->m_holder.alloc(), x.priv_raw_begin()
+ , x.size(), this->priv_raw_begin());
+ }
+
+ //! <b>Effects</b>: Move constructor. Moves x's resources to *this.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ vector(BOOST_RV_REF(vector) x) BOOST_NOEXCEPT_OR_NOTHROW
+ : m_holder(boost::move(x.m_holder))
+ { BOOST_STATIC_ASSERT((!allocator_traits_type::is_partially_propagable::value)); }
+
+ #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
+ //! and inserts a copy of the range [il.begin(), il.last()) in the vector
+ //!
+ //! <b>Throws</b>: If T's constructor taking a dereferenced initializer_list iterator throws.
+ //!
+ //! <b>Complexity</b>: Linear to the range [il.begin(), il.end()).
+ vector(std::initializer_list<value_type> il, const allocator_type& a = allocator_type())
+ : m_holder(a)
+ {
+ this->assign(il.begin(), il.end());
+ }
+ #endif
+
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ //! <b>Effects</b>: Move constructor. Moves x's resources to *this.
+ //!
+ //! <b>Throws</b>: If T's move constructor or allocation throws
+ //!
+ //! <b>Complexity</b>: Linear.
+ //!
+ //! <b>Note</b>: Non-standard extension to support static_vector
+ template<class OtherAllocator>
+ vector(BOOST_RV_REF_BEG vector<T, OtherAllocator> BOOST_RV_REF_END x
+ , typename dtl::enable_if_c
+ < dtl::is_version<OtherAllocator, 0>::value>::type * = 0
+ )
+ : m_holder(boost::move(x.m_holder))
+ {}
+
+ #endif //!defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ //! <b>Effects</b>: Copy constructs a vector using the specified allocator.
+ //!
+ //! <b>Postcondition</b>: x == *this.
+ //!
+ //! <b>Throws</b>: If allocation
+ //! throws or T's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to the elements x contains.
+ vector(const vector &x, const allocator_type &a)
+ : m_holder(vector_uninitialized_size, a, x.size())
+ {
+ #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
+ this->num_alloc += x.size() != 0;
+ #endif
+ ::boost::container::uninitialized_copy_alloc_n_source
+ ( this->m_holder.alloc(), x.priv_raw_begin()
+ , x.size(), this->priv_raw_begin());
+ }
+
+ //! <b>Effects</b>: Move constructor using the specified allocator.
+ //! 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 == x.get_allocator(), linear otherwise.
+ vector(BOOST_RV_REF(vector) x, const allocator_type &a)
+ : m_holder( vector_uninitialized_size, a
+ , is_propagable_from(x.get_stored_allocator(), x.m_holder.start(), a, true) ? 0 : x.size()
+ )
+ {
+ if(is_propagable_from(x.get_stored_allocator(), x.m_holder.start(), a, true)){
+ this->m_holder.steal_resources(x.m_holder);
+ }
+ else{
+ const size_type n = x.size();
+ #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
+ this->num_alloc += n != 0;
+ #endif
+ ::boost::container::uninitialized_move_alloc_n_source
+ ( this->m_holder.alloc(), x.priv_raw_begin()
+ , n, this->priv_raw_begin());
+ }
+ }
+
+ //! <b>Effects</b>: Destroys the vector. All stored values are destroyed
+ //! and used memory is deallocated.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements.
+ ~vector() BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ boost::container::destroy_alloc_n
+ (this->get_stored_allocator(), this->priv_raw_begin(), this->m_holder.m_size);
+ //vector_alloc_holder deallocates the data
+ }
+
+ //! <b>Effects</b>: Makes *this contain the same elements as x.
+ //!
+ //! <b>Postcondition</b>: this->size() == x.size(). *this contains a copy
+ //! of each of x's elements.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or T's copy/move constructor/assignment throws.
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in x.
+ BOOST_CONTAINER_FORCEINLINE vector& operator=(BOOST_COPY_ASSIGN_REF(vector) x)
+ {
+ if (&x != this){
+ this->priv_copy_assign(x);
+ }
+ return *this;
+ }
+
+ #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Make *this container contains elements from il.
+ //!
+ //! <b>Complexity</b>: Linear to the range [il.begin(), il.end()).
+ BOOST_CONTAINER_FORCEINLINE vector& operator=(std::initializer_list<value_type> il)
+ {
+ this->assign(il.begin(), il.end());
+ return *this;
+ }
+ #endif
+
+ //! <b>Effects</b>: Move assignment. All x's values are transferred to *this.
+ //!
+ //! <b>Postcondition</b>: x.empty(). *this contains a the elements x had
+ //! before the function.
+ //!
+ //! <b>Throws</b>: If allocator_traits_type::propagate_on_container_move_assignment
+ //! is false and (allocation throws or value_type's move constructor throws)
+ //!
+ //! <b>Complexity</b>: Constant if allocator_traits_type::
+ //! propagate_on_container_move_assignment is true or
+ //! this->get>allocator() == x.get_allocator(). Linear otherwise.
+ BOOST_CONTAINER_FORCEINLINE vector& operator=(BOOST_RV_REF(vector) x)
+ BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value
+ || allocator_traits_type::is_always_equal::value)
+ {
+ BOOST_ASSERT(&x != this);
+ this->priv_move_assign(boost::move(x));
+ return *this;
+ }
+
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ //! <b>Effects</b>: Move assignment. All x's values are transferred to *this.
+ //!
+ //! <b>Postcondition</b>: x.empty(). *this contains a the elements x had
+ //! before the function.
+ //!
+ //! <b>Throws</b>: If move constructor/assignment of T throws or allocation throws
+ //!
+ //! <b>Complexity</b>: Linear.
+ //!
+ //! <b>Note</b>: Non-standard extension to support static_vector
+ template<class OtherAllocator>
+ BOOST_CONTAINER_FORCEINLINE typename dtl::enable_if_and
+ < vector&
+ , dtl::is_version<OtherAllocator, 0>
+ , dtl::is_different<OtherAllocator, allocator_type>
+ >::type
+ operator=(BOOST_RV_REF_BEG vector<value_type, OtherAllocator> BOOST_RV_REF_END x)
+ {
+ this->priv_move_assign(boost::move(x));
+ return *this;
+ }
+
+ //! <b>Effects</b>: Copy assignment. All x's values are copied to *this.
+ //!
+ //! <b>Postcondition</b>: x.empty(). *this contains a the elements x had
+ //! before the function.
+ //!
+ //! <b>Throws</b>: If move constructor/assignment of T throws or allocation throws
+ //!
+ //! <b>Complexity</b>: Linear.
+ //!
+ //! <b>Note</b>: Non-standard extension to support static_vector
+ template<class OtherAllocator>
+ BOOST_CONTAINER_FORCEINLINE typename dtl::enable_if_and
+ < vector&
+ , dtl::is_version<OtherAllocator, 0>
+ , dtl::is_different<OtherAllocator, allocator_type>
+ >::type
+ operator=(const vector<value_type, OtherAllocator> &x)
+ {
+ this->priv_copy_assign(x);
+ return *this;
+ }
+
+ #endif
+
+ //! <b>Effects</b>: Assigns the the range [first, last) to *this.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or T's copy/move constructor/assignment or
+ //! T's constructor/assignment from dereferencing InpIt throws.
+ //!
+ //! <b>Complexity</b>: Linear to n.
+ template <class InIt>
+ void assign(InIt first, InIt last
+ //Input iterators or version 0 allocator
+ BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_or
+ < void
+ BOOST_MOVE_I dtl::is_convertible<InIt BOOST_MOVE_I size_type>
+ BOOST_MOVE_I dtl::and_
+ < dtl::is_different<alloc_version BOOST_MOVE_I version_0>
+ BOOST_MOVE_I dtl::is_not_input_iterator<InIt>
+ >
+ >::type * = 0)
+ )
+ {
+ //Overwrite all elements we can from [first, last)
+ iterator cur = this->begin();
+ const iterator end_it = this->end();
+ for ( ; first != last && cur != end_it; ++cur, ++first){
+ *cur = *first;
+ }
+
+ if (first == last){
+ //There are no more elements in the sequence, erase remaining
+ T* const end_pos = this->priv_raw_end();
+ const size_type n = static_cast<size_type>(end_pos - boost::movelib::iterator_to_raw_pointer(cur));
+ this->priv_destroy_last_n(n);
+ }
+ else{
+ //There are more elements in the range, insert the remaining ones
+ this->insert(this->cend(), first, last);
+ }
+ }
+
+ #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Assigns the the range [il.begin(), il.end()) to *this.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or
+ //! T's constructor from dereferencing iniializer_list iterator throws.
+ //!
+ BOOST_CONTAINER_FORCEINLINE void assign(std::initializer_list<T> il)
+ {
+ this->assign(il.begin(), il.end());
+ }
+ #endif
+
+ //! <b>Effects</b>: Assigns the the range [first, last) to *this.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or T's copy/move constructor/assignment or
+ //! T's constructor/assignment from dereferencing InpIt throws.
+ //!
+ //! <b>Complexity</b>: Linear to n.
+ template <class FwdIt>
+ void assign(FwdIt first, FwdIt last
+ //Forward iterators and version > 0 allocator
+ BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_or
+ < void
+ BOOST_MOVE_I dtl::is_same<alloc_version BOOST_MOVE_I version_0>
+ BOOST_MOVE_I dtl::is_convertible<FwdIt BOOST_MOVE_I size_type>
+ BOOST_MOVE_I dtl::is_input_iterator<FwdIt>
+ >::type * = 0)
+ )
+ {
+ //For Fwd iterators the standard only requires EmplaceConstructible and assignable from *first
+ //so we can't do any backwards allocation
+ const size_type input_sz = static_cast<size_type>(boost::container::iterator_distance(first, last));
+ const size_type old_capacity = this->capacity();
+ if(input_sz > old_capacity){ //If input range is too big, we need to reallocate
+ size_type real_cap = 0;
+ pointer reuse(this->m_holder.start());
+ pointer const ret(this->m_holder.allocation_command(allocate_new|expand_fwd, input_sz, real_cap = input_sz, reuse));
+ if(!reuse){ //New allocation, just emplace new values
+ #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
+ ++this->num_alloc;
+ #endif
+ pointer const old_p = this->m_holder.start();
+ if(old_p){
+ this->priv_destroy_all();
+ this->m_holder.deallocate(old_p, old_capacity);
+ }
+ this->m_holder.start(ret);
+ this->m_holder.capacity(real_cap);
+ this->m_holder.m_size = 0;
+ this->priv_uninitialized_construct_at_end(first, last);
+ return;
+ }
+ else{
+ #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
+ ++this->num_expand_fwd;
+ #endif
+ this->m_holder.capacity(real_cap);
+ //Forward expansion, use assignment + back deletion/construction that comes later
+ }
+ }
+
+ boost::container::copy_assign_range_alloc_n(this->m_holder.alloc(), first, input_sz, this->priv_raw_begin(), this->size());
+ this->m_holder.m_size = input_sz;
+ }
+
+ //! <b>Effects</b>: Assigns the n copies of val to *this.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or
+ //! T's copy/move constructor/assignment throws.
+ //!
+ //! <b>Complexity</b>: Linear to n.
+ BOOST_CONTAINER_FORCEINLINE void assign(size_type n, const value_type& val)
+ { this->assign(cvalue_iterator(val, n), cvalue_iterator()); }
+
+ //! <b>Effects</b>: Returns a copy of the internal allocator.
+ //!
+ //! <b>Throws</b>: If allocator's copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Constant.
+ allocator_type get_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->m_holder.alloc(); }
+
+ //! <b>Effects</b>: Returns a reference to the internal allocator.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->m_holder.alloc(); }
+
+ //! <b>Effects</b>: Returns a reference to the internal allocator.
+ //!
+ //! <b>Throws</b>: Nothing
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ BOOST_CONTAINER_FORCEINLINE const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->m_holder.alloc(); }
+
+ //////////////////////////////////////////////
+ //
+ // iterators
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Returns an iterator to the first element contained in the vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE iterator begin() BOOST_NOEXCEPT_OR_NOTHROW
+ { return iterator(this->m_holder.start()); }
+
+ //! <b>Effects</b>: Returns a const_iterator to the first element contained in the vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return const_iterator(this->m_holder.start()); }
+
+ //! <b>Effects</b>: Returns an iterator to the end of the vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE iterator end() BOOST_NOEXCEPT_OR_NOTHROW
+ { return iterator(this->m_holder.start() + this->m_holder.m_size); }
+
+ //! <b>Effects</b>: Returns a const_iterator to the end of the vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->cend(); }
+
+ //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
+ //! of the reversed vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW
+ { return reverse_iterator(this->end()); }
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
+ //! of the reversed vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->crbegin(); }
+
+ //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
+ //! of the reversed vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW
+ { return reverse_iterator(this->begin()); }
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
+ //! of the reversed vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->crend(); }
+
+ //! <b>Effects</b>: Returns a const_iterator to the first element contained in the vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return const_iterator(this->m_holder.start()); }
+
+ //! <b>Effects</b>: Returns a const_iterator to the end of the vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return const_iterator(this->m_holder.start() + this->m_holder.m_size); }
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
+ //! of the reversed vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return const_reverse_iterator(this->end());}
+
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
+ //! of the reversed vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return const_reverse_iterator(this->begin()); }
+
+ //////////////////////////////////////////////
+ //
+ // capacity
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Returns true if the vector contains no elements.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE bool empty() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return !this->m_holder.m_size; }
+
+ //! <b>Effects</b>: Returns the number of the elements contained in the vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE size_type size() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->m_holder.m_size; }
+
+ //! <b>Effects</b>: Returns the largest possible size of the vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return allocator_traits_type::max_size(this->m_holder.alloc()); }
+
+ //! <b>Effects</b>: Inserts or erases elements at the end such that
+ //! the size becomes n. New elements are value initialized.
+ //!
+ //! <b>Throws</b>: If memory allocation throws, or T's copy/move or value initialization throws.
+ //!
+ //! <b>Complexity</b>: Linear to the difference between size() and new_size.
+ void resize(size_type new_size)
+ { this->priv_resize(new_size, value_init); }
+
+ //! <b>Effects</b>: Inserts or erases elements at the end such that
+ //! the size becomes n. New elements are default initialized.
+ //!
+ //! <b>Throws</b>: If memory allocation throws, or T's copy/move or default initialization throws.
+ //!
+ //! <b>Complexity</b>: Linear to the difference between size() and new_size.
+ //!
+ //! <b>Note</b>: Non-standard extension
+ void resize(size_type new_size, default_init_t)
+ { this->priv_resize(new_size, default_init); }
+
+ //! <b>Effects</b>: Inserts or erases elements at the end such that
+ //! the size becomes n. New elements are copy constructed from x.
+ //!
+ //! <b>Throws</b>: If memory allocation throws, or T's copy/move constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to the difference between size() and new_size.
+ void resize(size_type new_size, const T& x)
+ { this->priv_resize(new_size, x); }
+
+ //! <b>Effects</b>: Number of elements for which memory has been allocated.
+ //! capacity() is always greater than or equal to size().
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->m_holder.capacity(); }
+
+ //! <b>Effects</b>: If n is less than or equal to capacity(), this call has no
+ //! effect. Otherwise, it is a request for allocation of additional memory.
+ //! If the request is successful, then capacity() is greater than or equal to
+ //! n; otherwise, capacity() is unchanged. In either case, size() is unchanged.
+ //!
+ //! <b>Throws</b>: If memory allocation allocation throws or T's copy/move constructor throws.
+ BOOST_CONTAINER_FORCEINLINE void reserve(size_type new_cap)
+ {
+ if (this->capacity() < new_cap){
+ this->priv_reserve_no_capacity(new_cap, alloc_version());
+ }
+ }
+
+ //! <b>Effects</b>: Tries to deallocate the excess of memory created
+ //! with previous allocations. The size of the vector is unchanged
+ //!
+ //! <b>Throws</b>: If memory allocation throws, or T's copy/move constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to size().
+ BOOST_CONTAINER_FORCEINLINE void shrink_to_fit()
+ { this->priv_shrink_to_fit(alloc_version()); }
+
+ //////////////////////////////////////////////
+ //
+ // element access
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Requires</b>: !empty()
+ //!
+ //! <b>Effects</b>: Returns a reference to the first
+ //! element of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ reference front() BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(!this->empty());
+ return *this->m_holder.start();
+ }
+
+ //! <b>Requires</b>: !empty()
+ //!
+ //! <b>Effects</b>: Returns a const reference to the first
+ //! element of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reference front() const BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(!this->empty());
+ return *this->m_holder.start();
+ }
+
+ //! <b>Requires</b>: !empty()
+ //!
+ //! <b>Effects</b>: Returns a reference to the last
+ //! element of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ reference back() BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(!this->empty());
+ return this->m_holder.start()[this->m_holder.m_size - 1];
+ }
+
+ //! <b>Requires</b>: !empty()
+ //!
+ //! <b>Effects</b>: Returns a const reference to the last
+ //! element of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reference back() const BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(!this->empty());
+ return this->m_holder.start()[this->m_holder.m_size - 1];
+ }
+
+ //! <b>Requires</b>: size() > n.
+ //!
+ //! <b>Effects</b>: Returns a reference to the nth element
+ //! from the beginning of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ reference operator[](size_type n) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(this->m_holder.m_size > n);
+ return this->m_holder.start()[n];
+ }
+
+ //! <b>Requires</b>: size() > n.
+ //!
+ //! <b>Effects</b>: Returns a const reference to the nth element
+ //! from the beginning of the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reference operator[](size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(this->m_holder.m_size > n);
+ return this->m_holder.start()[n];
+ }
+
+ //! <b>Requires</b>: size() >= n.
+ //!
+ //! <b>Effects</b>: Returns an iterator to the nth element
+ //! from the beginning of the container. Returns end()
+ //! if n == size().
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Note</b>: Non-standard extension
+ iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(this->m_holder.m_size >= n);
+ return iterator(this->m_holder.start()+n);
+ }
+
+ //! <b>Requires</b>: size() >= n.
+ //!
+ //! <b>Effects</b>: Returns a const_iterator to the nth element
+ //! from the beginning of the container. Returns end()
+ //! if n == size().
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Note</b>: Non-standard extension
+ const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(this->m_holder.m_size >= n);
+ return const_iterator(this->m_holder.start()+n);
+ }
+
+ //! <b>Requires</b>: 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(iterator p) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ //Range check assert done in priv_index_of
+ return this->priv_index_of(vector_iterator_get_ptr(p));
+ }
+
+ //! <b>Requires</b>: begin() <= p <= end().
+ //!
+ //! <b>Effects</b>: Returns the index of the element pointed by p
+ //! and size() if p == end().
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Note</b>: Non-standard extension
+ size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ //Range check assert done in priv_index_of
+ return this->priv_index_of(vector_iterator_get_ptr(p));
+ }
+
+ //! <b>Requires</b>: size() > n.
+ //!
+ //! <b>Effects</b>: Returns a reference to the nth element
+ //! from the beginning of the container.
+ //!
+ //! <b>Throws</b>: std::range_error if n >= size()
+ //!
+ //! <b>Complexity</b>: Constant.
+ reference at(size_type n)
+ {
+ this->priv_throw_if_out_of_range(n);
+ return this->m_holder.start()[n];
+ }
+
+ //! <b>Requires</b>: size() > n.
+ //!
+ //! <b>Effects</b>: Returns a const reference to the nth element
+ //! from the beginning of the container.
+ //!
+ //! <b>Throws</b>: std::range_error if n >= size()
+ //!
+ //! <b>Complexity</b>: Constant.
+ const_reference at(size_type n) const
+ {
+ this->priv_throw_if_out_of_range(n);
+ return this->m_holder.start()[n];
+ }
+
+ //////////////////////////////////////////////
+ //
+ // data access
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Returns</b>: A pointer such that [data(),data() + size()) is a valid range.
+ //! For a non-empty vector, data() == &front().
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ T* data() BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->priv_raw_begin(); }
+
+ //! <b>Returns</b>: A pointer such that [data(),data() + size()) is a valid range.
+ //! For a non-empty vector, data() == &front().
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ const T * data() const BOOST_NOEXCEPT_OR_NOTHROW
+ { return this->priv_raw_begin(); }
+
+ //////////////////////////////////////////////
+ //
+ // modifiers
+ //
+ //////////////////////////////////////////////
+
+ #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... in the end of the vector.
+ //!
+ //! <b>Returns</b>: A reference to the created object.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or the in-place constructor throws or
+ //! T's copy/move constructor throws.
+ //!
+ //! <b>Complexity</b>: Amortized constant time.
+ template<class ...Args>
+ BOOST_CONTAINER_FORCEINLINE reference emplace_back(BOOST_FWD_REF(Args)...args)
+ {
+ if (BOOST_LIKELY(this->room_enough())){
+ //There is more memory, just construct a new object at the end
+ T* const p = this->priv_raw_end();
+ allocator_traits_type::construct(this->m_holder.alloc(), p, ::boost::forward<Args>(args)...);
+ ++this->m_holder.m_size;
+ return *p;
+ }
+ else{
+ typedef dtl::insert_emplace_proxy<Allocator, T*, Args...> type;
+ return *this->priv_forward_range_insert_no_capacity
+ (this->back_ptr(), 1, type(::boost::forward<Args>(args)...), alloc_version());
+ }
+ }
+
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... in the end of the vector.
+ //!
+ //! <b>Throws</b>: If the in-place constructor throws.
+ //!
+ //! <b>Complexity</b>: Constant time.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ template<class ...Args>
+ BOOST_CONTAINER_FORCEINLINE bool stable_emplace_back(BOOST_FWD_REF(Args)...args)
+ {
+ const bool is_room_enough = this->room_enough() || (alloc_version::value == 2 && this->m_holder.try_expand_fwd(1u));
+ if (BOOST_LIKELY(is_room_enough)){
+ //There is more memory, just construct a new object at the end
+ allocator_traits_type::construct(this->m_holder.alloc(), this->priv_raw_end(), ::boost::forward<Args>(args)...);
+ ++this->m_holder.m_size;
+ }
+ return is_room_enough;
+ }
+
+ //! <b>Requires</b>: position must be a valid iterator of *this.
+ //!
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... before position
+ //!
+ //! <b>Throws</b>: If memory allocation throws or the in-place constructor throws or
+ //! T's copy/move constructor/assignment throws.
+ //!
+ //! <b>Complexity</b>: If position is end(), amortized constant time
+ //! Linear time otherwise.
+ template<class ...Args>
+ iterator emplace(const_iterator position, BOOST_FWD_REF(Args) ...args)
+ {
+ BOOST_ASSERT(this->priv_in_range_or_end(position));
+ //Just call more general insert(pos, size, value) and return iterator
+ typedef dtl::insert_emplace_proxy<Allocator, T*, Args...> type;
+ return this->priv_forward_range_insert( vector_iterator_get_ptr(position), 1
+ , type(::boost::forward<Args>(args)...));
+ }
+
+ #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ #define BOOST_CONTAINER_VECTOR_EMPLACE_CODE(N) \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ BOOST_CONTAINER_FORCEINLINE reference emplace_back(BOOST_MOVE_UREF##N)\
+ {\
+ if (BOOST_LIKELY(this->room_enough())){\
+ T* const p = this->priv_raw_end();\
+ allocator_traits_type::construct (this->m_holder.alloc()\
+ , this->priv_raw_end() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
+ ++this->m_holder.m_size;\
+ return *p;\
+ }\
+ else{\
+ typedef dtl::insert_emplace_proxy_arg##N<Allocator, T* BOOST_MOVE_I##N BOOST_MOVE_TARG##N> type;\
+ return *this->priv_forward_range_insert_no_capacity\
+ ( this->back_ptr(), 1, type(BOOST_MOVE_FWD##N), alloc_version());\
+ }\
+ }\
+ \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ BOOST_CONTAINER_FORCEINLINE bool stable_emplace_back(BOOST_MOVE_UREF##N)\
+ {\
+ const bool is_room_enough = this->room_enough() || (alloc_version::value == 2 && this->m_holder.try_expand_fwd(1u));\
+ if (BOOST_LIKELY(is_room_enough)){\
+ allocator_traits_type::construct (this->m_holder.alloc()\
+ , this->priv_raw_end() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
+ ++this->m_holder.m_size;\
+ }\
+ return is_room_enough;\
+ }\
+ \
+ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
+ iterator emplace(const_iterator pos BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
+ {\
+ BOOST_ASSERT(this->priv_in_range_or_end(pos));\
+ typedef dtl::insert_emplace_proxy_arg##N<Allocator, T* BOOST_MOVE_I##N BOOST_MOVE_TARG##N> type;\
+ return this->priv_forward_range_insert(vector_iterator_get_ptr(pos), 1, type(BOOST_MOVE_FWD##N));\
+ }\
+ //
+ BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_VECTOR_EMPLACE_CODE)
+ #undef BOOST_CONTAINER_VECTOR_EMPLACE_CODE
+
+ #endif
+
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ //! <b>Effects</b>: Inserts a copy of x at the end of the vector.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or
+ //! T's copy/move constructor throws.
+ //!
+ //! <b>Complexity</b>: Amortized constant time.
+ void push_back(const T &x);
+
+ //! <b>Effects</b>: Constructs a new element in the end of the vector
+ //! and moves the resources of x to this new element.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or
+ //! T's copy/move constructor throws.
+ //!
+ //! <b>Complexity</b>: Amortized constant time.
+ void push_back(T &&x);
+ #else
+ BOOST_MOVE_CONVERSION_AWARE_CATCH(push_back, T, void, priv_push_back)
+ #endif
+
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ //! <b>Requires</b>: position must be a valid iterator of *this.
+ //!
+ //! <b>Effects</b>: Insert a copy of x before position.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or T's copy/move constructor/assignment throws.
+ //!
+ //! <b>Complexity</b>: If position is end(), amortized constant time
+ //! Linear time otherwise.
+ iterator insert(const_iterator position, const T &x);
+
+ //! <b>Requires</b>: position must be a valid iterator of *this.
+ //!
+ //! <b>Effects</b>: Insert a new element before position with x's resources.
+ //!
+ //! <b>Throws</b>: If memory allocation throws.
+ //!
+ //! <b>Complexity</b>: If position is end(), amortized constant time
+ //! Linear time otherwise.
+ iterator insert(const_iterator position, T &&x);
+ #else
+ BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator, const_iterator)
+ #endif
+
+ //! <b>Requires</b>: p must be a valid iterator of *this.
+ //!
+ //! <b>Effects</b>: Insert n copies of x before pos.
+ //!
+ //! <b>Returns</b>: an iterator to the first inserted element or p if n is 0.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or T's copy/move constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to n.
+ iterator insert(const_iterator p, size_type n, const T& x)
+ {
+ BOOST_ASSERT(this->priv_in_range_or_end(p));
+ dtl::insert_n_copies_proxy<Allocator, T*> proxy(x);
+ return this->priv_forward_range_insert(vector_iterator_get_ptr(p), n, proxy);
+ }
+
+ //! <b>Requires</b>: p must be a valid iterator of *this.
+ //!
+ //! <b>Effects</b>: Insert a copy of the [first, last) range before pos.
+ //!
+ //! <b>Returns</b>: an iterator to the first inserted element or pos if first == last.
+ //!
+ //! <b>Throws</b>: If memory allocation throws, T's constructor from a
+ //! dereferenced InpIt throws or T's copy/move constructor/assignment throws.
+ //!
+ //! <b>Complexity</b>: Linear to boost::container::iterator_distance [first, last).
+ template <class InIt>
+ iterator insert(const_iterator pos, InIt first, InIt last
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename dtl::disable_if_or
+ < void
+ , dtl::is_convertible<InIt, size_type>
+ , dtl::is_not_input_iterator<InIt>
+ >::type * = 0
+ #endif
+ )
+ {
+ BOOST_ASSERT(this->priv_in_range_or_end(pos));
+ const size_type n_pos = pos - this->cbegin();
+ iterator it(vector_iterator_get_ptr(pos));
+ for(;first != last; ++first){
+ it = this->emplace(it, *first);
+ ++it;
+ }
+ return iterator(this->m_holder.start() + n_pos);
+ }
+
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ template <class FwdIt>
+ iterator insert(const_iterator pos, FwdIt first, FwdIt last
+ , typename dtl::disable_if_or
+ < void
+ , dtl::is_convertible<FwdIt, size_type>
+ , dtl::is_input_iterator<FwdIt>
+ >::type * = 0
+ )
+ {
+ BOOST_ASSERT(this->priv_in_range_or_end(pos));
+ dtl::insert_range_proxy<Allocator, FwdIt, T*> proxy(first);
+ return this->priv_forward_range_insert(vector_iterator_get_ptr(pos), boost::container::iterator_distance(first, last), proxy);
+ }
+ #endif
+
+ //! <b>Requires</b>: p must be a valid iterator of *this. num, must
+ //! be equal to boost::container::iterator_distance(first, last)
+ //!
+ //! <b>Effects</b>: Insert a copy of the [first, last) range before pos.
+ //!
+ //! <b>Returns</b>: an iterator to the first inserted element or pos if first == last.
+ //!
+ //! <b>Throws</b>: If memory allocation throws, T's constructor from a
+ //! dereferenced InpIt throws or T's copy/move constructor/assignment throws.
+ //!
+ //! <b>Complexity</b>: Linear to boost::container::iterator_distance [first, last).
+ //!
+ //! <b>Note</b>: This function avoids a linear operation to calculate boost::container::iterator_distance[first, last)
+ //! for forward and bidirectional iterators, and a one by one insertion for input iterators. This is a
+ //! a non-standard extension.
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ template <class InIt>
+ iterator insert(const_iterator pos, size_type num, InIt first, InIt last)
+ {
+ BOOST_ASSERT(this->priv_in_range_or_end(pos));
+ BOOST_ASSERT(dtl::is_input_iterator<InIt>::value ||
+ num == static_cast<size_type>(boost::container::iterator_distance(first, last)));
+ (void)last;
+ dtl::insert_range_proxy<Allocator, InIt, T*> proxy(first);
+ return this->priv_forward_range_insert(vector_iterator_get_ptr(pos), num, proxy);
+ }
+ #endif
+
+ #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Requires</b>: position must be a valid iterator of *this.
+ //!
+ //! <b>Effects</b>: Insert a copy of the [il.begin(), il.end()) range before position.
+ //!
+ //! <b>Returns</b>: an iterator to the first inserted element or position if first == last.
+ //!
+ //! <b>Complexity</b>: Linear to the range [il.begin(), il.end()).
+ iterator insert(const_iterator position, std::initializer_list<value_type> il)
+ {
+ //Assertion done in insert()
+ return this->insert(position, il.begin(), il.end());
+ }
+ #endif
+
+ //! <b>Effects</b>: Removes the last element from the container.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant time.
+ void pop_back() BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(!this->empty());
+ //Destroy last element
+ this->priv_destroy_last();
+ }
+
+ //! <b>Effects</b>: Erases the element at position pos.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Linear to the elements between pos and the
+ //! last element. Constant if pos is the last element.
+ iterator erase(const_iterator position)
+ {
+ BOOST_ASSERT(this->priv_in_range(position));
+ const pointer p = vector_iterator_get_ptr(position);
+ T *const pos_ptr = boost::movelib::to_raw_pointer(p);
+ T *const beg_ptr = this->priv_raw_begin();
+ T *const new_end_ptr = ::boost::container::move(pos_ptr + 1, beg_ptr + this->m_holder.m_size, pos_ptr);
+ //Move elements forward and destroy last
+ this->priv_destroy_last(pos_ptr != new_end_ptr);
+ return iterator(p);
+ }
+
+ //! <b>Effects</b>: Erases the elements pointed by [first, last).
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Linear to the distance between first and last
+ //! plus linear to the elements between pos and the last element.
+ iterator erase(const_iterator first, const_iterator last)
+ {
+ BOOST_ASSERT(first == last ||
+ (first < last && this->priv_in_range(first) && this->priv_in_range_or_end(last)));
+ if (first != last){
+ T* const old_end_ptr = this->priv_raw_end();
+ T* const first_ptr = boost::movelib::to_raw_pointer(vector_iterator_get_ptr(first));
+ T* const last_ptr = boost::movelib::to_raw_pointer(vector_iterator_get_ptr(last));
+ T* const ptr = boost::movelib::to_raw_pointer(boost::container::move(last_ptr, old_end_ptr, first_ptr));
+ this->priv_destroy_last_n(old_end_ptr - ptr);
+ }
+ return iterator(vector_iterator_get_ptr(first));
+ }
+
+ //! <b>Effects</b>: Swaps the contents of *this and x.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE void swap(vector& x)
+ BOOST_NOEXCEPT_IF( ((allocator_traits_type::propagate_on_container_swap::value
+ || allocator_traits_type::is_always_equal::value) &&
+ !dtl::is_version<Allocator, 0>::value))
+ {
+ this->priv_swap(x, dtl::bool_<dtl::is_version<Allocator, 0>::value>());
+ }
+
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ //! <b>Effects</b>: Swaps the contents of *this and x.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Linear
+ //!
+ //! <b>Note</b>: Non-standard extension to support static_vector
+ template<class OtherAllocator>
+ BOOST_CONTAINER_FORCEINLINE void swap(vector<T, OtherAllocator> & x
+ , typename dtl::enable_if_and
+ < void
+ , dtl::is_version<OtherAllocator, 0>
+ , dtl::is_different<OtherAllocator, allocator_type>
+ >::type * = 0
+ )
+ { this->m_holder.deep_swap(x.m_holder); }
+
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ //! <b>Effects</b>: Erases all the elements of the vector.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ BOOST_CONTAINER_FORCEINLINE void clear() BOOST_NOEXCEPT_OR_NOTHROW
+ { this->priv_destroy_all(); }
+
+ //! <b>Effects</b>: Returns true if x and y are equal
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ BOOST_CONTAINER_FORCEINLINE friend bool operator==(const vector& x, const vector& y)
+ { return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin()); }
+
+ //! <b>Effects</b>: Returns true if x and y are unequal
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ BOOST_CONTAINER_FORCEINLINE friend bool operator!=(const vector& x, const vector& y)
+ { return !(x == y); }
+
+ //! <b>Effects</b>: Returns true if x is less than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator<(const vector& x, const vector& y)
+ {
+ const_iterator first1(x.cbegin()), first2(y.cbegin());
+ const const_iterator last1(x.cend()), last2(y.cend());
+ for ( ; (first1 != last1) && (first2 != last2); ++first1, ++first2 ) {
+ if (*first1 < *first2) return true;
+ if (*first2 < *first1) return false;
+ }
+ return (first1 == last1) && (first2 != last2);
+ }
+
+ //! <b>Effects</b>: Returns true if x is greater than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ BOOST_CONTAINER_FORCEINLINE friend bool operator>(const vector& x, const vector& y)
+ { return y < x; }
+
+ //! <b>Effects</b>: Returns true if x is equal or less than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ BOOST_CONTAINER_FORCEINLINE friend bool operator<=(const vector& x, const vector& y)
+ { return !(y < x); }
+
+ //! <b>Effects</b>: Returns true if x is equal or greater than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ BOOST_CONTAINER_FORCEINLINE friend bool operator>=(const vector& x, const vector& y)
+ { return !(x < y); }
+
+ //! <b>Effects</b>: x.swap(y)
+ //!
+ //! <b>Complexity</b>: Constant.
+ BOOST_CONTAINER_FORCEINLINE friend void swap(vector& x, vector& y)
+ { x.swap(y); }
+
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ //! <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
+ //! (memory expansion) that will not invalidate iterators.
+ //! If the request is successful, then capacity() is greater than or equal to
+ //! n; otherwise, capacity() is unchanged. In either case, size() is unchanged.
+ //!
+ //! <b>Throws</b>: If memory allocation allocation throws or T's copy/move constructor throws.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ bool stable_reserve(size_type new_cap)
+ {
+ const size_type cp = this->capacity();
+ return cp >= new_cap || (alloc_version::value == 2 && this->m_holder.try_expand_fwd(new_cap - cp));
+ }
+
+ //Absolutely experimental. This function might change, disappear or simply crash!
+ template<class BiDirPosConstIt, class BiDirValueIt>
+ BOOST_CONTAINER_FORCEINLINE void insert_ordered_at(const size_type element_count, BiDirPosConstIt last_position_it, BiDirValueIt last_value_it)
+ {
+ typedef vector_insert_ordered_cursor<BiDirPosConstIt, BiDirValueIt> inserter_t;
+ return this->priv_insert_ordered_at(element_count, inserter_t(last_position_it, last_value_it));
+ }
+
+ template<class InputIt>
+ BOOST_CONTAINER_FORCEINLINE void merge(InputIt first, InputIt last)
+ { this->merge(first, last, value_less_t()); }
+
+ template<class InputIt, class Compare>
+ BOOST_CONTAINER_FORCEINLINE void merge(InputIt first, InputIt last, Compare comp)
+ {
+ size_type const s = this->size();
+ size_type const c = this->capacity();
+ size_type n = 0;
+ size_type const free_cap = c - s;
+ //If not input iterator and new elements don't fit in the remaining capacity, merge in new buffer
+ if(!dtl::is_input_iterator<InputIt>::value &&
+ free_cap < (n = static_cast<size_type>(boost::container::iterator_distance(first, last)))){
+ this->priv_merge_in_new_buffer(first, n, comp, alloc_version());
+ }
+ else{
+ iterator pos(this->insert(this->cend(), first, last));
+ T *const raw_beg = this->priv_raw_begin();
+ T *const raw_end = this->priv_raw_end();
+ T *const raw_pos = raw_beg + s;
+ boost::movelib::adaptive_merge(raw_beg, raw_pos, raw_end, comp, raw_end, free_cap - n);
+ }
+ }
+
+ template<class InputIt>
+ BOOST_CONTAINER_FORCEINLINE void merge_unique(InputIt first, InputIt last)
+ { this->merge_unique(first, last, value_less_t()); }
+
+ template<class InputIt, class Compare>
+ BOOST_CONTAINER_FORCEINLINE void merge_unique(InputIt first, InputIt last, Compare comp)
+ {
+ size_type const old_size = this->size();
+ this->priv_set_difference_back(first, last, comp);
+ T *const raw_beg = this->priv_raw_begin();
+ T *const raw_end = this->priv_raw_end();
+ T *raw_pos = raw_beg + old_size;
+ boost::movelib::adaptive_merge(raw_beg, raw_pos, raw_end, comp, raw_end, this->capacity() - this->size());
+ }
+
+ private:
+ template<class PositionValue>
+ void priv_insert_ordered_at(const size_type element_count, PositionValue position_value)
+ {
+ const size_type old_size_pos = this->size();
+ this->reserve(old_size_pos + element_count);
+ T* const begin_ptr = this->priv_raw_begin();
+ size_type insertions_left = element_count;
+ size_type prev_pos = old_size_pos;
+ size_type old_hole_size = element_count;
+
+ //Exception rollback. If any copy throws before the hole is filled, values
+ //already inserted/copied at the end of the buffer will be destroyed.
+ typename value_traits::ArrayDestructor past_hole_values_destroyer
+ (begin_ptr + old_size_pos + element_count, this->m_holder.alloc(), size_type(0u));
+ //Loop for each insertion backwards, first moving the elements after the insertion point,
+ //then inserting the element.
+ while(insertions_left){
+ --position_value;
+ size_type const pos = position_value.get_pos();
+ BOOST_ASSERT(pos != size_type(-1) && pos <= old_size_pos && pos <= prev_pos);
+ //If needed shift the range after the insertion point and the previous insertion point.
+ //Function will take care if the shift crosses the size() boundary, using copy/move
+ //or uninitialized copy/move if necessary.
+ size_type new_hole_size = (pos != prev_pos)
+ ? priv_insert_ordered_at_shift_range(pos, prev_pos, this->size(), insertions_left)
+ : old_hole_size
+ ;
+ if(new_hole_size){
+ //The hole was reduced by priv_insert_ordered_at_shift_range so expand exception rollback range backwards
+ past_hole_values_destroyer.increment_size_backwards(prev_pos - pos);
+ //Insert the new value in the hole
+ allocator_traits_type::construct(this->m_holder.alloc(), begin_ptr + pos + insertions_left - 1, position_value.get_val());
+ if(--new_hole_size){
+ //The hole was reduced by the new insertion by one
+ past_hole_values_destroyer.increment_size_backwards(size_type(1u));
+ }
+ else{
+ //Hole was just filled, disable exception rollback and change vector size
+ past_hole_values_destroyer.release();
+ this->m_holder.m_size += element_count;
+ }
+ }
+ else{
+ if(old_hole_size){
+ //Hole was just filled by priv_insert_ordered_at_shift_range, disable exception rollback and change vector size
+ past_hole_values_destroyer.release();
+ this->m_holder.m_size += element_count;
+ }
+ //Insert the new value in the already constructed range
+ begin_ptr[pos + insertions_left - 1] = position_value.get_val();
+ }
+ --insertions_left;
+ old_hole_size = new_hole_size;
+ prev_pos = pos;
+ }
+ }
+
+ template<class InputIt, class Compare>
+ void priv_set_difference_back(InputIt first1, InputIt last1, Compare comp)
+ {
+ T * old_first2 = this->priv_raw_begin();
+ T * first2 = old_first2;
+ T * last2 = this->priv_raw_end();
+
+ while (first1 != last1) {
+ if (first2 == last2){
+ this->insert(this->cend(), first1, last1);
+ return;
+ }
+
+ if (comp(*first1, *first2)) {
+ this->emplace_back(*first1);
+ T * const raw_begin = this->priv_raw_begin();
+ if(old_first2 != raw_begin)
+ {
+ //Reallocation happened, update range
+ first2 = raw_begin + (first2 - old_first2);
+ last2 = raw_begin + (last2 - old_first2);
+ old_first2 = raw_begin;
+ }
+ ++first1;
+ }
+ else {
+ if (!comp(*first2, *first1)) {
+ ++first1;
+ }
+ ++first2;
+ }
+ }
+ }
+
+ template<class FwdIt, class Compare>
+ BOOST_CONTAINER_FORCEINLINE void priv_merge_in_new_buffer(FwdIt, size_type, Compare, version_0)
+ {
+ throw_bad_alloc();
+ }
+
+ template<class FwdIt, class Compare, class Version>
+ void priv_merge_in_new_buffer(FwdIt first, size_type n, Compare comp, Version)
+ {
+ size_type const new_size = this->size() + n;
+ size_type new_cap = new_size;
+ pointer p = pointer();
+ pointer const new_storage = this->m_holder.allocation_command(allocate_new, new_size, new_cap, p);
+
+ BOOST_ASSERT((new_cap >= this->size() ) && (new_cap - this->size()) >= n);
+ allocator_type &a = this->m_holder.alloc();
+ typename value_traits::ArrayDeallocator new_buffer_deallocator(new_storage, a, new_cap);
+ typename value_traits::ArrayDestructor new_values_destroyer(new_storage, a, 0u);
+ T* pbeg = this->priv_raw_begin();
+ size_type const old_size = this->size();
+ T* const pend = pbeg + old_size;
+ T* d_first = boost::movelib::to_raw_pointer(new_storage);
+ size_type added = n;
+ //Merge in new buffer loop
+ while(1){
+ if(!n) {
+ ::boost::container::uninitialized_move_alloc(this->m_holder.alloc(), pbeg, pend, d_first);
+ break;
+ }
+ else if(pbeg == pend) {
+ ::boost::container::uninitialized_move_alloc_n(this->m_holder.alloc(), first, n, d_first);
+ break;
+ }
+ //maintain stability moving external values only if they are strictly less
+ else if(comp(*first, *pbeg)) {
+ allocator_traits_type::construct( this->m_holder.alloc(), d_first, *first );
+ new_values_destroyer.increment_size(1u);
+ ++first;
+ --n;
+ ++d_first;
+ }
+ else{
+ allocator_traits_type::construct( this->m_holder.alloc(), d_first, boost::move(*pbeg) );
+ new_values_destroyer.increment_size(1u);
+ ++pbeg;
+ ++d_first;
+ }
+ }
+
+ //Nothrow operations
+ pointer const old_p = this->m_holder.start();
+ size_type const old_cap = this->m_holder.capacity();
+ boost::container::destroy_alloc_n(a, boost::movelib::to_raw_pointer(old_p), old_size);
+ this->m_holder.deallocate(old_p, old_cap);
+ this->m_holder.m_size = old_size + added;
+ this->m_holder.start(new_storage);
+ this->m_holder.capacity(new_cap);
+ new_buffer_deallocator.release();
+ new_values_destroyer.release();
+ }
+
+ BOOST_CONTAINER_FORCEINLINE bool room_enough() const
+ { return this->m_holder.m_size < this->m_holder.capacity(); }
+
+ BOOST_CONTAINER_FORCEINLINE pointer back_ptr() const
+ { return this->m_holder.start() + this->m_holder.m_size; }
+
+ size_type priv_index_of(pointer p) const
+ {
+ BOOST_ASSERT(this->m_holder.start() <= p);
+ BOOST_ASSERT(p <= (this->m_holder.start()+this->size()));
+ return static_cast<size_type>(p - this->m_holder.start());
+ }
+
+ template<class OtherAllocator>
+ void priv_move_assign(BOOST_RV_REF_BEG vector<T, OtherAllocator> BOOST_RV_REF_END x
+ , typename dtl::enable_if_c
+ < dtl::is_version<OtherAllocator, 0>::value >::type * = 0)
+ {
+ if(!dtl::is_same<OtherAllocator, allocator_type>::value &&
+ this->capacity() < x.size()){
+ throw_bad_alloc();
+ }
+ T* const this_start = this->priv_raw_begin();
+ T* const other_start = x.priv_raw_begin();
+ const size_type this_sz = m_holder.m_size;
+ const size_type other_sz = static_cast<size_type>(x.m_holder.m_size);
+ boost::container::move_assign_range_alloc_n(this->m_holder.alloc(), other_start, other_sz, this_start, this_sz);
+ this->m_holder.m_size = other_sz;
+ }
+
+ template<class OtherAllocator>
+ void priv_move_assign(BOOST_RV_REF_BEG vector<T, OtherAllocator> BOOST_RV_REF_END x
+ , typename dtl::disable_if_or
+ < void
+ , dtl::is_version<OtherAllocator, 0>
+ , dtl::is_different<OtherAllocator, allocator_type>
+ >::type * = 0)
+ {
+ //for move assignment, no aliasing (&x != this) is assummed.
+ BOOST_ASSERT(this != &x);
+ allocator_type &this_alloc = this->m_holder.alloc();
+ allocator_type &x_alloc = x.m_holder.alloc();
+ const bool propagate_alloc = allocator_traits_type::propagate_on_container_move_assignment::value;
+
+ const bool is_propagable_from_x = is_propagable_from(x_alloc, x.m_holder.start(), this_alloc, propagate_alloc);
+ const bool is_propagable_from_t = is_propagable_from(this_alloc, m_holder.start(), x_alloc, propagate_alloc);
+ const bool are_both_propagable = is_propagable_from_x && is_propagable_from_t;
+
+ //Resources can be transferred if both allocators are
+ //going to be equal after this function (either propagated or already equal)
+ if(are_both_propagable){
+ //Destroy objects but retain memory in case x reuses it in the future
+ this->clear();
+ this->m_holder.swap_resources(x.m_holder);
+ }
+ else if(is_propagable_from_x){
+ this->clear();
+ this->m_holder.deallocate(this->m_holder.m_start, this->m_holder.m_capacity);
+ this->m_holder.steal_resources(x.m_holder);
+ }
+ //Else do a one by one move
+ else{
+ this->assign( boost::make_move_iterator(boost::movelib::iterator_to_raw_pointer(x.begin()))
+ , boost::make_move_iterator(boost::movelib::iterator_to_raw_pointer(x.end() ))
+ );
+ }
+ //Move allocator if needed
+ dtl::move_alloc(this_alloc, x_alloc, dtl::bool_<propagate_alloc>());
+ }
+
+ template<class OtherAllocator>
+ void priv_copy_assign(const vector<T, OtherAllocator> &x
+ , typename dtl::enable_if_c
+ < dtl::is_version<OtherAllocator, 0>::value >::type * = 0)
+ {
+ if(!dtl::is_same<OtherAllocator, allocator_type>::value &&
+ this->capacity() < x.size()){
+ throw_bad_alloc();
+ }
+ T* const this_start = this->priv_raw_begin();
+ T* const other_start = x.priv_raw_begin();
+ const size_type this_sz = m_holder.m_size;
+ const size_type other_sz = static_cast<size_type>(x.m_holder.m_size);
+ boost::container::copy_assign_range_alloc_n(this->m_holder.alloc(), other_start, other_sz, this_start, this_sz);
+ this->m_holder.m_size = other_sz;
+ }
+
+ template<class OtherAllocator>
+ typename dtl::disable_if_or
+ < void
+ , dtl::is_version<OtherAllocator, 0>
+ , dtl::is_different<OtherAllocator, allocator_type>
+ >::type
+ priv_copy_assign(const vector<T, OtherAllocator> &x)
+ {
+ allocator_type &this_alloc = this->m_holder.alloc();
+ const allocator_type &x_alloc = x.m_holder.alloc();
+ dtl::bool_<allocator_traits_type::
+ propagate_on_container_copy_assignment::value> flag;
+ if(flag && this_alloc != x_alloc){
+ this->clear();
+ this->shrink_to_fit();
+ }
+ dtl::assign_alloc(this_alloc, x_alloc, flag);
+ this->assign( x.priv_raw_begin(), x.priv_raw_end() );
+ }
+
+ template<class Vector> //Template it to avoid it in explicit instantiations
+ void priv_swap(Vector &x, dtl::true_type) //version_0
+ { this->m_holder.deep_swap(x.m_holder); }
+
+ template<class Vector> //Template it to avoid it in explicit instantiations
+ void priv_swap(Vector &x, dtl::false_type) //version_N
+ {
+ const bool propagate_alloc = allocator_traits_type::propagate_on_container_swap::value;
+ if(are_swap_propagable( this->get_stored_allocator(), this->m_holder.start()
+ , x.get_stored_allocator(), x.m_holder.start(), propagate_alloc)){
+ //Just swap internals
+ this->m_holder.swap_resources(x.m_holder);
+ }
+ else{
+ //Else swap element by element...
+ bool const t_smaller = this->size() < x.size();
+ vector &sml = t_smaller ? *this : x;
+ vector &big = t_smaller ? x : *this;
+
+ size_type const common_elements = sml.size();
+ for(size_type i = 0; i != common_elements; ++i){
+ boost::adl_move_swap(sml[i], big[i]);
+ }
+ //... and move-insert the remaining range
+ sml.insert( sml.cend()
+ , boost::make_move_iterator(boost::movelib::iterator_to_raw_pointer(big.nth(common_elements)))
+ , boost::make_move_iterator(boost::movelib::iterator_to_raw_pointer(big.end()))
+ );
+ //Destroy remaining elements
+ big.erase(big.nth(common_elements), big.cend());
+ }
+ //And now swap the allocator
+ dtl::swap_alloc(this->m_holder.alloc(), x.m_holder.alloc(), dtl::bool_<propagate_alloc>());
+ }
+
+ void priv_reserve_no_capacity(size_type, version_0)
+ { throw_bad_alloc(); }
+
+ dtl::insert_range_proxy<Allocator, boost::move_iterator<T*>, T*> priv_dummy_empty_proxy()
+ {
+ return dtl::insert_range_proxy<Allocator, boost::move_iterator<T*>, T*>
+ (::boost::make_move_iterator((T *)0));
+ }
+
+ void priv_reserve_no_capacity(size_type new_cap, version_1)
+ {
+ //There is not enough memory, allocate a new buffer
+ //Pass the hint so that allocators can take advantage of this.
+ pointer const p = this->m_holder.allocate(new_cap);
+ //We will reuse insert code, so create a dummy input iterator
+ this->priv_forward_range_insert_new_allocation
+ ( boost::movelib::to_raw_pointer(p), new_cap, this->priv_raw_end(), 0, this->priv_dummy_empty_proxy());
+ }
+
+ void priv_reserve_no_capacity(size_type new_cap, version_2)
+ {
+ //There is not enough memory, allocate a new
+ //buffer or expand the old one.
+ bool same_buffer_start;
+ size_type real_cap = 0;
+ pointer reuse(this->m_holder.start());
+ pointer const ret(this->m_holder.allocation_command(allocate_new | expand_fwd | expand_bwd, new_cap, real_cap = new_cap, reuse));
+
+ //Check for forward expansion
+ same_buffer_start = reuse && this->m_holder.start() == ret;
+ if(same_buffer_start){
+ #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
+ ++this->num_expand_fwd;
+ #endif
+ this->m_holder.capacity(real_cap);
+ }
+ else{ //If there is no forward expansion, move objects, we will reuse insertion code
+ T * const new_mem = boost::movelib::to_raw_pointer(ret);
+ T * const ins_pos = this->priv_raw_end();
+ if(reuse){ //Backwards (and possibly forward) expansion
+ #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
+ ++this->num_expand_bwd;
+ #endif
+ this->priv_forward_range_insert_expand_backwards
+ ( new_mem , real_cap, ins_pos, 0, this->priv_dummy_empty_proxy());
+ }
+ else{ //New buffer
+ #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
+ ++this->num_alloc;
+ #endif
+ this->priv_forward_range_insert_new_allocation
+ ( new_mem, real_cap, ins_pos, 0, this->priv_dummy_empty_proxy());
+ }
+ }
+ }
+
+ void priv_destroy_last(const bool moved = false) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ (void)moved;
+ const bool skip_destructor = value_traits::trivial_dctr || (value_traits::trivial_dctr_after_move && moved);
+ if(!skip_destructor){
+ value_type* const p = this->priv_raw_end() - 1;
+ allocator_traits_type::destroy(this->get_stored_allocator(), p);
+ }
+ --this->m_holder.m_size;
+ }
+
+ void priv_destroy_last_n(const size_type n) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ BOOST_ASSERT(n <= this->m_holder.m_size);
+ if(!value_traits::trivial_dctr){
+ T* const destroy_pos = this->priv_raw_begin() + (this->m_holder.m_size-n);
+ boost::container::destroy_alloc_n(this->get_stored_allocator(), destroy_pos, n);
+ }
+ this->m_holder.m_size -= n;
+ }
+
+ template<class InpIt>
+ void priv_uninitialized_construct_at_end(InpIt first, InpIt last)
+ {
+ T* const old_end_pos = this->priv_raw_end();
+ T* const new_end_pos = boost::container::uninitialized_copy_alloc(this->m_holder.alloc(), first, last, old_end_pos);
+ this->m_holder.m_size += new_end_pos - old_end_pos;
+ }
+
+ void priv_destroy_all() BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ boost::container::destroy_alloc_n
+ (this->get_stored_allocator(), this->priv_raw_begin(), this->m_holder.m_size);
+ this->m_holder.m_size = 0;
+ }
+
+ template<class U>
+ iterator priv_insert(const const_iterator &p, BOOST_FWD_REF(U) x)
+ {
+ BOOST_ASSERT(this->priv_in_range_or_end(p));
+ return this->priv_forward_range_insert
+ ( vector_iterator_get_ptr(p), 1, dtl::get_insert_value_proxy<T*, Allocator>(::boost::forward<U>(x)));
+ }
+
+ dtl::insert_copy_proxy<Allocator, T*> priv_single_insert_proxy(const T &x)
+ { return dtl::insert_copy_proxy<Allocator, T*> (x); }
+
+ dtl::insert_move_proxy<Allocator, T*> priv_single_insert_proxy(BOOST_RV_REF(T) x)
+ { return dtl::insert_move_proxy<Allocator, T*> (x); }
+
+ template <class U>
+ void priv_push_back(BOOST_FWD_REF(U) u)
+ {
+ if (BOOST_LIKELY(this->room_enough())){
+ //There is more memory, just construct a new object at the end
+ allocator_traits_type::construct
+ ( this->m_holder.alloc(), this->priv_raw_end(), ::boost::forward<U>(u) );
+ ++this->m_holder.m_size;
+ }
+ else{
+ this->priv_forward_range_insert_no_capacity
+ ( this->back_ptr(), 1
+ , this->priv_single_insert_proxy(::boost::forward<U>(u)), alloc_version());
+ }
+ }
+
+ BOOST_CONTAINER_FORCEINLINE dtl::insert_n_copies_proxy<Allocator, T*> priv_resize_proxy(const T &x)
+ { return dtl::insert_n_copies_proxy<Allocator, T*>(x); }
+
+ BOOST_CONTAINER_FORCEINLINE dtl::insert_default_initialized_n_proxy<Allocator, T*> priv_resize_proxy(default_init_t)
+ { return dtl::insert_default_initialized_n_proxy<Allocator, T*>(); }
+
+ BOOST_CONTAINER_FORCEINLINE dtl::insert_value_initialized_n_proxy<Allocator, T*> priv_resize_proxy(value_init_t)
+ { return dtl::insert_value_initialized_n_proxy<Allocator, T*>(); }
+
+ template <class U>
+ void priv_resize(size_type new_size, const U& u)
+ {
+ const size_type sz = this->size();
+ if (new_size < sz){
+ //Destroy last elements
+ this->priv_destroy_last_n(sz - new_size);
+ }
+ else{
+ const size_type n = new_size - this->size();
+ this->priv_forward_range_insert_at_end(n, this->priv_resize_proxy(u), alloc_version());
+ }
+ }
+
+ BOOST_CONTAINER_FORCEINLINE void priv_shrink_to_fit(version_0) BOOST_NOEXCEPT_OR_NOTHROW
+ {}
+
+ void priv_shrink_to_fit(version_1)
+ {
+ const size_type cp = this->m_holder.capacity();
+ if(cp){
+ const size_type sz = this->size();
+ if(!sz){
+ this->m_holder.deallocate(this->m_holder.m_start, cp);
+ this->m_holder.m_start = pointer();
+ this->m_holder.m_capacity = 0;
+ }
+ else if(sz < cp){
+ //Allocate a new buffer.
+ //Pass the hint so that allocators can take advantage of this.
+ pointer const p = this->m_holder.allocate(sz);
+
+ //We will reuse insert code, so create a dummy input iterator
+ #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
+ ++this->num_alloc;
+ #endif
+ this->priv_forward_range_insert_new_allocation
+ ( boost::movelib::to_raw_pointer(p), sz
+ , this->priv_raw_begin(), 0, this->priv_dummy_empty_proxy());
+ }
+ }
+ }
+
+ void priv_shrink_to_fit(version_2) BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ const size_type cp = this->m_holder.capacity();
+ if(cp){
+ const size_type sz = this->size();
+ if(!sz){
+ this->m_holder.deallocate(this->m_holder.m_start, cp);
+ this->m_holder.m_start = pointer();
+ this->m_holder.m_capacity = 0;
+ }
+ else{
+ size_type received_size = sz;
+ pointer reuse(this->m_holder.start());
+ if(this->m_holder.allocation_command
+ (shrink_in_place | nothrow_allocation, cp, received_size, reuse)){
+ this->m_holder.capacity(received_size);
+ #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
+ ++this->num_shrink;
+ #endif
+ }
+ }
+ }
+ }
+
+ template <class InsertionProxy>
+ iterator priv_forward_range_insert_no_capacity
+ (const pointer &pos, const size_type, const InsertionProxy , version_0)
+ {
+ throw_bad_alloc();
+ return iterator(pos);
+ }
+
+ template <class InsertionProxy>
+ iterator priv_forward_range_insert_no_capacity
+ (const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy, version_1)
+ {
+ //Check if we have enough memory or try to expand current memory
+ const size_type n_pos = pos - this->m_holder.start();
+ T *const raw_pos = boost::movelib::to_raw_pointer(pos);
+
+ const size_type new_cap = this->m_holder.template next_capacity<growth_factor_type>(n);
+ //Pass the hint so that allocators can take advantage of this.
+ T * const new_buf = boost::movelib::to_raw_pointer(this->m_holder.allocate(new_cap));
+ #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
+ ++this->num_alloc;
+ #endif
+ this->priv_forward_range_insert_new_allocation
+ ( new_buf, new_cap, raw_pos, n, insert_range_proxy);
+ return iterator(this->m_holder.start() + n_pos);
+ }
+
+ template <class InsertionProxy>
+ iterator priv_forward_range_insert_no_capacity
+ (const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy, version_2)
+ {
+ //Check if we have enough memory or try to expand current memory
+ T *const raw_pos = boost::movelib::to_raw_pointer(pos);
+ const size_type n_pos = raw_pos - this->priv_raw_begin();
+
+ //There is not enough memory, allocate a new
+ //buffer or expand the old one.
+ size_type real_cap = this->m_holder.template next_capacity<growth_factor_type>(n);
+ pointer reuse(this->m_holder.start());
+ pointer const ret (this->m_holder.allocation_command
+ (allocate_new | expand_fwd | expand_bwd, this->m_holder.m_size + n, real_cap, reuse));
+
+ //Buffer reallocated
+ if(reuse){
+ //Forward expansion, delay insertion
+ if(this->m_holder.start() == ret){
+ #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
+ ++this->num_expand_fwd;
+ #endif
+ this->m_holder.capacity(real_cap);
+ //Expand forward
+ this->priv_forward_range_insert_expand_forward(raw_pos, n, insert_range_proxy);
+ }
+ //Backwards (and possibly forward) expansion
+ else{
+ #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
+ ++this->num_expand_bwd;
+ #endif
+ this->priv_forward_range_insert_expand_backwards
+ (boost::movelib::to_raw_pointer(ret), real_cap, raw_pos, n, insert_range_proxy);
+ }
+ }
+ //New buffer
+ else{
+ #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
+ ++this->num_alloc;
+ #endif
+ this->priv_forward_range_insert_new_allocation
+ ( boost::movelib::to_raw_pointer(ret), real_cap, raw_pos, n, insert_range_proxy);
+ }
+
+ return iterator(this->m_holder.start() + n_pos);
+ }
+
+ template <class InsertionProxy>
+ iterator priv_forward_range_insert
+ (const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy)
+ {
+ BOOST_ASSERT(this->m_holder.capacity() >= this->m_holder.m_size);
+ //Check if we have enough memory or try to expand current memory
+ const size_type remaining = this->m_holder.capacity() - this->m_holder.m_size;
+
+ bool same_buffer_start = n <= remaining;
+ if (!same_buffer_start){
+ return priv_forward_range_insert_no_capacity(pos, n, insert_range_proxy, alloc_version());
+ }
+ else{
+ //Expand forward
+ T *const raw_pos = boost::movelib::to_raw_pointer(pos);
+ const size_type n_pos = raw_pos - this->priv_raw_begin();
+ this->priv_forward_range_insert_expand_forward(raw_pos, n, insert_range_proxy);
+ return iterator(this->m_holder.start() + n_pos);
+ }
+ }
+
+ template <class InsertionProxy>
+ iterator priv_forward_range_insert_at_end
+ (const size_type n, const InsertionProxy insert_range_proxy, version_0)
+ {
+ //Check if we have enough memory or try to expand current memory
+ const size_type remaining = this->m_holder.capacity() - this->m_holder.m_size;
+
+ if (n > remaining){
+ //This will trigger an error
+ throw_bad_alloc();
+ }
+ this->priv_forward_range_insert_at_end_expand_forward(n, insert_range_proxy);
+ return this->end();
+ }
+
+ template <class InsertionProxy, class AllocVersion>
+ BOOST_CONTAINER_FORCEINLINE iterator priv_forward_range_insert_at_end
+ (const size_type n, const InsertionProxy insert_range_proxy, AllocVersion)
+ {
+ return this->priv_forward_range_insert(this->back_ptr(), n, insert_range_proxy);
+ }
+
+ //Takes the range pointed by [first_pos, last_pos) and shifts it to the right
+ //by 'shift_count'. 'limit_pos' marks the end of constructed elements.
+ //
+ //Precondition: first_pos <= last_pos <= limit_pos
+ //
+ //The shift operation might cross limit_pos so elements to moved beyond limit_pos
+ //are uninitialized_moved with an allocator. Other elements are moved.
+ //
+ //The shift operation might left uninitialized elements after limit_pos
+ //and the number of uninitialized elements is returned by the function.
+ //
+ //Old situation:
+ // first_pos last_pos old_limit
+ // | | |
+ // ____________V_______V__________________V_____________
+ //| prefix | range | suffix |raw_mem ~
+ //|____________|_______|__________________|_____________~
+ //
+ //New situation in Case A (hole_size == 0):
+ // range is moved through move assignments
+ //
+ // first_pos last_pos limit_pos
+ // | | |
+ // ____________V_______V__________________V_____________
+ //| prefix' | | | range |suffix'|raw_mem ~
+ //|________________+______|___^___|_______|_____________~
+ // | |
+ // |_>_>_>_>_>^
+ //
+ //
+ //New situation in Case B (hole_size >= 0):
+ // range is moved through uninitialized moves
+ //
+ // first_pos last_pos limit_pos
+ // | | |
+ // ____________V_______V__________________V________________
+ //| prefix' | | | [hole] | range |
+ //|_______________________________________|________|___^___|
+ // | |
+ // |_>_>_>_>_>_>_>_>_>_>_>_>_>_>_>_>_>_^
+ //
+ //New situation in Case C (hole_size == 0):
+ // range is moved through move assignments and uninitialized moves
+ //
+ // first_pos last_pos limit_pos
+ // | | |
+ // ____________V_______V__________________V___
+ //| prefix' | | | range |
+ //|___________________________________|___^___|
+ // | |
+ // |_>_>_>_>_>_>_>_>_>_>_>^
+ size_type priv_insert_ordered_at_shift_range
+ (size_type first_pos, size_type last_pos, size_type limit_pos, size_type shift_count)
+ {
+ BOOST_ASSERT(first_pos <= last_pos);
+ BOOST_ASSERT(last_pos <= limit_pos);
+ //
+ T* const begin_ptr = this->priv_raw_begin();
+ T* const first_ptr = begin_ptr + first_pos;
+ T* const last_ptr = begin_ptr + last_pos;
+
+ size_type hole_size = 0;
+ //Case A:
+ if((last_pos + shift_count) <= limit_pos){
+ //All move assigned
+ boost::container::move_backward(first_ptr, last_ptr, last_ptr + shift_count);
+ }
+ //Case B:
+ else if((first_pos + shift_count) >= limit_pos){
+ //All uninitialized_moved
+ ::boost::container::uninitialized_move_alloc
+ (this->m_holder.alloc(), first_ptr, last_ptr, first_ptr + shift_count);
+ hole_size = first_pos + shift_count - limit_pos;
+ }
+ //Case C:
+ else{
+ //Some uninitialized_moved
+ T* const limit_ptr = begin_ptr + limit_pos;
+ T* const boundary_ptr = limit_ptr - shift_count;
+ ::boost::container::uninitialized_move_alloc(this->m_holder.alloc(), boundary_ptr, last_ptr, limit_ptr);
+ //The rest is move assigned
+ boost::container::move_backward(first_ptr, boundary_ptr, limit_ptr);
+ }
+ return hole_size;
+ }
+
+ private:
+ BOOST_CONTAINER_FORCEINLINE T *priv_raw_begin() const
+ { return boost::movelib::to_raw_pointer(m_holder.start()); }
+
+ BOOST_CONTAINER_FORCEINLINE T* priv_raw_end() const
+ { return this->priv_raw_begin() + this->m_holder.m_size; }
+
+ template <class InsertionProxy>
+ void priv_forward_range_insert_at_end_expand_forward(const size_type n, InsertionProxy insert_range_proxy)
+ {
+ T* const old_finish = this->priv_raw_end();
+ insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), old_finish, n);
+ this->m_holder.m_size += n;
+ }
+
+ template <class InsertionProxy>
+ void priv_forward_range_insert_expand_forward(T* const pos, const size_type n, InsertionProxy insert_range_proxy)
+ {
+ //n can't be 0, because there is nothing to do in that case
+ if(BOOST_UNLIKELY(!n)) return;
+ //There is enough memory
+ T* const old_finish = this->priv_raw_end();
+ const size_type elems_after = old_finish - pos;
+
+ if (!elems_after){
+ insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), old_finish, n);
+ this->m_holder.m_size += n;
+ }
+ else if (elems_after >= n){
+ //New elements can be just copied.
+ //Move to uninitialized memory last objects
+ ::boost::container::uninitialized_move_alloc
+ (this->m_holder.alloc(), old_finish - n, old_finish, old_finish);
+ this->m_holder.m_size += n;
+ //Copy previous to last objects to the initialized end
+ boost::container::move_backward(pos, old_finish - n, old_finish);
+ //Insert new objects in the pos
+ insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), pos, n);
+ }
+ else {
+ //The new elements don't fit in the [pos, end()) range.
+
+ //Copy old [pos, end()) elements to the uninitialized memory (a gap is created)
+ ::boost::container::uninitialized_move_alloc(this->m_holder.alloc(), pos, old_finish, pos + n);
+ BOOST_TRY{
+ //Copy first new elements in pos (gap is still there)
+ insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), pos, elems_after);
+ //Copy to the beginning of the unallocated zone the last new elements (the gap is closed).
+ insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), old_finish, n - elems_after);
+ this->m_holder.m_size += n;
+ }
+ BOOST_CATCH(...){
+ boost::container::destroy_alloc_n(this->get_stored_allocator(), pos + n, elems_after);
+ BOOST_RETHROW
+ }
+ BOOST_CATCH_END
+ }
+ }
+
+ template <class InsertionProxy>
+ void priv_forward_range_insert_new_allocation
+ (T* const new_start, size_type new_cap, T* const pos, const size_type n, InsertionProxy insert_range_proxy)
+ {
+ //n can be zero, if we want to reallocate!
+ T *new_finish = new_start;
+ T *old_finish;
+ //Anti-exception rollbacks
+ typename value_traits::ArrayDeallocator new_buffer_deallocator(new_start, this->m_holder.alloc(), new_cap);
+ typename value_traits::ArrayDestructor new_values_destroyer(new_start, this->m_holder.alloc(), 0u);
+
+ //Initialize with [begin(), pos) old buffer
+ //the start of the new buffer
+ T * const old_buffer = this->priv_raw_begin();
+ if(old_buffer){
+ new_finish = ::boost::container::uninitialized_move_alloc
+ (this->m_holder.alloc(), this->priv_raw_begin(), pos, old_finish = new_finish);
+ new_values_destroyer.increment_size(new_finish - old_finish);
+ }
+ //Initialize new objects, starting from previous point
+ old_finish = new_finish;
+ insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), old_finish, n);
+ new_finish += n;
+ new_values_destroyer.increment_size(new_finish - old_finish);
+ //Initialize from the rest of the old buffer,
+ //starting from previous point
+ if(old_buffer){
+ new_finish = ::boost::container::uninitialized_move_alloc
+ (this->m_holder.alloc(), pos, old_buffer + this->m_holder.m_size, new_finish);
+ //Destroy and deallocate old elements
+ //If there is allocated memory, destroy and deallocate
+ if(!value_traits::trivial_dctr_after_move)
+ boost::container::destroy_alloc_n(this->get_stored_allocator(), old_buffer, this->m_holder.m_size);
+ this->m_holder.deallocate(this->m_holder.start(), this->m_holder.capacity());
+ }
+ this->m_holder.start(new_start);
+ this->m_holder.m_size = size_type(new_finish - new_start);
+ this->m_holder.capacity(new_cap);
+ //All construction successful, disable rollbacks
+ new_values_destroyer.release();
+ new_buffer_deallocator.release();
+ }
+
+ template <class InsertionProxy>
+ void priv_forward_range_insert_expand_backwards
+ (T* const new_start, const size_type new_capacity,
+ T* const pos, const size_type n, InsertionProxy insert_range_proxy)
+ {
+ //n can be zero to just expand capacity
+ //Backup old data
+ T* const old_start = this->priv_raw_begin();
+ const size_type old_size = this->m_holder.m_size;
+ T* const old_finish = old_start + old_size;
+
+ //We can have 8 possibilities:
+ const size_type elemsbefore = static_cast<size_type>(pos - old_start);
+ const size_type s_before = static_cast<size_type>(old_start - new_start);
+ const size_type before_plus_new = elemsbefore + n;
+
+ //Update the vector buffer information to a safe state
+ this->m_holder.start(new_start);
+ this->m_holder.capacity(new_capacity);
+ this->m_holder.m_size = 0;
+
+ //If anything goes wrong, this object will destroy
+ //all the old objects to fulfill previous vector state
+ typename value_traits::ArrayDestructor old_values_destroyer(old_start, this->m_holder.alloc(), old_size);
+ //Check if s_before is big enough to hold the beginning of old data + new data
+ if(s_before >= before_plus_new){
+ //Copy first old values before pos, after that the new objects
+ T *const new_elem_pos =
+ ::boost::container::uninitialized_move_alloc(this->m_holder.alloc(), old_start, pos, new_start);
+ this->m_holder.m_size = elemsbefore;
+ insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), new_elem_pos, n);
+ this->m_holder.m_size = before_plus_new;
+ const size_type new_size = old_size + n;
+ //Check if s_before is so big that even copying the old data + new data
+ //there is a gap between the new data and the old data
+ if(s_before >= new_size){
+ //Old situation:
+ // _________________________________________________________
+ //| raw_mem | old_begin | old_end |
+ //| __________________________________|___________|_________|
+ //
+ //New situation:
+ // _________________________________________________________
+ //| old_begin | new | old_end | raw_mem |
+ //|___________|__________|_________|________________________|
+ //
+ //Now initialize the rest of memory with the last old values
+ if(before_plus_new != new_size){ //Special case to avoid operations in back insertion
+ ::boost::container::uninitialized_move_alloc
+ (this->m_holder.alloc(), pos, old_finish, new_start + before_plus_new);
+ //All new elements correctly constructed, avoid new element destruction
+ this->m_holder.m_size = new_size;
+ }
+ //Old values destroyed automatically with "old_values_destroyer"
+ //when "old_values_destroyer" goes out of scope unless the have trivial
+ //destructor after move.
+ if(value_traits::trivial_dctr_after_move)
+ old_values_destroyer.release();
+ }
+ //s_before is so big that divides old_end
+ else{
+ //Old situation:
+ // __________________________________________________
+ //| raw_mem | old_begin | old_end |
+ //| ___________________________|___________|_________|
+ //
+ //New situation:
+ // __________________________________________________
+ //| old_begin | new | old_end | raw_mem |
+ //|___________|__________|_________|_________________|
+ //
+ //Now initialize the rest of memory with the last old values
+ //All new elements correctly constructed, avoid new element destruction
+ const size_type raw_gap = s_before - before_plus_new;
+ if(!value_traits::trivial_dctr){
+ //Now initialize the rest of s_before memory with the
+ //first of elements after new values
+ ::boost::container::uninitialized_move_alloc_n
+ (this->m_holder.alloc(), pos, raw_gap, new_start + before_plus_new);
+ //Now we have a contiguous buffer so program trailing element destruction
+ //and update size to the final size.
+ old_values_destroyer.shrink_forward(new_size-s_before);
+ this->m_holder.m_size = new_size;
+ //Now move remaining last objects in the old buffer begin
+ T * const remaining_pos = pos + raw_gap;
+ if(remaining_pos != old_start){ //Make sure data has to be moved
+ ::boost::container::move(remaining_pos, old_finish, old_start);
+ }
+ //Once moved, avoid calling the destructors if trivial after move
+ if(value_traits::trivial_dctr_after_move){
+ old_values_destroyer.release();
+ }
+ }
+ else{ //If trivial destructor, we can uninitialized copy + copy in a single uninitialized copy
+ ::boost::container::uninitialized_move_alloc_n
+ (this->m_holder.alloc(), pos, static_cast<size_type>(old_finish - pos), new_start + before_plus_new);
+ this->m_holder.m_size = new_size;
+ old_values_destroyer.release();
+ }
+ }
+ }
+ else{
+ //Check if we have to do the insertion in two phases
+ //since maybe s_before is not big enough and
+ //the buffer was expanded both sides
+ //
+ //Old situation:
+ // _________________________________________________
+ //| raw_mem | old_begin + old_end | raw_mem |
+ //|_________|_____________________|_________________|
+ //
+ //New situation with do_after:
+ // _________________________________________________
+ //| old_begin + new + old_end | raw_mem |
+ //|___________________________________|_____________|
+ //
+ //New without do_after:
+ // _________________________________________________
+ //| old_begin + new + old_end | raw_mem |
+ //|____________________________|____________________|
+ //
+ const bool do_after = n > s_before;
+
+ //Now we can have two situations: the raw_mem of the
+ //beginning divides the old_begin, or the new elements:
+ if (s_before <= elemsbefore) {
+ //The raw memory divides the old_begin group:
+ //
+ //If we need two phase construction (do_after)
+ //new group is divided in new = new_beg + new_end groups
+ //In this phase only new_beg will be inserted
+ //
+ //Old situation:
+ // _________________________________________________
+ //| raw_mem | old_begin | old_end | raw_mem |
+ //|_________|___________|_________|_________________|
+ //
+ //New situation with do_after(1):
+ //This is not definitive situation, the second phase
+ //will include
+ // _________________________________________________
+ //| old_begin | new_beg | old_end | raw_mem |
+ //|___________|_________|_________|_________________|
+ //
+ //New situation without do_after:
+ // _________________________________________________
+ //| old_begin | new | old_end | raw_mem |
+ //|___________|_____|_________|_____________________|
+ //
+ //Copy the first part of old_begin to raw_mem
+ ::boost::container::uninitialized_move_alloc_n
+ (this->m_holder.alloc(), old_start, s_before, new_start);
+ //The buffer is all constructed until old_end,
+ //so program trailing destruction and assign final size
+ //if !do_after, s_before+n otherwise.
+ size_type new_1st_range;
+ if(do_after){
+ new_1st_range = s_before;
+ //release destroyer and update size
+ old_values_destroyer.release();
+ }
+ else{
+ new_1st_range = n;
+ if(value_traits::trivial_dctr_after_move)
+ old_values_destroyer.release();
+ else{
+ old_values_destroyer.shrink_forward(old_size - (s_before - n));
+ }
+ }
+ this->m_holder.m_size = old_size + new_1st_range;
+ //Now copy the second part of old_begin overwriting itself
+ T *const next = ::boost::container::move(old_start + s_before, pos, old_start);
+ //Now copy the new_beg elements
+ insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), next, new_1st_range);
+
+ //If there is no after work and the last old part needs to be moved to front, do it
+ if(!do_after && (n != s_before)){
+ //Now displace old_end elements
+ ::boost::container::move(pos, old_finish, next + new_1st_range);
+ }
+ }
+ else {
+ //If we have to expand both sides,
+ //we will play if the first new values so
+ //calculate the upper bound of new values
+
+ //The raw memory divides the new elements
+ //
+ //If we need two phase construction (do_after)
+ //new group is divided in new = new_beg + new_end groups
+ //In this phase only new_beg will be inserted
+ //
+ //Old situation:
+ // _______________________________________________________
+ //| raw_mem | old_begin | old_end | raw_mem |
+ //|_______________|___________|_________|_________________|
+ //
+ //New situation with do_after():
+ // ____________________________________________________
+ //| old_begin | new_beg | old_end | raw_mem |
+ //|___________|_______________|_________|______________|
+ //
+ //New situation without do_after:
+ // ______________________________________________________
+ //| old_begin | new | old_end | raw_mem |
+ //|___________|_____|_________|__________________________|
+ //
+ //First copy whole old_begin and part of new to raw_mem
+ T * const new_pos = ::boost::container::uninitialized_move_alloc
+ (this->m_holder.alloc(), old_start, pos, new_start);
+ this->m_holder.m_size = elemsbefore;
+ const size_type mid_n = s_before - elemsbefore;
+ insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), new_pos, mid_n);
+ //The buffer is all constructed until old_end,
+ //release destroyer
+ this->m_holder.m_size = old_size + s_before;
+ old_values_destroyer.release();
+
+ if(do_after){
+ //Copy new_beg part
+ insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), old_start, elemsbefore);
+ }
+ else{
+ //Copy all new elements
+ const size_type rest_new = n - mid_n;
+ insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), old_start, rest_new);
+ T* const move_start = old_start + rest_new;
+ //Displace old_end, but make sure data has to be moved
+ T* const move_end = move_start != pos ? ::boost::container::move(pos, old_finish, move_start)
+ : old_finish;
+ //Destroy remaining moved elements from old_end except if they
+ //have trivial destructor after being moved
+ size_type n_destroy = s_before - n;
+ if(!value_traits::trivial_dctr_after_move)
+ boost::container::destroy_alloc_n(this->get_stored_allocator(), move_end, n_destroy);
+ this->m_holder.m_size -= n_destroy;
+ }
+ }
+
+ //This is only executed if two phase construction is needed
+ if(do_after){
+ //The raw memory divides the new elements
+ //
+ //Old situation:
+ // ______________________________________________________
+ //| raw_mem | old_begin | old_end | raw_mem |
+ //|______________|___________|____________|______________|
+ //
+ //New situation with do_after(1):
+ // _______________________________________________________
+ //| old_begin + new_beg | new_end |old_end | raw_mem |
+ //|__________________________|_________|________|_________|
+ //
+ //New situation with do_after(2):
+ // ______________________________________________________
+ //| old_begin + new | old_end |raw |
+ //|_______________________________________|_________|____|
+ //
+ const size_type n_after = n - s_before;
+ const size_type elemsafter = old_size - elemsbefore;
+
+ //We can have two situations:
+ if (elemsafter >= n_after){
+ //The raw_mem from end will divide displaced old_end
+ //
+ //Old situation:
+ // ______________________________________________________
+ //| raw_mem | old_begin | old_end | raw_mem |
+ //|______________|___________|____________|______________|
+ //
+ //New situation with do_after(1):
+ // _______________________________________________________
+ //| old_begin + new_beg | new_end |old_end | raw_mem |
+ //|__________________________|_________|________|_________|
+ //
+ //First copy the part of old_end raw_mem
+ T* finish_n = old_finish - n_after;
+ ::boost::container::uninitialized_move_alloc
+ (this->m_holder.alloc(), finish_n, old_finish, old_finish);
+ this->m_holder.m_size += n_after;
+ //Displace the rest of old_end to the new position
+ boost::container::move_backward(pos, finish_n, old_finish);
+ //Now overwrite with new_end
+ //The new_end part is [first + (n - n_after), last)
+ insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), pos, n_after);
+ }
+ else {
+ //The raw_mem from end will divide new_end part
+ //
+ //Old situation:
+ // _____________________________________________________________
+ //| raw_mem | old_begin | old_end | raw_mem |
+ //|______________|___________|____________|_____________________|
+ //
+ //New situation with do_after(2):
+ // _____________________________________________________________
+ //| old_begin + new_beg | new_end |old_end | raw_mem |
+ //|__________________________|_______________|________|_________|
+ //
+
+ const size_type mid_last_dist = n_after - elemsafter;
+ //First initialize data in raw memory
+
+ //Copy to the old_end part to the uninitialized zone leaving a gap.
+ ::boost::container::uninitialized_move_alloc
+ (this->m_holder.alloc(), pos, old_finish, old_finish + mid_last_dist);
+
+ typename value_traits::ArrayDestructor old_end_destroyer
+ (old_finish + mid_last_dist, this->m_holder.alloc(), old_finish - pos);
+
+ //Copy the first part to the already constructed old_end zone
+ insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), pos, elemsafter);
+ //Copy the rest to the uninitialized zone filling the gap
+ insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), old_finish, mid_last_dist);
+ this->m_holder.m_size += n_after;
+ old_end_destroyer.release();
+ }
+ }
+ }
+ }
+
+ void priv_throw_if_out_of_range(size_type n) const
+ {
+ //If n is out of range, throw an out_of_range exception
+ if (n >= this->size()){
+ throw_out_of_range("vector::at out of range");
+ }
+ }
+
+ BOOST_CONTAINER_FORCEINLINE bool priv_in_range(const_iterator pos) const
+ {
+ return (this->begin() <= pos) && (pos < this->end());
+ }
+
+ BOOST_CONTAINER_FORCEINLINE bool priv_in_range_or_end(const_iterator pos) const
+ {
+ return (this->begin() <= pos) && (pos <= this->end());
+ }
+
+ #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
+ public:
+ unsigned int num_expand_fwd;
+ unsigned int num_expand_bwd;
+ unsigned int num_shrink;
+ unsigned int num_alloc;
+ void reset_alloc_stats()
+ { num_expand_fwd = num_expand_bwd = num_alloc = 0, num_shrink = 0; }
+ #endif
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+};
+
+#if __cplusplus >= 201703L
+
+template <typename InputIterator>
+vector(InputIterator, InputIterator) ->
+ vector<typename iterator_traits<InputIterator>::value_type>;
+
+template <typename InputIterator, typename Allocator>
+vector(InputIterator, InputIterator, Allocator const&) ->
+ vector<typename iterator_traits<InputIterator>::value_type, Allocator>;
+
+#endif
+
+
+}} //namespace boost::container
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+namespace boost {
+
+//!has_trivial_destructor_after_move<> == true_type
+//!specialization for optimizations
+template <class T, class Allocator>
+struct has_trivial_destructor_after_move<boost::container::vector<T, Allocator> >
+{
+ typedef typename ::boost::container::allocator_traits<Allocator>::pointer pointer;
+ static const bool value = ::boost::has_trivial_destructor_after_move<Allocator>::value &&
+ ::boost::has_trivial_destructor_after_move<pointer>::value;
+};
+
+}
+
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif // #ifndef BOOST_CONTAINER_CONTAINER_VECTOR_HPP