summaryrefslogtreecommitdiff
path: root/boost/container
diff options
context:
space:
mode:
Diffstat (limited to 'boost/container')
-rw-r--r--boost/container/adaptive_pool.hpp349
-rw-r--r--boost/container/allocator.hpp367
-rw-r--r--boost/container/allocator_traits.hpp214
-rw-r--r--boost/container/container_fwd.hpp223
-rw-r--r--boost/container/deque.hpp2244
-rw-r--r--boost/container/detail/adaptive_node_pool.hpp162
-rw-r--r--boost/container/detail/adaptive_node_pool_impl.hpp725
-rw-r--r--boost/container/detail/advanced_insert_int.hpp630
-rw-r--r--boost/container/detail/algorithms.hpp32
-rw-r--r--boost/container/detail/alloc_lib.h326
-rw-r--r--boost/container/detail/alloc_lib_auto_link.hpp20
-rw-r--r--boost/container/detail/allocation_type.hpp12
-rw-r--r--boost/container/detail/allocator_version_traits.hpp168
-rw-r--r--boost/container/detail/auto_link.hpp38
-rw-r--r--boost/container/detail/config_begin.hpp9
-rw-r--r--boost/container/detail/config_end.hpp6
-rw-r--r--boost/container/detail/destroyers.hpp141
-rw-r--r--boost/container/detail/flat_tree.hpp694
-rw-r--r--boost/container/detail/function_detector.hpp6
-rw-r--r--boost/container/detail/hash_table.hpp383
-rw-r--r--boost/container/detail/iterators.hpp385
-rw-r--r--boost/container/detail/math_functions.hpp12
-rw-r--r--boost/container/detail/memory_util.hpp25
-rw-r--r--boost/container/detail/mpl.hpp37
-rw-r--r--boost/container/detail/multiallocation_chain.hpp178
-rw-r--r--boost/container/detail/mutex.hpp284
-rw-r--r--boost/container/detail/node_alloc_holder.hpp236
-rw-r--r--boost/container/detail/node_pool.hpp156
-rw-r--r--boost/container/detail/node_pool_impl.hpp59
-rw-r--r--boost/container/detail/pair.hpp41
-rw-r--r--boost/container/detail/placement_new.hpp27
-rw-r--r--boost/container/detail/pool_common.hpp15
-rw-r--r--boost/container/detail/pool_common_alloc.hpp98
-rw-r--r--boost/container/detail/preprocessor.hpp113
-rw-r--r--boost/container/detail/singleton.hpp117
-rw-r--r--boost/container/detail/std_fwd.hpp59
-rw-r--r--boost/container/detail/stored_ref.hpp92
-rw-r--r--boost/container/detail/transform_iterator.hpp19
-rw-r--r--boost/container/detail/tree.hpp1066
-rw-r--r--boost/container/detail/type_traits.hpp39
-rw-r--r--boost/container/detail/utilities.hpp1173
-rw-r--r--boost/container/detail/value_init.hpp6
-rw-r--r--boost/container/detail/variadic_templates_tools.hpp7
-rw-r--r--boost/container/detail/version_type.hpp17
-rw-r--r--boost/container/detail/workaround.hpp46
-rw-r--r--boost/container/flat_map.hpp1342
-rw-r--r--boost/container/flat_set.hpp1450
-rw-r--r--boost/container/list.hpp1390
-rw-r--r--boost/container/map.hpp1251
-rw-r--r--boost/container/node_allocator.hpp344
-rw-r--r--boost/container/options.hpp76
-rw-r--r--boost/container/scoped_allocator.hpp394
-rw-r--r--boost/container/scoped_allocator_fwd.hpp18
-rw-r--r--boost/container/set.hpp1304
-rw-r--r--boost/container/slist.hpp1685
-rw-r--r--boost/container/stable_vector.hpp2143
-rw-r--r--boost/container/static_vector.hpp1156
-rw-r--r--boost/container/string.hpp1870
-rw-r--r--boost/container/throw_exception.hpp166
-rw-r--r--boost/container/vector.hpp3142
60 files changed, 18154 insertions, 10633 deletions
diff --git a/boost/container/adaptive_pool.hpp b/boost/container/adaptive_pool.hpp
new file mode 100644
index 0000000000..c12d511c65
--- /dev/null
+++ b/boost/container/adaptive_pool.hpp
@@ -0,0 +1,349 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# 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/alloc_lib_auto_link.hpp>
+#include <boost/container/detail/singleton.hpp>
+
+#include <boost/container/detail/placement_new.hpp>
+
+#include <boost/assert.hpp>
+#include <boost/utility/addressof.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/move/utility_core.hpp>
+#include <memory>
+#include <algorithm>
+#include <cstddef>
+
+
+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_CONTAINER_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_CONTAINER_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::
+ container_detail::unvoid<T>::type & reference;
+ typedef const typename ::boost::container::
+ container_detail::unvoid<T>::type & const_reference;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+
+ typedef boost::container::container_detail::
+ version_type<self_t, Version> version;
+
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ typedef boost::container::container_detail::
+ basic_multiallocation_chain<void*> multiallocation_chain_void;
+ typedef boost::container::container_detail::
+ 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_CONTAINER_I Version)
+ > other;
+ };
+
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ private:
+ //!Not assignable from related adaptive_pool
+ template<class T2, unsigned Version2, std::size_t N2, std::size_t F2>
+ adaptive_pool& operator=
+ (const adaptive_pool<T2, Version2, N2, F2>&);
+
+ //!Not assignable from other adaptive_pool
+ adaptive_pool& operator=(const adaptive_pool&);
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ public:
+ //!Default constructor
+ adaptive_pool() BOOST_CONTAINER_NOEXCEPT
+ {}
+
+ //!Copy constructor from other adaptive_pool.
+ adaptive_pool(const adaptive_pool &) BOOST_CONTAINER_NOEXCEPT
+ {}
+
+ //!Copy constructor from related adaptive_pool.
+ template<class T2>
+ adaptive_pool
+ (const adaptive_pool<T2, NodesPerBlock, MaxFreeBlocks, OverheadPercent
+ BOOST_CONTAINER_DOCIGN(BOOST_CONTAINER_I Version)> &) BOOST_CONTAINER_NOEXCEPT
+ {}
+
+ //!Destructor
+ ~adaptive_pool() BOOST_CONTAINER_NOEXCEPT
+ {}
+
+ //!Returns the number of elements that could be allocated.
+ //!Never throws
+ size_type max_size() const BOOST_CONTAINER_NOEXCEPT
+ { return size_type(-1)/sizeof(T); }
+
+ //!Allocate memory for an array of count elements.
+ //!Throws std::bad_alloc if there is no enough memory
+ pointer allocate(size_type count, const void * = 0)
+ {
+ if(count > this->max_size())
+ boost::container::throw_bad_alloc();
+
+ if(Version == 1 && count == 1){
+ typedef typename container_detail::shared_adaptive_node_pool
+ <sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
+ typedef container_detail::singleton_default<shared_pool_t> singleton_t;
+ return pointer(static_cast<T*>(singleton_t::instance().allocate_node()));
+ }
+ else{
+ return static_cast<pointer>(boost_cont_malloc(count*sizeof(T)));
+ }
+ }
+
+ //!Deallocate allocated memory.
+ //!Never throws
+ void deallocate(const pointer &ptr, size_type count) BOOST_CONTAINER_NOEXCEPT
+ {
+ (void)count;
+ if(Version == 1 && count == 1){
+ typedef container_detail::shared_adaptive_node_pool
+ <sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
+ typedef container_detail::singleton_default<shared_pool_t> singleton_t;
+ singleton_t::instance().deallocate_node(ptr);
+ }
+ else{
+ boost_cont_free(ptr);
+ }
+ }
+
+ std::pair<pointer, bool>
+ allocation_command(allocation_type command,
+ size_type limit_size,
+ size_type preferred_size,
+ size_type &received_size, pointer reuse = pointer())
+ {
+ std::pair<pointer, bool> ret =
+ this->priv_allocation_command(command, limit_size, preferred_size, received_size, reuse);
+ if(!ret.first && !(command & BOOST_CONTAINER_NOTHROW_ALLOCATION))
+ boost::container::throw_bad_alloc();
+ return ret;
+ }
+
+ //!Returns maximum the number of objects the previously allocated memory
+ //!pointed by p can hold.
+ size_type size(pointer p) const BOOST_CONTAINER_NOEXCEPT
+ { return boost_cont_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 container_detail::shared_adaptive_node_pool
+ <sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
+ typedef container_detail::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 container_detail::shared_adaptive_node_pool
+ <sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
+ typedef container_detail::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_CONTAINER_NOEXCEPT
+ {
+ typedef container_detail::shared_adaptive_node_pool
+ <sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
+ typedef container_detail::singleton_default<shared_pool_t> singleton_t;
+ singleton_t::instance().deallocate_node(p);
+ }
+
+ void deallocate_individual(multiallocation_chain &chain) BOOST_CONTAINER_NOEXCEPT
+ {
+ typedef container_detail::shared_adaptive_node_pool
+ <sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
+ typedef container_detail::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 ));/*
+ boost_cont_memchain ch;
+ BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
+ if(!boost_cont_multialloc_nodes(n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch)){
+ boost::container::throw_bad_alloc();
+ }
+ chain.incorporate_after(chain.before_begin()
+ ,(T*)BOOST_CONTAINER_MEMCHAIN_FIRSTMEM(&ch)
+ ,(T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch)
+ ,BOOST_CONTAINER_MEMCHAIN_SIZE(&ch) );*/
+ if(!boost_cont_multialloc_nodes(n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, reinterpret_cast<boost_cont_memchain *>(&chain))){
+ 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 ));/*
+ boost_cont_memchain ch;
+ BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
+ if(!boost_cont_multialloc_arrays(n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch)){
+ boost::container::throw_bad_alloc();
+ }
+ chain.incorporate_after(chain.before_begin()
+ ,(T*)BOOST_CONTAINER_MEMCHAIN_FIRSTMEM(&ch)
+ ,(T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch)
+ ,BOOST_CONTAINER_MEMCHAIN_SIZE(&ch) );*/
+ if(!boost_cont_multialloc_arrays(n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, reinterpret_cast<boost_cont_memchain *>(&chain))){
+ boost::container::throw_bad_alloc();
+ }
+ }
+
+ void deallocate_many(multiallocation_chain &chain) BOOST_CONTAINER_NOEXCEPT
+ {/*
+ boost_cont_memchain ch;
+ void *beg(&*chain.begin()), *last(&*chain.last());
+ size_t size(chain.size());
+ BOOST_CONTAINER_MEMCHAIN_INIT_FROM(&ch, beg, last, size);
+ boost_cont_multidealloc(&ch);*/
+ boost_cont_multidealloc(reinterpret_cast<boost_cont_memchain *>(&chain));
+ }
+
+ //!Deallocates all free blocks of the pool
+ static void deallocate_free_blocks() BOOST_CONTAINER_NOEXCEPT
+ {
+ typedef container_detail::shared_adaptive_node_pool
+ <sizeof(T), NodesPerBlock, MaxFreeBlocks, OverheadPercent> shared_pool_t;
+ typedef container_detail::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_CONTAINER_NOEXCEPT
+ {}
+
+ //!An allocator always compares to true, as memory allocated with one
+ //!instance can be deallocated by another instance
+ friend bool operator==(const adaptive_pool &, const adaptive_pool &) BOOST_CONTAINER_NOEXCEPT
+ { return true; }
+
+ //!An allocator always compares to false, as memory allocated with one
+ //!instance can be deallocated by another instance
+ friend bool operator!=(const adaptive_pool &, const adaptive_pool &) BOOST_CONTAINER_NOEXCEPT
+ { return false; }
+
+ private:
+ std::pair<pointer, bool> priv_allocation_command
+ (allocation_type command, std::size_t limit_size
+ ,std::size_t preferred_size,std::size_t &received_size, void *reuse_ptr)
+ {
+ boost_cont_command_ret_t ret = {0 , 0};
+ if(limit_size > this->max_size() || preferred_size > this->max_size()){
+// ret.first = 0;
+ return std::pair<pointer, bool>(pointer(), false);
+ }
+ std::size_t l_size = limit_size*sizeof(T);
+ std::size_t p_size = preferred_size*sizeof(T);
+ std::size_t r_size;
+ {
+ ret = boost_cont_allocation_command(command, sizeof(T), l_size, p_size, &r_size, reuse_ptr);
+ }
+ received_size = r_size/sizeof(T);
+ return std::pair<pointer, bool>(static_cast<pointer>(ret.first), !!ret.second);
+ }
+};
+
+} //namespace container {
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_CONTAINER_ADAPTIVE_POOL_HPP
diff --git a/boost/container/allocator.hpp b/boost/container/allocator.hpp
new file mode 100644
index 0000000000..14d56452b6
--- /dev/null
+++ b/boost/container/allocator.hpp
@@ -0,0 +1,367 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# 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/alloc_lib_auto_link.hpp>
+#include <boost/container/detail/multiallocation_chain.hpp>
+#include <boost/static_assert.hpp>
+#include <cstddef>
+#include <cassert>
+#include <new>
+
+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::container_detail::
+ version_type<self_t, Version> version;
+
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ typedef boost::container::container_detail::
+ 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
+
+//!\file
+//! 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.
+#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
+template<class T>
+#else
+//! 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, unsigned int AllocationDisableMask>
+#endif //#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
+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>&);
+
+ //Not assignable from other allocator
+ allocator& operator=(const allocator&);
+
+ 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::container_detail::
+ version_type<self_t, Version> version;
+
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ typedef boost::container::container_detail::
+ basic_multiallocation_chain<void*> void_multiallocation_chain;
+
+ typedef boost::container::container_detail::
+ 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_CONTAINER_NOEXCEPT
+ {}
+
+ //!Constructor from other allocator.
+ //!Never throws
+ allocator(const allocator &) BOOST_CONTAINER_NOEXCEPT
+ {}
+
+ //!Constructor from related allocator.
+ //!Never throws
+ template<class T2>
+ allocator(const allocator<T2
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ , Version, AllocationDisableMask
+ #endif
+ > &) BOOST_CONTAINER_NOEXCEPT
+ {}
+
+ //!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 = boost_cont_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_CONTAINER_NOEXCEPT
+ { boost_cont_free(ptr); }
+
+ //!Returns the maximum number of elements that could be allocated.
+ //!Never throws
+ size_type max_size() const BOOST_CONTAINER_NOEXCEPT
+ { return size_type(-1)/sizeof(T); }
+
+ //!Swaps two allocators, does nothing
+ //!because this allocator is stateless
+ friend void swap(self_t &, self_t &) BOOST_CONTAINER_NOEXCEPT
+ {}
+
+ //!An allocator always compares to true, as memory allocated with one
+ //!instance can be deallocated by another instance
+ friend bool operator==(const allocator &, const allocator &) BOOST_CONTAINER_NOEXCEPT
+ { return true; }
+
+ //!An allocator always compares to false, as memory allocated with one
+ //!instance can be deallocated by another instance
+ friend bool operator!=(const allocator &, const allocator &) BOOST_CONTAINER_NOEXCEPT
+ { return false; }
+
+ //!An advanced function that offers in-place expansion shrink to fit and new allocation
+ //!capabilities. Memory allocated with this function can only be deallocated with deallocate()
+ //!or deallocate_many().
+ //!This function is available only with Version == 2
+ std::pair<pointer, bool>
+ allocation_command(allocation_type command,
+ size_type limit_size,
+ size_type preferred_size,
+ size_type &received_size, pointer reuse = pointer())
+ {
+ BOOST_STATIC_ASSERT(( Version > 1 ));
+ const allocation_type mask(AllocationDisableMask);
+ command &= ~mask;
+ std::pair<pointer, bool> ret =
+ priv_allocation_command(command, limit_size, preferred_size, received_size, reuse);
+ if(!ret.first && !(command & BOOST_CONTAINER_NOTHROW_ALLOCATION))
+ 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_CONTAINER_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT(( Version > 1 ));
+ return boost_cont_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_CONTAINER_NOEXCEPT
+ {
+ 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_CONTAINER_NOEXCEPT
+ {
+ 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 ));/*
+ boost_cont_memchain ch;
+ BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
+ if(!boost_cont_multialloc_nodes(n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch)){
+ boost::container::throw_bad_alloc();
+ }
+ chain.incorporate_after(chain.before_begin()
+ ,(T*)BOOST_CONTAINER_MEMCHAIN_FIRSTMEM(&ch)
+ ,(T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch)
+ ,BOOST_CONTAINER_MEMCHAIN_SIZE(&ch) );*/
+ if(!boost_cont_multialloc_nodes(n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, reinterpret_cast<boost_cont_memchain *>(&chain))){
+ 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 ));
+ boost_cont_memchain ch;
+ BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
+ if(!boost_cont_multialloc_arrays(n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch)){
+ boost::container::throw_bad_alloc();
+ }
+ chain.incorporate_after(chain.before_begin()
+ ,(T*)BOOST_CONTAINER_MEMCHAIN_FIRSTMEM(&ch)
+ ,(T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch)
+ ,BOOST_CONTAINER_MEMCHAIN_SIZE(&ch) );
+ /*
+ if(!boost_cont_multialloc_arrays(n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, reinterpret_cast<boost_cont_memchain *>(&chain))){
+ 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_CONTAINER_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT(( Version > 1 ));
+ boost_cont_memchain ch;
+ void *beg(&*chain.begin()), *last(&*chain.last());
+ size_t size(chain.size());
+ BOOST_CONTAINER_MEMCHAIN_INIT_FROM(&ch, beg, last, size);
+ boost_cont_multidealloc(&ch);
+ //boost_cont_multidealloc(reinterpret_cast<boost_cont_memchain *>(&chain));
+ }
+
+ private:
+
+ std::pair<pointer, bool> priv_allocation_command
+ (allocation_type command, std::size_t limit_size
+ ,std::size_t preferred_size,std::size_t &received_size, void *reuse_ptr)
+ {
+ boost_cont_command_ret_t ret = {0 , 0};
+ if((limit_size > this->max_size()) | (preferred_size > this->max_size())){
+ return std::pair<pointer, bool>(pointer(), false);
+ }
+ std::size_t l_size = limit_size*sizeof(T);
+ std::size_t p_size = preferred_size*sizeof(T);
+ std::size_t r_size;
+ {
+ ret = boost_cont_allocation_command(command, sizeof(T), l_size, p_size, &r_size, reuse_ptr);
+ }
+ received_size = r_size/sizeof(T);
+ return std::pair<pointer, bool>(static_cast<pointer>(ret.first), !!ret.second);
+ }
+};
+
+} //namespace container {
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //BOOST_CONTAINER_ALLOCATOR_HPP
+
diff --git a/boost/container/allocator_traits.hpp b/boost/container/allocator_traits.hpp
index 8e537ccf6f..a85831f984 100644
--- a/boost/container/allocator_traits.hpp
+++ b/boost/container/allocator_traits.hpp
@@ -6,7 +6,7 @@
//
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2011-2012. Distributed under the Boost
+// (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)
//
@@ -17,27 +17,34 @@
#ifndef BOOST_CONTAINER_ALLOCATOR_ALLOCATOR_TRAITS_HPP
#define BOOST_CONTAINER_ALLOCATOR_ALLOCATOR_TRAITS_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
+#include <boost/container/container_fwd.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/intrusive/detail/memory_util.hpp>
#include <boost/container/detail/memory_util.hpp>
-#include <boost/type_traits/integral_constant.hpp>
#include <boost/container/detail/mpl.hpp>
-#include <boost/move/move.hpp>
-#include <limits> //numeric_limits<>::max()
-#include <new> //placement new
-#include <memory> //std::allocator
+#include <boost/container/detail/placement_new.hpp>
+#include <boost/move/utility_core.hpp>
+
+#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#include <boost/container/detail/preprocessor.hpp>
+#endif
+
-///@cond
namespace boost {
namespace container {
+namespace allocator_traits_detail {
+
+}
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
namespace container_detail {
//workaround needed for C++03 compilers with no construct()
@@ -52,7 +59,7 @@ struct is_std_allocator< std::allocator<T> >
} //namespace container_detail {
-///@endcond
+#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
@@ -70,52 +77,52 @@ struct allocator_traits
typedef unspecified pointer;
//! Alloc::const_pointer if such a type exists ; otherwise, pointer_traits<pointer>::rebind<const
//!
- typedef unspecified const_pointer;
+ typedef see_documentation const_pointer;
//! Non-standard extension
//! Alloc::reference if such a type exists; otherwise, value_type&
- typedef unspecified reference;
+ typedef see_documentation reference;
//! Non-standard extension
//! Alloc::const_reference if such a type exists ; otherwise, const value_type&
- typedef unspecified const_reference;
+ typedef see_documentation const_reference;
//! Alloc::void_pointer if such a type exists ; otherwise, pointer_traits<pointer>::rebind<void>.
//!
- typedef unspecified void_pointer;
+ typedef see_documentation void_pointer;
//! Alloc::const_void_pointer if such a type exists ; otherwis e, pointer_traits<pointer>::rebind<const
//!
- typedef unspecified const_void_pointer;
+ typedef see_documentation const_void_pointer;
//! Alloc::difference_type if such a type exists ; otherwise, pointer_traits<pointer>::difference_type.
//!
- typedef unspecified difference_type;
+ typedef see_documentation difference_type;
//! Alloc::size_type if such a type exists ; otherwise, make_unsigned<difference_type>::type
//!
- typedef unspecified size_type;
+ typedef see_documentation size_type;
//! Alloc::propagate_on_container_copy_assignment if such a type exists, otherwise an integral_constant
- //! type with internal constant static member `value` == false.
- typedef unspecified propagate_on_container_copy_assignment;
+ //! type with internal constant static member <code>value</code> == false.
+ typedef see_documentation propagate_on_container_copy_assignment;
//! Alloc::propagate_on_container_move_assignment if such a type exists, otherwise an integral_constant
- //! type with internal constant static member `value` == false.
- typedef unspecified propagate_on_container_move_assignment;
+ //! type with internal constant static member <code>value</code> == false.
+ typedef see_documentation propagate_on_container_move_assignment;
//! Alloc::propagate_on_container_swap if such a type exists, otherwise an integral_constant
- //! type with internal constant static member `value` == false.
- typedef unspecified propagate_on_container_swap;
+ //! type with internal constant static member <code>value</code> == false.
+ typedef see_documentation propagate_on_container_swap;
//! Defines an allocator: Alloc::rebind<T>::other if such a type exists; otherwise, Alloc<T, Args>
//! if Alloc is a class template instantiation of the form Alloc<U, Args>, where Args is zero or
//! more type arguments ; otherwise, the instantiation of rebind_alloc is ill-formed.
//!
- //! In C++03 compilers `rebind_alloc` is a struct derived from an allocator
+ //! 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 = unspecified;
+ template <class T> using rebind_alloc = see_documentation;
- //! In C++03 compilers `rebind_traits` is a struct derived from
- //! `allocator_traits<OtherAlloc>`, where `OtherAlloc` is
- //! the allocator deduced by rules explained in `rebind_alloc`.
+ //! 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.
- //! `type` is an allocator related to Alloc deduced deduced by rules explained in `rebind_alloc`.
+ //! <code>type</code> is an allocator related to Alloc deduced deduced by rules explained in <code>rebind_alloc</code>.
template <class T>
struct portable_rebind_alloc
- { typedef unspecified_type type; };
+ { typedef see_documentation type; };
#else
//pointer
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc,
@@ -154,33 +161,33 @@ struct allocator_traits
size_type;
//propagate_on_container_copy_assignment
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc,
- propagate_on_container_copy_assignment, boost::false_type)
+ propagate_on_container_copy_assignment, container_detail::false_type)
propagate_on_container_copy_assignment;
//propagate_on_container_move_assignment
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc,
- propagate_on_container_move_assignment, boost::false_type)
+ propagate_on_container_move_assignment, container_detail::false_type)
propagate_on_container_move_assignment;
//propagate_on_container_swap
typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, Alloc,
- propagate_on_container_swap, boost::false_type)
+ propagate_on_container_swap, container_detail::false_type)
propagate_on_container_swap;
- #if !defined(BOOST_NO_TEMPLATE_ALIASES)
+ #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
//C++11
- template <typename T> using rebind_alloc = typename boost::intrusive::detail::type_rebinder<Alloc, T>::type;
+ template <typename T> using rebind_alloc = typename boost::intrusive::pointer_rebind<Alloc, T>::type;
template <typename T> using rebind_traits = allocator_traits< rebind_alloc<T> >;
- #else // #if !defined(BOOST_NO_TEMPLATE_ALIASES)
+ #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::detail::type_rebinder<Alloc,T>::type
+ struct rebind_alloc : boost::intrusive::pointer_rebind<Alloc,T>::type
{
- typedef typename boost::intrusive::detail::type_rebinder<Alloc,T>::type Base;
- #if !defined(BOOST_NO_VARIADIC_TEMPLATES)
+ typedef typename boost::intrusive::pointer_rebind<Alloc,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_VARIADIC_TEMPLATES)
+ #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#define BOOST_PP_LOCAL_MACRO(n) \
BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
rebind_alloc(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
@@ -189,192 +196,209 @@ struct allocator_traits
//
#define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
- #endif // #if !defined(BOOST_NO_VARIADIC_TEMPLATES)
+ #endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
};
template <typename T>
struct rebind_traits
- : allocator_traits<typename boost::intrusive::detail::type_rebinder<Alloc, T>::type>
+ : allocator_traits<typename boost::intrusive::pointer_rebind<Alloc, T>::type>
{};
- #endif // #if !defined(BOOST_NO_TEMPLATE_ALIASES)
+ #endif // #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
template <class T>
struct portable_rebind_alloc
- { typedef typename boost::intrusive::detail::type_rebinder<Alloc, T>::type type; };
+ { typedef typename boost::intrusive::pointer_rebind<Alloc, T>::type type; };
#endif //BOOST_CONTAINER_DOXYGEN_INVOKED
- //! <b>Returns</b>: `a.allocate(n)`
+ //! <b>Returns</b>: <code>a.allocate(n)</code>
//!
static pointer allocate(Alloc &a, size_type n)
{ return a.allocate(n); }
- //! <b>Returns</b>: `a.deallocate(p, n)`
+ //! <b>Returns</b>: <code>a.deallocate(p, n)</code>
//!
//! <b>Throws</b>: Nothing
static void deallocate(Alloc &a, pointer p, size_type n)
- { return a.deallocate(p, n); }
+ { a.deallocate(p, n); }
- //! <b>Effects</b>: calls `a.allocate(n, p)` if that call is well-formed;
- //! otherwise, invokes `a.allocate(n)`
+ //! <b>Effects</b>: calls <code>a.allocate(n, p)</code> if that call is well-formed;
+ //! otherwise, invokes <code>a.allocate(n)</code>
static pointer allocate(Alloc &a, size_type n, const_void_pointer p)
{
const bool value = boost::container::container_detail::
has_member_function_callable_with_allocate
<Alloc, const size_type, const const_void_pointer>::value;
- ::boost::integral_constant<bool, value> flag;
+ container_detail::bool_<value> flag;
return allocator_traits::priv_allocate(flag, a, n, p);
}
- //! <b>Effects</b>: calls `a.destroy(p)` if that call is well-formed;
- //! otherwise, invokes `p->~T()`.
+ //! <b>Effects</b>: calls <code>a.destroy(p)</code> if that call is well-formed;
+ //! otherwise, invokes <code>p->~T()</code>.
template<class T>
- static void destroy(Alloc &a, T*p)
+ static void destroy(Alloc &a, T*p) BOOST_CONTAINER_NOEXCEPT
{
typedef T* destroy_pointer;
const bool value = boost::container::container_detail::
has_member_function_callable_with_destroy
<Alloc, const destroy_pointer>::value;
- ::boost::integral_constant<bool, value> flag;
+ container_detail::bool_<value> flag;
allocator_traits::priv_destroy(flag, a, p);
}
- //! <b>Returns</b>: `a.max_size()` if that expression is well-formed; otherwise,
- //! `numeric_limits<size_type>::max()`.
- static size_type max_size(const Alloc &a)
+ //! <b>Returns</b>: <code>a.max_size()</code> if that expression is well-formed; otherwise,
+ //! <code>numeric_limits<size_type>::max()</code>.
+ static size_type max_size(const Alloc &a) BOOST_CONTAINER_NOEXCEPT
{
const bool value = boost::container::container_detail::
has_member_function_callable_with_max_size
<const Alloc>::value;
- ::boost::integral_constant<bool, value> flag;
+ container_detail::bool_<value> flag;
return allocator_traits::priv_max_size(flag, a);
}
- //! <b>Returns</b>: `a.select_on_container_copy_construction()` if that expression is well-formed;
+ //! <b>Returns</b>: <code>a.select_on_container_copy_construction()</code> if that expression is well-formed;
//! otherwise, a.
- static Alloc select_on_container_copy_construction(const Alloc &a)
+ static
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ typename container_detail::if_c
+ < boost::container::container_detail::
+ has_member_function_callable_with_select_on_container_copy_construction
+ <const Alloc>::value
+ , Alloc
+ , const Alloc &
+ >::type
+ #else
+ Alloc
+ #endif
+ select_on_container_copy_construction(const Alloc &a)
{
const bool value = boost::container::container_detail::
has_member_function_callable_with_select_on_container_copy_construction
<const Alloc>::value;
- ::boost::integral_constant<bool, value> flag;
+ container_detail::bool_<value> flag;
return allocator_traits::priv_select_on_container_copy_construction(flag, a);
}
- #if !defined(BOOST_NO_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- //! <b>Effects</b>: calls `a.construct(p, std::forward<Args>(args)...)` if that call is well-formed;
- //! otherwise, invokes `::new (static_cast<void*>(p)) T(std::forward<Args>(args)...)`
+ #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ //! <b>Effects</b>: calls <code>a.construct(p, std::forward<Args>(args)...)</code> if that call is well-formed;
+ //! otherwise, invokes <code>::new (static_cast<void*>(p)) T(std::forward<Args>(args)...)</code>
template <class T, class ...Args>
static void construct(Alloc & a, T* p, BOOST_FWD_REF(Args)... args)
{
- ::boost::integral_constant<bool, container_detail::is_std_allocator<Alloc>::value> flag;
+ container_detail::bool_<container_detail::is_std_allocator<Alloc>::value> flag;
allocator_traits::priv_construct(flag, a, p, ::boost::forward<Args>(args)...);
}
#endif
- ///@cond
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
private:
- static pointer priv_allocate(boost::true_type, Alloc &a, size_type n, const_void_pointer p)
+ static pointer priv_allocate(container_detail::true_type, Alloc &a, size_type n, const_void_pointer p)
{ return a.allocate(n, p); }
- static pointer priv_allocate(boost::false_type, Alloc &a, size_type n, const_void_pointer)
+ static pointer priv_allocate(container_detail::false_type, Alloc &a, size_type n, const_void_pointer)
{ return allocator_traits::allocate(a, n); }
template<class T>
- static void priv_destroy(boost::true_type, Alloc &a, T* p)
+ static void priv_destroy(container_detail::true_type, Alloc &a, T* p) BOOST_CONTAINER_NOEXCEPT
{ a.destroy(p); }
template<class T>
- static void priv_destroy(boost::false_type, Alloc &, T* p)
+ static void priv_destroy(container_detail::false_type, Alloc &, T* p) BOOST_CONTAINER_NOEXCEPT
{ p->~T(); (void)p; }
- static size_type priv_max_size(boost::true_type, const Alloc &a)
+ static size_type priv_max_size(container_detail::true_type, const Alloc &a) BOOST_CONTAINER_NOEXCEPT
{ return a.max_size(); }
- static size_type priv_max_size(boost::false_type, const Alloc &)
- { return (std::numeric_limits<size_type>::max)(); }
+ static size_type priv_max_size(container_detail::false_type, const Alloc &) BOOST_CONTAINER_NOEXCEPT
+ { return size_type(-1); }
- static Alloc priv_select_on_container_copy_construction(boost::true_type, const Alloc &a)
+ static Alloc priv_select_on_container_copy_construction(container_detail::true_type, const Alloc &a)
{ return a.select_on_container_copy_construction(); }
- static Alloc priv_select_on_container_copy_construction(boost::false_type, const Alloc &a)
+ static const Alloc &priv_select_on_container_copy_construction(container_detail::false_type, const Alloc &a) BOOST_CONTAINER_NOEXCEPT
{ return a; }
- #if !defined(BOOST_NO_VARIADIC_TEMPLATES)
+ #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template<class T, class ...Args>
- static void priv_construct(boost::false_type, Alloc &a, T *p, BOOST_FWD_REF(Args) ...args)
- {
+ static void priv_construct(container_detail::false_type, Alloc &a, T *p, BOOST_FWD_REF(Args) ...args)
+ {
const bool value = boost::container::container_detail::
has_member_function_callable_with_construct
< Alloc, T*, Args... >::value;
- ::boost::integral_constant<bool, value> flag;
+ container_detail::bool_<value> flag;
priv_construct_dispatch2(flag, a, p, ::boost::forward<Args>(args)...);
}
template<class T, class ...Args>
- static void priv_construct(boost::true_type, Alloc &a, T *p, BOOST_FWD_REF(Args) ...args)
+ static void priv_construct(container_detail::true_type, Alloc &a, T *p, BOOST_FWD_REF(Args) ...args)
{
- priv_construct_dispatch2(boost::false_type(), a, p, ::boost::forward<Args>(args)...);
+ priv_construct_dispatch2(container_detail::false_type(), a, p, ::boost::forward<Args>(args)...);
}
template<class T, class ...Args>
- static void priv_construct_dispatch2(boost::true_type, Alloc &a, T *p, BOOST_FWD_REF(Args) ...args)
+ static void priv_construct_dispatch2(container_detail::true_type, Alloc &a, T *p, BOOST_FWD_REF(Args) ...args)
{ a.construct( p, ::boost::forward<Args>(args)...); }
template<class T, class ...Args>
- static void priv_construct_dispatch2(boost::false_type, Alloc &, T *p, BOOST_FWD_REF(Args) ...args)
- { ::new((void*)p) T(::boost::forward<Args>(args)...); }
- #else // #if !defined(BOOST_NO_VARIADIC_TEMPLATES)
+ static void priv_construct_dispatch2(container_detail::false_type, Alloc &, T *p, BOOST_FWD_REF(Args) ...args)
+ { ::new((void*)p, boost_container_new_t()) T(::boost::forward<Args>(args)...); }
+ #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
public:
#define BOOST_PP_LOCAL_MACRO(n) \
template<class T BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) > \
static void construct(Alloc &a, T *p \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
{ \
- ::boost::integral_constant<bool, container_detail::is_std_allocator<Alloc>::value> flag; \
+ container_detail::bool_ \
+ <container_detail::is_std_allocator<Alloc>::value> flag; \
allocator_traits::priv_construct(flag, a, p \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
} \
//
#define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
-
+
private:
#define BOOST_PP_LOCAL_MACRO(n) \
template<class T BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) > \
- static void priv_construct(boost::false_type, Alloc &a, T *p \
+ static void priv_construct(container_detail::false_type, Alloc &a, T *p \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST,_)) \
{ \
const bool value = \
boost::container::container_detail::has_member_function_callable_with_construct \
< Alloc, T* BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_FWD_TYPE, _) >::value; \
- ::boost::integral_constant<bool, value> flag; \
+ container_detail::bool_<value> flag; \
priv_construct_dispatch2(flag, a, p \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \
} \
\
template<class T BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) > \
- static void priv_construct(boost::true_type, Alloc &a, T *p \
+ static void priv_construct(container_detail::true_type, Alloc &a, T *p \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST,_)) \
{ \
- priv_construct_dispatch2(boost::false_type(), a, p \
+ priv_construct_dispatch2(container_detail::false_type(), a, p \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \
} \
\
template<class T BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) > \
- static void priv_construct_dispatch2(boost::true_type, Alloc &a, T *p \
+ static void priv_construct_dispatch2(container_detail::true_type, Alloc &a, T *p \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST,_)) \
{ a.construct( p BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); } \
\
template<class T BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) > \
- static void priv_construct_dispatch2(boost::false_type, Alloc &, T *p \
+ static void priv_construct_dispatch2(container_detail::false_type, Alloc &, T *p \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _) ) \
- { ::new((void*)p) T(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); } \
+ { ::new((void*)p, boost_container_new_t()) T(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); }\
//
#define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
- #endif // #if !defined(BOOST_NO_VARIADIC_TEMPLATES)
+ #endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+ template<class T>
+ static void priv_construct_dispatch2(container_detail::false_type, Alloc &, T *p, ::boost::container::default_init_t)
+ { ::new((void*)p) T; }
#endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- ///@endcond
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
};
} //namespace container {
diff --git a/boost/container/container_fwd.hpp b/boost/container/container_fwd.hpp
index c52b04a1c9..20ac77861d 100644
--- a/boost/container/container_fwd.hpp
+++ b/boost/container/container_fwd.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
+// (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)
//
@@ -11,15 +11,42 @@
#ifndef BOOST_CONTAINER_CONTAINER_FWD_HPP
#define BOOST_CONTAINER_CONTAINER_FWD_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
-//////////////////////////////////////////////////////////////////////////////
-// Standard predeclarations
-//////////////////////////////////////////////////////////////////////////////
-
-/// @cond
+//! \file
+//! This header file forward declares the following containers:
+//! - boost::container::vector
+//! - boost::container::stable_vector
+//! - boost::container::static_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
+//!
+//! It forward declares the following allocators:
+//! - boost::container::allocator
+//! - boost::container::node_allocator
+//! - boost::container::adaptive_pool
+//!
+//! 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{
@@ -27,18 +54,12 @@ namespace intrusive{
}}
namespace boost{ namespace container{ namespace container_detail{
-
-namespace bi = boost::intrusive;
-
+ namespace bi = boost::intrusive;
}}}
-#include <utility>
-#include <memory>
-#include <functional>
-#include <iosfwd>
-#include <string>
+#include <cstddef>
-/// @endcond
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//////////////////////////////////////////////////////////////////////////////
// Containers
@@ -47,94 +68,155 @@ namespace bi = boost::intrusive;
namespace boost {
namespace container {
-//vector class
+//! 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
+};
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
template <class T
- ,class A = std::allocator<T> >
+ ,class Allocator = std::allocator<T> >
class vector;
-//vector class
template <class T
- ,class A = std::allocator<T> >
+ ,class Allocator = std::allocator<T> >
class stable_vector;
-//vector class
+template <class T, std::size_t Capacity>
+class static_vector;
+
template <class T
- ,class A = std::allocator<T> >
+ ,class Allocator = std::allocator<T> >
class deque;
-//list class
template <class T
- ,class A = std::allocator<T> >
+ ,class Allocator = std::allocator<T> >
class list;
-//slist class
template <class T
- ,class A = std::allocator<T> >
+ ,class Allocator = std::allocator<T> >
class slist;
-//set class
-template <class T
- ,class Pred = std::less<T>
- ,class A = std::allocator<T> >
+template<tree_type_enum TreeType, bool OptimizeSize>
+struct tree_opt;
+
+typedef tree_opt<red_black_tree, true> tree_assoc_defaults;
+
+template <class Key
+ ,class Compare = std::less<Key>
+ ,class Allocator = std::allocator<Key>
+ ,class Options = tree_assoc_defaults >
class set;
-//multiset class
-template <class T
- ,class Pred = std::less<T>
- ,class A = std::allocator<T> >
+template <class Key
+ ,class Compare = std::less<Key>
+ ,class Allocator = std::allocator<Key>
+ ,class Options = tree_assoc_defaults >
class multiset;
-//map class
template <class Key
,class T
- ,class Pred = std::less<Key>
- ,class A = std::allocator<std::pair<const Key, T> > >
+ ,class Compare = std::less<Key>
+ ,class Allocator = std::allocator<std::pair<const Key, T> >
+ ,class Options = tree_assoc_defaults >
class map;
-//multimap class
template <class Key
,class T
- ,class Pred = std::less<Key>
- ,class A = std::allocator<std::pair<const Key, T> > >
+ ,class Compare = std::less<Key>
+ ,class Allocator = std::allocator<std::pair<const Key, T> >
+ ,class Options = tree_assoc_defaults >
class multimap;
-//flat_set class
-template <class T
- ,class Pred = std::less<T>
- ,class A = std::allocator<T> >
+template <class Key
+ ,class Compare = std::less<Key>
+ ,class Allocator = std::allocator<Key> >
class flat_set;
-//flat_multiset class
-template <class T
- ,class Pred = std::less<T>
- ,class A = std::allocator<T> >
+template <class Key
+ ,class Compare = std::less<Key>
+ ,class Allocator = std::allocator<Key> >
class flat_multiset;
-//flat_map class
template <class Key
,class T
- ,class Pred = std::less<Key>
- ,class A = std::allocator<std::pair<Key, T> > >
+ ,class Compare = std::less<Key>
+ ,class Allocator = std::allocator<std::pair<Key, T> > >
class flat_map;
-//flat_multimap class
template <class Key
,class T
- ,class Pred = std::less<Key>
- ,class A = std::allocator<std::pair<Key, T> > >
+ ,class Compare = std::less<Key>
+ ,class Allocator = std::allocator<std::pair<Key, T> > >
class flat_multimap;
-//basic_string class
template <class CharT
,class Traits = std::char_traits<CharT>
- ,class A = std::allocator<CharT> >
+ ,class Allocator = std::allocator<CharT> >
class basic_string;
+typedef basic_string
+ <char
+ ,std::char_traits<char>
+ ,std::allocator<char> >
+string;
+
+typedef basic_string
+ <wchar_t
+ ,std::char_traits<wchar_t>
+ ,std::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;
+
+#else
+
+//! Default options for tree-based associative containers
+//! - tree_type<red_black_tree>
+//! - optimize_size<true>
+typedef implementation_defined tree_assoc_defaults;
+
+#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
@@ -142,16 +224,29 @@ struct ordered_unique_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();
-
-//! 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();
-/// @cond
+//! Type used to tag that the inserted values
+//! should be default initialized
+struct default_init_t
+{};
-namespace detail_really_deep_namespace {
+//! 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
@@ -161,12 +256,14 @@ struct dummy
{
(void)ordered_range;
(void)ordered_unique_range;
+ (void)default_init;
}
};
} //detail_really_deep_namespace {
-/// @endcond
+
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
}} //namespace boost { namespace container {
diff --git a/boost/container/deque.hpp b/boost/container/deque.hpp
index 6a85ae9486..d8a546c86f 100644
--- a/boost/container/deque.hpp
+++ b/boost/container/deque.hpp
@@ -1,39 +1,17 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
+// (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.
//
//////////////////////////////////////////////////////////////////////////////
-// Copyright (c) 1996,1997
-// Silicon Graphics Computer Systems, Inc.
-//
-// Permission to use, copy, modify, distribute and sell this software
-// and its documentation for any purpose is hereby granted without fee,
-// provided that the above copyright notice appear in all copies and
-// that both that copyright notice and this permission notice appear
-// in supporting documentation. Silicon Graphics makes no
-// representations about the suitability of this software for any
-// purpose. It is provided "as is" without express or implied warranty.
-//
-//
-// Copyright (c) 1994
-// Hewlett-Packard Company
-//
-// Permission to use, copy, modify, distribute and sell this software
-// and its documentation for any purpose is hereby granted without fee,
-// provided that the above copyright notice appear in all copies and
-// that both that copyright notice and this permission notice appear
-// in supporting documentation. Hewlett-Packard Company makes no
-// representations about the suitability of this software for any
-// purpose. It is provided "as is" without express or implied warranty.
#ifndef BOOST_CONTAINER_DEQUE_HPP
#define BOOST_CONTAINER_DEQUE_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -46,41 +24,43 @@
#include <boost/container/detail/mpl.hpp>
#include <boost/container/allocator_traits.hpp>
#include <boost/container/container_fwd.hpp>
+#include <boost/container/throw_exception.hpp>
#include <cstddef>
#include <iterator>
#include <boost/assert.hpp>
#include <memory>
#include <algorithm>
-#include <stdexcept>
-#include <boost/detail/no_exceptions_support.hpp>
+#include <boost/core/no_exceptions_support.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp>
#include <boost/type_traits/has_trivial_copy.hpp>
#include <boost/type_traits/has_trivial_assign.hpp>
#include <boost/type_traits/has_nothrow_copy.hpp>
#include <boost/type_traits/has_nothrow_assign.hpp>
-#include <boost/move/move.hpp>
-#include <boost/move/move_helpers.hpp>
+#include <boost/move/utility_core.hpp>
+#include <boost/move/iterator.hpp>
+#include <boost/move/algorithm.hpp>
+#include <boost/move/detail/move_helpers.hpp>
+#include <boost/move/traits.hpp>
#include <boost/container/detail/advanced_insert_int.hpp>
+#include <boost/core/no_exceptions_support.hpp>
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+#include <initializer_list>
+#endif
namespace boost {
namespace container {
-/// @cond
-#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
-template <class T, class A = std::allocator<T> >
-#else
-template <class T, class A>
-#endif
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+template <class T, class Allocator>
class deque;
-template <class T, class A>
+template <class T>
struct deque_value_traits
{
typedef T value_type;
- typedef A allocator_type;
static const bool trivial_dctr = boost::has_trivial_destructor<value_type>::value;
- static const bool trivial_dctr_after_move = false;
- //::boost::has_trivial_destructor_after_move<value_type>::value || trivial_dctr;
+ static const bool trivial_dctr_after_move = ::boost::has_trivial_destructor_after_move<value_type>::value;
static const bool trivial_copy = has_trivial_copy<value_type>::value;
static const bool nothrow_copy = has_nothrow_copy<value_type>::value;
static const bool trivial_assign = has_trivial_assign<value_type>::value;
@@ -90,290 +70,257 @@ struct deque_value_traits
// Note: this function is simply a kludge to work around several compilers'
// bugs in handling constant expressions.
-inline std::size_t deque_buf_size(std::size_t size)
- { return size < 512 ? std::size_t(512 / size) : std::size_t(1); }
+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);
+};
-// 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 T, class A>
-class deque_base
+namespace container_detail {
+
+// 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).
+// Allocator 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
{
- BOOST_COPYABLE_AND_MOVABLE(deque_base)
public:
- typedef allocator_traits<A> 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 A allocator_type;
- typedef allocator_type stored_allocator_type;
- typedef val_alloc_size size_type;
+ 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;
- protected:
+ public:
- typedef deque_value_traits<T, A> traits_t;
- typedef ptr_alloc_t map_allocator_type;
+ 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; }
- static size_type s_buffer_size() { return deque_buf_size(sizeof(T)); }
+ deque_iterator(val_alloc_ptr x, index_pointer y) BOOST_CONTAINER_NOEXCEPT
+ : m_cur(x), m_first(*y), m_last(*y + s_buffer_size()), m_node(y)
+ {}
- val_alloc_ptr priv_allocate_node()
- { return this->alloc().allocate(s_buffer_size()); }
+ deque_iterator() BOOST_CONTAINER_NOEXCEPT
+ : m_cur(), m_first(), m_last(), m_node() //Value initialization to achieve "null iterators" (N3644)
+ {}
- void priv_deallocate_node(val_alloc_ptr p)
- { this->alloc().deallocate(p, s_buffer_size()); }
+ deque_iterator(deque_iterator<Pointer, false> const& x) BOOST_CONTAINER_NOEXCEPT
+ : m_cur(x.get_cur()), m_first(x.get_first()), m_last(x.get_last()), m_node(x.get_node())
+ {}
- ptr_alloc_ptr priv_allocate_map(size_type n)
- { return this->ptr_alloc().allocate(n); }
+ deque_iterator(Pointer cur, Pointer first, Pointer last, index_pointer node) BOOST_CONTAINER_NOEXCEPT
+ : m_cur(cur), m_first(first), m_last(last), m_node(node)
+ {}
- void priv_deallocate_map(ptr_alloc_ptr p, size_type n)
- { this->ptr_alloc().deallocate(p, n); }
+ deque_iterator<Pointer, false> unconst() const BOOST_CONTAINER_NOEXCEPT
+ {
+ return deque_iterator<Pointer, false>(this->get_cur(), this->get_first(), this->get_last(), this->get_node());
+ }
- public:
- // 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].
- class const_iterator
- : public std::iterator<std::random_access_iterator_tag,
- val_alloc_val, val_alloc_diff,
- val_alloc_cptr, val_alloc_cref>
- {
- public:
- static size_type s_buffer_size() { return deque_base<T, A>::s_buffer_size(); }
-
- typedef std::random_access_iterator_tag iterator_category;
- typedef val_alloc_val value_type;
- typedef val_alloc_cptr pointer;
- typedef val_alloc_cref reference;
- typedef val_alloc_diff difference_type;
-
- typedef ptr_alloc_ptr index_pointer;
- typedef const_iterator self_t;
-
- friend class deque<T, A>;
- friend class deque_base<T, A>;
-
- protected:
- val_alloc_ptr m_cur;
- val_alloc_ptr m_first;
- val_alloc_ptr m_last;
- index_pointer m_node;
-
- public:
- const_iterator(val_alloc_ptr x, index_pointer y)
- : m_cur(x), m_first(*y),
- m_last(*y + s_buffer_size()), m_node(y) {}
-
- const_iterator() : m_cur(0), m_first(0), m_last(0), m_node(0) {}
-
- const_iterator(const const_iterator& x)
- : m_cur(x.m_cur), m_first(x.m_first),
- m_last(x.m_last), m_node(x.m_node) {}
-
- reference operator*() const
- { return *this->m_cur; }
-
- pointer operator->() const
- { return this->m_cur; }
-
- difference_type operator-(const self_t& x) const
- {
- 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);
- }
+ reference operator*() const BOOST_CONTAINER_NOEXCEPT
+ { return *this->m_cur; }
- self_t& operator++()
- {
- ++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;
- }
+ pointer operator->() const BOOST_CONTAINER_NOEXCEPT
+ { return this->m_cur; }
- self_t operator++(int)
- {
- self_t tmp = *this;
- ++*this;
- return tmp;
+ difference_type operator-(const deque_iterator& x) const BOOST_CONTAINER_NOEXCEPT
+ {
+ 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);
+ }
- self_t& operator--()
- {
- 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++() BOOST_CONTAINER_NOEXCEPT
+ {
+ ++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;
+ }
- self_t operator--(int)
- {
- self_t tmp = *this;
- --*this;
- return tmp;
- }
+ deque_iterator operator++(int) BOOST_CONTAINER_NOEXCEPT
+ {
+ deque_iterator tmp(*this);
+ ++*this;
+ return tmp;
+ }
- self_t& operator+=(difference_type n)
- {
- 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--() BOOST_CONTAINER_NOEXCEPT
+ {
+ 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;
+ }
- self_t operator+(difference_type n) const
- { self_t tmp = *this; return tmp += n; }
-
- self_t& operator-=(difference_type n)
- { return *this += -n; }
-
- self_t operator-(difference_type n) const
- { self_t tmp = *this; return tmp -= n; }
-
- reference operator[](difference_type n) const
- { return *(*this + n); }
+ deque_iterator operator--(int) BOOST_CONTAINER_NOEXCEPT
+ {
+ deque_iterator tmp(*this);
+ --*this;
+ return tmp;
+ }
- bool operator==(const self_t& x) const
- { return this->m_cur == x.m_cur; }
+ deque_iterator& operator+=(difference_type n) BOOST_CONTAINER_NOEXCEPT
+ {
+ 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;
+ }
- bool operator!=(const self_t& x) const
- { return !(*this == x); }
+ deque_iterator operator+(difference_type n) const BOOST_CONTAINER_NOEXCEPT
+ { deque_iterator tmp(*this); return tmp += n; }
- bool operator<(const self_t& x) const
- {
- return (this->m_node == x.m_node) ?
- (this->m_cur < x.m_cur) : (this->m_node < x.m_node);
- }
+ deque_iterator& operator-=(difference_type n) BOOST_CONTAINER_NOEXCEPT
+ { return *this += -n; }
- bool operator>(const self_t& x) const
- { return x < *this; }
+ deque_iterator operator-(difference_type n) const BOOST_CONTAINER_NOEXCEPT
+ { deque_iterator tmp(*this); return tmp -= n; }
- bool operator<=(const self_t& x) const
- { return !(x < *this); }
+ reference operator[](difference_type n) const BOOST_CONTAINER_NOEXCEPT
+ { return *(*this + n); }
- bool operator>=(const self_t& x) const
- { return !(*this < x); }
+ friend bool operator==(const deque_iterator& l, const deque_iterator& r) BOOST_CONTAINER_NOEXCEPT
+ { return l.m_cur == r.m_cur; }
- void priv_set_node(index_pointer new_node)
- {
- this->m_node = new_node;
- this->m_first = *new_node;
- this->m_last = this->m_first + difference_type(this->s_buffer_size());
- }
+ friend bool operator!=(const deque_iterator& l, const deque_iterator& r) BOOST_CONTAINER_NOEXCEPT
+ { return l.m_cur != r.m_cur; }
- friend const_iterator operator+(difference_type n, const const_iterator& x)
- { return x + n; }
- };
+ friend bool operator<(const deque_iterator& l, const deque_iterator& r) BOOST_CONTAINER_NOEXCEPT
+ { return (l.m_node == r.m_node) ? (l.m_cur < r.m_cur) : (l.m_node < r.m_node); }
- //Deque iterator
- class iterator : public const_iterator
- {
- public:
- typedef std::random_access_iterator_tag iterator_category;
- typedef val_alloc_val value_type;
- typedef val_alloc_ptr pointer;
- typedef val_alloc_ref reference;
- typedef val_alloc_diff difference_type;
- typedef ptr_alloc_ptr index_pointer;
- typedef const_iterator self_t;
+ friend bool operator>(const deque_iterator& l, const deque_iterator& r) BOOST_CONTAINER_NOEXCEPT
+ { return r < l; }
- friend class deque<T, A>;
- friend class deque_base<T, A>;
+ friend bool operator<=(const deque_iterator& l, const deque_iterator& r) BOOST_CONTAINER_NOEXCEPT
+ { return !(r < l); }
- private:
- explicit iterator(const const_iterator& x) : const_iterator(x){}
+ friend bool operator>=(const deque_iterator& l, const deque_iterator& r) BOOST_CONTAINER_NOEXCEPT
+ { return !(l < r); }
- public:
- //Constructors
- iterator(val_alloc_ptr x, index_pointer y) : const_iterator(x, y){}
- iterator() : const_iterator(){}
- //iterator(const const_iterator &cit) : const_iterator(cit){}
- iterator(const iterator& x) : const_iterator(x){}
+ void priv_set_node(index_pointer new_node) BOOST_CONTAINER_NOEXCEPT
+ {
+ this->m_node = new_node;
+ this->m_first = *new_node;
+ this->m_last = this->m_first + this->s_buffer_size();
+ }
- //Pointer like operators
- reference operator*() const { return *this->m_cur; }
- pointer operator->() const { return this->m_cur; }
+ friend deque_iterator operator+(difference_type n, deque_iterator x) BOOST_CONTAINER_NOEXCEPT
+ { return x += n; }
+};
- reference operator[](difference_type n) const { return *(*this + n); }
+} //namespace container_detail {
- //Increment / Decrement
- iterator& operator++()
- { this->const_iterator::operator++(); return *this; }
+// 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;
- iterator operator++(int)
- { iterator tmp = *this; ++*this; return tmp; }
-
- iterator& operator--()
- { this->const_iterator::operator--(); return *this; }
+ protected:
- iterator operator--(int)
- { iterator tmp = *this; --*this; return tmp; }
+ typedef deque_value_traits<val_alloc_val> traits_t;
+ typedef ptr_alloc_t map_allocator_type;
- // Arithmetic
- iterator& operator+=(difference_type off)
- { this->const_iterator::operator+=(off); return *this; }
+ static size_type s_buffer_size() BOOST_CONTAINER_NOEXCEPT
+ { return deque_buf_size<val_alloc_val>::value; }
- iterator operator+(difference_type off) const
- { return iterator(this->const_iterator::operator+(off)); }
+ val_alloc_ptr priv_allocate_node()
+ { return this->alloc().allocate(s_buffer_size()); }
- friend iterator operator+(difference_type off, const iterator& right)
- { return iterator(off+static_cast<const const_iterator &>(right)); }
+ void priv_deallocate_node(val_alloc_ptr p) BOOST_CONTAINER_NOEXCEPT
+ { this->alloc().deallocate(p, s_buffer_size()); }
- iterator& operator-=(difference_type off)
- { this->const_iterator::operator-=(off); return *this; }
+ ptr_alloc_ptr priv_allocate_map(size_type n)
+ { return this->ptr_alloc().allocate(n); }
- iterator operator-(difference_type off) const
- { return iterator(this->const_iterator::operator-(off)); }
+ void priv_deallocate_map(ptr_alloc_ptr p, size_type n) BOOST_CONTAINER_NOEXCEPT
+ { this->ptr_alloc().deallocate(p, n); }
- difference_type operator-(const const_iterator& right) const
- { return static_cast<const const_iterator&>(*this) - right; }
- };
+ typedef container_detail::deque_iterator<val_alloc_ptr, false> iterator;
+ typedef container_detail::deque_iterator<val_alloc_ptr, true > const_iterator;
deque_base(size_type num_elements, const allocator_type& a)
: members_(a)
@@ -402,10 +349,10 @@ class deque_base
private:
deque_base(const deque_base&);
-
+
protected:
- void swap_members(deque_base &x)
+ void swap_members(deque_base &x) BOOST_CONTAINER_NOEXCEPT
{
std::swap(this->members_.m_start, x.members_.m_start);
std::swap(this->members_.m_finish, x.members_.m_finish);
@@ -423,7 +370,7 @@ class deque_base
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);
}
@@ -457,13 +404,13 @@ class deque_base
BOOST_CATCH_END
}
- void priv_destroy_nodes(ptr_alloc_ptr nstart, ptr_alloc_ptr nfinish)
+ void priv_destroy_nodes(ptr_alloc_ptr nstart, ptr_alloc_ptr nfinish) BOOST_CONTAINER_NOEXCEPT
{
for (ptr_alloc_ptr n = nstart; n < nfinish; ++n)
this->priv_deallocate_node(*n);
}
- void priv_clear_map()
+ void priv_clear_map() BOOST_CONTAINER_NOEXCEPT
{
if (this->members_.m_map) {
this->priv_destroy_nodes(this->members_.m_start.m_node, this->members_.m_finish.m_node + 1);
@@ -508,324 +455,76 @@ class deque_base
iterator m_finish;
} members_;
- ptr_alloc_t &ptr_alloc()
+ ptr_alloc_t &ptr_alloc() BOOST_CONTAINER_NOEXCEPT
{ return members_; }
-
- const ptr_alloc_t &ptr_alloc() const
+
+ const ptr_alloc_t &ptr_alloc() const BOOST_CONTAINER_NOEXCEPT
{ return members_; }
- allocator_type &alloc()
+ allocator_type &alloc() BOOST_CONTAINER_NOEXCEPT
{ return members_; }
-
- const allocator_type &alloc() const
+
+ const allocator_type &alloc() const BOOST_CONTAINER_NOEXCEPT
{ return members_; }
};
-/// @endcond
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
-//! Deque class
-//!
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
-template <class T, class A = std::allocator<T> >
+//! 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 = std::allocator<T> >
#else
-template <class T, class A>
+template <class T, class Allocator>
#endif
-class deque : protected deque_base<T, A>
+class deque : protected deque_base<Allocator>
{
- /// @cond
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
- typedef deque_base<T, A> Base;
- typedef typename Base::val_alloc_val val_alloc_val;
- typedef typename Base::val_alloc_ptr val_alloc_ptr;
- typedef typename Base::val_alloc_cptr val_alloc_cptr;
- typedef typename Base::val_alloc_ref val_alloc_ref;
- typedef typename Base::val_alloc_cref val_alloc_cref;
- typedef typename Base::val_alloc_size val_alloc_size;
- typedef typename Base::val_alloc_diff val_alloc_diff;
-
- typedef typename Base::ptr_alloc_t ptr_alloc_t;
- typedef typename Base::ptr_alloc_val ptr_alloc_val;
- typedef typename Base::ptr_alloc_ptr ptr_alloc_ptr;
- typedef typename Base::ptr_alloc_cptr ptr_alloc_cptr;
- typedef typename Base::ptr_alloc_ref ptr_alloc_ref;
- typedef typename Base::ptr_alloc_cref ptr_alloc_cref;
- /// @endcond
-
- public: // Basic types
- typedef T value_type;
- typedef val_alloc_ptr pointer;
- typedef val_alloc_cptr const_pointer;
- typedef val_alloc_ref reference;
- typedef val_alloc_cref const_reference;
- typedef val_alloc_size size_type;
- typedef val_alloc_diff difference_type;
- typedef typename Base::allocator_type allocator_type;
-
- public: // Iterators
- typedef typename Base::iterator iterator;
- typedef typename Base::const_iterator const_iterator;
-
- typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
- typedef std::reverse_iterator<iterator> reverse_iterator;
-
- typedef allocator_type stored_allocator_type;
-
- /// @cond
+ 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(container_detail::reverse_iterator<iterator>) reverse_iterator;
+ typedef BOOST_CONTAINER_IMPDEF(container_detail::reverse_iterator<const_iterator>) const_reverse_iterator;
+
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private: // Internal typedefs
BOOST_COPYABLE_AND_MOVABLE(deque)
- typedef ptr_alloc_ptr index_pointer;
+ typedef typename Base::ptr_alloc_ptr index_pointer;
static size_type s_buffer_size()
{ return Base::s_buffer_size(); }
- typedef container_detail::advanced_insert_aux_int<iterator> advanced_insert_aux_int_t;
- typedef repeat_iterator<T, difference_type> r_iterator;
- typedef boost::move_iterator<r_iterator> move_it;
- typedef allocator_traits<A> allocator_traits_type;
+ typedef allocator_traits<Allocator> allocator_traits_type;
- /// @endcond
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public:
-
- //! <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_CONTAINER_NOEXCEPT
- { 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_CONTAINER_NOEXCEPT
- { 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.
- stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT
- { 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_CONTAINER_NOEXCEPT
- { 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_CONTAINER_NOEXCEPT
- { return this->members_.m_finish; }
-
- //! <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_CONTAINER_NOEXCEPT
- { 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 end() const BOOST_CONTAINER_NOEXCEPT
- { 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_CONTAINER_NOEXCEPT
- { return 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_CONTAINER_NOEXCEPT
- { return reverse_iterator(this->members_.m_start); }
-
- //! <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_CONTAINER_NOEXCEPT
- { 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 rend() const BOOST_CONTAINER_NOEXCEPT
- { 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_CONTAINER_NOEXCEPT
- { 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_CONTAINER_NOEXCEPT
- { 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_CONTAINER_NOEXCEPT
- { 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_CONTAINER_NOEXCEPT
- { return const_reverse_iterator(this->members_.m_start); }
-
- //! <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_CONTAINER_NOEXCEPT
- { 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_CONTAINER_NOEXCEPT
- { return this->members_.m_start[difference_type(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)
- { this->priv_range_check(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_range_check(n); return (*this)[n]; }
-
- //! <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_CONTAINER_NOEXCEPT
- { 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_CONTAINER_NOEXCEPT
- { 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_CONTAINER_NOEXCEPT
- { 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_CONTAINER_NOEXCEPT
- { return *(cend()-1); }
-
- //! <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_CONTAINER_NOEXCEPT
- { 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_CONTAINER_NOEXCEPT
- { return allocator_traits_type::max_size(this->alloc()); }
-
- //! <b>Effects</b>: Returns true if the deque contains no elements.
- //!
- //! <b>Throws</b>: Nothing.
- //!
- //! <b>Complexity</b>: Constant.
- bool empty() const BOOST_CONTAINER_NOEXCEPT
- { return this->members_.m_finish == this->members_.m_start; }
+ //////////////////////////////////////////////
+ //
+ // construct/copy/destroy
+ //
+ //////////////////////////////////////////////
//! <b>Effects</b>: Default constructors a deque.
//!
@@ -838,33 +537,50 @@ class deque : protected deque_base<T, A>
//! <b>Effects</b>: Constructs a deque taking the allocator as parameter.
//!
- //! <b>Throws</b>: If allocator_type's copy constructor throws.
+ //! <b>Throws</b>: Nothing
//!
//! <b>Complexity</b>: Constant.
- explicit deque(const allocator_type& a)
+ explicit deque(const allocator_type& a) BOOST_CONTAINER_NOEXCEPT
: Base(a)
{}
//! <b>Effects</b>: Constructs a deque that will use a copy of allocator a
- //! and inserts n default contructed values.
+ //! and inserts n value initialized values.
//!
- //! <b>Throws</b>: If allocator_type's default constructor or copy constructor
- //! throws or T's default or copy constructor throws.
+ //! <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())
{
- container_detail::default_construct_aux_proxy<A, iterator> proxy(this->alloc(), n);
- proxy.uninitialized_copy_remaining_to(this->begin());
+ container_detail::insert_value_initialized_n_proxy<Allocator, iterator> proxy;
+ proxy.uninitialized_copy_n_and_update(this->alloc(), this->begin(), n);
+ //deque_base will deallocate in case of exception...
+ }
+
+ //! <b>Effects</b>: Constructs a deque that will use a copy of allocator a
+ //! and inserts n default initialized values.
+ //!
+ //! <b>Throws</b>: If allocator_type's default constructor
+ //! throws or T's default initialization or copy constructor throws.
+ //!
+ //! <b>Complexity</b>: Linear to n.
+ //!
+ //! <b>Note</b>: Non-standard extension
+ deque(size_type n, default_init_t)
+ : Base(n, allocator_type())
+ {
+ container_detail::insert_default_initialized_n_proxy<Allocator, iterator> proxy;
+ proxy.uninitialized_copy_n_and_update(this->alloc(), this->begin(), n);
//deque_base will deallocate in case of exception...
}
//! <b>Effects</b>: Constructs a deque that will use a copy of allocator a
//! and inserts n copies of value.
//!
- //! <b>Throws</b>: If allocator_type's default constructor or copy constructor
- //! throws or T's default or copy constructor throws.
+ //! <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,
@@ -872,6 +588,42 @@ class deque : protected deque_base<T, 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, const allocator_type& a = allocator_type()
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename container_detail::enable_if_c
+ < !container_detail::is_convertible<InIt, size_type>::value
+ >::type * = 0
+ #endif
+ )
+ : Base(a)
+ {
+ typedef typename std::iterator_traits<InIt>::iterator_category ItCat;
+ this->priv_range_initialize(first, last, ItCat());
+ }
+
+#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(), std::input_iterator_tag());
+ }
+#endif
+
//! <b>Effects</b>: Copy constructs a deque.
//!
//! <b>Postcondition</b>: x == *this.
@@ -936,23 +688,6 @@ class deque : protected deque_base<T, A>
}
}
- //! <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 or copy constructor
- //! throws or T's constructor taking an dereferenced InIt throws.
- //!
- //! <b>Complexity</b>: Linear to the range [first, last).
- template <class InpIt>
- deque(InpIt first, InpIt last, const allocator_type& a = allocator_type())
- : Base(a)
- {
- //Dispatch depending on integer/iterator
- const bool aux_boolean = container_detail::is_convertible<InpIt, size_type>::value;
- typedef container_detail::bool_<aux_boolean> Result;
- this->priv_initialize_dispatch(first, last, Result());
- }
-
//! <b>Effects</b>: Destroys the deque. All stored values are destroyed
//! and used memory is deallocated.
//!
@@ -961,7 +696,7 @@ class deque : protected deque_base<T, A>
//! <b>Complexity</b>: Linear to the number of elements.
~deque() BOOST_CONTAINER_NOEXCEPT
{
- priv_destroy_range(this->members_.m_start, this->members_.m_finish);
+ this->priv_destroy_range(this->members_.m_start, this->members_.m_finish);
}
//! <b>Effects</b>: Makes *this contain the same elements as x.
@@ -990,52 +725,58 @@ class deque : protected deque_base<T, A>
return *this;
}
- //! <b>Effects</b>: Move assignment. All mx's values are transferred to *this.
- //!
- //! <b>Postcondition</b>: x.empty(). *this contains a the elements x had
- //! before the function.
+ //! <b>Effects</b>: Move assignment. All x's values are transferred to *this.
//!
- //! <b>Throws</b>: If allocator_type's copy constructor throws.
+ //! <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>: Linear.
+ //! <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)
- {
- if (&x != this){
- allocator_type &this_alloc = this->alloc();
- allocator_type &x_alloc = x.alloc();
- //If allocators are equal we can just swap pointers
- if(this_alloc == x_alloc){
- //Destroy objects but retain memory in case x reuses it in the future
- this->clear();
- this->swap_members(x);
- //Move allocator if needed
- container_detail::bool_<allocator_traits_type::
- propagate_on_container_move_assignment::value> flag;
- container_detail::move_alloc(this_alloc, x_alloc, flag);
- container_detail::move_alloc(this->ptr_alloc(), x.ptr_alloc(), flag);
- }
- //If unequal allocators, then do a one by one move
- else{
- typedef typename std::iterator_traits<iterator>::iterator_category ItCat;
- this->assign( boost::make_move_iterator(x.begin())
- , boost::make_move_iterator(x.end()));
- }
+ BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::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;
+ container_detail::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
+ container_detail::move_alloc(this_alloc, x_alloc, flag);
+ container_detail::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;
}
- //! <b>Effects</b>: Swaps the contents of *this and x.
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Makes *this contain the same elements as il.
//!
- //! <b>Throws</b>: Nothing.
+ //! <b>Postcondition</b>: this->size() == il.size(). *this contains a copy
+ //! of each of x's elements.
//!
- //! <b>Complexity</b>: Constant.
- void swap(deque &x)
+ //! <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->swap_members(x);
- container_detail::bool_<allocator_traits_type::propagate_on_container_swap::value> flag;
- container_detail::swap_alloc(this->alloc(), x.alloc(), flag);
- container_detail::swap_alloc(this->ptr_alloc(), x.ptr_alloc(), flag);
+ this->assign(il.begin(), il.end());
+ return *this;
}
+#endif
//! <b>Effects</b>: Assigns the n copies of val to *this.
//!
@@ -1043,207 +784,462 @@ class deque : protected deque_base<T, A>
//!
//! <b>Complexity</b>: Linear to n.
void assign(size_type n, const T& val)
- { this->priv_fill_assign(n, 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 InpIt throws.
+ //! T's constructor from dereferencing InIt throws.
//!
//! <b>Complexity</b>: Linear to n.
- template <class InpIt>
- void assign(InpIt first, InpIt last)
- {
- //Dispatch depending on integer/iterator
- const bool aux_boolean = container_detail::is_convertible<InpIt, size_type>::value;
- typedef container_detail::bool_<aux_boolean> Result;
- this->priv_assign_dispatch(first, last, Result());
+ template <class InIt>
+ void assign(InIt first, InIt last
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename container_detail::enable_if_c
+ < !container_detail::is_convertible<InIt, size_type>::value
+ && container_detail::is_input_iterator<InIt>::value
+ >::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)
- //! <b>Effects</b>: Inserts a copy of x at the end of the deque.
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ template <class FwdIt>
+ void assign(FwdIt first, FwdIt last
+ , typename container_detail::enable_if_c
+ < !container_detail::is_convertible<FwdIt, size_type>::value
+ && !container_detail::is_input_iterator<FwdIt>::value
+ >::type * = 0
+ )
+ {
+ const size_type len = std::distance(first, last);
+ if (len > size()) {
+ FwdIt mid = first;
+ std::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 copy constructor throws.
+ //! T's constructor from dereferencing std::initializer_list iterator throws.
//!
- //! <b>Complexity</b>: Amortized constant time.
- void push_back(const T &x);
+ //! <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>: Constructs a new element in the end of the deque
- //! and moves the resources of mx to this new element.
+ //! <b>Effects</b>: Returns a copy of the internal allocator.
//!
- //! <b>Throws</b>: If memory allocation throws.
+ //! <b>Throws</b>: If allocator's copy 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
+ //! <b>Complexity</b>: Constant.
+ allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT
+ { return Base::alloc(); }
- #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- //! <b>Effects</b>: Inserts a copy of x at the front of the deque.
+ //! <b>Effects</b>: Returns a reference to the internal allocator.
//!
- //! <b>Throws</b>: If memory allocation throws or
- //! T's copy constructor throws.
+ //! <b>Throws</b>: Nothing
//!
- //! <b>Complexity</b>: Amortized constant time.
- void push_front(const T &x);
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT
+ { return Base::alloc(); }
- //! <b>Effects</b>: Constructs a new element in the front of the deque
- //! and moves the resources of mx to this new element.
+ //////////////////////////////////////////////
+ //
+ // iterators
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Returns a reference to the internal allocator.
//!
- //! <b>Throws</b>: If memory allocation throws.
+ //! <b>Throws</b>: Nothing
//!
- //! <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
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT
+ { return Base::alloc(); }
- //! <b>Effects</b>: Removes the last element from the deque.
+ //! <b>Effects</b>: Returns an iterator to the first element contained in the deque.
//!
//! <b>Throws</b>: Nothing.
//!
- //! <b>Complexity</b>: Constant time.
- void pop_back() BOOST_CONTAINER_NOEXCEPT
+ //! <b>Complexity</b>: Constant.
+ iterator begin() BOOST_CONTAINER_NOEXCEPT
+ { 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_CONTAINER_NOEXCEPT
+ { 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_CONTAINER_NOEXCEPT
+ { 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_CONTAINER_NOEXCEPT
+ { 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_CONTAINER_NOEXCEPT
+ { 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_CONTAINER_NOEXCEPT
+ { 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_CONTAINER_NOEXCEPT
+ { 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_CONTAINER_NOEXCEPT
+ { 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_CONTAINER_NOEXCEPT
+ { 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_CONTAINER_NOEXCEPT
+ { 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_CONTAINER_NOEXCEPT
+ { 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_CONTAINER_NOEXCEPT
+ { 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_CONTAINER_NOEXCEPT
+ { 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_CONTAINER_NOEXCEPT
+ { 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_CONTAINER_NOEXCEPT
+ { 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)
{
- 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()
- , container_detail::to_raw_pointer(this->members_.m_finish.m_cur)
- );
+ 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();
+ container_detail::insert_value_initialized_n_proxy<Allocator, iterator> proxy;
+ priv_insert_back_aux_impl(n, proxy);
}
- else
- this->priv_pop_back_aux();
}
- //! <b>Effects</b>: Removes the first element from the deque.
+ //! <b>Effects</b>: Inserts or erases elements at the end such that
+ //! the size becomes n. New elements are default initialized.
//!
- //! <b>Throws</b>: Nothing.
+ //! <b>Throws</b>: If memory allocation throws, or T's constructor throws.
//!
- //! <b>Complexity</b>: Constant time.
- void pop_front() BOOST_CONTAINER_NOEXCEPT
+ //! <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)
{
- if (this->members_.m_start.m_cur != this->members_.m_start.m_last - 1) {
- allocator_traits_type::destroy
- ( this->alloc()
- , container_detail::to_raw_pointer(this->members_.m_start.m_cur)
- );
- ++this->members_.m_start.m_cur;
+ 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();
+ container_detail::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->priv_pop_front_aux();
+ this->insert(this->members_.m_finish, new_size - len, x);
}
- #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ //! <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();
+ }
+ }
- //! <b>Requires</b>: position must be a valid iterator of *this.
+ //////////////////////////////////////////////
+ //
+ // element access
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Requires</b>: !empty()
//!
- //! <b>Effects</b>: Insert a copy of x before position.
+ //! <b>Effects</b>: Returns a reference to the first
+ //! element of the container.
//!
- //! <b>Throws</b>: If memory allocation throws or x's copy constructor throws.
+ //! <b>Throws</b>: Nothing.
//!
- //! <b>Complexity</b>: If position is end(), amortized constant time
- //! Linear time otherwise.
- iterator insert(const_iterator position, const T &x);
+ //! <b>Complexity</b>: Constant.
+ reference front() BOOST_CONTAINER_NOEXCEPT
+ { return *this->members_.m_start; }
- //! <b>Requires</b>: position must be a valid iterator of *this.
+ //! <b>Requires</b>: !empty()
//!
- //! <b>Effects</b>: Insert a new element before position with mx's resources.
+ //! <b>Effects</b>: Returns a const reference to the first element
+ //! from the beginning of the container.
//!
- //! <b>Throws</b>: If memory allocation throws.
+ //! <b>Throws</b>: Nothing.
//!
- //! <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)
- #endif
+ //! <b>Complexity</b>: Constant.
+ const_reference front() const BOOST_CONTAINER_NOEXCEPT
+ { return *this->members_.m_start; }
- //! <b>Requires</b>: pos must be a valid iterator of *this.
+ //! <b>Requires</b>: !empty()
//!
- //! <b>Effects</b>: Insert n copies of x before pos.
+ //! <b>Effects</b>: Returns a reference to the last
+ //! element of the container.
//!
- //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
+ //! <b>Throws</b>: Nothing.
//!
- //! <b>Complexity</b>: Linear to n.
- void insert(const_iterator pos, size_type n, const value_type& x)
- { this->priv_fill_insert(pos, n, x); }
+ //! <b>Complexity</b>: Constant.
+ reference back() BOOST_CONTAINER_NOEXCEPT
+ { return *(end()-1); }
- //! <b>Requires</b>: pos must be a valid iterator of *this.
+ //! <b>Requires</b>: !empty()
//!
- //! <b>Effects</b>: Insert a copy of the [first, last) range before pos.
+ //! <b>Effects</b>: Returns a const reference to the last
+ //! element of the container.
//!
- //! <b>Throws</b>: If memory allocation throws, T's constructor from a
- //! dereferenced InpIt throws or T's copy constructor throws.
+ //! <b>Throws</b>: Nothing.
//!
- //! <b>Complexity</b>: Linear to std::distance [first, last).
- template <class InpIt>
- void insert(const_iterator pos, InpIt first, InpIt last)
- {
- //Dispatch depending on integer/iterator
- const bool aux_boolean = container_detail::is_convertible<InpIt, size_type>::value;
- typedef container_detail::bool_<aux_boolean> Result;
- this->priv_insert_dispatch(pos, first, last, Result());
- }
+ //! <b>Complexity</b>: Constant.
+ const_reference back() const BOOST_CONTAINER_NOEXCEPT
+ { 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_CONTAINER_NOEXCEPT
+ { 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_CONTAINER_NOEXCEPT
+ { return this->members_.m_start[difference_type(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)
+ { this->priv_range_check(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_range_check(n); return (*this)[n]; }
+
+ //////////////////////////////////////////////
+ //
+ // modifiers
+ //
+ //////////////////////////////////////////////
#if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! <b>Effects</b>: Inserts an object of type T constructed with
- //! std::forward<Args>(args)... in the end of the deque.
+ //! std::forward<Args>(args)... in the beginning of the deque.
//!
//! <b>Throws</b>: If memory allocation throws or the in-place constructor throws.
//!
//! <b>Complexity</b>: Amortized constant time
template <class... Args>
- void emplace_back(Args&&... args)
+ void emplace_front(Args&&... args)
{
- if(this->priv_push_back_simple_available()){
+ if(this->priv_push_front_simple_available()){
allocator_traits_type::construct
( this->alloc()
- , this->priv_push_back_simple_pos()
+ , this->priv_push_front_simple_pos()
, boost::forward<Args>(args)...);
- this->priv_push_back_simple_commit();
+ this->priv_push_front_simple_commit();
}
else{
- typedef container_detail::advanced_insert_aux_non_movable_emplace<A, iterator, Args...> type;
- type &&proxy = type(this->alloc(), boost::forward<Args>(args)...);
- this->priv_insert_back_aux_impl(1, proxy);
+ typedef container_detail::insert_non_movable_emplace_proxy<Allocator, iterator, Args...> type;
+ 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 beginning of the deque.
+ //! std::forward<Args>(args)... in the end of the deque.
//!
//! <b>Throws</b>: If memory allocation throws or the in-place constructor throws.
//!
//! <b>Complexity</b>: Amortized constant time
template <class... Args>
- void emplace_front(Args&&... args)
+ void emplace_back(Args&&... args)
{
- if(this->priv_push_front_simple_available()){
+ if(this->priv_push_back_simple_available()){
allocator_traits_type::construct
( this->alloc()
- , this->priv_push_front_simple_pos()
+ , this->priv_push_back_simple_pos()
, boost::forward<Args>(args)...);
- this->priv_push_front_simple_commit();
+ this->priv_push_back_simple_commit();
}
else{
- typedef container_detail::advanced_insert_aux_non_movable_emplace<A, iterator, Args...> type;
- type &&proxy = type(this->alloc(), boost::forward<Args>(args)...);
- this->priv_insert_front_aux_impl(1, proxy);
+ typedef container_detail::insert_non_movable_emplace_proxy<Allocator, iterator, Args...> type;
+ this->priv_insert_back_aux_impl(1, type(boost::forward<Args>(args)...));
}
}
- //! <b>Requires</b>: position must be a valid iterator of *this.
+ //! <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 position
+ //! std::forward<Args>(args)... before p
//!
//! <b>Throws</b>: If memory allocation throws or the in-place constructor throws.
//!
- //! <b>Complexity</b>: If position is end(), amortized constant time
+ //! <b>Complexity</b>: If p is end(), amortized constant time
//! Linear time otherwise.
template <class... Args>
iterator emplace(const_iterator p, Args&&... args)
@@ -1257,11 +1253,8 @@ class deque : protected deque_base<T, A>
return (this->end()-1);
}
else{
- size_type n = p - this->cbegin();
- typedef container_detail::advanced_insert_aux_emplace<A, iterator, Args...> type;
- type &&proxy = type(this->alloc(), boost::forward<Args>(args)...);
- this->priv_insert_aux_impl(p, 1, proxy);
- return iterator(this->begin() + n);
+ typedef container_detail::insert_emplace_proxy<Allocator, iterator, Args...> type;
+ return this->priv_insert_aux_impl(p, 1, type(boost::forward<Args>(args)...));
}
}
@@ -1269,41 +1262,39 @@ class deque : protected deque_base<T, A>
//advanced_insert_int.hpp includes all necessary preprocessor machinery...
#define BOOST_PP_LOCAL_MACRO(n) \
- BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
- void emplace_back(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
+ BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, > ) \
+ void emplace_front(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
{ \
- if(priv_push_back_simple_available()){ \
+ if(priv_push_front_simple_available()){ \
allocator_traits_type::construct \
( this->alloc() \
- , this->priv_push_back_simple_pos() \
+ , this->priv_push_front_simple_pos() \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
- priv_push_back_simple_commit(); \
+ priv_push_front_simple_commit(); \
} \
else{ \
- container_detail::BOOST_PP_CAT(BOOST_PP_CAT( \
- advanced_insert_aux_non_movable_emplace, n), arg) \
- <A, iterator BOOST_PP_ENUM_TRAILING_PARAMS(n, P)> proxy \
- (this->alloc() BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
- priv_insert_back_aux_impl(1, proxy); \
+ typedef container_detail::BOOST_PP_CAT(insert_non_movable_emplace_proxy_arg, n) \
+ <Allocator, iterator BOOST_PP_ENUM_TRAILING_PARAMS(n, P)> type; \
+ priv_insert_front_aux_impl \
+ (1, type(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \
} \
} \
\
- BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, > ) \
- void emplace_front(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
+ BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
+ void emplace_back(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
{ \
- if(priv_push_front_simple_available()){ \
+ if(priv_push_back_simple_available()){ \
allocator_traits_type::construct \
( this->alloc() \
- , this->priv_push_front_simple_pos() \
+ , this->priv_push_back_simple_pos() \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
- priv_push_front_simple_commit(); \
+ priv_push_back_simple_commit(); \
} \
else{ \
- container_detail::BOOST_PP_CAT(BOOST_PP_CAT \
- (advanced_insert_aux_non_movable_emplace, n), arg) \
- <A, iterator BOOST_PP_ENUM_TRAILING_PARAMS(n, P)> proxy \
- (this->alloc() BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
- priv_insert_front_aux_impl(1, proxy); \
+ typedef container_detail::BOOST_PP_CAT(insert_non_movable_emplace_proxy_arg, n) \
+ <Allocator, iterator BOOST_PP_ENUM_TRAILING_PARAMS(n, P)> type; \
+ priv_insert_back_aux_impl \
+ (1, type(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \
} \
} \
\
@@ -1320,12 +1311,10 @@ class deque : protected deque_base<T, A>
return (this->end()-1); \
} \
else{ \
- size_type pos_num = p - this->cbegin(); \
- container_detail::BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \
- <A, iterator BOOST_PP_ENUM_TRAILING_PARAMS(n, P)> proxy \
- (this->alloc() BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
- this->priv_insert_aux_impl(p, 1, proxy); \
- return iterator(this->begin() + pos_num); \
+ typedef container_detail::BOOST_PP_CAT(insert_emplace_proxy_arg, n) \
+ <Allocator, iterator BOOST_PP_ENUM_TRAILING_PARAMS(n, P)> type; \
+ return this->priv_insert_aux_impl \
+ (p, 1, type(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \
} \
} \
//!
@@ -1334,40 +1323,188 @@ class deque : protected deque_base<T, A>
#endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
- //! <b>Effects</b>: Inserts or erases elements at the end such that
- //! the size becomes n. New elements are copy constructed from x.
+ #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>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)
+ //! <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 mx 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 mx 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 mx'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)
{
- const size_type len = size();
- if (new_size < len)
- this->erase(this->members_.m_start + new_size, this->members_.m_finish);
+ 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 std::distance [first, last).
+ template <class InIt>
+ iterator insert(const_iterator pos, InIt first, InIt last
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename container_detail::enable_if_c
+ < !container_detail::is_convertible<InIt, size_type>::value
+ && container_detail::is_input_iterator<InIt>::value
+ >::type * = 0
+ #endif
+ )
+ {
+ 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 std::distance [il.begin(), il.end()).
+ iterator insert(const_iterator pos, std::initializer_list<value_type> il)
+ { 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 container_detail::enable_if_c
+ < !container_detail::is_convertible<FwdIt, size_type>::value
+ && !container_detail::is_input_iterator<FwdIt>::value
+ >::type * = 0
+ #endif
+ )
+ {
+ container_detail::insert_range_proxy<Allocator, FwdIt, iterator> proxy(first);
+ return priv_insert_aux_impl(p, (size_type)std::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_CONTAINER_NOEXCEPT
+ {
+ if (this->members_.m_start.m_cur != this->members_.m_start.m_last - 1) {
+ allocator_traits_type::destroy
+ ( this->alloc()
+ , container_detail::to_raw_pointer(this->members_.m_start.m_cur)
+ );
+ ++this->members_.m_start.m_cur;
+ }
else
- this->insert(this->members_.m_finish, new_size - len, x);
+ this->priv_pop_front_aux();
}
- //! <b>Effects</b>: Inserts or erases elements at the end such that
- //! the size becomes n. New elements are default constructed.
+ //! <b>Effects</b>: Removes the last element from the deque.
//!
- //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
+ //! <b>Throws</b>: Nothing.
//!
- //! <b>Complexity</b>: Linear to the difference between size() and new_size.
- void resize(size_type new_size)
+ //! <b>Complexity</b>: Constant time.
+ void pop_back() BOOST_CONTAINER_NOEXCEPT
{
- const size_type len = size();
- if (new_size < len)
- this->priv_erase_last_n(len - new_size);
- else{
- size_type n = new_size - this->size();
- container_detail::default_construct_aux_proxy<A, iterator> proxy(this->alloc(), n);
- priv_insert_back_aux_impl(n, proxy);
+ 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()
+ , container_detail::to_raw_pointer(this->members_.m_finish.m_cur)
+ );
}
+ else
+ this->priv_pop_back_aux();
}
- //! <b>Effects</b>: Erases the element at position pos.
+ //! <b>Effects</b>: Erases the element at p.
//!
//! <b>Throws</b>: Nothing.
//!
@@ -1377,15 +1514,15 @@ class deque : protected deque_base<T, A>
//! Constant if pos is the first or the last element.
iterator erase(const_iterator pos) BOOST_CONTAINER_NOEXCEPT
{
- const_iterator next = pos;
+ iterator next = pos.unconst();
++next;
- difference_type index = pos - this->members_.m_start;
- if (size_type(index) < (this->size() >> 1)) {
- boost::move_backward(begin(), iterator(pos), iterator(next));
+ size_type index = pos - this->members_.m_start;
+ if (index < (this->size()/2)) {
+ boost::move_backward(this->begin(), pos.unconst(), next);
pop_front();
}
else {
- boost::move(iterator(next), end(), iterator(pos));
+ boost::move(next, this->end(), pos.unconst());
pop_back();
}
return this->members_.m_start + index;
@@ -1406,10 +1543,10 @@ class deque : protected deque_base<T, A>
return this->members_.m_finish;
}
else {
- difference_type n = last - first;
- difference_type elems_before = first - this->members_.m_start;
- if (elems_before < static_cast<difference_type>(this->size() - n) - elems_before) {
- boost::move_backward(begin(), iterator(first), iterator(last));
+ const size_type n = static_cast<size_type>(last - first);
+ const size_type elems_before = static_cast<size_type>(first - this->members_.m_start);
+ if (elems_before < (this->size() - n) - elems_before) {
+ boost::move_backward(begin(), first.unconst(), last.unconst());
iterator new_start = this->members_.m_start + n;
if(!Base::traits_t::trivial_dctr_after_move)
this->priv_destroy_range(this->members_.m_start, new_start);
@@ -1417,7 +1554,7 @@ class deque : protected deque_base<T, A>
this->members_.m_start = new_start;
}
else {
- boost::move(iterator(last), end(), iterator(first));
+ boost::move(last.unconst(), end(), first.unconst());
iterator new_finish = this->members_.m_finish - n;
if(!Base::traits_t::trivial_dctr_after_move)
this->priv_destroy_range(new_finish, this->members_.m_finish);
@@ -1428,18 +1565,17 @@ class deque : protected deque_base<T, A>
}
}
- void priv_erase_last_n(size_type n)
+ //! <b>Effects</b>: Swaps the contents of *this and x.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ void swap(deque &x)
{
- if(n == this->size()) {
- this->clear();
- }
- else {
- iterator new_finish = this->members_.m_finish - n;
- if(!Base::traits_t::trivial_dctr_after_move)
- this->priv_destroy_range(new_finish, this->members_.m_finish);
- this->priv_destroy_nodes(new_finish.m_node + 1, this->members_.m_finish.m_node + 1);
- this->members_.m_finish = new_finish;
- }
+ this->swap_members(x);
+ container_detail::bool_<allocator_traits_type::propagate_on_container_swap::value> flag;
+ container_detail::swap_alloc(this->alloc(), x.alloc(), flag);
+ container_detail::swap_alloc(this->ptr_alloc(), x.ptr_alloc(), flag);
}
//! <b>Effects</b>: Erases all the elements of the deque.
@@ -1467,108 +1603,113 @@ class deque : protected deque_base<T, A>
this->members_.m_finish = this->members_.m_start;
}
- //! <b>Effects</b>: Tries to deallocate the excess of memory created
- //! with previous allocations. The size of the deque is unchanged
+ //! <b>Effects</b>: Returns true if x and y are equal
//!
- //! <b>Throws</b>: If memory allocation throws.
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator==(const deque& x, const deque& y)
+ { return x.size() == y.size() && std::equal(x.begin(), x.end(), y.begin()); }
+
+ //! <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 std::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.
- 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();
- }
- }
+ friend void swap(deque& x, deque& y)
+ { x.swap(y); }
- /// @cond
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
- void priv_range_check(size_type n) const
- { if (n >= this->size()) BOOST_RETHROW std::out_of_range("deque"); }
- iterator priv_insert(const_iterator position, const value_type &x)
+ void priv_erase_last_n(size_type n)
{
- if (position == cbegin()){
- this->push_front(x);
- return begin();
- }
- else if (position == cend()){
- this->push_back(x);
- return (end()-1);
+ if(n == this->size()) {
+ this->clear();
}
else {
- size_type n = position - cbegin();
- this->priv_insert_aux(position, size_type(1), x);
- return iterator(this->begin() + n);
+ iterator new_finish = this->members_.m_finish - n;
+ if(!Base::traits_t::trivial_dctr_after_move)
+ this->priv_destroy_range(new_finish, this->members_.m_finish);
+ this->priv_destroy_nodes(new_finish.m_node + 1, this->members_.m_finish.m_node + 1);
+ this->members_.m_finish = new_finish;
}
}
- iterator priv_insert(const_iterator position, BOOST_RV_REF(value_type) mx)
+ void priv_range_check(size_type n) const
+ { if (n >= this->size()) throw_out_of_range("deque::at out of range"); }
+
+ template <class U>
+ iterator priv_insert(const_iterator p, BOOST_FWD_REF(U) x)
{
- if (position == cbegin()) {
- this->push_front(boost::move(mx));
+ if (p == cbegin()){
+ this->push_front(::boost::forward<U>(x));
return begin();
}
- else if (position == cend()) {
- this->push_back(boost::move(mx));
- return(end()-1);
+ else if (p == cend()){
+ this->push_back(::boost::forward<U>(x));
+ return --end();
}
else {
- //Just call more general insert(pos, size, value) and return iterator
- size_type n = position - begin();
- this->priv_insert_aux(position, move_it(r_iterator(mx, 1)), move_it(r_iterator()));
- return iterator(this->begin() + n);
- }
- }
-
- void priv_push_front(const value_type &t)
- {
- if(this->priv_push_front_simple_available()){
- allocator_traits_type::construct
- ( this->alloc(), this->priv_push_front_simple_pos(), t);
- this->priv_push_front_simple_commit();
- }
- else{
- this->priv_insert_aux(cbegin(), size_type(1), t);
+ return priv_insert_aux_impl
+ ( p, (size_type)1
+ , container_detail::get_insert_value_proxy<iterator, Allocator>(::boost::forward<U>(x)));
}
}
- void priv_push_front(BOOST_RV_REF(value_type) t)
+ 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::move(t));
+ ( this->alloc(), this->priv_push_front_simple_pos(), ::boost::forward<U>(x));
this->priv_push_front_simple_commit();
}
else{
- this->priv_insert_aux(cbegin(), move_it(r_iterator(t, 1)), move_it(r_iterator()));
+ priv_insert_aux_impl
+ ( this->cbegin(), (size_type)1
+ , container_detail::get_insert_value_proxy<iterator, Allocator>(::boost::forward<U>(x)));
}
}
- void priv_push_back(const value_type &t)
+ 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(), t);
+ ( this->alloc(), this->priv_push_back_simple_pos(), ::boost::forward<U>(x));
this->priv_push_back_simple_commit();
}
else{
- this->priv_insert_aux(cend(), size_type(1), t);
- }
- }
-
- void priv_push_back(BOOST_RV_REF(T) t)
- {
- if(this->priv_push_back_simple_available()){
- allocator_traits_type::construct
- ( this->alloc(), this->priv_push_back_simple_pos(), boost::move(t));
- this->priv_push_back_simple_commit();
- }
- else{
- this->priv_insert_aux(cend(), move_it(r_iterator(t, 1)), move_it(r_iterator()));
+ priv_insert_aux_impl
+ ( this->cend(), (size_type)1
+ , container_detail::get_insert_value_proxy<iterator, Allocator>(::boost::forward<U>(x)));
}
}
@@ -1600,54 +1741,12 @@ class deque : protected deque_base<T, A>
void priv_push_front_simple_commit()
{ --this->members_.m_start.m_cur; }
- template <class InpIt>
- void priv_insert_aux(const_iterator pos, InpIt first, InpIt last, std::input_iterator_tag)
- {
- for(;first != last; ++first){
- this->insert(pos, boost::move(value_type(*first)));
- }
- }
-
- template <class FwdIt>
- void priv_insert_aux(const_iterator pos, FwdIt first, FwdIt last, std::forward_iterator_tag)
- { this->priv_insert_aux(pos, first, last); }
-
- // assign(), a generalized assignment member function. Two
- // versions: one that takes a count, and one that takes a range.
- // The range version is a member template, so we dispatch on whether
- // or not the type is an integer.
- void priv_fill_assign(size_type n, const T& val)
- {
- if (n > size()) {
- std::fill(begin(), end(), val);
- this->insert(cend(), n - size(), val);
- }
- else {
- this->erase(cbegin() + n, cend());
- std::fill(begin(), end(), val);
- }
- }
-
- template <class Integer>
- void priv_initialize_dispatch(Integer n, Integer x, container_detail::true_)
- {
- this->priv_initialize_map(n);
- this->priv_fill_initialize(x);
- }
-
- template <class InpIt>
- void priv_initialize_dispatch(InpIt first, InpIt last, container_detail::false_)
- {
- typedef typename std::iterator_traits<InpIt>::iterator_category ItCat;
- this->priv_range_initialize(first, last, ItCat());
- }
-
void priv_destroy_range(iterator p, iterator p2)
{
for(;p != p2; ++p){
allocator_traits_type::destroy
( this->alloc()
- , container_detail::to_raw_pointer(&*p)
+ , container_detail::to_raw_pointer(container_detail::iterator_to_pointer(p))
);
}
}
@@ -1657,132 +1756,92 @@ class deque : protected deque_base<T, A>
for(;p != p2; ++p){
allocator_traits_type::destroy
( this->alloc()
- , container_detail::to_raw_pointer(&*p)
+ , container_detail::to_raw_pointer(container_detail::iterator_to_pointer(p))
);
}
}
- template <class Integer>
- void priv_assign_dispatch(Integer n, Integer val, container_detail::true_)
- { this->priv_fill_assign((size_type) n, (value_type)val); }
-
- template <class InpIt>
- void priv_assign_dispatch(InpIt first, InpIt last, container_detail::false_)
- {
- typedef typename std::iterator_traits<InpIt>::iterator_category ItCat;
- this->priv_assign_aux(first, last, ItCat());
- }
-
- template <class InpIt>
- void priv_assign_aux(InpIt first, InpIt last, std::input_iterator_tag)
- {
- iterator cur = begin();
- for ( ; first != last && cur != end(); ++cur, ++first)
- *cur = *first;
- if (first == last)
- this->erase(cur, cend());
- else
- this->insert(cend(), first, last);
- }
-
- template <class FwdIt>
- void priv_assign_aux(FwdIt first, FwdIt last, std::forward_iterator_tag)
- {
- size_type len = std::distance(first, last);
- if (len > size()) {
- FwdIt mid = first;
- std::advance(mid, size());
- boost::copy_or_move(first, mid, begin());
- this->insert(cend(), mid, last);
- }
- else
- this->erase(boost::copy_or_move(first, last, begin()), cend());
- }
-
- template <class Integer>
- void priv_insert_dispatch(const_iterator pos, Integer n, Integer x, container_detail::true_)
- { this->priv_fill_insert(pos, (size_type) n, (value_type)x); }
-
- template <class InpIt>
- void priv_insert_dispatch(const_iterator pos,InpIt first, InpIt last, container_detail::false_)
+ template<class InsertProxy>
+ iterator priv_insert_aux_impl(const_iterator p, size_type n, InsertProxy proxy)
{
- typedef typename std::iterator_traits<InpIt>::iterator_category ItCat;
- this->priv_insert_aux(pos, first, last, ItCat());
- }
-
- void priv_insert_aux(const_iterator pos, size_type n, const value_type& x)
- {
- typedef constant_iterator<value_type, difference_type> c_it;
- this->priv_insert_aux(pos, c_it(x, n), c_it());
- }
-
- //Just forward all operations to priv_insert_aux_impl
- template <class FwdIt>
- void priv_insert_aux(const_iterator p, FwdIt first, FwdIt last)
- {
- container_detail::advanced_insert_aux_proxy<A, FwdIt, iterator> proxy(this->alloc(), first, last);
- priv_insert_aux_impl(p, (size_type)std::distance(first, last), proxy);
- }
-
- void priv_insert_aux_impl(const_iterator p, size_type n, advanced_insert_aux_int_t &interf)
- {
- iterator pos(p);
+ 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 difference_type elemsbefore = pos - this->members_.m_start;
- size_type length = this->size();
- if (elemsbefore < static_cast<difference_type>(length / 2)) {
- iterator new_start = this->priv_reserve_elements_at_front(n);
- iterator old_start = this->members_.m_start;
- pos = this->members_.m_start + elemsbefore;
- if (elemsbefore >= difference_type(n)) {
- iterator start_n = this->members_.m_start + difference_type(n);
- ::boost::container::uninitialized_move_alloc
- (this->alloc(), this->members_.m_start, start_n, new_start);
+ 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;
- boost::move(start_n, pos, old_start);
- interf.copy_remaining_to(pos - difference_type(n));
}
- else {
- difference_type mid_count = (difference_type(n) - elemsbefore);
- iterator mid_start = old_start - mid_count;
- interf.uninitialized_copy_some_and_update(mid_start, mid_count, true);
- this->members_.m_start = mid_start;
- ::boost::container::uninitialized_move_alloc
- (this->alloc(), old_start, pos, new_start);
- this->members_.m_start = new_start;
- interf.copy_remaining_to(old_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::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 {
- iterator new_finish = this->priv_reserve_elements_at_back(n);
- iterator old_finish = this->members_.m_finish;
- const difference_type elemsafter =
- difference_type(length) - elemsbefore;
- pos = this->members_.m_finish - elemsafter;
- if (elemsafter >= difference_type(n)) {
- iterator finish_n = this->members_.m_finish - difference_type(n);
- ::boost::container::uninitialized_move_alloc
- (this->alloc(), finish_n, this->members_.m_finish, this->members_.m_finish);
+ 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;
- boost::move_backward(pos, finish_n, old_finish);
- interf.copy_remaining_to(pos);
}
- else {
- interf.uninitialized_copy_some_and_update(old_finish, elemsafter, false);
- this->members_.m_finish += n-elemsafter;
- ::boost::container::uninitialized_move_alloc
- (this->alloc(), pos, old_finish, this->members_.m_finish);
- this->members_.m_finish = new_finish;
- interf.copy_remaining_to(pos);
+ 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::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;
}
- void priv_insert_back_aux_impl(size_type n, advanced_insert_aux_int_t &interf)
+ template <class InsertProxy>
+ iterator priv_insert_back_aux_impl(size_type n, InsertProxy proxy)
{
if(!this->members_.m_map){
this->priv_initialize_map(0);
@@ -1790,26 +1849,28 @@ class deque : protected deque_base<T, A>
iterator new_finish = this->priv_reserve_elements_at_back(n);
iterator old_finish = this->members_.m_finish;
- interf.uninitialized_copy_some_and_update(old_finish, n, true);
+ proxy.uninitialized_copy_n_and_update(this->alloc(), old_finish, n);
this->members_.m_finish = new_finish;
+ return iterator(this->members_.m_finish - n);
}
- void priv_insert_front_aux_impl(size_type n, advanced_insert_aux_int_t &interf)
+ 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);
- interf.uninitialized_copy_some_and_update(new_start, difference_type(n), true);
+ proxy.uninitialized_copy_n_and_update(this->alloc(), new_start, n);
this->members_.m_start = new_start;
+ return new_start;
}
-
- void priv_fill_insert(const_iterator pos, size_type n, const value_type& x)
+ iterator priv_fill_insert(const_iterator pos, size_type n, const value_type& x)
{
typedef constant_iterator<value_type, difference_type> c_it;
- this->insert(pos, c_it(x, n), 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,
@@ -1832,13 +1893,13 @@ class deque : protected deque_base<T, A>
BOOST_CATCH_END
}
- template <class InpIt>
- void priv_range_initialize(InpIt first, InpIt last, std::input_iterator_tag)
+ template <class InIt>
+ void priv_range_initialize(InIt first, InIt last, std::input_iterator_tag)
{
this->priv_initialize_map(0);
BOOST_TRY {
for ( ; first != last; ++first)
- this->push_back(*first);
+ this->emplace_back(*first);
}
BOOST_CATCH(...){
this->clear();
@@ -1861,12 +1922,10 @@ class deque : protected deque_base<T, A>
++cur_node) {
FwdIt mid = first;
std::advance(mid, this->s_buffer_size());
- ::boost::container::uninitialized_copy_or_move_alloc
- (this->alloc(), first, mid, *cur_node);
+ ::boost::container::uninitialized_copy_alloc(this->alloc(), first, mid, *cur_node);
first = mid;
}
- ::boost::container::uninitialized_copy_or_move_alloc
- (this->alloc(), first, last, this->members_.m_finish.m_first);
+ ::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));
@@ -1876,7 +1935,7 @@ class deque : protected deque_base<T, A>
}
// Called only if this->members_.m_finish.m_cur == this->members_.m_finish.m_first.
- void priv_pop_back_aux()
+ void priv_pop_back_aux() BOOST_CONTAINER_NOEXCEPT
{
this->priv_deallocate_node(this->members_.m_finish.m_first);
this->members_.m_finish.priv_set_node(this->members_.m_finish.m_node - 1);
@@ -1891,7 +1950,7 @@ class deque : protected deque_base<T, A>
// 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()
+ void priv_pop_front_aux() BOOST_CONTAINER_NOEXCEPT
{
allocator_traits_type::destroy
( this->alloc()
@@ -1900,7 +1959,7 @@ class deque : protected deque_base<T, A>
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)
{
@@ -1920,7 +1979,7 @@ class deque : protected deque_base<T, A>
}
BOOST_CATCH(...) {
for (size_type j = 1; j < i; ++j)
- this->priv_deallocate_node(*(this->members_.m_start.m_node - j));
+ this->priv_deallocate_node(*(this->members_.m_start.m_node - j));
BOOST_RETHROW
}
BOOST_CATCH_END
@@ -1945,7 +2004,7 @@ class deque : protected deque_base<T, A>
}
BOOST_CATCH(...) {
for (size_type j = 1; j < i; ++j)
- this->priv_deallocate_node(*(this->members_.m_finish.m_node + j));
+ this->priv_deallocate_node(*(this->members_.m_finish.m_node + j));
BOOST_RETHROW
}
BOOST_CATCH_END
@@ -1985,66 +2044,25 @@ class deque : protected deque_base<T, A>
this->members_.m_start.priv_set_node(new_nstart);
this->members_.m_finish.priv_set_node(new_nstart + old_num_nodes - 1);
}
- /// @endcond
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
};
-// Nonmember functions.
-template <class T, class A>
-inline bool operator==(const deque<T, A>& x,
- const deque<T, A>& y)
-{
- return x.size() == y.size() && equal(x.begin(), x.end(), y.begin());
-}
-
-template <class T, class A>
-inline bool operator<(const deque<T, A>& x,
- const deque<T, A>& y)
-{
- return lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
-}
-
-template <class T, class A>
-inline bool operator!=(const deque<T, A>& x,
- const deque<T, A>& y)
- { return !(x == y); }
-
-template <class T, class A>
-inline bool operator>(const deque<T, A>& x,
- const deque<T, A>& y)
- { return y < x; }
-
-template <class T, class A>
-inline bool operator<=(const deque<T, A>& x,
- const deque<T, A>& y)
- { return !(y < x); }
-
-template <class T, class A>
-inline bool operator>=(const deque<T, A>& x,
- const deque<T, A>& y)
- { return !(x < y); }
-
-
-template <class T, class A>
-inline void swap(deque<T, A>& x, deque<T, A>& y)
-{ x.swap(y); }
-
}}
-/// @cond
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
namespace boost {
-/*
+
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
-template <class T, class A>
-struct has_trivial_destructor_after_move<boost::container::deque<T, A> >
-{
- enum { value = has_trivial_destructor<A>::value };
-};
-*/
+template <class T, class Allocator>
+struct has_trivial_destructor_after_move<boost::container::deque<T, Allocator> >
+ : public ::boost::has_trivial_destructor_after_move<Allocator>
+{};
+
}
-/// @endcond
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
#include <boost/container/detail/config_end.hpp>
diff --git a/boost/container/detail/adaptive_node_pool.hpp b/boost/container/detail/adaptive_node_pool.hpp
new file mode 100644
index 0000000000..4e7375412b
--- /dev/null
+++ b/boost/container/detail/adaptive_node_pool.hpp
@@ -0,0 +1,162 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+
+#include <boost/intrusive/set.hpp>
+#include <boost/aligned_storage.hpp>
+#include <boost/container/detail/alloc_lib_auto_link.hpp>
+#include <boost/container/detail/multiallocation_chain.hpp>
+#include <boost/container/detail/pool_common_alloc.hpp>
+#include <boost/container/detail/mutex.hpp>
+#include <boost/container/detail/adaptive_node_pool_impl.hpp>
+#include <boost/container/detail/multiallocation_chain.hpp>
+#include <cstddef>
+#include <cmath>
+#include <cassert>
+
+
+namespace boost {
+namespace container {
+namespace container_detail {
+
+template<bool AlignOnly>
+struct select_private_adaptive_node_pool_impl
+{
+ typedef boost::container::container_detail::
+ private_adaptive_node_pool_impl
+ < fake_segment_manager
+ , unsigned(AlignOnly)*::boost::container::adaptive_pool_flag::align_only
+ | ::boost::container::adaptive_pool_flag::size_ordered | ::boost::container::adaptive_pool_flag::address_ordered
+ > type;
+};
+
+//!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 select_private_adaptive_node_pool_impl<(OverheadPercent == 0)>::type
+{
+ typedef typename select_private_adaptive_node_pool_impl<OverheadPercent == 0>::type base_t;
+ //Non-copyable
+ private_adaptive_node_pool(const private_adaptive_node_pool &);
+ private_adaptive_node_pool &operator=(const private_adaptive_node_pool &);
+
+ public:
+ typedef typename base_t::multiallocation_chain multiallocation_chain;
+ static const std::size_t nodes_per_block = NodesPerBlock;
+
+ //!Constructor. Never throws
+ private_adaptive_node_pool()
+ : base_t(0
+ , NodeSize
+ , NodesPerBlock
+ , MaxFreeBlocks
+ , (unsigned char)OverheadPercent)
+ {}
+};
+
+//!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 container_detail {
+} //namespace container {
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_HPP
diff --git a/boost/container/detail/adaptive_node_pool_impl.hpp b/boost/container/detail/adaptive_node_pool_impl.hpp
index afba6b5f1b..dc1a7f102e 100644
--- a/boost/container/detail/adaptive_node_pool_impl.hpp
+++ b/boost/container/detail/adaptive_node_pool_impl.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
+// (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)
//
@@ -11,26 +11,40 @@
#ifndef BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_IMPL_HPP
#define BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_IMPL_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
-#include "config_begin.hpp"
-#include <boost/container/container_fwd.hpp>
+#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
+
+#include <boost/container/container_fwd.hpp>
#include <boost/container/detail/utilities.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/intrusive/set.hpp>
+#include <boost/intrusive/list.hpp>
#include <boost/intrusive/slist.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <boost/container/detail/math_functions.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/pool_common.hpp>
+#include <boost/container/throw_exception.hpp>
#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 container_detail {
template<class size_type>
@@ -42,42 +56,160 @@ struct hdr_offset_holder_t
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, bool ordered>
+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;
+ const const_block_iterator this_block
+ (Container::s_iterator_to(const_cast<typename Container::const_reference>(v)));
+ const_block_iterator next_block(this_block);
+ if(++next_block != container.cend()){
+ if(this_block->free_nodes.size() > next_block->free_nodes.size()){
+ 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, false>
+{
+ 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();
+ }
+};
+
+template<class MultiallocationChain, class VoidPointer, class SizeType, unsigned int Flags>
struct adaptive_pool_types
{
typedef VoidPointer void_pointer;
- typedef typename bi::make_set_base_hook
- < bi::void_pointer<void_pointer>
- , bi::optimize_size<true>
- , bi::constant_time_size<false>
- , bi::link_mode<bi::normal_link> >::type multiset_hook_t;
-
+ static const bool ordered = (Flags & (adaptive_pool_flag::size_ordered | adaptive_pool_flag::address_ordered)) != 0;
+ 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 multiset_hook_t
+ : public hdr_offset_holder,
+ public hook_t
{
- typedef typename node_slist<void_pointer>::node_slist_t free_nodes_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 l.free_nodes.size() < r.free_nodes.size(); }
- //Let's order blocks first by free nodes and then by address
- //so that highest address fully free blocks are deallocated.
- //This improves returning memory to the OS (trimming).
- const bool is_less = l.free_nodes.size() < r.free_nodes.size();
- const bool is_equal = l.free_nodes.size() == r.free_nodes.size();
- return is_less || (is_equal && (&l < &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 bi::make_multiset
- <block_info_t, bi::base_hook<multiset_hook_t> >::type block_multiset_t;
+ typedef typename block_container_traits_t:: template container<block_info_t>::type block_container_t;
};
template<class size_type>
@@ -113,9 +245,9 @@ inline void calculate_num_subblocks
, size_type &num_subblocks, size_type &real_num_node, size_type overhead_percent
, size_type hdr_size, size_type hdr_offset_size, size_type payload_per_allocation)
{
+ const size_type hdr_subblock_elements = (alignment - hdr_size - payload_per_allocation)/real_node_size;
size_type elements_per_subblock = (alignment - hdr_offset_size)/real_node_size;
size_type possible_num_subblock = (elements_per_block - 1)/elements_per_subblock + 1;
- size_type hdr_subblock_elements = (alignment - hdr_size - payload_per_allocation)/real_node_size;
while(((possible_num_subblock-1)*elements_per_subblock + hdr_subblock_elements) < elements_per_block){
++possible_num_subblock;
}
@@ -135,7 +267,7 @@ inline void calculate_num_subblocks
real_num_node = (possible_num_subblock-1)*elements_per_subblock + hdr_subblock_elements;
}
-template<class SegmentManagerBase, bool AlignOnly = false>
+template<class SegmentManagerBase, unsigned int Flags>
class private_adaptive_node_pool_impl
{
//Non-copyable
@@ -147,27 +279,42 @@ class private_adaptive_node_pool_impl
typedef typename SegmentManagerBase::void_pointer void_pointer;
static const typename SegmentManagerBase::
size_type PayloadPerAllocation = SegmentManagerBase::PayloadPerAllocation;
+ //Flags
+ //align_only
+ static const bool AlignOnly = (Flags & adaptive_pool_flag::align_only) != 0;
typedef bool_<AlignOnly> IsAlignOnly;
typedef true_ AlignOnlyTrue;
typedef false_ AlignOnlyFalse;
+ //size_ordered
+ static const bool SizeOrdered = (Flags & adaptive_pool_flag::size_ordered) != 0;
+ typedef bool_<SizeOrdered> IsSizeOrdered;
+ typedef true_ SizeOrderedTrue;
+ typedef false_ SizeOrderedFalse;
+ //address_ordered
+ static const bool AddressOrdered = (Flags & adaptive_pool_flag::address_ordered) != 0;
+ typedef bool_<AddressOrdered> IsAddressOrdered;
+ typedef true_ AddressOrderedTrue;
+ typedef false_ AddressOrderedFalse;
public:
- 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;
+ typedef typename SegmentManagerBase::multiallocation_chain multiallocation_chain;
+ typedef typename SegmentManagerBase::size_type size_type;
private:
- typedef typename adaptive_pool_types<void_pointer, size_type>::block_info_t block_info_t;
- typedef typename adaptive_pool_types<void_pointer, size_type>::block_multiset_t block_multiset_t;
- typedef typename block_multiset_t::iterator block_iterator;
- typedef typename adaptive_pool_types<void_pointer, size_type>::hdr_offset_holder hdr_offset_holder;
-
- static const size_type MaxAlign = alignment_of<node_t>::value;
+ 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;
+
+ 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;
-
public:
//!Segment manager typedef
typedef SegmentManagerBase segment_manager_base_type;
@@ -181,7 +328,7 @@ class private_adaptive_node_pool_impl
, unsigned char overhead_percent
)
: m_max_free_blocks(max_free_blocks)
- , m_real_node_size(lcm(node_size, size_type(alignment_of<node_t>::value)))
+ , m_real_node_size(lcm(node_size, size_type(alignment_of<void_pointer>::value)))
//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
@@ -195,7 +342,7 @@ class private_adaptive_node_pool_impl
, m_real_num_node(AlignOnly ? (m_real_block_alignment - PayloadPerAllocation - HdrSize)/m_real_node_size : 0)
//General purpose allocator
, mp_segment_mngr_base(segment_mngr_base)
- , m_block_multiset()
+ , m_block_container()
, m_totally_free_blocks(0)
{
if(!AlignOnly){
@@ -214,7 +361,7 @@ class private_adaptive_node_pool_impl
//!Destructor. Deallocates all allocated blocks. Never throws
~private_adaptive_node_pool_impl()
- { priv_clear(); }
+ { this->priv_clear(); }
size_type get_real_num_node() const
{ return m_real_num_node; }
@@ -226,84 +373,157 @@ class private_adaptive_node_pool_impl
//!Allocates array of count elements. Can throw
void *allocate_node()
{
- priv_invariants();
+ this->priv_invariants();
//If there are no free nodes we allocate a new block
- if (m_block_multiset.empty()){
- priv_alloc_block(1);
+ 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 = container_detail::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 == m_real_num_node);
+ this->priv_invariants();
+ return first_node;
+ }
+ else{
+ multiallocation_chain chain;
+ this->priv_append_from_new_blocks(1, chain, IsAlignOnly());
+ return container_detail::to_raw_pointer(chain.pop_front());
}
- //We take the first free node the multiset can't be empty
- return priv_take_first_node();
}
//!Deallocates an array pointed by ptr. Never throws
void deallocate_node(void *pElem)
{
- multiallocation_chain chain;
- chain.push_front(void_pointer(pElem));
- this->priv_reinsert_nodes_in_block(chain, 1);
- //Update free block count<
- if(m_totally_free_blocks > m_max_free_blocks){
- this->priv_deallocate_free_blocks(m_max_free_blocks);
- }
- priv_invariants();
+ this->priv_invariants();
+ block_info_t &block_info = *this->priv_block_from_node(pElem);
+ BOOST_ASSERT(block_info.free_nodes.size() < m_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, block_info.free_nodes.size() == 1);
+ this->priv_deallocate_free_blocks(m_max_free_blocks);
+ this->priv_invariants();
}
//!Allocates n nodes.
//!Can throw
- multiallocation_chain allocate_nodes(const size_type n)
+ void allocate_nodes(const size_type n, multiallocation_chain &chain)
{
- multiallocation_chain chain;
size_type i = 0;
- try{
- priv_invariants();
+ BOOST_TRY{
+ this->priv_invariants();
while(i != n){
//If there are no free nodes we allocate all needed blocks
- if (m_block_multiset.empty()){
- priv_alloc_block(((n - i) - 1)/m_real_num_node + 1);
+ if (m_block_container.empty()){
+ this->priv_append_from_new_blocks(n - i, chain, 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_multiset.begin()->free_nodes;
+ free_nodes_t &free_nodes = m_block_container.begin()->free_nodes;
const size_type free_nodes_count_before = free_nodes.size();
- if(free_nodes_count_before == m_real_num_node){
- --m_totally_free_blocks;
- }
- const size_type num_elems = ((n-i) < free_nodes_count_before) ? (n-i) : free_nodes_count_before;
- for(size_type j = 0; j != num_elems; ++j){
- void *new_node = &free_nodes.front();
- free_nodes.pop_front();
- chain.push_back(new_node);
+ m_totally_free_blocks -= static_cast<size_type>(free_nodes_count_before == m_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());
}
-
- if(free_nodes.empty()){
- m_block_multiset.erase(m_block_multiset.begin());
+ 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;
}
}
- catch(...){
- this->deallocate_nodes(boost::move(chain));
- throw;
+ BOOST_CATCH(...){
+ this->deallocate_nodes(chain);
+ BOOST_RETHROW
}
- priv_invariants();
- return boost::move(chain);
+ BOOST_CATCH_END
+ this->priv_invariants();
}
//!Deallocates a linked list of nodes. Never throws
- void deallocate_nodes(multiallocation_chain nodes)
+ void deallocate_nodes(multiallocation_chain &nodes)
{
- this->priv_reinsert_nodes_in_block(nodes, nodes.size());
- if(m_totally_free_blocks > m_max_free_blocks){
+ this->priv_invariants();
+ //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 = container_detail::to_raw_pointer(container_detail::iterator_to_pointer(itf));
+ block_info_t &block_info = *this->priv_block_from_node(pElem);
+ BOOST_ASSERT(block_info.free_nodes.size() < m_real_num_node);
+ ++splice_node_count;
+
+ //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);
+ 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);
+ this->priv_invariants();
this->priv_deallocate_free_blocks(m_max_free_blocks);
}
}
void deallocate_free_blocks()
- { this->priv_deallocate_free_blocks(0); }
+ { this->priv_deallocate_free_blocks(0); }
size_type num_free_nodes()
{
- typedef typename block_multiset_t::const_iterator citerator;
+ typedef typename block_container_t::const_iterator citerator;
size_type count = 0;
- citerator it (m_block_multiset.begin()), itend(m_block_multiset.end());
+ citerator it (m_block_container.begin()), itend(m_block_container.end());
for(; it != itend; ++it){
count += it->free_nodes.size();
}
@@ -318,7 +538,7 @@ class private_adaptive_node_pool_impl
BOOST_ASSERT(m_real_num_node == other.m_real_num_node);
std::swap(mp_segment_mngr_base, other.mp_segment_mngr_base);
std::swap(m_totally_free_blocks, other.m_totally_free_blocks);
- m_block_multiset.swap(other.m_block_multiset);
+ m_block_container.swap(other.m_block_container);
}
//Deprecated, use deallocate_free_blocks
@@ -326,84 +546,54 @@ class private_adaptive_node_pool_impl
{ this->priv_deallocate_free_blocks(0); }
private:
+
void priv_deallocate_free_blocks(size_type max_free_blocks)
+ { //Trampoline function to ease inlining
+ if(m_totally_free_blocks > max_free_blocks){
+ this->priv_deallocate_free_blocks_impl(max_free_blocks);
+ }
+ }
+
+ void priv_deallocate_free_blocks_impl(size_type max_free_blocks)
{
- priv_invariants();
+ this->priv_invariants();
//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
- for( block_iterator itend = m_block_multiset.end()
- ; m_totally_free_blocks > max_free_blocks
- ; --m_totally_free_blocks
- ){
- BOOST_ASSERT(!m_block_multiset.empty());
- block_iterator it = itend;
+ multiallocation_chain chain;
+ {
+ const const_block_iterator itend = m_block_container.cend();
+ const_block_iterator it = itend;
--it;
- BOOST_ASSERT(it->free_nodes.size() == m_real_num_node);
- m_block_multiset.erase_and_dispose(it, block_destroyer(this));
- }
- }
-
- void priv_reinsert_nodes_in_block(multiallocation_chain &chain, size_type n)
- {
- block_iterator block_it(m_block_multiset.end());
- while(n--){
- void *pElem = container_detail::to_raw_pointer(chain.front());
- chain.pop_front();
- priv_invariants();
- block_info_t *block_info = this->priv_block_from_node(pElem);
- BOOST_ASSERT(block_info->free_nodes.size() < m_real_num_node);
- //We put the node at the beginning of the free node list
- node_t * to_deallocate = static_cast<node_t*>(pElem);
- block_info->free_nodes.push_front(*to_deallocate);
-
- block_iterator this_block(block_multiset_t::s_iterator_to(*block_info));
- block_iterator next_block(this_block);
- ++next_block;
-
- //Cache the free nodes from the block
- size_type this_block_free_nodes = this_block->free_nodes.size();
-
- if(this_block_free_nodes == 1){
- m_block_multiset.insert(m_block_multiset.begin(), *block_info);
+ 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() == m_real_num_node);
+ void *addr = priv_first_subblock_from_block(const_cast<block_info_t*>(&*it));
+ --it;
+ block_container_traits_t::erase_last(m_block_container);
+ chain.push_front(void_pointer(addr));
}
- else{
- block_iterator next_block(this_block);
- ++next_block;
- if(next_block != block_it){
- size_type next_free_nodes = next_block->free_nodes.size();
- if(this_block_free_nodes > next_free_nodes){
- //Now move the block to the new position
- m_block_multiset.erase(this_block);
- m_block_multiset.insert(*block_info);
- }
- }
- }
- //Update free block count
- if(this_block_free_nodes == m_real_num_node){
- ++m_totally_free_blocks;
- }
- priv_invariants();
+ 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);
}
- node_t *priv_take_first_node()
+ void priv_reinsert_block(block_info_t &prev_block_info, const bool prev_block_was_empty)
{
- BOOST_ASSERT(m_block_multiset.begin() != m_block_multiset.end());
- //We take the first free node the multiset can't be empty
- free_nodes_t &free_nodes = m_block_multiset.begin()->free_nodes;
- node_t *first_node = &free_nodes.front();
- const size_type free_nodes_count = free_nodes.size();
- BOOST_ASSERT(0 != free_nodes_count);
- free_nodes.pop_front();
- if(free_nodes_count == 1){
- m_block_multiset.erase(m_block_multiset.begin());
+ //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 == m_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 if(free_nodes_count == m_real_num_node){
- --m_totally_free_blocks;
+ else{
+ block_container_traits_t::reinsert_was_used(m_block_container, prev_block_info, is_full);
}
- priv_invariants();
- return first_node;
}
class block_destroyer;
@@ -412,33 +602,31 @@ class private_adaptive_node_pool_impl
class block_destroyer
{
public:
- block_destroyer(const this_type *impl)
- : mp_impl(impl)
+ block_destroyer(const this_type *impl, multiallocation_chain &chain)
+ : mp_impl(impl), m_chain(chain)
{}
- void operator()(typename block_multiset_t::pointer to_deallocate)
+ void operator()(typename block_container_t::pointer to_deallocate)
{ return this->do_destroy(to_deallocate, IsAlignOnly()); }
private:
- void do_destroy(typename block_multiset_t::pointer to_deallocate, AlignOnlyTrue)
+ void do_destroy(typename block_container_t::pointer to_deallocate, AlignOnlyTrue)
{
- size_type free_nodes = to_deallocate->free_nodes.size();
- (void)free_nodes;
- BOOST_ASSERT(free_nodes == mp_impl->m_real_num_node);
- mp_impl->mp_segment_mngr_base->deallocate(to_deallocate);
+ BOOST_ASSERT(to_deallocate->free_nodes.size() == mp_impl->m_real_num_node);
+ m_chain.push_back(to_deallocate);
}
- void do_destroy(typename block_multiset_t::pointer to_deallocate, AlignOnlyFalse)
+ void do_destroy(typename block_container_t::pointer to_deallocate, AlignOnlyFalse)
{
- size_type free_nodes = to_deallocate->free_nodes.size();
- (void)free_nodes;
- BOOST_ASSERT(free_nodes == mp_impl->m_real_num_node);
+ BOOST_ASSERT(to_deallocate->free_nodes.size() == mp_impl->m_real_num_node);
BOOST_ASSERT(0 == to_deallocate->hdr_offset);
- hdr_offset_holder *hdr_off_holder = mp_impl->priv_first_subblock_from_block(container_detail::to_raw_pointer(to_deallocate));
- mp_impl->mp_segment_mngr_base->deallocate(hdr_off_holder);
+ hdr_offset_holder *hdr_off_holder =
+ mp_impl->priv_first_subblock_from_block(container_detail::to_raw_pointer(to_deallocate));
+ m_chain.push_back(hdr_off_holder);
}
const this_type *mp_impl;
+ multiallocation_chain &m_chain;
};
//This macro will activate invariant checking. Slow, but helpful for debugging the code.
@@ -447,44 +635,45 @@ class private_adaptive_node_pool_impl
#ifdef BOOST_CONTAINER_ADAPTIVE_NODE_POOL_CHECK_INVARIANTS
#undef BOOST_CONTAINER_ADAPTIVE_NODE_POOL_CHECK_INVARIANTS
{
- //We iterate through the block tree to free the memory
- block_iterator it(m_block_multiset.begin()),
- itend(m_block_multiset.end()), to_deallocate;
- if(it != itend){
- for(++it; it != itend; ++it){
- block_iterator prev(it);
- --prev;
- size_type sp = prev->free_nodes.size(),
- si = it->free_nodes.size();
- BOOST_ASSERT(sp <= si);
- (void)sp; (void)si;
+ const const_block_iterator itend(m_block_container.end());
+
+ { //We iterate through the block tree to free the memory
+ const_block_iterator it(m_block_container.begin());
+
+ if(it != itend){
+ for(++it; it != itend; ++it){
+ const_block_iterator prev(it);
+ --prev;
+ BOOST_ASSERT(*prev < *it);
+ (void)prev; (void)it;
+ }
}
}
- //Check that the total free nodes are correct
- it = m_block_multiset.begin();
- itend = m_block_multiset.end();
- size_type total_free_nodes = 0;
- for(; it != itend; ++it){
- total_free_nodes += it->free_nodes.size();
+ { //Check that the total free nodes are correct
+ const_block_iterator it(m_block_container.cbegin());
+ size_type total_free_nodes = 0;
+ for(; it != itend; ++it){
+ total_free_nodes += it->free_nodes.size();
+ }
+ BOOST_ASSERT(total_free_nodes >= m_totally_free_blocks*m_real_num_node);
}
- BOOST_ASSERT(total_free_nodes >= m_totally_free_blocks*m_real_num_node);
-
- //Check that the total totally free blocks are correct
- it = m_block_multiset.begin();
- itend = m_block_multiset.end();
- total_free = 0;
- for(; it != itend; ++it){
- total_free += it->free_nodes.size() == m_real_num_node;
+ { //Check that the total totally free blocks are correct
+ BOOST_ASSERT(m_block_container.size() >= m_totally_free_blocks);
+ const_block_iterator it = m_block_container.cend();
+ size_type total_free_blocks = m_totally_free_blocks;
+ while(total_free_blocks--){
+ BOOST_ASSERT((--it)->free_nodes.size() == m_real_num_node);
+ }
}
- BOOST_ASSERT(total_free >= m_totally_free_blocks);
if(!AlignOnly){
//Check that header offsets are correct
- it = m_block_multiset.begin();
+ const_block_iterator it = m_block_container.begin();
for(; it != itend; ++it){
- hdr_offset_holder *hdr_off_holder = priv_first_subblock_from_block(&*it);
+ hdr_offset_holder *hdr_off_holder = this->priv_first_subblock_from_block(const_cast<block_info_t *>(&*it));
for(size_type i = 0, max = m_num_subblocks; i < max; ++i){
- BOOST_ASSERT(hdr_off_holder->hdr_offset == size_type(reinterpret_cast<char*>(&*it)- reinterpret_cast<char*>(hdr_off_holder)));
+ const size_type offset = reinterpret_cast<char*>(const_cast<block_info_t *>(&*it)) - reinterpret_cast<char*>(hdr_off_holder);
+ BOOST_ASSERT(hdr_off_holder->hdr_offset == offset);
BOOST_ASSERT(0 == ((size_type)hdr_off_holder & (m_real_block_alignment - 1)));
BOOST_ASSERT(0 == (hdr_off_holder->hdr_offset & (m_real_block_alignment - 1)));
hdr_off_holder = reinterpret_cast<hdr_offset_holder *>(reinterpret_cast<char*>(hdr_off_holder) + m_real_block_alignment);
@@ -500,19 +689,21 @@ class private_adaptive_node_pool_impl
void priv_clear()
{
#ifndef NDEBUG
- block_iterator it = m_block_multiset.begin();
- block_iterator itend = m_block_multiset.end();
- size_type num_free_nodes = 0;
+ 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() == m_real_num_node);
- ++num_free_nodes;
+ ++n_free_nodes;
}
- BOOST_ASSERT(num_free_nodes == m_totally_free_blocks);
+ BOOST_ASSERT(n_free_nodes == m_totally_free_blocks);
#endif
//Check for memory leaks
- priv_invariants();
- m_block_multiset.clear_and_dispose(block_destroyer(this));
+ this->priv_invariants();
+ multiallocation_chain chain;
+ m_block_container.clear_and_dispose(block_destroyer(this, chain));
+ this->mp_segment_mngr_base->deallocate_many(chain);
m_totally_free_blocks = 0;
}
@@ -534,93 +725,129 @@ class private_adaptive_node_pool_impl
}
block_info_t *priv_block_from_node(void *node) const
- { return priv_block_from_node(node, IsAlignOnly()); }
+ { return this->priv_block_from_node(node, IsAlignOnly()); }
hdr_offset_holder *priv_first_subblock_from_block(block_info_t *block) const
+ { return this->priv_first_subblock_from_block(block, IsAlignOnly()); }
+
+ hdr_offset_holder *priv_first_subblock_from_block(block_info_t *block, AlignOnlyFalse) const
{
- hdr_offset_holder *hdr_off_holder = reinterpret_cast<hdr_offset_holder*>
+ hdr_offset_holder *const hdr_off_holder = reinterpret_cast<hdr_offset_holder*>
(reinterpret_cast<char*>(block) - (m_num_subblocks-1)*m_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 & (m_real_block_alignment - 1)));
+ BOOST_ASSERT(0 == ((std::size_t)hdr_off_holder & (m_real_block_alignment - 1)));
BOOST_ASSERT(0 == (hdr_off_holder->hdr_offset & (m_real_block_alignment - 1)));
return hdr_off_holder;
}
+ hdr_offset_holder *priv_first_subblock_from_block(block_info_t *block, AlignOnlyTrue) const
+ {
+ return reinterpret_cast<hdr_offset_holder*>(block);
+ }
+
+ void priv_dispatch_block_chain_or_free
+ ( multiallocation_chain &chain, block_info_t &c_info, size_type num_node
+ , char *mem_address, size_type total_elements, bool insert_block_if_free)
+ {
+ BOOST_ASSERT(chain.size() <= total_elements);
+ //First add all possible nodes to the chain
+ const size_type left = total_elements - chain.size();
+ const size_type max_chain = (num_node < left) ? num_node : left;
+ mem_address = static_cast<char *>(container_detail::to_raw_pointer
+ (chain.incorporate_after(chain.last(), void_pointer(mem_address), m_real_node_size, max_chain)));
+ //Now store remaining nodes in the free list
+ if(const size_type max_free = num_node - max_chain){
+ free_nodes_t & free_nodes = c_info.free_nodes;
+ free_nodes.incorporate_after(free_nodes.last(), void_pointer(mem_address), m_real_node_size, max_free);
+ if(insert_block_if_free){
+ m_block_container.push_front(c_info);
+ }
+ }
+ }
+
//!Allocates a several blocks of nodes. Can throw
- void priv_alloc_block(size_type n, AlignOnlyTrue)
+ void priv_append_from_new_blocks(size_type min_elements, multiallocation_chain &chain, AlignOnlyTrue)
{
- size_type real_block_size = m_real_block_alignment - PayloadPerAllocation;
+ BOOST_ASSERT(m_block_container.empty());
+ BOOST_ASSERT(min_elements > 0);
+ const size_type n = (min_elements - 1)/m_real_num_node + 1;
+ const size_type real_block_size = m_real_block_alignment - PayloadPerAllocation;
+ const size_type total_elements = 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, m_real_block_alignment));
- if(!mem_address) throw std::bad_alloc();
- ++m_totally_free_blocks;
- block_info_t *c_info = new(mem_address)block_info_t();
- m_block_multiset.insert(m_block_multiset.end(), *c_info);
-
+ 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->deallocate_nodes(chain);
+ throw_bad_alloc();
+ }
+ block_info_t &c_info = *new(mem_address)block_info_t();
mem_address += HdrSize;
- //We initialize all Nodes in Node Block to insert
- //them in the free Node list
- typename free_nodes_t::iterator prev_insert_pos = c_info->free_nodes.before_begin();
- for(size_type i = 0; i < m_real_num_node; ++i){
- prev_insert_pos = c_info->free_nodes.insert_after(prev_insert_pos, *(node_t*)mem_address);
- mem_address += m_real_node_size;
+ if(i != (n-1)){
+ chain.incorporate_after(chain.last(), void_pointer(mem_address), m_real_node_size, m_real_num_node);
+ }
+ else{
+ this->priv_dispatch_block_chain_or_free(chain, c_info, m_real_num_node, mem_address, total_elements, true);
}
}
}
- void priv_alloc_block(size_type n, AlignOnlyFalse)
+ void priv_append_from_new_blocks(size_type min_elements, multiallocation_chain &chain, AlignOnlyFalse)
{
- size_type real_block_size = m_real_block_alignment*m_num_subblocks - PayloadPerAllocation;
- size_type elements_per_subblock = (m_real_block_alignment - HdrOffsetSize)/m_real_node_size;
- size_type hdr_subblock_elements = (m_real_block_alignment - HdrSize - PayloadPerAllocation)/m_real_node_size;
+ BOOST_ASSERT(m_block_container.empty());
+ BOOST_ASSERT(min_elements > 0);
+ const size_type n = (min_elements - 1)/m_real_num_node + 1;
+ const size_type real_block_size = m_real_block_alignment*m_num_subblocks - PayloadPerAllocation;
+ const size_type elements_per_subblock = (m_real_block_alignment - HdrOffsetSize)/m_real_node_size;
+ const size_type hdr_subblock_elements = (m_real_block_alignment - HdrSize - PayloadPerAllocation)/m_real_node_size;
+ const size_type total_elements = 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, m_real_block_alignment));
- if(!mem_address) throw std::bad_alloc();
- ++m_totally_free_blocks;
-
+ 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->deallocate_nodes(chain);
+ throw_bad_alloc();
+ }
//First initialize header information on the last subblock
char *hdr_addr = mem_address + m_real_block_alignment*(m_num_subblocks-1);
- block_info_t *c_info = new(hdr_addr)block_info_t();
+ 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));
- typename free_nodes_t::iterator prev_insert_pos = c_info->free_nodes.before_begin();
- for( size_type subblock = 0, maxsubblock = m_num_subblocks - 1
- ; subblock < maxsubblock
- ; ++subblock, mem_address += m_real_block_alignment){
- //Initialize header offset mark
- new(mem_address) hdr_offset_holder(size_type(hdr_addr - mem_address));
- char *pNode = mem_address + HdrOffsetSize;
- for(size_type i = 0; i < elements_per_subblock; ++i){
- prev_insert_pos = c_info->free_nodes.insert_after(prev_insert_pos, *new (pNode) node_t);
- pNode += m_real_node_size;
+ BOOST_ASSERT(static_cast<void*>(&static_cast<hdr_offset_holder&>(c_info).hdr_offset) ==
+ static_cast<void*>(&c_info)); (void)c_info;
+ if(i != (n-1)){
+ for( size_type subblock = 0, maxsubblock = m_num_subblocks - 1
+ ; subblock < maxsubblock
+ ; ++subblock, mem_address += m_real_block_alignment){
+ //Initialize header offset mark
+ new(mem_address) hdr_offset_holder(size_type(hdr_addr - mem_address));
+ chain.incorporate_after
+ (chain.last(), void_pointer(mem_address + HdrOffsetSize), m_real_node_size, elements_per_subblock);
}
+ chain.incorporate_after(chain.last(), void_pointer(hdr_addr + HdrSize), m_real_node_size, hdr_subblock_elements);
}
- {
- char *pNode = hdr_addr + HdrSize;
- //We initialize all Nodes in Node Block to insert
- //them in the free Node list
- for(size_type i = 0; i < hdr_subblock_elements; ++i){
- prev_insert_pos = c_info->free_nodes.insert_after(prev_insert_pos, *new (pNode) node_t);
- pNode += m_real_node_size;
+ else{
+ for( size_type subblock = 0, maxsubblock = m_num_subblocks - 1
+ ; subblock < maxsubblock
+ ; ++subblock, mem_address += m_real_block_alignment){
+ //Initialize header offset mark
+ new(mem_address) hdr_offset_holder(size_type(hdr_addr - mem_address));
+ this->priv_dispatch_block_chain_or_free
+ (chain, c_info, elements_per_subblock, mem_address + HdrOffsetSize, total_elements, false);
}
+ this->priv_dispatch_block_chain_or_free
+ (chain, c_info, hdr_subblock_elements, hdr_addr + HdrSize, total_elements, true);
}
- //Insert the block after the free node list is full
- m_block_multiset.insert(m_block_multiset.end(), *c_info);
}
}
- //!Allocates a block of nodes. Can throw std::bad_alloc
- void priv_alloc_block(size_type n)
- { return priv_alloc_block(n, IsAlignOnly()); }
-
private:
typedef typename boost::intrusive::pointer_traits
<void_pointer>::template rebind_pointer<segment_manager_base_type>::type segment_mngr_base_ptr_t;
@@ -634,9 +861,9 @@ class private_adaptive_node_pool_impl
//This is the real number of nodes per block
//const
size_type m_real_num_node;
- segment_mngr_base_ptr_t mp_segment_mngr_base; //Segment manager
- block_multiset_t m_block_multiset; //Intrusive block list
- size_type m_totally_free_blocks; //Free blocks
+ 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
};
} //namespace container_detail {
diff --git a/boost/container/detail/advanced_insert_int.hpp b/boost/container/detail/advanced_insert_int.hpp
index a97af282e0..a35279dcf7 100644
--- a/boost/container/detail/advanced_insert_int.hpp
+++ b/boost/container/detail/advanced_insert_int.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost
+// (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)
//
@@ -11,170 +11,198 @@
#ifndef BOOST_CONTAINER_ADVANCED_INSERT_INT_HPP
#define BOOST_CONTAINER_ADVANCED_INSERT_INT_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
-#include "config_begin.hpp"
+#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
+
#include <boost/container/allocator_traits.hpp>
#include <boost/container/detail/destroyers.hpp>
#include <boost/aligned_storage.hpp>
-#include <boost/move/move.hpp>
+#include <boost/move/utility_core.hpp>
+#include <boost/container/detail/mpl.hpp>
+#include <boost/container/detail/utilities.hpp>
+#include <boost/container/detail/type_traits.hpp>
+#include <boost/container/detail/iterators.hpp>
#include <iterator> //std::iterator_traits
#include <boost/assert.hpp>
+#include <boost/core/no_exceptions_support.hpp>
namespace boost { namespace container { namespace container_detail {
-//This class will be interface for operations dependent on FwdIt types used advanced_insert_aux_impl
-template<class Iterator>
-struct advanced_insert_aux_int
+template<class A, class FwdIt, class Iterator>
+struct move_insert_range_proxy
{
- typedef typename std::iterator_traits<Iterator>::difference_type difference_type;
- virtual void copy_remaining_to(Iterator p) = 0;
- virtual void uninitialized_copy_remaining_to(Iterator p) = 0;
- virtual void uninitialized_copy_some_and_update(Iterator pos, difference_type division_count, bool first) = 0;
- virtual void copy_some_and_update(Iterator pos, difference_type division_count, bool first) = 0;
- virtual ~advanced_insert_aux_int() {}
+ typedef typename allocator_traits<A>::size_type size_type;
+ typedef typename allocator_traits<A>::value_type value_type;
+
+ explicit move_insert_range_proxy(FwdIt first)
+ : first_(first)
+ {}
+
+ void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n)
+ {
+ this->first_ = ::boost::container::uninitialized_move_alloc_n_source
+ (a, this->first_, n, p);
+ }
+
+ void copy_n_and_update(A &, Iterator p, size_type n)
+ {
+ this->first_ = ::boost::container::move_n_source(this->first_, n, p);
+ }
+
+ FwdIt first_;
};
-//This class template will adapt each FwIt types to advanced_insert_aux_int
+
template<class A, class FwdIt, class Iterator>
-struct advanced_insert_aux_proxy
- : public advanced_insert_aux_int<Iterator>
+struct insert_range_proxy
{
typedef typename allocator_traits<A>::size_type size_type;
typedef typename allocator_traits<A>::value_type value_type;
- typedef typename advanced_insert_aux_int<Iterator>::difference_type difference_type;
-
- advanced_insert_aux_proxy(A& a, FwdIt first, FwdIt last)
- : a_(a), first_(first), last_(last)
- {}
- virtual ~advanced_insert_aux_proxy()
+ explicit insert_range_proxy(FwdIt first)
+ : first_(first)
{}
- virtual void copy_remaining_to(Iterator p)
- { ::boost::copy_or_move(this->first_, this->last_, p); }
-
- virtual void uninitialized_copy_remaining_to(Iterator p)
- { ::boost::container::uninitialized_copy_or_move_alloc(this->a_, this->first_, this->last_, p); }
+ void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n)
+ {
+ this->first_ = ::boost::container::uninitialized_copy_alloc_n_source(a, this->first_, n, p);
+ }
- virtual void uninitialized_copy_some_and_update(Iterator pos, difference_type division_count, bool first_n)
+ void copy_n_and_update(A &, Iterator p, size_type n)
{
- FwdIt mid = this->first_;
- std::advance(mid, division_count);
- if(first_n){
- ::boost::container::uninitialized_copy_or_move_alloc(this->a_, this->first_, mid, pos);
- this->first_ = mid;
- }
- else{
- ::boost::container::uninitialized_copy_or_move_alloc(this->a_, mid, this->last_, pos);
- this->last_ = mid;
- }
+ this->first_ = ::boost::container::copy_n_source(this->first_, n, p);
}
- virtual void copy_some_and_update(Iterator pos, difference_type division_count, bool first_n)
+ FwdIt first_;
+};
+
+
+template<class A, class Iterator>
+struct insert_n_copies_proxy
+{
+ typedef typename allocator_traits<A>::size_type size_type;
+ typedef typename allocator_traits<A>::value_type value_type;
+
+ explicit insert_n_copies_proxy(const value_type &v)
+ : v_(v)
+ {}
+
+ void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n) const
+ { boost::container::uninitialized_fill_alloc_n(a, v_, n, p); }
+
+ void copy_n_and_update(A &, Iterator p, size_type n) const
{
- FwdIt mid = this->first_;
- std::advance(mid, division_count);
- if(first_n){
- ::boost::copy_or_move(this->first_, mid, pos);
- this->first_ = mid;
- }
- else{
- ::boost::copy_or_move(mid, this->last_, pos);
- this->last_ = mid;
+ for (; 0 < n; --n, ++p){
+ *p = v_;
}
}
- A &a_;
- FwdIt first_, last_;
+
+ const value_type &v_;
};
-//This class template will adapt default construction insertions to advanced_insert_aux_int
template<class A, class Iterator>
-struct default_construct_aux_proxy
- : public advanced_insert_aux_int<Iterator>
+struct insert_value_initialized_n_proxy
{
typedef ::boost::container::allocator_traits<A> alloc_traits;
typedef typename allocator_traits<A>::size_type size_type;
typedef typename allocator_traits<A>::value_type value_type;
- typedef typename advanced_insert_aux_int<Iterator>::difference_type difference_type;
- default_construct_aux_proxy(A &a, size_type count)
- : a_(a), count_(count)
- {}
+ void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n) const
+ { boost::container::uninitialized_value_init_alloc_n(a, n, p); }
+
+ void copy_n_and_update(A &, Iterator, size_type) const
+ { BOOST_ASSERT(false); }
+};
- virtual ~default_construct_aux_proxy()
+template<class A, class Iterator>
+struct insert_default_initialized_n_proxy
+{
+ typedef ::boost::container::allocator_traits<A> alloc_traits;
+ typedef typename allocator_traits<A>::size_type size_type;
+ typedef typename allocator_traits<A>::value_type value_type;
+
+ void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n) const
+ { boost::container::uninitialized_default_init_alloc_n(a, n, p); }
+
+ void copy_n_and_update(A &, Iterator, size_type) const
+ { BOOST_ASSERT(false); }
+};
+
+template<class A, class Iterator>
+struct insert_copy_proxy
+{
+ typedef boost::container::allocator_traits<A> alloc_traits;
+ typedef typename alloc_traits::size_type size_type;
+ typedef typename alloc_traits::value_type value_type;
+
+ explicit insert_copy_proxy(const value_type &v)
+ : v_(v)
{}
- virtual void copy_remaining_to(Iterator)
- { //This should never be called with any count
- BOOST_ASSERT(this->count_ == 0);
+ void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n) const
+ {
+ BOOST_ASSERT(n == 1); (void)n;
+ alloc_traits::construct( a, iterator_to_raw_pointer(p), v_);
}
- virtual void uninitialized_copy_remaining_to(Iterator p)
- { this->priv_uninitialized_copy(p, this->count_); }
-
- virtual void uninitialized_copy_some_and_update(Iterator pos, difference_type division_count, bool first_n)
+ void copy_n_and_update(A &, Iterator p, size_type n) const
{
- size_type new_count;
- if(first_n){
- new_count = division_count;
- }
- else{
- BOOST_ASSERT(difference_type(this->count_)>= division_count);
- new_count = this->count_ - division_count;
- }
- this->priv_uninitialized_copy(pos, new_count);
+ BOOST_ASSERT(n == 1); (void)n;
+ *p =v_;
}
- virtual void copy_some_and_update(Iterator , difference_type division_count, bool first_n)
+ const value_type &v_;
+};
+
+
+template<class A, class Iterator>
+struct insert_move_proxy
+{
+ typedef boost::container::allocator_traits<A> alloc_traits;
+ typedef typename alloc_traits::size_type size_type;
+ typedef typename alloc_traits::value_type value_type;
+
+ explicit insert_move_proxy(value_type &v)
+ : v_(v)
+ {}
+
+ void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n) const
{
- BOOST_ASSERT(this->count_ == 0);
- size_type new_count;
- if(first_n){
- new_count = division_count;
- }
- else{
- BOOST_ASSERT(difference_type(this->count_)>= division_count);
- new_count = this->count_ - division_count;
- }
- //This function should never called with a count different to zero
- BOOST_ASSERT(new_count == 0);
- (void)new_count;
+ BOOST_ASSERT(n == 1); (void)n;
+ alloc_traits::construct( a, iterator_to_raw_pointer(p), ::boost::move(v_) );
}
- private:
- void priv_uninitialized_copy(Iterator p, const size_type n)
+ void copy_n_and_update(A &, Iterator p, size_type n) const
{
- BOOST_ASSERT(n <= this->count_);
- Iterator orig_p = p;
- size_type i = 0;
- try{
- for(; i < n; ++i, ++p){
- alloc_traits::construct(this->a_, container_detail::to_raw_pointer(&*p));
- }
- }
- catch(...){
- while(i--){
- alloc_traits::destroy(this->a_, container_detail::to_raw_pointer(&*orig_p++));
- }
- throw;
- }
- this->count_ -= n;
+ BOOST_ASSERT(n == 1); (void)n;
+ *p = ::boost::move(v_);
}
- A &a_;
- size_type count_;
+
+ value_type &v_;
};
+template<class It, class A>
+insert_move_proxy<A, It> get_insert_value_proxy(BOOST_RV_REF(typename std::iterator_traits<It>::value_type) v)
+{
+ return insert_move_proxy<A, It>(v);
+}
+
+template<class It, class A>
+insert_copy_proxy<A, It> get_insert_value_proxy(const typename std::iterator_traits<It>::value_type &v)
+{
+ return insert_copy_proxy<A, It>(v);
+}
+
}}} //namespace boost { namespace container { namespace container_detail {
#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
#include <boost/container/detail/variadic_templates_tools.hpp>
-#include <boost/container/detail/stored_ref.hpp>
-#include <boost/move/move.hpp>
+#include <boost/move/utility_core.hpp>
#include <typeinfo>
//#include <iostream> //For debugging purposes
@@ -182,143 +210,117 @@ namespace boost {
namespace container {
namespace container_detail {
-
-//This class template will adapt emplace construction insertions of movable types
-//to advanced_insert_aux_int
template<class A, class Iterator, class ...Args>
-struct advanced_insert_aux_non_movable_emplace
- : public advanced_insert_aux_int<Iterator>
+struct insert_non_movable_emplace_proxy
{
- typedef boost::container::allocator_traits<A> alloc_traits;
- typedef typename allocator_traits<A>::size_type size_type;
- typedef typename allocator_traits<A>::value_type value_type;
- typedef typename advanced_insert_aux_int<Iterator>::difference_type difference_type;
- typedef typename build_number_seq<sizeof...(Args)>::type index_tuple_t;
+ typedef boost::container::allocator_traits<A> alloc_traits;
+ typedef typename alloc_traits::size_type size_type;
+ typedef typename alloc_traits::value_type value_type;
- explicit advanced_insert_aux_non_movable_emplace(A &a, Args&&... args)
- : a_(a)
- , args_(args...)
- , used_(false)
- {}
+ typedef typename build_number_seq<sizeof...(Args)>::type index_tuple_t;
- ~advanced_insert_aux_non_movable_emplace()
+ explicit insert_non_movable_emplace_proxy(Args&&... args)
+ : args_(args...)
{}
- virtual void copy_remaining_to(Iterator)
- //This code can't be called since value_type is not movable or copyable
- { BOOST_ASSERT(false); }
-
- virtual void uninitialized_copy_remaining_to(Iterator p)
- { this->priv_uninitialized_copy_remaining_to(index_tuple_t(), p); }
-
- virtual void uninitialized_copy_some_and_update(Iterator p, difference_type division_count, bool first_n)
- { this->priv_uninitialized_copy_some_and_update(index_tuple_t(), p, division_count, first_n); }
-
- virtual void copy_some_and_update(Iterator, difference_type, bool )
- //This code can't be called since value_type is not movable or copyable
- { BOOST_ASSERT(false); }
+ void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n)
+ { this->priv_uninitialized_copy_some_and_update(a, index_tuple_t(), p, n); }
private:
template<int ...IdxPack>
- void priv_uninitialized_copy_some_and_update(const index_tuple<IdxPack...>&, Iterator p, difference_type division_count, bool first_n)
+ void priv_uninitialized_copy_some_and_update(A &a, const index_tuple<IdxPack...>&, Iterator p, size_type n)
{
- BOOST_ASSERT(division_count <=1);
- if((first_n && division_count == 1) || (!first_n && division_count == 0)){
- if(!this->used_){
- alloc_traits::construct( this->a_
- , container_detail::to_raw_pointer(&*p)
- , ::boost::container::container_detail::
- stored_ref<Args>::forward(get<IdxPack>(this->args_))...
- );
- this->used_ = true;
- }
- }
- }
-
- template<int ...IdxPack>
- void priv_uninitialized_copy_remaining_to(const index_tuple<IdxPack...>&, Iterator p)
- {
- if(!this->used_){
- alloc_traits::construct( this->a_
- , container_detail::to_raw_pointer(&*p)
- , ::boost::container::container_detail::
- stored_ref<Args>::forward(get<IdxPack>(this->args_))...
- );
- this->used_ = true;
- }
+ BOOST_ASSERT(n == 1); (void)n;
+ alloc_traits::construct( a, iterator_to_raw_pointer(p), ::boost::forward<Args>(get<IdxPack>(this->args_))... );
}
protected:
- A &a_;
tuple<Args&...> args_;
- bool used_;
};
-//This class template will adapt emplace construction insertions of movable types
-//to advanced_insert_aux_int
template<class A, class Iterator, class ...Args>
-struct advanced_insert_aux_emplace
- : public advanced_insert_aux_non_movable_emplace<A, Iterator, Args...>
+struct insert_emplace_proxy
+ : public insert_non_movable_emplace_proxy<A, Iterator, Args...>
{
- typedef advanced_insert_aux_non_movable_emplace<A, Iterator, Args...> base_t;
- typedef boost::container::allocator_traits<A> alloc_traits;
- typedef typename base_t::value_type value_type;
- typedef typename base_t::difference_type difference_type;
- typedef typename base_t::index_tuple_t index_tuple_t;
-
- explicit advanced_insert_aux_emplace(A &a, Args&&... args)
- : base_t(a, ::boost::forward<Args>(args)...)
+ typedef insert_non_movable_emplace_proxy<A, Iterator, Args...> base_t;
+ typedef boost::container::allocator_traits<A> alloc_traits;
+ typedef typename base_t::value_type value_type;
+ typedef typename base_t::size_type size_type;
+ typedef typename base_t::index_tuple_t index_tuple_t;
+
+ explicit insert_emplace_proxy(Args&&... args)
+ : base_t(::boost::forward<Args>(args)...)
{}
- ~advanced_insert_aux_emplace()
- {}
-
- //Override only needed functions
- virtual void copy_remaining_to(Iterator p)
- { this->priv_copy_remaining_to(index_tuple_t(), p); }
-
- virtual void copy_some_and_update(Iterator p, difference_type division_count, bool first_n)
- { this->priv_copy_some_and_update(index_tuple_t(), p, division_count, first_n); }
+ void copy_n_and_update(A &a, Iterator p, size_type n)
+ { this->priv_copy_some_and_update(a, index_tuple_t(), p, n); }
private:
+
template<int ...IdxPack>
- void priv_copy_remaining_to(const index_tuple<IdxPack...>&, Iterator p)
+ void priv_copy_some_and_update(A &a, const index_tuple<IdxPack...>&, Iterator p, size_type n)
{
- if(!this->used_){
- aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v;
- value_type *vp = static_cast<value_type *>(static_cast<void *>(&v));
- alloc_traits::construct(this->a_, vp,
- ::boost::container::container_detail::stored_ref<Args>::forward(get<IdxPack>(this->args_))...);
- scoped_destructor<A> d(this->a_, vp);
+ BOOST_ASSERT(n ==1); (void)n;
+ aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v;
+ value_type *vp = static_cast<value_type *>(static_cast<void *>(&v));
+ alloc_traits::construct(a, vp,
+ ::boost::forward<Args>(get<IdxPack>(this->args_))...);
+ BOOST_TRY{
*p = ::boost::move(*vp);
- d.release();
- this->used_ = true;
}
- }
-
- template<int ...IdxPack>
- void priv_copy_some_and_update(const index_tuple<IdxPack...>&, Iterator p, difference_type division_count, bool first_n)
- {
- BOOST_ASSERT(division_count <=1);
- if((first_n && division_count == 1) || (!first_n && division_count == 0)){
- if(!this->used_){
- aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v;
- value_type *vp = static_cast<value_type *>(static_cast<void *>(&v));
- alloc_traits::construct(this->a_, vp,
- ::boost::container::container_detail::stored_ref<Args>::forward(get<IdxPack>(this->args_))...);
- try {
- *p = ::boost::move(*vp);
- } catch (...) {
- alloc_traits::destroy(this->a_, vp);
- throw;
- }
- alloc_traits::destroy(this->a_, vp);
- this->used_ = true;
- }
+ 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 A, class Iterator>
+struct insert_emplace_proxy<A, Iterator, typename boost::container::allocator_traits<A>::value_type>
+ : public insert_move_proxy<A, Iterator>
+{
+ explicit insert_emplace_proxy(typename boost::container::allocator_traits<A>::value_type &&v)
+ : insert_move_proxy<A, 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 A, class Iterator>
+struct insert_emplace_proxy<A, Iterator
+ , typename boost::container::container_detail::add_const<typename boost::container::allocator_traits<A>::value_type>::type
+ >
+ : public insert_copy_proxy<A, Iterator>
+{
+ explicit insert_emplace_proxy(const typename boost::container::allocator_traits<A>::value_type &v)
+ : insert_copy_proxy<A, Iterator>(v)
+ {}
+};
+
+template<class A, class Iterator>
+struct insert_emplace_proxy<A, Iterator, typename boost::container::allocator_traits<A>::value_type &>
+ : public insert_copy_proxy<A, Iterator>
+{
+ explicit insert_emplace_proxy(const typename boost::container::allocator_traits<A>::value_type &v)
+ : insert_copy_proxy<A, Iterator>(v)
+ {}
+};
+
+template<class A, class Iterator>
+struct insert_emplace_proxy<A, Iterator
+ , typename boost::container::container_detail::add_const<typename boost::container::allocator_traits<A>::value_type>::type &
+ >
+ : public insert_copy_proxy<A, Iterator>
+{
+ explicit insert_emplace_proxy(const typename boost::container::allocator_traits<A>::value_type &v)
+ : insert_copy_proxy<A, Iterator>(v)
+ {}
+};
+
}}} //namespace boost { namespace container { namespace container_detail {
#else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
@@ -330,118 +332,142 @@ namespace boost {
namespace container {
namespace container_detail {
-#define BOOST_PP_LOCAL_MACRO(n) \
-template<class A, class Iterator BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) > \
-struct BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_non_movable_emplace, n), arg) \
- : public advanced_insert_aux_int<Iterator> \
+#define BOOST_PP_LOCAL_MACRO(N) \
+template<class A, class Iterator BOOST_PP_ENUM_TRAILING_PARAMS(N, class P) > \
+struct BOOST_PP_CAT(insert_non_movable_emplace_proxy_arg, N) \
{ \
typedef boost::container::allocator_traits<A> alloc_traits; \
- typedef typename allocator_traits<A>::size_type size_type; \
- typedef typename allocator_traits<A>::value_type value_type; \
- typedef typename advanced_insert_aux_int<Iterator>::difference_type \
- difference_type; \
+ typedef typename alloc_traits::size_type size_type; \
+ typedef typename alloc_traits::value_type value_type; \
\
- BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_non_movable_emplace, n), arg) \
- ( A &a BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _) ) \
- : a_(a) \
- , used_(false) \
- BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_INIT, _) \
- {} \
+ explicit BOOST_PP_CAT(insert_non_movable_emplace_proxy_arg, N) \
+ ( BOOST_PP_ENUM(N, BOOST_CONTAINER_PP_PARAM_LIST, _) ) \
+ BOOST_PP_EXPR_IF(N, :) BOOST_PP_ENUM(N, BOOST_CONTAINER_PP_PARAM_INIT, _) \
+ {} \
\
- virtual void copy_remaining_to(Iterator) \
- { BOOST_ASSERT(false); } \
- \
- virtual void uninitialized_copy_remaining_to(Iterator p) \
+ void uninitialized_copy_n_and_update(A &a, Iterator p, size_type n) \
{ \
- if(!this->used_){ \
- alloc_traits::construct \
- ( this->a_ \
- , container_detail::to_raw_pointer(&*p) \
- BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_MEMBER_FORWARD, _) \
- ); \
- this->used_ = true; \
- } \
+ BOOST_ASSERT(n == 1); (void)n; \
+ alloc_traits::construct \
+ ( a, iterator_to_raw_pointer(p) \
+ BOOST_PP_ENUM_TRAILING(N, BOOST_CONTAINER_PP_MEMBER_FORWARD, _) \
+ ); \
} \
\
- virtual void uninitialized_copy_some_and_update \
- (Iterator p, difference_type division_count, bool first_n) \
- { \
- BOOST_ASSERT(division_count <=1); \
- if((first_n && division_count == 1) || (!first_n && division_count == 0)){ \
- if(!this->used_){ \
- alloc_traits::construct \
- ( this->a_ \
- , container_detail::to_raw_pointer(&*p) \
- BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_MEMBER_FORWARD, _) \
- ); \
- this->used_ = true; \
- } \
- } \
- } \
- \
- virtual void copy_some_and_update(Iterator, difference_type, bool) \
+ void copy_n_and_update(A &, Iterator, size_type) \
{ BOOST_ASSERT(false); } \
\
- A &a_; \
- bool used_; \
- BOOST_PP_REPEAT(n, BOOST_CONTAINER_PP_PARAM_DEFINE, _) \
+ protected: \
+ BOOST_PP_REPEAT(N, BOOST_CONTAINER_PP_PARAM_DEFINE, _) \
}; \
\
-template<class A, class Iterator BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) > \
-struct BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \
- : BOOST_PP_CAT(BOOST_PP_CAT( \
- advanced_insert_aux_non_movable_emplace, n), arg) \
- < A, Iterator BOOST_PP_ENUM_TRAILING_PARAMS(n, P) > \
+template<class A, class Iterator BOOST_PP_ENUM_TRAILING_PARAMS(N, class P) > \
+struct BOOST_PP_CAT(insert_emplace_proxy_arg, N) \
+ : BOOST_PP_CAT(insert_non_movable_emplace_proxy_arg, N) \
+ < A, Iterator BOOST_PP_ENUM_TRAILING_PARAMS(N, P) > \
{ \
- typedef BOOST_PP_CAT(BOOST_PP_CAT( \
- advanced_insert_aux_non_movable_emplace, n), arg) \
- <A, Iterator BOOST_PP_ENUM_TRAILING_PARAMS(n, P) > base_t; \
+ typedef BOOST_PP_CAT(insert_non_movable_emplace_proxy_arg, N) \
+ <A, Iterator BOOST_PP_ENUM_TRAILING_PARAMS(N, P) > base_t; \
typedef typename base_t::value_type value_type; \
- typedef typename base_t::difference_type difference_type; \
+ typedef typename base_t::size_type size_type; \
typedef boost::container::allocator_traits<A> alloc_traits; \
\
- BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \
- ( A &a BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _) ) \
- : base_t(a BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ) \
- {} \
+ explicit BOOST_PP_CAT(insert_emplace_proxy_arg, N) \
+ ( BOOST_PP_ENUM(N, BOOST_CONTAINER_PP_PARAM_LIST, _) ) \
+ : base_t(BOOST_PP_ENUM(N, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ) \
+ {} \
\
- virtual void copy_remaining_to(Iterator p) \
+ void copy_n_and_update(A &a, Iterator p, size_type n) \
{ \
- if(!this->used_){ \
- aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v; \
- value_type *vp = static_cast<value_type *>(static_cast<void *>(&v)); \
- alloc_traits::construct(this->a_, vp \
- BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_MEMBER_FORWARD, _)); \
- scoped_destructor<A> d(this->a_, vp); \
- *p = ::boost::move(*vp); \
- d.release(); \
- this->used_ = true; \
+ BOOST_ASSERT(n == 1); (void)n; \
+ aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v; \
+ value_type *vp = static_cast<value_type *>(static_cast<void *>(&v)); \
+ alloc_traits::construct(a, vp \
+ BOOST_PP_ENUM_TRAILING(N, BOOST_CONTAINER_PP_MEMBER_FORWARD, _)); \
+ BOOST_TRY{ \
+ *p = ::boost::move(*vp); \
} \
- } \
- \
- virtual void copy_some_and_update \
- (Iterator p, difference_type division_count, bool first_n) \
- { \
- BOOST_ASSERT(division_count <=1); \
- if((first_n && division_count == 1) || (!first_n && division_count == 0)){ \
- if(!this->used_){ \
- aligned_storage<sizeof(value_type), alignment_of<value_type>::value> v; \
- value_type *vp = static_cast<value_type *>(static_cast<void *>(&v)); \
- alloc_traits::construct(this->a_, vp \
- BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_MEMBER_FORWARD, _)); \
- scoped_destructor<A> d(this->a_, vp); \
- *p = ::boost::move(*vp); \
- d.release(); \
- this->used_ = true; \
- } \
+ BOOST_CATCH(...){ \
+ alloc_traits::destroy(a, vp); \
+ BOOST_RETHROW \
} \
+ BOOST_CATCH_END \
+ alloc_traits::destroy(a, vp); \
} \
}; \
//!
-
#define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
+#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+
+//Specializations to avoid an unneeded temporary when emplacing from a single argument o type value_type
+template<class A, class Iterator>
+struct insert_emplace_proxy_arg1<A, Iterator, ::boost::rv<typename boost::container::allocator_traits<A>::value_type> >
+ : public insert_move_proxy<A, Iterator>
+{
+ explicit insert_emplace_proxy_arg1(typename boost::container::allocator_traits<A>::value_type &v)
+ : insert_move_proxy<A, Iterator>(v)
+ {}
+};
+
+template<class A, class Iterator>
+struct insert_emplace_proxy_arg1<A, Iterator, typename boost::container::allocator_traits<A>::value_type>
+ : public insert_copy_proxy<A, Iterator>
+{
+ explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<A>::value_type &v)
+ : insert_copy_proxy<A, Iterator>(v)
+ {}
+};
+
+#else //e.g. MSVC10 & MSVC11
+
+//Specializations to avoid an unneeded temporary when emplacing from a single argument o type value_type
+template<class A, class Iterator>
+struct insert_emplace_proxy_arg1<A, Iterator, typename boost::container::allocator_traits<A>::value_type>
+ : public insert_move_proxy<A, Iterator>
+{
+ explicit insert_emplace_proxy_arg1(typename boost::container::allocator_traits<A>::value_type &&v)
+ : insert_move_proxy<A, 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 A, class Iterator>
+struct insert_emplace_proxy_arg1<A, Iterator
+ , typename boost::container::container_detail::add_const<typename boost::container::allocator_traits<A>::value_type>::type
+ >
+ : public insert_copy_proxy<A, Iterator>
+{
+ explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<A>::value_type &v)
+ : insert_copy_proxy<A, Iterator>(v)
+ {}
+};
+
+template<class A, class Iterator>
+struct insert_emplace_proxy_arg1<A, Iterator, typename boost::container::allocator_traits<A>::value_type &>
+ : public insert_copy_proxy<A, Iterator>
+{
+ explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<A>::value_type &v)
+ : insert_copy_proxy<A, Iterator>(v)
+ {}
+};
+
+template<class A, class Iterator>
+struct insert_emplace_proxy_arg1<A, Iterator
+ , typename boost::container::container_detail::add_const<typename boost::container::allocator_traits<A>::value_type>::type &
+ >
+ : public insert_copy_proxy<A, Iterator>
+{
+ explicit insert_emplace_proxy_arg1(const typename boost::container::allocator_traits<A>::value_type &v)
+ : insert_copy_proxy<A, Iterator>(v)
+ {}
+};
+
+#endif
+
}}} //namespace boost { namespace container { namespace container_detail {
#endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
diff --git a/boost/container/detail/algorithms.hpp b/boost/container/detail/algorithms.hpp
index dc09575b24..af15f65737 100644
--- a/boost/container/detail/algorithms.hpp
+++ b/boost/container/detail/algorithms.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012.
+// (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
@@ -13,38 +13,40 @@
#ifndef BOOST_CONTAINER_DETAIL_ALGORITHMS_HPP
#define BOOST_CONTAINER_DETAIL_ALGORITHMS_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
-#include "config_begin.hpp"
+#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
-
-#include <boost/type_traits/has_trivial_copy.hpp>
-#include <boost/type_traits/has_trivial_assign.hpp>
-#include <boost/detail/no_exceptions_support.hpp>
-
-#include <boost/container/detail/type_traits.hpp>
-#include <boost/container/detail/mpl.hpp>
+#include <boost/container/allocator_traits.hpp>
#include <boost/container/detail/iterators.hpp>
-
-#include <cstring>
-
namespace boost {
namespace container {
template<class A, class T, class InpIt>
inline void construct_in_place(A &a, T* dest, InpIt source)
{ boost::container::allocator_traits<A>::construct(a, dest, *source); }
-//#endif
template<class A, class T, class U, class D>
-inline void construct_in_place(A &a, T *dest, default_construct_iterator<U, D>)
+inline void construct_in_place(A &a, T *dest, value_init_construct_iterator<U, D>)
{
boost::container::allocator_traits<A>::construct(a, dest);
}
+template <class T, class Difference>
+class default_init_construct_iterator;
+
+template<class A, class T, class U, class D>
+inline void construct_in_place(A &a, T *dest, default_init_construct_iterator<U, D>)
+{
+ boost::container::allocator_traits<A>::construct(a, dest, default_init);
+}
+
+template <class T, class EmplaceFunctor, class Difference>
+class emplace_iterator;
+
template<class A, class T, class U, class EF, class D>
inline void construct_in_place(A &a, T *dest, emplace_iterator<U, EF, D> ei)
{
diff --git a/boost/container/detail/alloc_lib.h b/boost/container/detail/alloc_lib.h
new file mode 100644
index 0000000000..4802d9d814
--- /dev/null
+++ b/boost/container/detail/alloc_lib.h
@@ -0,0 +1,326 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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)
+
+/*
+ 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 __declspec(dllexport)
+#else
+# define BOOST_CONTAINER_DECL __declspec(dllimport)
+#endif /* BOOST_CONTAINER_SOURCE */
+#endif /* DYN_LINK */
+#endif /* _MSC_VER */
+
+/* if BOOST_CONTAINER_DECL isn't defined yet define it now: */
+#ifndef BOOST_CONTAINER_DECL
+#define BOOST_CONTAINER_DECL
+#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)\
+/**/
+
+BOOST_CONTAINER_DECL size_t boost_cont_size(const void *p);
+
+BOOST_CONTAINER_DECL void* boost_cont_malloc(size_t bytes);
+
+BOOST_CONTAINER_DECL void boost_cont_free(void* mem);
+
+BOOST_CONTAINER_DECL void* boost_cont_memalign(size_t bytes, size_t alignment);
+
+/*!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))
+
+BOOST_CONTAINER_DECL int boost_cont_multialloc_nodes
+ (size_t n_elements, size_t elem_size, size_t contiguous_elements, boost_cont_memchain *pchain);
+
+BOOST_CONTAINER_DECL 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);
+
+BOOST_CONTAINER_DECL void boost_cont_multidealloc(boost_cont_memchain *pchain);
+
+BOOST_CONTAINER_DECL size_t boost_cont_footprint();
+
+BOOST_CONTAINER_DECL size_t boost_cont_allocated_memory();
+
+BOOST_CONTAINER_DECL size_t boost_cont_chunksize(const void *p);
+
+BOOST_CONTAINER_DECL int boost_cont_all_deallocated();
+
+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;
+
+BOOST_CONTAINER_DECL boost_cont_malloc_stats_t boost_cont_malloc_stats();
+
+BOOST_CONTAINER_DECL size_t boost_cont_in_use_memory();
+
+BOOST_CONTAINER_DECL int boost_cont_trim(size_t pad);
+
+BOOST_CONTAINER_DECL int boost_cont_mallopt
+ (int parameter_number, int parameter_value);
+
+BOOST_CONTAINER_DECL int boost_cont_grow
+ (void* oldmem, size_t minbytes, size_t maxbytes, size_t *received);
+
+BOOST_CONTAINER_DECL int boost_cont_shrink
+ (void* oldmem, size_t minbytes, size_t maxbytes, size_t *received, int do_commit);
+
+BOOST_CONTAINER_DECL void* boost_cont_alloc
+ (size_t minbytes, size_t preferred_bytes, size_t *received_bytes);
+
+BOOST_CONTAINER_DECL int boost_cont_malloc_check();
+
+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;
+
+BOOST_CONTAINER_DECL 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
+ );
+
+BOOST_CONTAINER_DECL int boost_cont_mallopt(int param_number, int value);
+
+#ifdef __cplusplus
+} //extern "C" {
+#endif
+
+#ifdef _MSC_VER
+#pragma warning (pop)
+#endif
+
+
+#endif //#define BOOST_CONTAINERDLMALLOC__EXT_H
diff --git a/boost/container/detail/alloc_lib_auto_link.hpp b/boost/container/detail/alloc_lib_auto_link.hpp
new file mode 100644
index 0000000000..e0a01b6086
--- /dev/null
+++ b/boost/container/detail/alloc_lib_auto_link.hpp
@@ -0,0 +1,20 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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_BOOST_CONT_EXT_AUTO_LINK_HPP
+#define BOOST_CONTAINER_DETAIL_BOOST_CONT_EXT_AUTO_LINK_HPP
+
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
+#include <boost/container/detail/auto_link.hpp>
+#include <boost/container/detail/alloc_lib.h>
+
+#endif //#ifndef BOOST_CONTAINER_DETAIL_BOOST_CONT_EXT_AUTO_LINK_HPP
diff --git a/boost/container/detail/allocation_type.hpp b/boost/container/detail/allocation_type.hpp
index 1ebf20ed70..65d543ad50 100644
--- a/boost/container/detail/allocation_type.hpp
+++ b/boost/container/detail/allocation_type.hpp
@@ -1,6 +1,6 @@
///////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
+// (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)
//
@@ -11,19 +11,19 @@
#ifndef BOOST_CONTAINER_ALLOCATION_TYPE_HPP
#define BOOST_CONTAINER_ALLOCATION_TYPE_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
-#include "config_begin.hpp"
+#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
namespace boost {
namespace container {
-/// @cond
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
enum allocation_type_v
-{
+{
// constants for allocation commands
allocate_new_v = 0x01,
expand_fwd_v = 0x02,
@@ -37,7 +37,7 @@ enum allocation_type_v
};
typedef int allocation_type;
-/// @endcond
+#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;
diff --git a/boost/container/detail/allocator_version_traits.hpp b/boost/container/detail/allocator_version_traits.hpp
new file mode 100644
index 0000000000..18bb2ac613
--- /dev/null
+++ b/boost/container/detail/allocator_version_traits.hpp
@@ -0,0 +1,168 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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
+
+#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> //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 <utility> //pair
+#include <boost/core/no_exceptions_support.hpp> //BOOST_TRY
+
+namespace boost {
+namespace container {
+namespace container_detail {
+
+template<class Allocator, unsigned Version = boost::container::container_detail::version<Allocator>::value>
+struct allocator_version_traits
+{
+ typedef ::boost::container::container_detail::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 std::pair<pointer, bool>
+ allocation_command(Allocator &a, allocation_type command,
+ size_type limit_size, size_type preferred_size,
+ size_type &received_size, const pointer &reuse)
+ {
+ return a.allocation_command
+ (command, limit_size, preferred_size, received_size, reuse);
+ }
+};
+
+template<class Allocator>
+struct allocator_version_traits<Allocator, 1>
+{
+ typedef ::boost::container::container_detail::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 container_detail::basic_multiallocation_chain
+ <void_ptr> multialloc_cached_counted;
+ typedef boost::container::container_detail::
+ 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 std::pair<pointer, bool>
+ allocation_command(Allocator &a, allocation_type command,
+ size_type, size_type preferred_size,
+ size_type &received_size, const pointer &)
+ {
+ std::pair<pointer, bool> ret(pointer(), false);
+ if(!(command & allocate_new)){
+ if(!(command & nothrow_allocation)){
+ throw_logic_error("version 1 allocator without allocate_new flag");
+ }
+ }
+ else{
+ received_size = preferred_size;
+ BOOST_TRY{
+ ret.first = a.allocate(received_size);
+ }
+ BOOST_CATCH(...){
+ if(!(command & nothrow_allocation)){
+ BOOST_RETHROW
+ }
+ }
+ BOOST_CATCH_END
+ }
+ return ret;
+ }
+};
+
+} //namespace container_detail {
+} //namespace container {
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif // ! defined(BOOST_CONTAINER_DETAIL_ALLOCATOR_VERSION_TRAITS_HPP)
diff --git a/boost/container/detail/auto_link.hpp b/boost/container/detail/auto_link.hpp
new file mode 100644
index 0000000000..2e4733363d
--- /dev/null
+++ b/boost/container/detail/auto_link.hpp
@@ -0,0 +1,38 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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
+
+#if defined(_MSC_VER)
+# pragma once
+#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_ALL_DYN_LINK) || defined(BOOST_CONTAINER_DYN_LINK)
+# 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/boost/container/detail/config_begin.hpp b/boost/container/detail/config_begin.hpp
index 83c2cfe40c..ca9dd59682 100644
--- a/boost/container/detail/config_begin.hpp
+++ b/boost/container/detail/config_begin.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
+// (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)
//
@@ -9,15 +9,13 @@
//////////////////////////////////////////////////////////////////////////////
#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
- #ifndef _CRT_SECURE_NO_DEPRECATE
- #define BOOST_CONTAINER_DETAIL_CRT_SECURE_NO_DEPRECATE
- #define _CRT_SECURE_NO_DEPRECATE
- #endif
#pragma warning (push)
#pragma warning (disable : 4702) // unreachable code
#pragma warning (disable : 4706) // assignment within conditional expression
@@ -46,4 +44,5 @@
#pragma warning (disable : 4673) // throwing '' the following types will not be considered at the catch site
#pragma warning (disable : 4671) // the copy constructor is inaccessible
#pragma warning (disable : 4584) // X is already a base-class of Y
+ #pragma warning (disable : 4510) // default constructor could not be generated
#endif //BOOST_MSVC
diff --git a/boost/container/detail/config_end.hpp b/boost/container/detail/config_end.hpp
index 34513718cc..f93c8f6f79 100644
--- a/boost/container/detail/config_end.hpp
+++ b/boost/container/detail/config_end.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
+// (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)
//
@@ -9,9 +9,5 @@
//////////////////////////////////////////////////////////////////////////////
#if defined BOOST_MSVC
#pragma warning (pop)
- #ifdef BOOST_CONTAINER_DETAIL_CRT_SECURE_NO_DEPRECATE
- #undef BOOST_CONTAINER_DETAIL_CRT_SECURE_NO_DEPRECATE
- #undef _CRT_SECURE_NO_DEPRECATE
- #endif
#endif
diff --git a/boost/container/detail/destroyers.hpp b/boost/container/detail/destroyers.hpp
index d1b118cdcc..ea9b617437 100644
--- a/boost/container/detail/destroyers.hpp
+++ b/boost/container/detail/destroyers.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012.
+// (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
@@ -13,12 +13,13 @@
#ifndef BOOST_CONTAINER_DESTROYERS_HPP
#define BOOST_CONTAINER_DESTROYERS_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
-#include "config_begin.hpp"
+#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
+
#include <boost/container/detail/version_type.hpp>
#include <boost/container/detail/utilities.hpp>
#include <boost/container/allocator_traits.hpp>
@@ -28,6 +29,74 @@ namespace container {
namespace container_detail {
//!A deleter for scoped_ptr that deallocates the memory
+//!allocated for an object using a STL allocator.
+template <class A>
+struct scoped_deallocator
+{
+ typedef allocator_traits<A> allocator_traits_type;
+ typedef typename allocator_traits_type::pointer pointer;
+ typedef container_detail::integral_constant<unsigned,
+ boost::container::container_detail::
+ version<A>::value> alloc_version;
+ typedef container_detail::integral_constant<unsigned, 1> allocator_v1;
+ typedef container_detail::integral_constant<unsigned, 2> allocator_v2;
+
+ private:
+ void priv_deallocate(allocator_v1)
+ { m_alloc.deallocate(m_ptr, 1); }
+
+ void priv_deallocate(allocator_v2)
+ { m_alloc.deallocate_one(m_ptr); }
+
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(scoped_deallocator)
+
+ public:
+
+ pointer m_ptr;
+ A& m_alloc;
+
+ scoped_deallocator(pointer p, A& 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
@@ -126,13 +195,17 @@ struct scoped_destructor_n
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 = container_detail::to_raw_pointer(m_p);
- for(size_type i = 0; i < m_n; ++i, ++raw_ptr)
- AllocTraits::destroy(m_a, raw_ptr);
+ while(m_n--){
+ AllocTraits::destroy(m_a, raw_ptr++);
+ }
}
private:
@@ -159,6 +232,9 @@ struct null_scoped_destructor_n
void increment_size_backwards(size_type)
{}
+ void shrink_forward(size_type)
+ {}
+
void release()
{}
};
@@ -183,6 +259,11 @@ class scoped_destructor
void release()
{ pv_ = 0; }
+
+ void set(value_type *ptr) { pv_ = ptr; }
+
+ value_type *get() const { return pv_; }
+
private:
value_type *pv_;
A &a_;
@@ -239,10 +320,56 @@ class allocator_destroyer
void operator()(const pointer &p)
{
AllocTraits::destroy(a_, container_detail::to_raw_pointer(p));
- priv_deallocate(p, alloc_version());
+ this->priv_deallocate(p, alloc_version());
}
};
+template <class A>
+class allocator_destroyer_and_chain_builder
+{
+ typedef allocator_traits<A> allocator_traits_type;
+ typedef typename allocator_traits_type::value_type value_type;
+ typedef typename A::multiallocation_chain multiallocation_chain;
+
+ A & a_;
+ multiallocation_chain &c_;
+
+ public:
+ allocator_destroyer_and_chain_builder(A &a, multiallocation_chain &c)
+ : a_(a), c_(c)
+ {}
+
+ void operator()(const typename A::pointer &p)
+ {
+ allocator_traits<A>::destroy(a_, container_detail::to_raw_pointer(p));
+ c_.push_back(p);
+ }
+};
+
+template <class A>
+class allocator_multialloc_chain_node_deallocator
+{
+ typedef allocator_traits<A> allocator_traits_type;
+ typedef typename allocator_traits_type::value_type value_type;
+ typedef typename A::multiallocation_chain multiallocation_chain;
+ typedef allocator_destroyer_and_chain_builder<A> chain_builder;
+
+ A & a_;
+ multiallocation_chain c_;
+
+ public:
+ allocator_multialloc_chain_node_deallocator(A &a)
+ : a_(a), c_()
+ {}
+
+ chain_builder get_chain_builder()
+ { return chain_builder(a_, c_); }
+
+ ~allocator_multialloc_chain_node_deallocator()
+ {
+ a_.deallocate_individual(c_);
+ }
+};
} //namespace container_detail {
} //namespace container {
diff --git a/boost/container/detail/flat_tree.hpp b/boost/container/detail/flat_tree.hpp
index 23be0bfd13..a6f7568b43 100644
--- a/boost/container/detail/flat_tree.hpp
+++ b/boost/container/detail/flat_tree.hpp
@@ -1,6 +1,6 @@
////////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
+// (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)
//
@@ -11,11 +11,11 @@
#ifndef BOOST_CONTAINER_FLAT_TREE_HPP
#define BOOST_CONTAINER_FLAT_TREE_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
-#include "config_begin.hpp"
+#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/container_fwd.hpp>
@@ -25,7 +25,7 @@
#include <utility>
#include <boost/type_traits/has_trivial_destructor.hpp>
-#include <boost/move/move.hpp>
+#include <boost/move/utility_core.hpp>
#include <boost/container/detail/utilities.hpp>
#include <boost/container/detail/pair.hpp>
@@ -33,7 +33,11 @@
#include <boost/container/detail/value_init.hpp>
#include <boost/container/detail/destroyers.hpp>
#include <boost/container/allocator_traits.hpp>
+#ifdef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
+#include <boost/intrusive/pointer_traits.hpp>
+#endif
#include <boost/aligned_storage.hpp>
+#include <boost/move/make_unique.hpp>
namespace boost {
@@ -48,7 +52,7 @@ class flat_tree_value_compare
typedef Value first_argument_type;
typedef Value second_argument_type;
typedef bool return_type;
- public:
+ public:
flat_tree_value_compare()
: Compare()
{}
@@ -65,7 +69,7 @@ class flat_tree_value_compare
const Compare &get_comp() const
{ return *this; }
-
+
Compare &get_comp()
{ return *this; }
};
@@ -73,12 +77,23 @@ class flat_tree_value_compare
template<class Pointer>
struct get_flat_tree_iterators
{
- typedef typename container_detail::
- vector_iterator<Pointer> iterator;
- typedef typename container_detail::
- vector_const_iterator<Pointer> const_iterator;
- typedef std::reverse_iterator<iterator> reverse_iterator;
- typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+ #ifdef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
+ typedef Pointer iterator;
+ typedef typename boost::intrusive::
+ pointer_traits<Pointer>::element_type iterator_element_type;
+ typedef typename boost::intrusive::
+ pointer_traits<Pointer>:: template
+ rebind_pointer<const iterator_element_type>::type const_iterator;
+ #else //BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
+ typedef typename boost::container::container_detail::
+ vec_iterator<Pointer, false> iterator;
+ typedef typename boost::container::container_detail::
+ vec_iterator<Pointer, true > const_iterator;
+ #endif //BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
+ typedef boost::container::container_detail::
+ reverse_iterator<iterator> reverse_iterator;
+ typedef boost::container::container_detail::
+ reverse_iterator<const_iterator> const_reverse_iterator;
};
template <class Key, class Value, class KeyOfValue,
@@ -103,7 +118,7 @@ class flat_tree
: value_compare(), m_vect()
{}
- Data(const Data &d)
+ explicit Data(const Data &d)
: value_compare(static_cast<const value_compare&>(d)), m_vect(d.m_vect)
{}
@@ -119,15 +134,18 @@ class flat_tree
: value_compare(boost::move(static_cast<value_compare&>(d))), m_vect(boost::move(d.m_vect), a)
{}
- Data(const Compare &comp)
+ explicit Data(const Compare &comp)
: value_compare(comp), m_vect()
{}
- Data(const Compare &comp,
- const allocator_t &alloc)
+ Data(const Compare &comp, const allocator_t &alloc)
: value_compare(comp), m_vect(alloc)
{}
+ explicit Data(const allocator_t &alloc)
+ : value_compare(), m_vect(alloc)
+ {}
+
Data& operator=(BOOST_COPY_ASSIGN_REF(Data) d)
{
this->value_compare::operator=(d);
@@ -145,7 +163,7 @@ class flat_tree
void swap(Data &d)
{
value_compare& mycomp = *this, & othercomp = d;
- container_detail::do_swap(mycomp, othercomp);
+ boost::container::swap_dispatch(mycomp, othercomp);
this->m_vect.swap(d.m_vect);
}
@@ -191,6 +209,10 @@ class flat_tree
: m_data(comp, a)
{ }
+ explicit flat_tree(const allocator_type& a)
+ : m_data(a)
+ { }
+
flat_tree(const flat_tree& x)
: m_data(x.m_data)
{ }
@@ -214,8 +236,31 @@ class flat_tree
: m_data(comp, a)
{ this->m_data.m_vect.insert(this->m_data.m_vect.end(), first, last); }
+ template <class InputIterator>
+ flat_tree( bool unique_insertion
+ , InputIterator first, InputIterator last
+ , const Compare& comp = Compare()
+ , const allocator_type& a = allocator_type())
+ : m_data(comp, a)
+ {
+ //Use cend() as hint to achieve linear time for
+ //ordered ranges as required by the standard
+ //for the constructor
+ //Call end() every iteration as reallocation might have invalidated iterators
+ if(unique_insertion){
+ for ( ; first != last; ++first){
+ this->insert_unique(this->cend(), *first);
+ }
+ }
+ else{
+ for ( ; first != last; ++first){
+ this->insert_equal(this->cend(), *first);
+ }
+ }
+ }
+
~flat_tree()
- { }
+ {}
flat_tree& operator=(BOOST_COPY_ASSIGN_REF(flat_tree) x)
{ m_data = x.m_data; return *this; }
@@ -223,11 +268,14 @@ class flat_tree
flat_tree& operator=(BOOST_RV_REF(flat_tree) mx)
{ m_data = boost::move(mx.m_data); return *this; }
- public:
+ public:
// accessors:
Compare key_comp() const
{ return this->m_data.get_comp(); }
+ value_compare value_comp() const
+ { return this->m_data; }
+
allocator_type get_allocator() const
{ return this->m_data.m_vect.get_allocator(); }
@@ -289,21 +337,21 @@ class flat_tree
// insert/erase
std::pair<iterator,bool> insert_unique(const value_type& val)
{
+ std::pair<iterator,bool> ret;
insert_commit_data data;
- std::pair<iterator,bool> ret = priv_insert_unique_prepare(val, data);
- if(ret.second){
- ret.first = priv_insert_commit(data, val);
- }
+ ret.second = this->priv_insert_unique_prepare(val, data);
+ ret.first = ret.second ? this->priv_insert_commit(data, val)
+ : 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;
- std::pair<iterator,bool> ret = priv_insert_unique_prepare(val, data);
- if(ret.second){
- ret.first = priv_insert_commit(data, boost::move(val));
- }
+ ret.second = this->priv_insert_unique_prepare(val, data);
+ ret.first = ret.second ? this->priv_insert_commit(data, boost::move(val))
+ : iterator(vector_iterator_get_ptr(data.position));
return ret;
}
@@ -323,69 +371,134 @@ class flat_tree
iterator insert_unique(const_iterator pos, const value_type& val)
{
+ std::pair<iterator,bool> ret;
insert_commit_data data;
- std::pair<iterator,bool> ret = priv_insert_unique_prepare(pos, val, data);
- if(ret.second){
- ret.first = priv_insert_commit(data, val);
- }
- return ret.first;
+ return this->priv_insert_unique_prepare(pos, val, data)
+ ? this->priv_insert_commit(data, val)
+ : iterator(vector_iterator_get_ptr(data.position));
}
- iterator insert_unique(const_iterator pos, BOOST_RV_REF(value_type) mval)
+ iterator insert_unique(const_iterator pos, BOOST_RV_REF(value_type) val)
{
+ std::pair<iterator,bool> ret;
insert_commit_data data;
- std::pair<iterator,bool> ret = priv_insert_unique_prepare(pos, mval, data);
- if(ret.second){
- ret.first = priv_insert_commit(data, boost::move(mval));
- }
- return ret.first;
+ return this->priv_insert_unique_prepare(pos, val, data)
+ ? this->priv_insert_commit(data, boost::move(val))
+ : iterator(vector_iterator_get_ptr(data.position));
}
iterator insert_equal(const_iterator pos, const value_type& val)
{
insert_commit_data data;
this->priv_insert_equal_prepare(pos, val, data);
- return priv_insert_commit(data, val);
+ return this->priv_insert_commit(data, val);
}
iterator insert_equal(const_iterator pos, BOOST_RV_REF(value_type) mval)
{
insert_commit_data data;
this->priv_insert_equal_prepare(pos, mval, data);
- return priv_insert_commit(data, boost::move(mval));
+ return this->priv_insert_commit(data, boost::move(mval));
}
template <class InIt>
void insert_unique(InIt first, InIt last)
{
- for ( ; first != last; ++first)
+ for ( ; first != last; ++first){
this->insert_unique(*first);
+ }
}
template <class InIt>
- void insert_equal(InIt first, InIt last)
+ void insert_equal(InIt first, InIt last
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename container_detail::enable_if_c
+ < container_detail::is_input_iterator<InIt>::value
+ >::type * = 0
+ #endif
+ )
+ { this->priv_insert_equal_loop(first, last); }
+
+ template <class InIt>
+ void insert_equal(InIt first, InIt last
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename container_detail::enable_if_c
+ < !container_detail::is_input_iterator<InIt>::value
+ >::type * = 0
+ #endif
+ )
{
- typedef typename
- std::iterator_traits<InIt>::iterator_category ItCat;
- this->priv_insert_equal(first, last, ItCat());
+ const size_type len = static_cast<size_type>(std::distance(first, last));
+ this->reserve(this->size()+len);
+ this->priv_insert_equal_loop(first, last);
}
+ //Ordered
+
template <class InIt>
- void insert_equal(ordered_range_t, InIt first, InIt last)
+ void insert_equal(ordered_range_t, InIt first, InIt last
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename container_detail::enable_if_c
+ < container_detail::is_input_iterator<InIt>::value
+ >::type * = 0
+ #endif
+ )
+ { this->priv_insert_equal_loop_ordered(first, last); }
+
+ template <class FwdIt>
+ void insert_equal(ordered_range_t, FwdIt first, FwdIt last
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename container_detail::enable_if_c
+ < !container_detail::is_input_iterator<FwdIt>::value &&
+ container_detail::is_forward_iterator<FwdIt>::value
+ >::type * = 0
+ #endif
+ )
{
- typedef typename
- std::iterator_traits<InIt>::iterator_category ItCat;
- this->priv_insert_equal(ordered_range_t(), first, last, ItCat());
+ const size_type len = static_cast<size_type>(std::distance(first, last));
+ this->reserve(this->size()+len);
+ this->priv_insert_equal_loop_ordered(first, last);
}
+ template <class BidirIt>
+ void insert_equal(ordered_range_t, BidirIt first, BidirIt last
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename container_detail::enable_if_c
+ < !container_detail::is_input_iterator<BidirIt>::value &&
+ !container_detail::is_forward_iterator<BidirIt>::value
+ >::type * = 0
+ #endif
+ )
+ { this->priv_insert_ordered_range(false, first, last); }
+
template <class InIt>
- void insert_unique(ordered_unique_range_t, InIt first, InIt last)
- {
- typedef typename
- std::iterator_traits<InIt>::iterator_category ItCat;
- this->priv_insert_unique(ordered_unique_range_t(), first, last, ItCat());
+ void insert_unique(ordered_unique_range_t, InIt first, InIt last
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename container_detail::enable_if_c
+ < container_detail::is_input_iterator<InIt>::value ||
+ container_detail::is_forward_iterator<InIt>::value
+ >::type * = 0
+ #endif
+ )
+ {
+ const_iterator pos(this->cend());
+ for ( ; first != last; ++first){
+ pos = this->insert_unique(pos, *first);
+ ++pos;
+ }
}
+ template <class BidirIt>
+ void insert_unique(ordered_unique_range_t, BidirIt first, BidirIt last
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename container_detail::enable_if_c
+ < !(container_detail::is_input_iterator<BidirIt>::value ||
+ container_detail::is_forward_iterator<BidirIt>::value)
+ >::type * = 0
+ #endif
+ )
+ { this->priv_insert_ordered_range(true, first, last); }
+
#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
template <class... Args>
@@ -396,13 +509,7 @@ class flat_tree
stored_allocator_type &a = this->get_stored_allocator();
stored_allocator_traits::construct(a, &val, ::boost::forward<Args>(args)... );
value_destructor<stored_allocator_type> d(a, val);
- insert_commit_data data;
- std::pair<iterator,bool> ret =
- priv_insert_unique_prepare(val, data);
- if(ret.second){
- ret.first = priv_insert_commit(data, boost::move(val));
- }
- return ret;
+ return this->insert_unique(::boost::move(val));
}
template <class... Args>
@@ -413,12 +520,7 @@ class flat_tree
stored_allocator_type &a = this->get_stored_allocator();
stored_allocator_traits::construct(a, &val, ::boost::forward<Args>(args)... );
value_destructor<stored_allocator_type> d(a, val);
- insert_commit_data data;
- std::pair<iterator,bool> ret = priv_insert_unique_prepare(hint, val, data);
- if(ret.second){
- ret.first = priv_insert_commit(data, boost::move(val));
- }
- return ret.first;
+ return this->insert_unique(hint, ::boost::move(val));
}
template <class... Args>
@@ -429,9 +531,7 @@ class flat_tree
stored_allocator_type &a = this->get_stored_allocator();
stored_allocator_traits::construct(a, &val, ::boost::forward<Args>(args)... );
value_destructor<stored_allocator_type> d(a, val);
- iterator i = this->upper_bound(KeyOfValue()(val));
- i = this->m_data.m_vect.insert(i, boost::move(val));
- return i;
+ return this->insert_equal(::boost::move(val));
}
template <class... Args>
@@ -442,10 +542,7 @@ class flat_tree
stored_allocator_type &a = this->get_stored_allocator();
stored_allocator_traits::construct(a, &val, ::boost::forward<Args>(args)... );
value_destructor<stored_allocator_type> d(a, val);
- insert_commit_data data;
- this->priv_insert_equal_prepare(hint, val, data);
- iterator i = priv_insert_commit(data, boost::move(val));
- return i;
+ return this->insert_equal(hint, ::boost::move(val));
}
#else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
@@ -461,12 +558,7 @@ class flat_tree
stored_allocator_traits::construct(a, &val \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \
value_destructor<stored_allocator_type> d(a, val); \
- insert_commit_data data; \
- std::pair<iterator,bool> ret = priv_insert_unique_prepare(val, data); \
- if(ret.second){ \
- ret.first = priv_insert_commit(data, boost::move(val)); \
- } \
- return ret; \
+ return this->insert_unique(::boost::move(val)); \
} \
\
BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
@@ -478,13 +570,8 @@ class flat_tree
stored_allocator_type &a = this->get_stored_allocator(); \
stored_allocator_traits::construct(a, &val \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \
- value_destructor<stored_allocator_type> d(a, val); \
- insert_commit_data data; \
- std::pair<iterator,bool> ret = priv_insert_unique_prepare(hint, val, data); \
- if(ret.second){ \
- ret.first = priv_insert_commit(data, boost::move(val)); \
- } \
- return ret.first; \
+ value_destructor<stored_allocator_type> d(a, val); \
+ return this->insert_unique(hint, ::boost::move(val)); \
} \
\
BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
@@ -496,9 +583,7 @@ class flat_tree
stored_allocator_traits::construct(a, &val \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \
value_destructor<stored_allocator_type> d(a, val); \
- iterator i = this->upper_bound(KeyOfValue()(val)); \
- i = this->m_data.m_vect.insert(i, boost::move(val)); \
- return i; \
+ return this->insert_equal(::boost::move(val)); \
} \
\
BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
@@ -511,12 +596,8 @@ class flat_tree
stored_allocator_traits::construct(a, &val \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \
value_destructor<stored_allocator_type> d(a, val); \
- insert_commit_data data; \
- this->priv_insert_equal_prepare(hint, val, data); \
- iterator i = priv_insert_commit(data, boost::move(val)); \
- return i; \
+ return this->insert_equal(hint, ::boost::move(val)); \
} \
-
//!
#define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
@@ -554,26 +635,26 @@ class flat_tree
// set operations:
iterator find(const key_type& k)
{
- const Compare &key_comp = this->m_data.get_comp();
iterator i = this->lower_bound(k);
-
- if (i != this->end() && key_comp(k, KeyOfValue()(*i))){
- i = this->end();
+ 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 Compare &key_comp = this->m_data.get_comp();
const_iterator i = this->lower_bound(k);
- if (i != this->end() && key_comp(k, KeyOfValue()(*i))){
- i = this->end();
+ const_iterator end_it = this->cend();
+ if (i != end_it && this->m_data.get_comp()(k, KeyOfValue()(*i))){
+ i = end_it;
}
return i;
}
+ // set operations:
size_type count(const key_type& k) const
{
std::pair<const_iterator, const_iterator> p = this->equal_range(k);
@@ -585,25 +666,57 @@ class flat_tree
{ return this->priv_lower_bound(this->begin(), this->end(), k); }
const_iterator lower_bound(const key_type& k) const
- { return this->priv_lower_bound(this->begin(), this->end(), k); }
+ { return this->priv_lower_bound(this->cbegin(), this->cend(), k); }
iterator upper_bound(const key_type& k)
{ return this->priv_upper_bound(this->begin(), this->end(), k); }
const_iterator upper_bound(const key_type& k) const
- { return this->priv_upper_bound(this->begin(), this->end(), k); }
+ { return this->priv_upper_bound(this->cbegin(), this->cend(), k); }
std::pair<iterator,iterator> equal_range(const key_type& k)
{ return this->priv_equal_range(this->begin(), this->end(), k); }
std::pair<const_iterator, const_iterator> equal_range(const key_type& k) const
- { return this->priv_equal_range(this->begin(), this->end(), k); }
+ { return this->priv_equal_range(this->cbegin(), this->cend(), k); }
+
+ std::pair<iterator, iterator> lower_bound_range(const key_type& k)
+ { return this->priv_lower_bound_range(this->begin(), this->end(), k); }
+
+ 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); }
- size_type capacity() const
+ size_type capacity() const
{ return this->m_data.m_vect.capacity(); }
- void reserve(size_type count)
- { this->m_data.m_vect.reserve(count); }
+ void reserve(size_type cnt)
+ { this->m_data.m_vect.reserve(cnt); }
+
+ friend bool operator==(const flat_tree& x, const flat_tree& y)
+ {
+ return x.size() == y.size() && std::equal(x.begin(), x.end(), y.begin());
+ }
+
+ friend bool operator<(const flat_tree& x, const flat_tree& y)
+ {
+ return std::lexicographical_compare(x.begin(), x.end(),
+ y.begin(), y.end());
+ }
+
+ friend bool operator!=(const flat_tree& x, const flat_tree& y)
+ { return !(x == y); }
+
+ friend bool operator>(const flat_tree& x, const flat_tree& y)
+ { return y < x; }
+
+ friend bool operator<=(const flat_tree& x, const flat_tree& y)
+ { return !(y < x); }
+
+ friend bool operator>=(const flat_tree& x, const flat_tree& y)
+ { return !(x < y); }
+
+ friend void swap(flat_tree& x, flat_tree& y)
+ { x.swap(y); }
private:
struct insert_commit_data
@@ -624,10 +737,10 @@ class flat_tree
// insert val before upper_bound(val)
// else
// insert val before lower_bound(val)
- const value_compare &value_comp = this->m_data;
+ const value_compare &val_cmp = this->m_data;
- if(pos == this->cend() || !value_comp(*pos, val)){
- if (pos == this->cbegin() || !value_comp(val, pos[-1])){
+ if(pos == this->cend() || !val_cmp(*pos, val)){
+ if (pos == this->cbegin() || !val_cmp(val, pos[-1])){
data.position = pos;
}
else{
@@ -641,21 +754,19 @@ class flat_tree
}
}
- std::pair<iterator,bool> priv_insert_unique_prepare
- (const_iterator beg, const_iterator end, const value_type& val, insert_commit_data &commit_data)
+ bool priv_insert_unique_prepare
+ (const_iterator b, const_iterator e, const value_type& val, insert_commit_data &commit_data)
{
- const value_compare &value_comp = this->m_data;
- commit_data.position = this->priv_lower_bound(beg, end, KeyOfValue()(val));
- return std::pair<iterator,bool>
- ( *reinterpret_cast<iterator*>(&commit_data.position)
- , commit_data.position == end || value_comp(val, *commit_data.position));
+ const value_compare &val_cmp = this->m_data;
+ commit_data.position = this->priv_lower_bound(b, e, KeyOfValue()(val));
+ return commit_data.position == e || val_cmp(val, *commit_data.position);
}
- std::pair<iterator,bool> priv_insert_unique_prepare
+ bool priv_insert_unique_prepare
(const value_type& val, insert_commit_data &commit_data)
- { return priv_insert_unique_prepare(this->begin(), this->end(), val, commit_data); }
+ { return this->priv_insert_unique_prepare(this->cbegin(), this->cend(), val, commit_data); }
- std::pair<iterator,bool> priv_insert_unique_prepare
+ bool priv_insert_unique_prepare
(const_iterator pos, const value_type& val, insert_commit_data &commit_data)
{
//N1780. Props to Howard Hinnant!
@@ -669,37 +780,32 @@ class flat_tree
// insert val after pos
//else
// insert val before lower_bound(val)
- const value_compare &value_comp = this->m_data;
-
- if(pos == this->cend() || value_comp(val, *pos)){
- if(pos != this->cbegin() && !value_comp(val, pos[-1])){
- if(value_comp(pos[-1], val)){
- commit_data.position = pos;
- return std::pair<iterator,bool>(*reinterpret_cast<iterator*>(&pos), true);
- }
- else{
- return std::pair<iterator,bool>(*reinterpret_cast<iterator*>(&pos), false);
- }
+ const value_compare &val_cmp = this->m_data;
+ const const_iterator cend_it = this->cend();
+ if(pos == cend_it || val_cmp(val, *pos)){ //Check if val 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(val_cmp(*prev, val)){ //If previous element was less, then it should go between prev and pos
+ return true;
+ }
+ else if(!val_cmp(val, *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 val
+ return this->priv_insert_unique_prepare(cbeg, prev, val, commit_data);
}
- return this->priv_insert_unique_prepare(this->cbegin(), pos, val, commit_data);
}
-
- // Works, but increases code complexity
- //Next check
- //else if (value_comp(*pos, val) && !value_comp(pos[1], val)){
- // if(value_comp(val, pos[1])){
- // commit_data.position = pos+1;
- // return std::pair<iterator,bool>(pos+1, true);
- // }
- // else{
- // return std::pair<iterator,bool>(pos+1, false);
- // }
- //}
else{
- //[... pos ... val ... ]
//The hint is before the insertion position, so insert it
- //in the remaining range
- return this->priv_insert_unique_prepare(pos, this->end(), val, commit_data);
+ //in the remaining range [pos, end)
+ return this->priv_insert_unique_prepare(pos, cend_it, val, commit_data);
}
}
@@ -713,50 +819,50 @@ class flat_tree
}
template <class RanIt>
- RanIt priv_lower_bound(RanIt first, RanIt last,
+ RanIt priv_lower_bound(RanIt first, const RanIt last,
const key_type & key) const
{
- const Compare &key_comp = this->m_data.get_comp();
+ const Compare &key_cmp = this->m_data.get_comp();
KeyOfValue key_extract;
- difference_type len = last - first, half;
+ size_type len = static_cast<size_type>(last - first);
RanIt middle;
- while (len > 0) {
- half = len >> 1;
+ while (len) {
+ size_type step = len >> 1;
middle = first;
- middle += half;
+ middle += step;
- if (key_comp(key_extract(*middle), key)) {
- ++middle;
- first = middle;
- len = len - half - 1;
+ if (key_cmp(key_extract(*middle), key)) {
+ first = ++middle;
+ len -= step + 1;
+ }
+ else{
+ len = step;
}
- else
- len = half;
}
return first;
}
template <class RanIt>
- RanIt priv_upper_bound(RanIt first, RanIt last,
+ RanIt priv_upper_bound(RanIt first, const RanIt last,
const key_type & key) const
{
- const Compare &key_comp = this->m_data.get_comp();
+ const Compare &key_cmp = this->m_data.get_comp();
KeyOfValue key_extract;
- difference_type len = last - first, half;
+ size_type len = static_cast<size_type>(last - first);
RanIt middle;
- while (len > 0) {
- half = len >> 1;
+ while (len) {
+ size_type step = len >> 1;
middle = first;
- middle += half;
+ middle += step;
- if (key_comp(key, key_extract(*middle))) {
- len = half;
+ if (key_cmp(key, key_extract(*middle))) {
+ len = step;
}
else{
first = ++middle;
- len = len - half - 1;
+ len -= step + 1;
}
}
return first;
@@ -766,189 +872,135 @@ class flat_tree
std::pair<RanIt, RanIt>
priv_equal_range(RanIt first, RanIt last, const key_type& key) const
{
- const Compare &key_comp = this->m_data.get_comp();
+ const Compare &key_cmp = this->m_data.get_comp();
KeyOfValue key_extract;
- difference_type len = last - first, half;
- RanIt middle, left, right;
+ size_type len = static_cast<size_type>(last - first);
+ RanIt middle;
- while (len > 0) {
- half = len >> 1;
+ while (len) {
+ size_type step = len >> 1;
middle = first;
- middle += half;
+ middle += step;
- if (key_comp(key_extract(*middle), key)){
- first = middle;
- ++first;
- len = len - half - 1;
+ if (key_cmp(key_extract(*middle), key)){
+ first = ++middle;
+ len -= step + 1;
}
- else if (key_comp(key, key_extract(*middle))){
- len = half;
+ else if (key_cmp(key, key_extract(*middle))){
+ len = step;
}
else {
- left = this->priv_lower_bound(first, middle, key);
- first += len;
- right = this->priv_upper_bound(++middle, first, key);
- return std::pair<RanIt, RanIt>(left, right);
+ //Middle is equal to key
+ last = first;
+ last += len;
+ return std::pair<RanIt, RanIt>
+ ( this->priv_lower_bound(first, middle, key)
+ , this->priv_upper_bound(++middle, last, key));
}
}
return std::pair<RanIt, RanIt>(first, first);
}
- template <class BidirIt>
- void priv_insert_equal(ordered_range_t, BidirIt first, BidirIt last, std::bidirectional_iterator_tag)
+ template<class RanIt>
+ std::pair<RanIt, RanIt> priv_lower_bound_range(RanIt first, RanIt last, const key_type& k) const
{
- size_type len = static_cast<size_type>(std::distance(first, last));
- const size_type BurstSize = 16;
- size_type positions[BurstSize];
+ 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);
+ }
- //Prereserve all memory so that iterators are not invalidated
- this->reserve(this->size()+len);
- const const_iterator beg(this->cbegin());
- const_iterator pos(beg);
- //Loop in burst sizes
- while(len){
- const size_type burst = len < BurstSize ? len : BurstSize;
- const const_iterator cend(this->cend());
- len -= burst;
- for(size_type i = 0; i != burst; ++i){
- //Get the insertion position for each key
- pos = const_cast<const flat_tree&>(*this).priv_upper_bound(pos, cend, KeyOfValue()(*first));
- positions[i] = static_cast<size_type>(pos - beg);
- ++first;
- }
- //Insert all in a single step in the precalculated positions
- this->m_data.m_vect.insert_ordered_at(burst, positions + burst, first);
- //Next search position updated
- pos += burst;
+ template<class InIt>
+ void priv_insert_equal_loop(InIt first, InIt last)
+ {
+ for ( ; first != last; ++first){
+ this->insert_equal(*first);
+ }
+ }
+
+ template<class InIt>
+ void priv_insert_equal_loop_ordered(InIt first, InIt last)
+ {
+ const_iterator pos(this->cend());
+ for ( ; first != last; ++first){
+ //If ordered, then try hint version
+ //to achieve constant-time complexity per insertion
+ pos = this->insert_equal(pos, *first);
+ ++pos;
}
}
template <class BidirIt>
- void priv_insert_unique(ordered_unique_range_t, BidirIt first, BidirIt last, std::bidirectional_iterator_tag)
+ void priv_insert_ordered_range(const bool unique_values, BidirIt first, BidirIt last)
{
size_type len = static_cast<size_type>(std::distance(first, last));
- const size_type BurstSize = 16;
- size_type positions[BurstSize];
- size_type skips[BurstSize];
-
//Prereserve all memory so that iterators are not invalidated
this->reserve(this->size()+len);
- const const_iterator beg(this->cbegin());
- const_iterator pos(beg);
- const value_compare &value_comp = this->m_data;
+ //Auxiliary data for insertion positions.
+ const size_type BurstSize = len;
+ const ::boost::movelib::unique_ptr<size_type[]> positions =
+ ::boost::movelib::make_unique_definit<size_type[]>(BurstSize);
+
+ const const_iterator b(this->cbegin());
+ const const_iterator ce(this->cend());
+ const_iterator pos(b);
+ const value_compare &val_cmp = this->m_data;
//Loop in burst sizes
- while(len){
- skips[0u] = 0u;
+ bool back_insert = false;
+ while(len && !back_insert){
const size_type burst = len < BurstSize ? len : BurstSize;
size_type unique_burst = 0u;
- const const_iterator cend(this->cend());
- while(unique_burst < burst && len > 0){
- //Get the insertion position for each key
- const value_type & val = *first++;
- --len;
- pos = const_cast<const flat_tree&>(*this).priv_lower_bound(pos, cend, KeyOfValue()(val));
+ size_type checked = 0;
+ for(; checked != burst; ++checked){
+ //Get the insertion position for each key, use std::iterator_traits<BidirIt>::value_type
+ //because it can be different from container::value_type
+ //(e.g. conversion between std::pair<A, B> -> boost::container::pair<A, B>
+ const typename std::iterator_traits<BidirIt>::value_type & val = *first;
+ pos = const_cast<const flat_tree&>(*this).priv_lower_bound(pos, ce, KeyOfValue()(val));
//Check if already present
- if(pos != cend && !value_comp(*pos, val)){
- ++skips[unique_burst];
- continue;
+ if (pos != ce){
+ ++first;
+ --len;
+ positions[checked] = (unique_values && !val_cmp(val, *pos)) ?
+ size_type(-1) : (++unique_burst, static_cast<size_type>(pos - b));
}
-
- //If not present, calculate position
- positions[unique_burst] = static_cast<size_type>(pos - beg);
- if(++unique_burst < burst)
- skips[unique_burst] = 0u;
+ else{ //this element and the remaining should be back inserted
+ back_insert = true;
+ break;
+ }
+ }
+ if(unique_burst){
+ //Insert all in a single step in the precalculated positions
+ this->m_data.m_vect.insert_ordered_at(unique_burst, positions.get() + checked, first);
+ //Next search position updated, iterator still valid because we've preserved the vector
+ pos += unique_burst;
}
- //Insert all in a single step in the precalculated positions
- this->m_data.m_vect.insert_ordered_at(unique_burst, positions + unique_burst, skips + unique_burst, first);
- //Next search position updated
- pos += unique_burst;
}
- }
-/*
- template <class FwdIt>
- void priv_insert_equal_forward(ordered_range_t, FwdIt first, FwdIt last, std::forward_iterator_tag)
- { this->priv_insert_equal(first, last, std::forward_iterator_tag()); }
-*/
- template <class InIt>
- void priv_insert_equal(ordered_range_t, InIt first, InIt last, std::input_iterator_tag)
- { this->priv_insert_equal(first, last, std::input_iterator_tag()); }
-
- template <class InIt>
- void priv_insert_unique(ordered_unique_range_t, InIt first, InIt last, std::input_iterator_tag)
- { this->priv_insert_unique(first, last, std::input_iterator_tag()); }
-/*
- template <class FwdIt>
- void priv_insert_equal_forward(FwdIt first, FwdIt last, std::forward_iterator_tag)
- {
- const size_type len = static_cast<size_type>(std::distance(first, last));
- this->reserve(this->size()+len);
- this->priv_insert_equal(first, last, std::input_iterator_tag());
- }
-*/
- template <class InIt>
- void priv_insert_equal(InIt first, InIt last, std::input_iterator_tag)
- {
- for ( ; first != last; ++first)
- this->insert_equal(*first);
+ //The remaining range should be back inserted
+ if(unique_values){
+ while(len--){
+ BidirIt next(first);
+ ++next;
+ if(next == last || val_cmp(*first, *next)){
+ const bool room = this->m_data.m_vect.stable_emplace_back(*first);
+ (void)room;
+ BOOST_ASSERT(room);
+ }
+ first = next;
+ }
+ BOOST_ASSERT(first == last);
+ }
+ else{
+ BOOST_ASSERT(size_type(std::distance(first, last)) == len);
+ if(len)
+ this->m_data.m_vect.insert(this->m_data.m_vect.cend(), len, first, last);
+ }
}
};
-template <class Key, class Value, class KeyOfValue,
- class Compare, class A>
-inline bool
-operator==(const flat_tree<Key,Value,KeyOfValue,Compare,A>& x,
- const flat_tree<Key,Value,KeyOfValue,Compare,A>& y)
-{
- return x.size() == y.size() &&
- std::equal(x.begin(), x.end(), y.begin());
-}
-
-template <class Key, class Value, class KeyOfValue,
- class Compare, class A>
-inline bool
-operator<(const flat_tree<Key,Value,KeyOfValue,Compare,A>& x,
- const flat_tree<Key,Value,KeyOfValue,Compare,A>& y)
-{
- return std::lexicographical_compare(x.begin(), x.end(),
- y.begin(), y.end());
-}
-
-template <class Key, class Value, class KeyOfValue,
- class Compare, class A>
-inline bool
-operator!=(const flat_tree<Key,Value,KeyOfValue,Compare,A>& x,
- const flat_tree<Key,Value,KeyOfValue,Compare,A>& y)
- { return !(x == y); }
-
-template <class Key, class Value, class KeyOfValue,
- class Compare, class A>
-inline bool
-operator>(const flat_tree<Key,Value,KeyOfValue,Compare,A>& x,
- const flat_tree<Key,Value,KeyOfValue,Compare,A>& y)
- { return y < x; }
-
-template <class Key, class Value, class KeyOfValue,
- class Compare, class A>
-inline bool
-operator<=(const flat_tree<Key,Value,KeyOfValue,Compare,A>& x,
- const flat_tree<Key,Value,KeyOfValue,Compare,A>& y)
- { return !(y < x); }
-
-template <class Key, class Value, class KeyOfValue,
- class Compare, class A>
-inline bool
-operator>=(const flat_tree<Key,Value,KeyOfValue,Compare,A>& x,
- const flat_tree<Key,Value,KeyOfValue,Compare,A>& y)
- { return !(x < y); }
-
-
-template <class Key, class Value, class KeyOfValue,
- class Compare, class A>
-inline void
-swap(flat_tree<Key,Value,KeyOfValue,Compare,A>& x,
- flat_tree<Key,Value,KeyOfValue,Compare,A>& y)
- { x.swap(y); }
-
} //namespace container_detail {
} //namespace container {
@@ -959,7 +1011,7 @@ template <class K, class V, class KOV,
class C, class A>
struct has_trivial_destructor_after_move<boost::container::container_detail::flat_tree<K, V, KOV, C, A> >
{
- static const bool value = has_trivial_destructor<A>::value && has_trivial_destructor<C>::value;
+ static const bool value = has_trivial_destructor_after_move<A>::value && has_trivial_destructor_after_move<C>::value;
};
*/
} //namespace boost {
diff --git a/boost/container/detail/function_detector.hpp b/boost/container/detail/function_detector.hpp
index 5a5f6fd77d..242eb41352 100644
--- a/boost/container/detail/function_detector.hpp
+++ b/boost/container/detail/function_detector.hpp
@@ -1,6 +1,6 @@
/////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2009-2012.
+// (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
@@ -22,6 +22,10 @@
#ifndef BOOST_CONTAINER_DETAIL_FUNCTION_DETECTOR_HPP
#define BOOST_CONTAINER_DETAIL_FUNCTION_DETECTOR_HPP
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <boost/container/detail/config_begin.hpp>
namespace boost {
diff --git a/boost/container/detail/hash_table.hpp b/boost/container/detail/hash_table.hpp
new file mode 100644
index 0000000000..da7bb536e4
--- /dev/null
+++ b/boost/container/detail/hash_table.hpp
@@ -0,0 +1,383 @@
+/*
+template <class Value, unsigned int Options = 0, class Hash = hash<Value>, class Pred = equal_to<Value>,
+ class Alloc = allocator<Value> >
+class hash_set
+{
+public:
+ // types
+ typedef Value key_type;
+ typedef key_type value_type;
+ typedef Hash hasher;
+ typedef Pred key_equal;
+ typedef Alloc allocator_type;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef typename allocator_traits<allocator_type>::pointer pointer;
+ typedef typename allocator_traits<allocator_type>::const_pointer const_pointer;
+ typedef typename allocator_traits<allocator_type>::size_type size_type;
+ typedef typename allocator_traits<allocator_type>::difference_type difference_type;
+
+ typedef /unspecified/ iterator;
+ typedef /unspecified/ const_iterator;
+ typedef /unspecified/ local_iterator;
+ typedef /unspecified/ const_local_iterator;
+
+ hash_set()
+ noexcept(
+ is_nothrow_default_constructible<hasher>::value &&
+ is_nothrow_default_constructible<key_equal>::value &&
+ is_nothrow_default_constructible<allocator_type>::value);
+ explicit hash_set(size_type n, const hasher& hf = hasher(),
+ const key_equal& eql = key_equal(),
+ const allocator_type& a = allocator_type());
+ template <class InputIterator>
+ hash_set(InputIterator f, InputIterator l,
+ size_type n = 0, const hasher& hf = hasher(),
+ const key_equal& eql = key_equal(),
+ const allocator_type& a = allocator_type());
+ explicit hash_set(const allocator_type&);
+ hash_set(const hash_set&);
+ hash_set(const hash_set&, const Allocator&);
+ hash_set(hash_set&&)
+ noexcept(
+ is_nothrow_move_constructible<hasher>::value &&
+ is_nothrow_move_constructible<key_equal>::value &&
+ is_nothrow_move_constructible<allocator_type>::value);
+ hash_set(hash_set&&, const Allocator&);
+ hash_set(initializer_list<value_type>, size_type n = 0,
+ const hasher& hf = hasher(), const key_equal& eql = key_equal(),
+ const allocator_type& a = allocator_type());
+ ~hash_set();
+ hash_set& operator=(const hash_set&);
+ hash_set& operator=(hash_set&&)
+ noexcept(
+ allocator_type::propagate_on_container_move_assignment::value &&
+ is_nothrow_move_assignable<allocator_type>::value &&
+ is_nothrow_move_assignable<hasher>::value &&
+ is_nothrow_move_assignable<key_equal>::value);
+ hash_set& operator=(initializer_list<value_type>);
+
+ allocator_type get_allocator() const noexcept;
+
+ bool empty() const noexcept;
+ size_type size() const noexcept;
+ size_type max_size() const noexcept;
+
+ iterator begin() noexcept;
+ iterator end() noexcept;
+ const_iterator begin() const noexcept;
+ const_iterator end() const noexcept;
+ const_iterator cbegin() const noexcept;
+ const_iterator cend() const noexcept;
+
+ template <class... Args>
+ pair<iterator, bool> emplace(Args&&... args);
+ template <class... Args>
+ iterator emplace_hint(const_iterator position, Args&&... args);
+ pair<iterator, bool> insert(const value_type& obj);
+ pair<iterator, bool> insert(value_type&& obj);
+ iterator insert(const_iterator hint, const value_type& obj);
+ iterator insert(const_iterator hint, value_type&& obj);
+ template <class InputIterator>
+ void insert(InputIterator first, InputIterator last);
+ void insert(initializer_list<value_type>);
+
+ iterator erase(const_iterator position);
+ size_type erase(const key_type& k);
+ iterator erase(const_iterator first, const_iterator last);
+ void clear() noexcept;
+
+ void swap(hash_set&)
+ noexcept(
+ (!allocator_type::propagate_on_container_swap::value ||
+ __is_nothrow_swappable<allocator_type>::value) &&
+ __is_nothrow_swappable<hasher>::value &&
+ __is_nothrow_swappable<key_equal>::value);
+
+ hasher hash_function() const;
+ key_equal key_eq() const;
+
+ iterator find(const key_type& k);
+ const_iterator find(const key_type& k) const;
+ size_type count(const key_type& k) const;
+ pair<iterator, iterator> equal_range(const key_type& k);
+ pair<const_iterator, const_iterator> equal_range(const key_type& k) const;
+
+ size_type bucket_count() const noexcept;
+ size_type max_bucket_count() const noexcept;
+
+ size_type bucket_size(size_type n) const;
+ size_type bucket(const key_type& k) const;
+
+ local_iterator begin(size_type n);
+ local_iterator end(size_type n);
+ const_local_iterator begin(size_type n) const;
+ const_local_iterator end(size_type n) const;
+ const_local_iterator cbegin(size_type n) const;
+ const_local_iterator cend(size_type n) const;
+
+ float load_factor() const noexcept;
+ float max_load_factor() const noexcept;
+ void max_load_factor(float z);
+ void rehash(size_type n);
+ void reserve(size_type n);
+};
+
+template <class Key, class T, unsigned int Options = 0, class Hash = hash<Key>, class Pred = equal_to<Key>,
+ class Alloc = allocator<pair<const Key, T> > >
+class hash_map
+{
+public:
+ // types
+ typedef Key key_type;
+ typedef T mapped_type;
+ typedef Hash hasher;
+ typedef Pred key_equal;
+ typedef Alloc allocator_type;
+ typedef pair<const key_type, mapped_type> value_type;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef typename allocator_traits<allocator_type>::pointer pointer;
+ typedef typename allocator_traits<allocator_type>::const_pointer const_pointer;
+ typedef typename allocator_traits<allocator_type>::size_type size_type;
+ typedef typename allocator_traits<allocator_type>::difference_type difference_type;
+
+ typedef /unspecified/ iterator;
+ typedef /unspecified/ const_iterator;
+ typedef /unspecified/ local_iterator;
+ typedef /unspecified/ const_local_iterator;
+
+ hash_map()
+ noexcept(
+ is_nothrow_default_constructible<hasher>::value &&
+ is_nothrow_default_constructible<key_equal>::value &&
+ is_nothrow_default_constructible<allocator_type>::value);
+ explicit hash_map(size_type n, const hasher& hf = hasher(),
+ const key_equal& eql = key_equal(),
+ const allocator_type& a = allocator_type());
+ template <class InputIterator>
+ hash_map(InputIterator f, InputIterator l,
+ size_type n = 0, const hasher& hf = hasher(),
+ const key_equal& eql = key_equal(),
+ const allocator_type& a = allocator_type());
+ explicit hash_map(const allocator_type&);
+ hash_map(const hash_map&);
+ hash_map(const hash_map&, const Allocator&);
+ hash_map(hash_map&&)
+ noexcept(
+ is_nothrow_move_constructible<hasher>::value &&
+ is_nothrow_move_constructible<key_equal>::value &&
+ is_nothrow_move_constructible<allocator_type>::value);
+ hash_map(hash_map&&, const Allocator&);
+ hash_map(initializer_list<value_type>, size_type n = 0,
+ const hasher& hf = hasher(), const key_equal& eql = key_equal(),
+ const allocator_type& a = allocator_type());
+ ~hash_map();
+ hash_map& operator=(const hash_map&);
+ hash_map& operator=(hash_map&&)
+ noexcept(
+ allocator_type::propagate_on_container_move_assignment::value &&
+ is_nothrow_move_assignable<allocator_type>::value &&
+ is_nothrow_move_assignable<hasher>::value &&
+ is_nothrow_move_assignable<key_equal>::value);
+ hash_map& operator=(initializer_list<value_type>);
+
+ allocator_type get_allocator() const noexcept;
+
+ bool empty() const noexcept;
+ size_type size() const noexcept;
+ size_type max_size() const noexcept;
+
+ iterator begin() noexcept;
+ iterator end() noexcept;
+ const_iterator begin() const noexcept;
+ const_iterator end() const noexcept;
+ const_iterator cbegin() const noexcept;
+ const_iterator cend() const noexcept;
+
+ template <class... Args>
+ pair<iterator, bool> emplace(Args&&... args);
+ template <class... Args>
+ iterator emplace_hint(const_iterator position, Args&&... args);
+ pair<iterator, bool> insert(const value_type& obj);
+ template <class P>
+ pair<iterator, bool> insert(P&& obj);
+ iterator insert(const_iterator hint, const value_type& obj);
+ template <class P>
+ iterator insert(const_iterator hint, P&& obj);
+ template <class InputIterator>
+ void insert(InputIterator first, InputIterator last);
+ void insert(initializer_list<value_type>);
+
+ iterator erase(const_iterator position);
+ size_type erase(const key_type& k);
+ iterator erase(const_iterator first, const_iterator last);
+ void clear() noexcept;
+
+ void swap(hash_map&)
+ noexcept(
+ (!allocator_type::propagate_on_container_swap::value ||
+ __is_nothrow_swappable<allocator_type>::value) &&
+ __is_nothrow_swappable<hasher>::value &&
+ __is_nothrow_swappable<key_equal>::value);
+
+ hasher hash_function() const;
+ key_equal key_eq() const;
+
+ iterator find(const key_type& k);
+ const_iterator find(const key_type& k) const;
+ size_type count(const key_type& k) const;
+ pair<iterator, iterator> equal_range(const key_type& k);
+ pair<const_iterator, const_iterator> equal_range(const key_type& k) const;
+
+ mapped_type& operator[](const key_type& k);
+ mapped_type& operator[](key_type&& k);
+
+ mapped_type& at(const key_type& k);
+ const mapped_type& at(const key_type& k) const;
+
+ size_type bucket_count() const noexcept;
+ size_type max_bucket_count() const noexcept;
+
+ size_type bucket_size(size_type n) const;
+ size_type bucket(const key_type& k) const;
+
+ local_iterator begin(size_type n);
+ local_iterator end(size_type n);
+ const_local_iterator begin(size_type n) const;
+ const_local_iterator end(size_type n) const;
+ const_local_iterator cbegin(size_type n) const;
+ const_local_iterator cend(size_type n) const;
+
+ float load_factor() const noexcept;
+ float max_load_factor() const noexcept;
+ void max_load_factor(float z);
+ void rehash(size_type n);
+ void reserve(size_type n);
+};
+
+*/
+
+template <class Key, class Value, class KeyOfValue, unsigned int Options = 0, class Hash = hash<Key>, class Pred = equal_to<Key>,
+ class Alloc = allocator<Value> >
+class hash_table
+{
+public:
+ // types
+ typedef Value key_type;
+ typedef key_type value_type;
+ typedef Hash hasher;
+ typedef Pred key_equal;
+ typedef Alloc allocator_type;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef typename allocator_traits<allocator_type>::pointer pointer;
+ typedef typename allocator_traits<allocator_type>::const_pointer const_pointer;
+ typedef typename allocator_traits<allocator_type>::size_type size_type;
+ typedef typename allocator_traits<allocator_type>::difference_type difference_type;
+
+ typedef /unspecified/ iterator;
+ typedef /unspecified/ const_iterator;
+ typedef /unspecified/ local_iterator;
+ typedef /unspecified/ const_local_iterator;
+
+ hash_set()
+ noexcept(
+ is_nothrow_default_constructible<hasher>::value &&
+ is_nothrow_default_constructible<key_equal>::value &&
+ is_nothrow_default_constructible<allocator_type>::value);
+ explicit hash_set(size_type n, const hasher& hf = hasher(),
+ const key_equal& eql = key_equal(),
+ const allocator_type& a = allocator_type());
+ template <class InputIterator>
+ hash_set(InputIterator f, InputIterator l,
+ size_type n = 0, const hasher& hf = hasher(),
+ const key_equal& eql = key_equal(),
+ const allocator_type& a = allocator_type());
+ explicit hash_set(const allocator_type&);
+ hash_set(const hash_set&);
+ hash_set(const hash_set&, const Allocator&);
+ hash_set(hash_set&&)
+ noexcept(
+ is_nothrow_move_constructible<hasher>::value &&
+ is_nothrow_move_constructible<key_equal>::value &&
+ is_nothrow_move_constructible<allocator_type>::value);
+ hash_set(hash_set&&, const Allocator&);
+ hash_set(initializer_list<value_type>, size_type n = 0,
+ const hasher& hf = hasher(), const key_equal& eql = key_equal(),
+ const allocator_type& a = allocator_type());
+ ~hash_set();
+ hash_set& operator=(const hash_set&);
+ hash_set& operator=(hash_set&&)
+ noexcept(
+ allocator_type::propagate_on_container_move_assignment::value &&
+ is_nothrow_move_assignable<allocator_type>::value &&
+ is_nothrow_move_assignable<hasher>::value &&
+ is_nothrow_move_assignable<key_equal>::value);
+ hash_set& operator=(initializer_list<value_type>);
+
+ allocator_type get_allocator() const noexcept;
+
+ bool empty() const noexcept;
+ size_type size() const noexcept;
+ size_type max_size() const noexcept;
+
+ iterator begin() noexcept;
+ iterator end() noexcept;
+ const_iterator begin() const noexcept;
+ const_iterator end() const noexcept;
+ const_iterator cbegin() const noexcept;
+ const_iterator cend() const noexcept;
+
+ template <class... Args>
+ pair<iterator, bool> emplace(Args&&... args);
+ template <class... Args>
+ iterator emplace_hint(const_iterator position, Args&&... args);
+ pair<iterator, bool> insert(const value_type& obj);
+ pair<iterator, bool> insert(value_type&& obj);
+ iterator insert(const_iterator hint, const value_type& obj);
+ iterator insert(const_iterator hint, value_type&& obj);
+ template <class InputIterator>
+ void insert(InputIterator first, InputIterator last);
+ void insert(initializer_list<value_type>);
+
+ iterator erase(const_iterator position);
+ size_type erase(const key_type& k);
+ iterator erase(const_iterator first, const_iterator last);
+ void clear() noexcept;
+
+ void swap(hash_set&)
+ noexcept(
+ (!allocator_type::propagate_on_container_swap::value ||
+ __is_nothrow_swappable<allocator_type>::value) &&
+ __is_nothrow_swappable<hasher>::value &&
+ __is_nothrow_swappable<key_equal>::value);
+
+ hasher hash_function() const;
+ key_equal key_eq() const;
+
+ iterator find(const key_type& k);
+ const_iterator find(const key_type& k) const;
+ size_type count(const key_type& k) const;
+ pair<iterator, iterator> equal_range(const key_type& k);
+ pair<const_iterator, const_iterator> equal_range(const key_type& k) const;
+
+ size_type bucket_count() const noexcept;
+ size_type max_bucket_count() const noexcept;
+
+ size_type bucket_size(size_type n) const;
+ size_type bucket(const key_type& k) const;
+
+ local_iterator begin(size_type n);
+ local_iterator end(size_type n);
+ const_local_iterator begin(size_type n) const;
+ const_local_iterator end(size_type n) const;
+ const_local_iterator cbegin(size_type n) const;
+ const_local_iterator cend(size_type n) const;
+
+ float load_factor() const noexcept;
+ float max_load_factor() const noexcept;
+ void max_load_factor(float z);
+ void rehash(size_type n);
+ void reserve(size_type n);
+};
diff --git a/boost/container/detail/iterators.hpp b/boost/container/detail/iterators.hpp
index 374b55c836..0dabd3c73e 100644
--- a/boost/container/detail/iterators.hpp
+++ b/boost/container/detail/iterators.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012.
+// (C) Copyright Ion Gaztanaga 2005-2013.
// (C) Copyright Gennaro Prota 2003 - 2004.
//
// Distributed under the Boost Software License, Version 1.0.
@@ -14,18 +14,20 @@
#ifndef BOOST_CONTAINER_DETAIL_ITERATORS_HPP
#define BOOST_CONTAINER_DETAIL_ITERATORS_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
-#include "config_begin.hpp"
+#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
-#include <boost/move/move.hpp>
#include <boost/container/allocator_traits.hpp>
+#include <boost/container/detail/type_traits.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/move/utility_core.hpp>
+#include <boost/intrusive/detail/reverse_iterator.hpp>
#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
#include <boost/container/detail/variadic_templates_tools.hpp>
-#include <boost/container/detail/stored_ref.hpp>
#else
#include <boost/container/detail/preprocessor.hpp>
#endif
@@ -52,7 +54,7 @@ class constant_iterator
constant_iterator& operator++()
{ increment(); return *this; }
-
+
constant_iterator operator++(int)
{
constant_iterator result (*this);
@@ -62,7 +64,7 @@ class constant_iterator
constant_iterator& operator--()
{ decrement(); return *this; }
-
+
constant_iterator operator--(int)
{
constant_iterator result (*this);
@@ -114,7 +116,7 @@ class constant_iterator
const T& operator*() const
{ return dereference(); }
- const T& operator[] (Difference n) const
+ const T& operator[] (Difference ) const
{ return dereference(); }
const T* operator->() const
@@ -146,90 +148,199 @@ class constant_iterator
{ return m_num - other.m_num; }
};
-template <class T, class Difference = std::ptrdiff_t>
-class default_construct_iterator
+template <class T, class Difference>
+class value_init_construct_iterator
: public std::iterator
<std::random_access_iterator_tag, T, Difference, const T*, const T &>
{
- typedef default_construct_iterator<T, Difference> this_type;
+ typedef value_init_construct_iterator<T, Difference> this_type;
public:
- explicit default_construct_iterator(Difference range_size)
+ explicit value_init_construct_iterator(Difference range_size)
: m_num(range_size){}
//Constructors
- default_construct_iterator()
+ value_init_construct_iterator()
: m_num(0){}
- default_construct_iterator& operator++()
+ value_init_construct_iterator& operator++()
{ increment(); return *this; }
-
- default_construct_iterator operator++(int)
+
+ value_init_construct_iterator operator++(int)
{
- default_construct_iterator result (*this);
+ value_init_construct_iterator result (*this);
increment();
return result;
}
- default_construct_iterator& operator--()
+ value_init_construct_iterator& operator--()
{ decrement(); return *this; }
-
- default_construct_iterator operator--(int)
+
+ value_init_construct_iterator operator--(int)
{
- default_construct_iterator result (*this);
+ value_init_construct_iterator result (*this);
decrement();
return result;
}
- friend bool operator== (const default_construct_iterator& i, const default_construct_iterator& i2)
+ friend bool operator== (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
{ return i.equal(i2); }
- friend bool operator!= (const default_construct_iterator& i, const default_construct_iterator& i2)
+ friend bool operator!= (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
{ return !(i == i2); }
- friend bool operator< (const default_construct_iterator& i, const default_construct_iterator& i2)
+ friend bool operator< (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
{ return i.less(i2); }
- friend bool operator> (const default_construct_iterator& i, const default_construct_iterator& i2)
+ friend bool operator> (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
{ return i2 < i; }
- friend bool operator<= (const default_construct_iterator& i, const default_construct_iterator& i2)
+ friend bool operator<= (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
{ return !(i > i2); }
- friend bool operator>= (const default_construct_iterator& i, const default_construct_iterator& i2)
+ friend bool operator>= (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
{ return !(i < i2); }
- friend Difference operator- (const default_construct_iterator& i, const default_construct_iterator& i2)
+ friend Difference operator- (const value_init_construct_iterator& i, const value_init_construct_iterator& i2)
{ return i2.distance_to(i); }
//Arithmetic
- default_construct_iterator& operator+=(Difference off)
+ value_init_construct_iterator& operator+=(Difference off)
{ this->advance(off); return *this; }
- default_construct_iterator operator+(Difference off) const
+ value_init_construct_iterator operator+(Difference off) const
{
- default_construct_iterator other(*this);
+ value_init_construct_iterator other(*this);
other.advance(off);
return other;
}
- friend default_construct_iterator operator+(Difference off, const default_construct_iterator& right)
+ friend value_init_construct_iterator operator+(Difference off, const value_init_construct_iterator& right)
{ return right + off; }
- default_construct_iterator& operator-=(Difference off)
+ value_init_construct_iterator& operator-=(Difference off)
{ this->advance(-off); return *this; }
- default_construct_iterator operator-(Difference off) const
+ value_init_construct_iterator operator-(Difference off) const
{ return *this + (-off); }
- const T& operator*() const
- { return dereference(); }
+ //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;
- const T* operator->() const
- { return &(dereference()); }
+ private:
+ Difference m_num;
- const T& operator[] (Difference n) const
- { return dereference(); }
+ 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 std::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;
@@ -259,6 +370,7 @@ class default_construct_iterator
{ return m_num - other.m_num; }
};
+
template <class T, class Difference = std::ptrdiff_t>
class repeat_iterator
: public std::iterator
@@ -275,7 +387,7 @@ class repeat_iterator
this_type& operator++()
{ increment(); return *this; }
-
+
this_type operator++(int)
{
this_type result (*this);
@@ -285,7 +397,7 @@ class repeat_iterator
this_type& operator--()
{ increment(); return *this; }
-
+
this_type operator--(int)
{
this_type result (*this);
@@ -337,7 +449,7 @@ class repeat_iterator
T& operator*() const
{ return dereference(); }
- T& operator[] (Difference n) const
+ T& operator[] (Difference ) const
{ return dereference(); }
T *operator->() const
@@ -386,7 +498,7 @@ class emplace_iterator
this_type& operator++()
{ increment(); return *this; }
-
+
this_type operator++(int)
{
this_type result (*this);
@@ -396,7 +508,7 @@ class emplace_iterator
this_type& operator--()
{ decrement(); return *this; }
-
+
this_type operator--(int)
{
this_type result (*this);
@@ -445,14 +557,12 @@ class emplace_iterator
this_type operator-(difference_type off) const
{ return *this + (-off); }
- const T& operator*() const
- { return dereference(); }
-
- const T& operator[](difference_type) const
- { return dereference(); }
-
- const T* operator->() const
- { return &(dereference()); }
+ //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;
template<class A>
void construct_in_place(A &a, T* ptr)
@@ -506,8 +616,7 @@ struct emplace_functor
void inplace_impl(A &a, T* ptr, const container_detail::index_tuple<IdxPack...>&)
{
allocator_traits<A>::construct
- (a, ptr, container_detail::stored_ref<Args>::forward
- (container_detail::get<IdxPack>(args_))...);
+ (a, ptr, ::boost::forward<Args>(container_detail::get<IdxPack>(args_))...);
}
container_detail::tuple<Args&...> args_;
@@ -539,10 +648,174 @@ struct emplace_functor
#endif
+namespace container_detail {
+
+template<class T>
+struct has_iterator_category
+{
+ template <typename X>
+ static char test(int, typename X::iterator_category*);
+
+ template <typename X>
+ static int 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, 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 std::iterator_traits<IIterator>::pointer it_pointer;
+ typedef typename std::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 std_iterator
+{
+ typedef typename std::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 std_iterator<IIterator, false>
+{
+ typedef typename std::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
+{
+ typedef typename std_iterator<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;
+
+ iterator()
+ {}
+
+ explicit iterator(IIterator iit) BOOST_CONTAINER_NOEXCEPT
+ : m_iit(iit)
+ {}
+
+ iterator(iterator<IIterator, false> const& other) BOOST_CONTAINER_NOEXCEPT
+ : m_iit(other.get())
+ {}
+
+ iterator& operator++() BOOST_CONTAINER_NOEXCEPT
+ { ++this->m_iit; return *this; }
+
+ iterator operator++(int) BOOST_CONTAINER_NOEXCEPT
+ {
+ iterator result (*this);
+ ++this->m_iit;
+ return result;
+ }
+
+ iterator& operator--() BOOST_CONTAINER_NOEXCEPT
+ {
+ //If the iterator is not a bidirectional iterator, operator-- should not exist
+ BOOST_STATIC_ASSERT((is_bidirectional_iterator<iterator>::value));
+ --this->m_iit; return *this;
+ }
+
+ iterator operator--(int) BOOST_CONTAINER_NOEXCEPT
+ {
+ iterator result (*this);
+ --this->m_iit;
+ return result;
+ }
+
+ friend bool operator== (const iterator& l, const iterator& r) BOOST_CONTAINER_NOEXCEPT
+ { return l.m_iit == r.m_iit; }
+
+ friend bool operator!= (const iterator& l, const iterator& r) BOOST_CONTAINER_NOEXCEPT
+ { return !(l == r); }
+
+ reference operator*() const BOOST_CONTAINER_NOEXCEPT
+ { return (*this->m_iit).get_data(); }
+
+ pointer operator->() const BOOST_CONTAINER_NOEXCEPT
+ { return ::boost::intrusive::pointer_traits<pointer>::pointer_to(this->operator*()); }
+
+ const IIterator &get() const BOOST_CONTAINER_NOEXCEPT
+ { return this->m_iit; }
+
+ private:
+ IIterator m_iit;
+};
+
+using ::boost::intrusive::detail::reverse_iterator;
+
+} //namespace container_detail {
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINER_DETAIL_ITERATORS_HPP
-
diff --git a/boost/container/detail/math_functions.hpp b/boost/container/detail/math_functions.hpp
index fe8386be69..6853b9c59f 100644
--- a/boost/container/detail/math_functions.hpp
+++ b/boost/container/detail/math_functions.hpp
@@ -1,7 +1,7 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Stephen Cleary 2000.
-// (C) Copyright Ion Gaztanaga 2007-2012.
+// (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
@@ -16,7 +16,13 @@
#ifndef BOOST_CONTAINER_DETAIL_MATH_FUNCTIONS_HPP
#define BOOST_CONTAINER_DETAIL_MATH_FUNCTIONS_HPP
-#include "config_begin.hpp"
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+
#include <climits>
#include <boost/static_assert.hpp>
@@ -94,7 +100,7 @@ inline std::size_t floor_log2 (std::size_t x)
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)
diff --git a/boost/container/detail/memory_util.hpp b/boost/container/detail/memory_util.hpp
index c00172c60c..7f055cb55b 100644
--- a/boost/container/detail/memory_util.hpp
+++ b/boost/container/detail/memory_util.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2011-2012. Distributed under the Boost
+// (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)
//
@@ -11,26 +11,28 @@
#ifndef BOOST_CONTAINER_ALLOCATOR_MEMORY_UTIL_HPP
#define BOOST_CONTAINER_ALLOCATOR_MEMORY_UTIL_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
+
#include <boost/container/detail/preprocessor.hpp>
+#include <boost/intrusive/detail/mpl.hpp>
#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME allocate
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace container { namespace container_detail {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
-#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, 2, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
+#define BOOST_PP_ITERATION_PARAMS_1 (3, (2, 2, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
#include BOOST_PP_ITERATE()
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME destroy
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace container { namespace container_detail {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
-#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, 3, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
+#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 1, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
#include BOOST_PP_ITERATE()
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME max_size
@@ -48,14 +50,23 @@
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME construct
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace container { namespace container_detail {
#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
-#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS+1, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
+#ifdef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_SINGLE_ITERATION
+# define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 1, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
+#else
+# define BOOST_PP_ITERATION_PARAMS_1 (3, (1, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS+1, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
+#endif
+#include BOOST_PP_ITERATE()
+
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME swap
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN namespace boost { namespace container { namespace container_detail {
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END }}}
+#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, 1, <boost/intrusive/detail/has_member_function_callable_with.hpp>))
#include BOOST_PP_ITERATE()
namespace boost {
namespace container {
namespace container_detail {
-
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(pointer)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(const_pointer)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(reference)
@@ -67,6 +78,8 @@ BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(propagate_on_container_copy_assig
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(propagate_on_container_move_assignment)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(propagate_on_container_swap)
BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(difference_type)
+BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(value_compare)
+BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(wrapped_value_compare)
} //namespace container_detail {
} //namespace container {
diff --git a/boost/container/detail/mpl.hpp b/boost/container/detail/mpl.hpp
index 74a1ce0e67..ceac52a371 100644
--- a/boost/container/detail/mpl.hpp
+++ b/boost/container/detail/mpl.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012.
+// (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
@@ -13,10 +13,13 @@
#ifndef BOOST_CONTAINER_CONTAINER_DETAIL_MPL_HPP
#define BOOST_CONTAINER_CONTAINER_DETAIL_MPL_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+
#include <cstddef>
namespace boost {
@@ -66,18 +69,32 @@ struct disable_if : public enable_if_c<!Cond::value, T> {};
template <bool B, class T = void>
struct disable_if_c : public enable_if_c<!B, T> {};
+#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+
+template <class T, class U>
+struct is_convertible
+{
+ static const bool value = __is_convertible_to(T, U);
+};
+
+#else
+
template <class T, class U>
class is_convertible
{
typedef char true_t;
class false_t { char dummy[2]; };
- static true_t dispatch(U);
+ //use any_conversion as first parameter since in MSVC
+ //overaligned types can't go through ellipsis
static false_t dispatch(...);
- static T trigger();
+ static true_t dispatch(U);
+ static T &trigger();
public:
- enum { value = sizeof(dispatch(trigger())) == sizeof(true_t) };
+ static const bool value = sizeof(dispatch(trigger())) == sizeof(true_t);
};
+#endif
+
template<
bool C
, typename T1
@@ -110,8 +127,10 @@ struct if_
template <class Pair>
struct select1st
-// : public std::unary_function<Pair, typename Pair::first_type>
{
+ typedef Pair argument_type;
+ typedef typename Pair::first_type result_type;
+
template<class OtherPair>
const typename Pair::first_type& operator()(const OtherPair& x) const
{ return x.first; }
@@ -123,8 +142,10 @@ struct select1st
// identity is an extension: it is not part of the standard.
template <class T>
struct identity
-// : public std::unary_function<T,T>
{
+ typedef T argument_type;
+ typedef T result_type;
+
typedef T type;
const T& operator()(const T& x) const
{ return x; }
@@ -156,5 +177,7 @@ template <> struct unvoid<const void> { struct type { }; };
} //namespace container {
} //namespace boost {
+#include <boost/container/detail/config_end.hpp>
+
#endif //#ifndef BOOST_CONTAINER_CONTAINER_DETAIL_MPL_HPP
diff --git a/boost/container/detail/multiallocation_chain.hpp b/boost/container/detail/multiallocation_chain.hpp
index c9952535eb..96f6202671 100644
--- a/boost/container/detail/multiallocation_chain.hpp
+++ b/boost/container/detail/multiallocation_chain.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
+// (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)
//
@@ -11,7 +11,13 @@
#ifndef BOOST_CONTAINER_DETAIL_MULTIALLOCATION_CHAIN_HPP
#define BOOST_CONTAINER_DETAIL_MULTIALLOCATION_CHAIN_HPP
-#include "config_begin.hpp"
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+
#include <boost/container/container_fwd.hpp>
#include <boost/container/detail/utilities.hpp>
#include <boost/container/detail/type_traits.hpp>
@@ -19,7 +25,7 @@
#include <boost/intrusive/slist.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/type_traits/make_unsigned.hpp>
-#include <boost/move/move.hpp>
+#include <boost/move/utility_core.hpp>
namespace boost {
namespace container {
@@ -45,30 +51,43 @@ class basic_multiallocation_chain
> slist_impl_t;
slist_impl_t slist_impl_;
- static node & to_node(VoidPointer p)
- { return *static_cast<node*>(static_cast<void*>(container_detail::to_raw_pointer(p))); }
+ 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*>(container_detail::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;
+ 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_()
- { slist_impl_.swap(other.slist_impl_); }
+ : slist_impl_(::boost::move(other.slist_impl_))
+ {}
basic_multiallocation_chain& operator=(BOOST_RV_REF(basic_multiallocation_chain) other)
{
- basic_multiallocation_chain tmp(boost::move(other));
- this->swap(tmp);
+ slist_impl_ = ::boost::move(other.slist_impl_);
return *this;
}
@@ -96,37 +115,52 @@ class basic_multiallocation_chain
iterator insert_after(iterator it, void_pointer m)
{ return slist_impl_.insert_after(it, to_node(m)); }
- void push_front(void_pointer m)
- { return slist_impl_.push_front(to_node(m)); }
+ void push_front(const void_pointer &m)
+ { return slist_impl_.push_front(to_node(m)); }
- void push_back(void_pointer m)
+ void push_back(const void_pointer &m)
{ return slist_impl_.push_back(to_node(m)); }
- void pop_front()
- { return slist_impl_.pop_front(); }
-
- void *front()
- { return &*slist_impl_.begin(); }
-
- void splice_after(iterator after_this, basic_multiallocation_chain &x, iterator before_begin, iterator before_end)
- { slist_impl_.splice_after(after_this, x.slist_impl_, before_begin, before_end); }
+ 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_begin, iterator before_end, size_type n)
- { slist_impl_.splice_after(after_this, x.slist_impl_, before_begin, before_end, n); }
+ 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 incorporate_after(iterator after_this, void_pointer begin , iterator before_end)
- { slist_impl_.incorporate_after(after_this, &to_node(begin), &to_node(before_end)); }
+ void erase_after(iterator before_b, iterator e, size_type n)
+ { slist_impl_.erase_after(before_b, e, n); }
- void incorporate_after(iterator after_this, void_pointer begin, void_pointer before_end, size_type n)
- { slist_impl_.incorporate_after(after_this, &to_node(begin), &to_node(before_end), 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 (container_detail::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(void_pointer p)
+ 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()
@@ -150,72 +184,75 @@ struct cast_functor
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 &);
- MultiallocationChain holder_;
typedef typename MultiallocationChain::void_pointer void_pointer;
typedef typename boost::intrusive::pointer_traits
- <void_pointer>::template rebind_pointer<T>::type pointer;
+ <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(void_pointer p)
- {
- return pointer(static_cast<T*>(container_detail::to_raw_pointer(p)));
- }
+ static pointer cast(const void_pointer &p)
+ { return pointer_traits::static_cast_from(p); }
public:
typedef transform_iterator
< typename MultiallocationChain::iterator
- , container_detail::cast_functor <T> > iterator;
- typedef typename MultiallocationChain::size_type size_type;
+ , container_detail::cast_functor <T> > iterator;
+ typedef typename MultiallocationChain::size_type size_type;
transform_multiallocation_chain()
- : holder_()
+ : MultiallocationChain()
{}
transform_multiallocation_chain(BOOST_RV_REF(transform_multiallocation_chain) other)
- : holder_()
- { this->swap(other); }
+ : MultiallocationChain(::boost::move(static_cast<MultiallocationChain&>(other)))
+ {}
transform_multiallocation_chain(BOOST_RV_REF(MultiallocationChain) other)
- : holder_(boost::move(other))
+ : MultiallocationChain(::boost::move(static_cast<MultiallocationChain&>(other)))
{}
transform_multiallocation_chain& operator=(BOOST_RV_REF(transform_multiallocation_chain) other)
{
- transform_multiallocation_chain tmp(boost::move(other));
- this->swap(tmp);
- return *this;
+ return static_cast<MultiallocationChain&>
+ (this->MultiallocationChain::operator=(::boost::move(static_cast<MultiallocationChain&>(other))));
}
-
- void push_front(pointer mem)
+/*
+ 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_begin, iterator before_end, size_type n)
- { holder_.splice_after(after_this.base(), x.holder_, before_begin.base(), before_end.base(), n); }
-
- void incorporate_after(iterator after_this, void_pointer begin, void_pointer before_end, size_type n)
- { holder_.incorporate_after(after_this.base(), begin, before_end, n); }
-
- void pop_front()
- { holder_.pop_front(); }
-
- pointer front()
- { return cast(holder_.front()); }
+ 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(holder_.begin()); }
-
+ { return iterator(this->MultiallocationChain::begin()); }
+/*
iterator end()
{ return iterator(holder_.end()); }
@@ -227,20 +264,21 @@ class transform_multiallocation_chain
void clear()
{ holder_.clear(); }
-
+*/
iterator insert_after(iterator it, pointer m)
- { return iterator(holder_.insert_after(it.base(), m)); }
+ { return iterator(this->MultiallocationChain::insert_after(it.base(), m)); }
- static iterator iterator_to(pointer p)
+ static iterator iterator_to(const pointer &p)
{ return iterator(MultiallocationChain::iterator_to(p)); }
- std::pair<void_pointer, void_pointer> extract_data()
- { return holder_.extract_data(); }
-
- MultiallocationChain extract_multiallocation_chain()
+ std::pair<pointer, pointer> extract_data()
{
- return MultiallocationChain(boost::move(holder_));
+ 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_; }*/
};
}}}
diff --git a/boost/container/detail/mutex.hpp b/boost/container/detail/mutex.hpp
new file mode 100644
index 0000000000..c53afa1f42
--- /dev/null
+++ b/boost/container/detail/mutex.hpp
@@ -0,0 +1,284 @@
+// Copyright (C) 2000 Stephen Cleary
+//
+// 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.
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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_MUTEX_HPP
+#define BOOST_CONTAINER_MUTEX_HPP
+
+#if defined(_MSC_VER)
+# 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 FORCEINLINE 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 FORCEINLINE 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_CONTAINER_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 container_detail {
+
+#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_CONTAINER_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 container_detail
+} // 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/boost/container/detail/node_alloc_holder.hpp b/boost/container/detail/node_alloc_holder.hpp
index 9797f1fbd5..250c559765 100644
--- a/boost/container/detail/node_alloc_holder.hpp
+++ b/boost/container/detail/node_alloc_holder.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
+// (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)
//
@@ -11,163 +11,89 @@
#ifndef BOOST_CONTAINER_DETAIL_NODE_ALLOC_HPP_
#define BOOST_CONTAINER_DETAIL_NODE_ALLOC_HPP_
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
-#include "config_begin.hpp"
+#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <utility>
#include <functional>
-#include <boost/move/move.hpp>
+#include <boost/move/utility_core.hpp>
#include <boost/intrusive/options.hpp>
#include <boost/container/detail/version_type.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <boost/container/detail/utilities.hpp>
#include <boost/container/allocator_traits.hpp>
+#include <boost/container/detail/allocator_version_traits.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/destroyers.hpp>
+#include <boost/container/detail/memory_util.hpp>
+#include <boost/container/detail/placement_new.hpp>
+#include <boost/core/no_exceptions_support.hpp>
#ifndef BOOST_CONTAINER_PERFECT_FORWARDING
#include <boost/container/detail/preprocessor.hpp>
#endif
#include <boost/container/detail/algorithms.hpp>
-#include <new>
+
namespace boost {
namespace container {
namespace container_detail {
-//!A deleter for scoped_ptr that deallocates the memory
-//!allocated for an object using a STL allocator.
-template <class A>
-struct scoped_deallocator
-{
- typedef allocator_traits<A> allocator_traits_type;
- typedef typename allocator_traits_type::pointer pointer;
- typedef container_detail::integral_constant<unsigned,
- boost::container::container_detail::
- version<A>::value> alloc_version;
- typedef container_detail::integral_constant<unsigned, 1> allocator_v1;
- typedef container_detail::integral_constant<unsigned, 2> allocator_v2;
-
- private:
- void priv_deallocate(allocator_v1)
- { m_alloc.deallocate(m_ptr, 1); }
-
- void priv_deallocate(allocator_v2)
- { m_alloc.deallocate_one(m_ptr); }
-
- BOOST_MOVABLE_BUT_NOT_COPYABLE(scoped_deallocator)
-
- public:
-
- pointer m_ptr;
- A& m_alloc;
-
- scoped_deallocator(pointer p, A& 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 release()
- { m_ptr = 0; }
-};
-
-template <class A>
-class allocator_destroyer_and_chain_builder
-{
- typedef allocator_traits<A> allocator_traits_type;
- typedef typename allocator_traits_type::value_type value_type;
- typedef typename A::multiallocation_chain multiallocation_chain;
-
- A & a_;
- multiallocation_chain &c_;
-
- public:
- allocator_destroyer_and_chain_builder(A &a, multiallocation_chain &c)
- : a_(a), c_(c)
- {}
-
- void operator()(const typename A::pointer &p)
- {
- allocator_traits<A>::destroy(a_, container_detail::to_raw_pointer(p));
- c_.push_front(p);
- }
-};
-
-template <class A>
-class allocator_multialloc_chain_node_deallocator
-{
- typedef allocator_traits<A> allocator_traits_type;
- typedef typename allocator_traits_type::value_type value_type;
- typedef typename A::multiallocation_chain multiallocation_chain;
- typedef allocator_destroyer_and_chain_builder<A> chain_builder;
-
- A & a_;
- multiallocation_chain c_;
-
- public:
- allocator_multialloc_chain_node_deallocator(A &a)
- : a_(a), c_()
- {}
-
- chain_builder get_chain_builder()
- { return chain_builder(a_, c_); }
-
- ~allocator_multialloc_chain_node_deallocator()
- {
- if(!c_.empty())
- a_.deallocate_individual(boost::move(c_));
- }
-};
-
template<class ValueCompare, class Node>
struct node_compare
: private ValueCompare
{
- typedef typename ValueCompare::key_type key_type;
- typedef typename ValueCompare::value_type value_type;
- typedef typename ValueCompare::key_of_value key_of_value;
+ typedef ValueCompare wrapped_value_compare;
+ typedef typename wrapped_value_compare::key_type key_type;
+ typedef typename wrapped_value_compare::value_type value_type;
+ typedef typename wrapped_value_compare::key_of_value key_of_value;
+
+ explicit node_compare(const wrapped_value_compare &pred)
+ : wrapped_value_compare(pred)
+ {}
- node_compare(const ValueCompare &pred)
- : ValueCompare(pred)
+ node_compare()
+ : wrapped_value_compare()
{}
- ValueCompare &value_comp()
- { return static_cast<ValueCompare &>(*this); }
+ wrapped_value_compare &value_comp()
+ { return static_cast<wrapped_value_compare &>(*this); }
- ValueCompare &value_comp() const
- { return static_cast<const ValueCompare &>(*this); }
+ wrapped_value_compare &value_comp() const
+ { return static_cast<const wrapped_value_compare &>(*this); }
bool operator()(const Node &a, const Node &b) const
- { return ValueCompare::operator()(a.get_data(), b.get_data()); }
+ { return wrapped_value_compare::operator()(a.get_data(), b.get_data()); }
};
-template<class A, class ICont, class Pred = container_detail::nat>
+template<class A, class ICont>
struct node_alloc_holder
{
+ //If the intrusive container is an associative container, obtain the predicate, which will
+ //be of type node_compare<>. If not an associative container value_compare will be a "nat" type.
+ typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, ICont,
+ value_compare, container_detail::nat) intrusive_value_compare;
+ //In that case obtain the value predicate from the node predicate via wrapped_value_compare
+ //if intrusive_value_compare is node_compare<>, nat otherwise
+ typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::container_detail::, ICont,
+ wrapped_value_compare, container_detail::nat) value_compare;
+
typedef allocator_traits<A> allocator_traits_type;
- typedef node_alloc_holder<A, ICont> self_t;
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 container_detail::allocator_version_traits<NodeAlloc> node_allocator_version_traits_type;
typedef A ValAlloc;
typedef typename node_allocator_traits_type::pointer NodePtr;
typedef container_detail::scoped_deallocator<NodeAlloc> Deallocator;
@@ -182,6 +108,7 @@ struct node_alloc_holder
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)
@@ -206,25 +133,25 @@ struct node_alloc_holder
{ this->icont().swap(x.icont()); }
//Constructors for associative containers
- explicit node_alloc_holder(const ValAlloc &a, const Pred &c)
+ explicit node_alloc_holder(const ValAlloc &a, const value_compare &c)
: members_(a, c)
{}
- explicit node_alloc_holder(const node_alloc_holder &x, const Pred &c)
+ explicit 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(const Pred &c)
+ 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 Pred &c)
+ 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)
- {
+ {
container_detail::bool_<allocator_traits_type::propagate_on_container_copy_assignment::value> flag;
container_detail::assign_alloc( static_cast<NodeAlloc &>(this->members_)
, static_cast<const NodeAlloc &>(x.members_), flag);
@@ -244,22 +171,10 @@ struct node_alloc_holder
{ return allocator_traits_type::max_size(this->node_alloc()); }
NodePtr allocate_one()
- { return this->allocate_one(alloc_version()); }
-
- NodePtr allocate_one(allocator_v1)
- { return this->node_alloc().allocate(1); }
-
- NodePtr allocate_one(allocator_v2)
- { return this->node_alloc().allocate_one(); }
+ { return AllocVersionTraits::allocate_one(this->node_alloc()); }
void deallocate_one(const NodePtr &p)
- { return this->deallocate_one(p, alloc_version()); }
-
- void deallocate_one(const NodePtr &p, allocator_v1)
- { this->node_alloc().deallocate(p, 1); }
-
- void deallocate_one(const NodePtr &p, allocator_v2)
- { this->node_alloc().deallocate_one(p); }
+ { AllocVersionTraits::deallocate_one(this->node_alloc(), p); }
#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
@@ -274,7 +189,7 @@ struct node_alloc_holder
node_deallocator.release();
//This does not throw
typedef typename Node::hook_type hook_type;
- ::new(static_cast<hook_type*>(container_detail::to_raw_pointer(p))) hook_type;
+ ::new(static_cast<hook_type*>(container_detail::to_raw_pointer(p)), boost_container_new_t()) hook_type;
return (p);
}
@@ -292,7 +207,7 @@ struct node_alloc_holder
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
node_deallocator.release(); \
typedef typename Node::hook_type hook_type; \
- ::new(static_cast<hook_type*>(container_detail::to_raw_pointer(p))) hook_type; \
+ ::new(static_cast<hook_type*>(container_detail::to_raw_pointer(p)), boost_container_new_t()) hook_type; \
return (p); \
} \
//!
@@ -310,7 +225,7 @@ struct node_alloc_holder
node_deallocator.release();
//This does not throw
typedef typename Node::hook_type hook_type;
- ::new(static_cast<hook_type*>(container_detail::to_raw_pointer(p))) hook_type;
+ ::new(static_cast<hook_type*>(container_detail::to_raw_pointer(p)), boost_container_new_t()) hook_type;
return (p);
}
@@ -328,41 +243,49 @@ struct node_alloc_holder
}
template<class FwdIterator, class Inserter>
- FwdIterator allocate_many_and_construct
+ void allocate_many_and_construct
(FwdIterator beg, difference_type n, Inserter inserter)
{
if(n){
- typedef typename NodeAlloc::multiallocation_chain multiallocation_chain;
+ typedef typename node_allocator_version_traits_type::multiallocation_chain multiallocation_chain;
//Try to allocate memory in a single block
- multiallocation_chain mem(this->node_alloc().allocate_individual(n));
- int constructed = 0;
+ 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{
- for(difference_type i = 0; i < n; ++i, ++beg, --constructed){
- p = container_detail::to_raw_pointer(mem.front());
- mem.pop_front();
+ Deallocator node_deallocator(NodePtr(), nalloc);
+ container_detail::scoped_destructor<NodeAlloc> sdestructor(nalloc, 0);
+ while(n--){
+ p = container_detail::to_raw_pointer(iterator_to_pointer(itbeg));
+ node_deallocator.set(p);
+ ++itbeg;
//This can throw
- constructed = 0;
- boost::container::construct_in_place(this->node_alloc(), container_detail::addressof(p->m_data), beg);
- ++constructed;
+ boost::container::construct_in_place(nalloc, container_detail::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*>(container_detail::to_raw_pointer(p))) hook_type;
- //This can throw in some containers (predicate might throw)
+ ::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(...){
- if(constructed){
- allocator_traits<NodeAlloc>::destroy(this->node_alloc(), container_detail::to_raw_pointer(p));
- }
- this->node_alloc().deallocate_individual(boost::move(mem));
+ mem.incorporate_after(mem.last(), &*itbeg, &*itlast, n);
+ node_allocator_version_traits_type::deallocate_individual(this->node_alloc(), mem);
BOOST_RETHROW
}
BOOST_CATCH_END
}
- return beg;
}
void clear(allocator_v1)
@@ -375,7 +298,7 @@ struct node_alloc_holder
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(boost::move(chain));
+ this->node_alloc().deallocate_individual(chain);
}
icont_iterator erase_range(const icont_iterator &first, const icont_iterator &last, allocator_v1)
@@ -383,8 +306,13 @@ struct node_alloc_holder
icont_iterator erase_range(const icont_iterator &first, const icont_iterator &last, allocator_v2)
{
- allocator_multialloc_chain_node_deallocator<NodeAlloc> chain_holder(this->node_alloc());
- return this->icont().erase_and_dispose(first, last, chain_holder.get_chain_builder());
+ 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>
@@ -430,12 +358,12 @@ struct node_alloc_holder
{}
template<class ConvertibleToAlloc>
- members_holder(BOOST_FWD_REF(ConvertibleToAlloc) c2alloc, const Pred &c)
+ members_holder(BOOST_FWD_REF(ConvertibleToAlloc) c2alloc, const value_compare &c)
: NodeAlloc(boost::forward<ConvertibleToAlloc>(c2alloc))
, m_icont(typename ICont::value_compare(c))
{}
- explicit members_holder(const Pred &c)
+ explicit members_holder(const value_compare &c)
: NodeAlloc()
, m_icont(typename ICont::value_compare(c))
{}
diff --git a/boost/container/detail/node_pool.hpp b/boost/container/detail/node_pool.hpp
new file mode 100644
index 0000000000..60d826675a
--- /dev/null
+++ b/boost/container/detail/node_pool.hpp
@@ -0,0 +1,156 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# 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/intrusive/slist.hpp>
+#include <boost/move/utility_core.hpp>
+#include <cstddef>
+#include <functional> //std::unary_function
+#include <algorithm> //std::swap
+#include <cassert>
+
+namespace boost {
+namespace container {
+namespace container_detail {
+
+//!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::container_detail::
+ private_node_pool_impl<fake_segment_manager>
+{
+ typedef boost::container::container_detail::
+ 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 container_detail {
+} //namespace container {
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_CONTAINER_DETAIL_NODE_POOL_HPP
diff --git a/boost/container/detail/node_pool_impl.hpp b/boost/container/detail/node_pool_impl.hpp
index 63c1278238..2450e5103e 100644
--- a/boost/container/detail/node_pool_impl.hpp
+++ b/boost/container/detail/node_pool_impl.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
+// (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)
//
@@ -11,13 +11,14 @@
#ifndef BOOST_CONTAINER_DETAIL_NODE_POOL_IMPL_HPP
#define BOOST_CONTAINER_DETAIL_NODE_POOL_IMPL_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
-#include "config_begin.hpp"
-#include <boost/container/container_fwd.hpp>
+#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
+
+#include <boost/container/container_fwd.hpp>
#include <boost/container/detail/utilities.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/intrusive/set.hpp>
@@ -26,9 +27,9 @@
#include <boost/container/detail/math_functions.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/pool_common.hpp>
+#include <boost/core/no_exceptions_support.hpp>
#include <boost/assert.hpp>
#include <cstddef>
-#include <functional> //std::unary_function
namespace boost {
namespace container {
@@ -85,19 +86,19 @@ class private_node_pool_impl
{ return container_detail::to_raw_pointer(mp_segment_mngr_base); }
void *allocate_node()
- { return priv_alloc_node(); }
-
+ { return this->priv_alloc_node(); }
+
//!Deallocates an array pointed by ptr. Never throws
void deallocate_node(void *ptr)
- { priv_dealloc_node(ptr); }
+ { this->priv_dealloc_node(ptr); }
//!Allocates a singly linked list of n nodes ending in null pointer.
- multiallocation_chain allocate_nodes(const size_type n)
+ 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){
- priv_alloc_block(((n - cur_nodes) - 1)/m_nodes_per_block + 1);
+ 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
@@ -118,20 +119,18 @@ class private_node_pool_impl
//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.
- multiallocation_chain chain;
chain.incorporate_after(chain.before_begin(), &*first_node, &*last_node, n);
m_allocated += n;
- return boost::move(chain);
}
- void deallocate_nodes(multiallocation_chain chain)
+ 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;
- priv_dealloc_node(pElem);
+ this->priv_dealloc_node(pElem);
}
}
@@ -208,8 +207,6 @@ class private_node_pool_impl
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);
- typename blockslist_t::iterator
- it(m_blocklist.begin()), itend(m_blocklist.end()), aux;
//We iterate though the NodeBlock list to free the memory
while(!m_blocklist.empty()){
@@ -238,7 +235,7 @@ class private_node_pool_impl
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);
@@ -253,12 +250,14 @@ class private_node_pool_impl
};
struct is_between
- : std::unary_function<typename free_nodes_t::value_type, bool>
{
+ 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) &&
@@ -275,7 +274,7 @@ class private_node_pool_impl
{
//If there are no free nodes we allocate a new block
if (m_freelist.empty())
- priv_alloc_block();
+ this->priv_alloc_block(1);
//We take the first free node
node_t *n = (node_t*)&m_freelist.front();
m_freelist.pop_front();
@@ -295,14 +294,13 @@ class private_node_pool_impl
}
//!Allocates several blocks of nodes. Can throw
- void priv_alloc_block(size_type num_blocks = 1)
+ void priv_alloc_block(size_type num_blocks)
{
- if(!num_blocks)
- return;
+ 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);
- try{
+ 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
@@ -313,15 +311,16 @@ class private_node_pool_impl
//We initialize all Nodes in Node Block to insert
//them in the free Node list
- for(size_type i = 0; i < m_nodes_per_block; ++i, pNode += m_real_node_size){
+ for(size_type j = 0; j < m_nodes_per_block; ++j, pNode += m_real_node_size){
m_freelist.push_front(*new (pNode) node_t);
}
}
}
- catch(...){
+ BOOST_CATCH(...){
//to-do: if possible, an efficient way to deallocate allocated blocks
- throw;
+ BOOST_RETHROW
}
+ BOOST_CATCH_END
}
//!Deprecated, use deallocate_free_blocks
@@ -335,13 +334,13 @@ class private_node_pool_impl
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);
+ {
+ 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);
}
diff --git a/boost/container/detail/pair.hpp b/boost/container/detail/pair.hpp
index 2a20ed13ec..b7ad84c80e 100644
--- a/boost/container/detail/pair.hpp
+++ b/boost/container/detail/pair.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012.
+// (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
@@ -13,11 +13,11 @@
#ifndef BOOST_CONTAINER_CONTAINER_DETAIL_PAIR_HPP
#define BOOST_CONTAINER_CONTAINER_DETAIL_PAIR_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
-#include "config_begin.hpp"
+#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/detail/mpl.hpp>
@@ -26,9 +26,10 @@
#include <boost/container/detail/type_traits.hpp>
#include <utility> //std::pair
+#include <algorithm> //std::swap
+
+#include <boost/move/utility_core.hpp>
-#include <boost/move/move.hpp>
-#include <boost/type_traits/is_class.hpp>
#ifndef BOOST_CONTAINER_PERFECT_FORWARDING
#include <boost/container/detail/preprocessor.hpp>
@@ -329,22 +330,42 @@ struct is_enum< ::boost::container::container_detail::pair<T, U> >
static const bool value = false;
};
+template <class T>
+struct is_class;
+
//This specialization is needed to avoid instantiation of pair in
//is_class, and allow recursive maps.
template <class T1, class T2>
struct is_class< ::boost::container::container_detail::pair<T1, T2> >
- : public ::boost::true_type
-{};
+{
+ static const bool value = true;
+};
-#ifdef BOOST_NO_RVALUE_REFERENCES
+#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
template<class T1, class T2>
struct has_move_emulation_enabled< ::boost::container::container_detail::pair<T1, T2> >
- : ::boost::true_type
-{};
+{
+ 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::container_detail::pair<T1, T2> >
+//This specialization is needed to avoid instantiation of pair in
+//is_class, and allow recursive maps.
+{
+ static const bool value = true;
+};
+
+
+} //namespace move_detail{
} //namespace boost {
diff --git a/boost/container/detail/placement_new.hpp b/boost/container/detail/placement_new.hpp
new file mode 100644
index 0000000000..2489d8a45e
--- /dev/null
+++ b/boost/container/detail/placement_new.hpp
@@ -0,0 +1,27 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// (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_PLACEMENT_NEW_HPP
+#define BOOST_CONTAINER_DETAIL_PLACEMENT_NEW_HPP
+
+#if defined(_MSC_VER)
+# 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/boost/container/detail/pool_common.hpp b/boost/container/detail/pool_common.hpp
index 500b9124d5..11fb6c2e50 100644
--- a/boost/container/detail/pool_common.hpp
+++ b/boost/container/detail/pool_common.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
+// (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)
//
@@ -8,16 +8,17 @@
//
//////////////////////////////////////////////////////////////////////////////
-#ifndef BOOST_CONTAINER_DETAIL_NODE_POOL_COMMON_HPP
-#define BOOST_CONTAINER_DETAIL_NODE_POOL_COMMON_HPP
+#ifndef BOOST_CONTAINER_DETAIL_POOL_COMMON_HPP
+#define BOOST_CONTAINER_DETAIL_POOL_COMMON_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
-#include "config_begin.hpp"
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+
#include <boost/intrusive/slist.hpp>
-#include <new>
namespace boost {
namespace container {
@@ -34,7 +35,7 @@ struct node_slist
typedef slist_hook_t node_t;
typedef typename bi::make_slist
- <node_t, bi::linear<true>, bi::base_hook<slist_hook_t> >::type node_slist_t;
+ <node_t, bi::linear<true>, bi::cache_last<true>, bi::base_hook<slist_hook_t> >::type node_slist_t;
};
template<class T>
diff --git a/boost/container/detail/pool_common_alloc.hpp b/boost/container/detail/pool_common_alloc.hpp
new file mode 100644
index 0000000000..dfae7efd13
--- /dev/null
+++ b/boost/container/detail/pool_common_alloc.hpp
@@ -0,0 +1,98 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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
+
+#if defined(_MSC_VER)
+# 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/alloc_lib.h>
+#include <cstddef>
+
+namespace boost{
+namespace container{
+namespace container_detail{
+
+struct node_slist_helper
+ : public boost::container::container_detail::node_slist<void*>
+{};
+
+struct fake_segment_manager
+{
+ typedef void * void_pointer;
+ static const std::size_t PayloadPerAllocation = BOOST_CONTAINER_ALLOCATION_PAYLOAD;
+
+ typedef boost::container::container_detail::
+ basic_multiallocation_chain<void*> multiallocation_chain;
+ static void deallocate(void_pointer p)
+ { boost_cont_free(p); }
+
+ static void deallocate_many(multiallocation_chain &chain)
+ {
+ std::size_t size = chain.size();
+ std::pair<void*, void*> ptrs = chain.extract_data();
+ boost_cont_memchain dlchain;
+ BOOST_CONTAINER_MEMCHAIN_INIT_FROM(&dlchain, ptrs.first, ptrs.second, size);
+ boost_cont_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 = boost_cont_memalign(nbytes, alignment);
+ if(!ret)
+ boost::container::throw_bad_alloc();
+ return ret;
+ }
+
+ static void *allocate(std::size_t nbytes)
+ {
+ void *ret = boost_cont_malloc(nbytes);
+ if(!ret)
+ boost::container::throw_bad_alloc();
+ return ret;
+ }
+};
+
+} //namespace boost{
+} //namespace container{
+} //namespace container_detail{
+
+namespace boost {
+namespace container {
+namespace container_detail {
+
+template<class T>
+struct is_stateless_segment_manager;
+
+template<>
+struct is_stateless_segment_manager
+ <boost::container::container_detail::fake_segment_manager>
+{
+ static const bool value = true;
+};
+
+} //namespace container_detail {
+} //namespace container {
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //BOOST_CONTAINER_DETAIL_POOL_COMMON_ALLOC_HPP
diff --git a/boost/container/detail/preprocessor.hpp b/boost/container/detail/preprocessor.hpp
index 1818094be1..838eff2ca1 100644
--- a/boost/container/detail/preprocessor.hpp
+++ b/boost/container/detail/preprocessor.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost
+// (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)
//
@@ -11,17 +11,13 @@
#ifndef BOOST_CONTAINER_DETAIL_PREPROCESSOR_HPP
#define BOOST_CONTAINER_DETAIL_PREPROCESSOR_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
-
-#ifndef BOOST_NO_RVALUE_REFERENCES
-#include <boost/container/detail/stored_ref.hpp>
-#endif //#ifndef BOOST_NO_RVALUE_REFERENCES
-
#include <boost/container/detail/workaround.hpp>
+#include <boost/move/utility_core.hpp>
#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
//#error "This file is not needed when perfect forwarding is available"
@@ -36,10 +32,7 @@
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
#include <boost/preprocessor/repetition/enum_trailing.hpp>
-#include <boost/preprocessor/repetition/enum_shifted_params.hpp>
-#include <boost/preprocessor/repetition/enum_shifted.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
-#include <boost/preprocessor/logical/not.hpp>
#include <boost/preprocessor/arithmetic/sub.hpp>
#include <boost/preprocessor/arithmetic/add.hpp>
#include <boost/preprocessor/iteration/iterate.hpp>
@@ -52,7 +45,7 @@
//This cast is ugly but it is necessary until "perfect forwarding"
//is achieved in C++0x. Meanwhile, if we want to be able to
//bind rvalues with non-const references, we have to be ugly
-#ifndef BOOST_NO_RVALUE_REFERENCES
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_CONTAINER_PP_PARAM_LIST(z, n, data) \
BOOST_PP_CAT(P, n) && BOOST_PP_CAT(p, n) \
//!
@@ -60,13 +53,13 @@
#define BOOST_CONTAINER_PP_PARAM_LIST(z, n, data) \
const BOOST_PP_CAT(P, n) & BOOST_PP_CAT(p, n) \
//!
-#endif //#ifndef BOOST_NO_RVALUE_REFERENCES
+#endif //#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_CONTAINER_PP_CONST_REF_PARAM_LIST_Q(z, n, Data) \
const BOOST_PP_CAT(Q, n) & BOOST_PP_CAT(q, n) \
//!
-#ifndef BOOST_NO_RVALUE_REFERENCES
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_CONTAINER_PP_PARAM(U, u) \
U && u \
//!
@@ -74,36 +67,87 @@ const BOOST_PP_CAT(Q, n) & BOOST_PP_CAT(q, n) \
#define BOOST_CONTAINER_PP_PARAM(U, u) \
const U & u \
//!
-#endif //#ifndef BOOST_NO_RVALUE_REFERENCES
-
-#ifndef BOOST_NO_RVALUE_REFERENCES
-
- #if defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
+#endif //#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
- #define BOOST_CONTAINER_PP_PARAM_INIT(z, n, data) \
- BOOST_PP_CAT(m_p, n) (static_cast<BOOST_PP_CAT(P, n)>( BOOST_PP_CAT(p, n) )) \
-
- #else //#if defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_CONTAINER_PP_PARAM_INIT(z, n, data) \
BOOST_PP_CAT(m_p, n) (::boost::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(p, n) )) \
//!
- #endif //BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
-
-#else //BOOST_NO_RVALUE_REFERENCES
+#else //BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_CONTAINER_PP_PARAM_INIT(z, n, data) \
BOOST_PP_CAT(m_p, n) (const_cast<BOOST_PP_CAT(P, n) &>(BOOST_PP_CAT(p, n))) \
//!
-#endif //#ifndef BOOST_NO_RVALUE_REFERENCES
+#endif //#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
-#ifndef BOOST_NO_RVALUE_REFERENCES
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
#if defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
+ namespace boost {
+ namespace container {
+ namespace container_detail {
+ template<class T>
+ struct ref_holder;
+
+ template<class T>
+ struct ref_holder<T &>
+ {
+ explicit ref_holder(T &t)
+ : t_(t)
+ {}
+ T &t_;
+ T & get() { return t_; }
+ };
+
+ template<class T>
+ struct ref_holder<const T>
+ {
+ explicit ref_holder(const T &t)
+ : t_(t)
+ {}
+ const T &t_;
+ const T & get() { return t_; }
+ };
+
+ template<class T>
+ struct ref_holder<const T &&>
+ {
+ explicit ref_holder(const T &t)
+ : t_(t)
+ {}
+ const T &t_;
+ const T & get() { return t_; }
+ };
+
+ template<class T>
+ struct ref_holder
+ {
+ explicit ref_holder(T &&t)
+ : t_(t)
+ {}
+ T &t_;
+ T && get() { return ::boost::move(t_); }
+ };
+
+ template<class T>
+ struct ref_holder<T &&>
+ {
+ explicit ref_holder(T &&t)
+ : t_(t)
+ {}
+ T &t_;
+ T && get() { return ::boost::move(t_); }
+ };
+
+ } //namespace container_detail {
+ } //namespace container {
+ } //namespace boost {
+
#define BOOST_CONTAINER_PP_PARAM_DEFINE(z, n, data) \
- BOOST_PP_CAT(P, n) & BOOST_PP_CAT(m_p, n); \
+ ::boost::container::container_detail::ref_holder<BOOST_PP_CAT(P, n)> BOOST_PP_CAT(m_p, n); \
//!
#else //BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG
@@ -114,26 +158,25 @@ const BOOST_PP_CAT(Q, n) & BOOST_PP_CAT(q, n) \
#endif //defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
-#else //BOOST_NO_RVALUE_REFERENCES
+#else //BOOST_NO_CXX11_RVALUE_REFERENCES
#define BOOST_CONTAINER_PP_PARAM_DEFINE(z, n, data) \
BOOST_PP_CAT(P, n) & BOOST_PP_CAT(m_p, n); \
//!
-#endif //#ifndef BOOST_NO_RVALUE_REFERENCES
+#endif //#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
-#if !defined(BOOST_NO_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
+#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
- #define BOOST_CONTAINER_PP_MEMBER_FORWARD(z, n, data) \
- ::boost::container::container_detail::stored_ref< BOOST_PP_CAT(P, n) >::forward( BOOST_PP_CAT(this->m_p, n) ) \
+ #define BOOST_CONTAINER_PP_MEMBER_FORWARD(z, n, data) BOOST_PP_CAT(this->m_p, n).get() \
//!
-#else //!defined(BOOST_NO_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
+#else //!defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
#define BOOST_CONTAINER_PP_MEMBER_FORWARD(z, n, data) \
::boost::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(this->m_p, n) ) \
//!
-#endif //!defined(BOOST_NO_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
+#endif //!defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
#define BOOST_CONTAINER_PP_PARAM_INC(z, n, data) \
BOOST_PP_CAT(++this->m_p, n) \
diff --git a/boost/container/detail/singleton.hpp b/boost/container/detail/singleton.hpp
new file mode 100644
index 0000000000..a2372c3a96
--- /dev/null
+++ b/boost/container/detail/singleton.hpp
@@ -0,0 +1,117 @@
+// 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
+
+#if defined(_MSC_VER)
+# 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 container_detail {
+
+// 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 container_detail
+} // namespace container
+} // namespace boost
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //BOOST_CONTAINER_DETAIL_SINGLETON_DETAIL_HPP
diff --git a/boost/container/detail/std_fwd.hpp b/boost/container/detail/std_fwd.hpp
new file mode 100644
index 0000000000..a2edeccff1
--- /dev/null
+++ b/boost/container/detail/std_fwd.hpp
@@ -0,0 +1,59 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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
+
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
+//////////////////////////////////////////////////////////////////////////////
+// Standard predeclarations
+//////////////////////////////////////////////////////////////////////////////
+
+#if defined(__clang__) && defined(_LIBCPP_VERSION)
+ #define BOOST_CONTAINER_CLANG_INLINE_STD_NS
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wc++11-extensions"
+ #define BOOST_CONTAINER_STD_NS_BEG _LIBCPP_BEGIN_NAMESPACE_STD
+ #define BOOST_CONTAINER_STD_NS_END _LIBCPP_END_NAMESPACE_STD
+#else
+ #define BOOST_CONTAINER_STD_NS_BEG namespace std{
+ #define BOOST_CONTAINER_STD_NS_END }
+#endif
+
+BOOST_CONTAINER_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;
+
+BOOST_CONTAINER_STD_NS_END
+
+#ifdef BOOST_CONTAINER_CLANG_INLINE_STD_NS
+ #pragma GCC diagnostic pop
+ #undef BOOST_CONTAINER_CLANG_INLINE_STD_NS
+#endif //BOOST_CONTAINER_CLANG_INLINE_STD_NS
+
+#endif //#ifndef BOOST_CONTAINER_DETAIL_STD_FWD_HPP
diff --git a/boost/container/detail/stored_ref.hpp b/boost/container/detail/stored_ref.hpp
deleted file mode 100644
index 80fda89615..0000000000
--- a/boost/container/detail/stored_ref.hpp
+++ /dev/null
@@ -1,92 +0,0 @@
-//////////////////////////////////////////////////////////////////////////////
-//
-// (C) Copyright Ion Gaztanaga 2008-2012. 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_STORED_REF_HPP
-#define BOOST_CONTAINER_DETAIL_STORED_REF_HPP
-
-#include "config_begin.hpp"
-#include <boost/container/detail/workaround.hpp>
-
-#ifndef BOOST_NO_RVALUE_REFERENCES
-
-namespace boost{
-namespace container{
-namespace container_detail{
-
-template<class T>
-struct stored_ref
-{
-
- static T && forward(T &t)
- #ifdef BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
- { return t; }
- #else
- { return boost::move(t); }
- #endif
-};
-
-template<class T>
-struct stored_ref<const T>
-{
- static const T && forward(const T &t)
- #ifdef BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
- { return t; }
- #else
- { return static_cast<const T&&>(t); }
- #endif
-};
-
-template<class T>
-struct stored_ref<T&&>
-{
- static T && forward(T &t)
- #ifdef BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
- { return t; }
- #else
- { return boost::move(t); }
- #endif
-};
-
-template<class T>
-struct stored_ref<const T&&>
-{
- static const T && forward(const T &t)
- #ifdef BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
- { return t; }
- #else
- { return static_cast<const T &&>(t); }
- #endif
-};
-
-template<class T>
-struct stored_ref<const T&>
-{
- static const T & forward(const T &t)
- { return t; }
-};
-
-template<class T>
-struct stored_ref<T&>
-{
- static T & forward(T &t)
- { return t; }
-};
-
-} //namespace container_detail{
-} //namespace container{
-} //namespace boost{
-
-#else
-#error "This header can be included only for compiler with rvalue references"
-#endif //BOOST_NO_RVALUE_REFERENCES
-
-#include <boost/container/detail/config_end.hpp>
-
-#endif //BOOST_CONTAINER_DETAIL_STORED_REF_HPP
diff --git a/boost/container/detail/transform_iterator.hpp b/boost/container/detail/transform_iterator.hpp
index 98f5c04d60..c4e746c389 100644
--- a/boost/container/detail/transform_iterator.hpp
+++ b/boost/container/detail/transform_iterator.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012.
+// (C) Copyright Ion Gaztanaga 2005-2013.
// (C) Copyright Gennaro Prota 2003 - 2004.
//
// Distributed under the Boost Software License, Version 1.0.
@@ -14,12 +14,13 @@
#ifndef BOOST_CONTAINER_DETAIL_TRANSFORM_ITERATORS_HPP
#define BOOST_CONTAINER_DETAIL_TRANSFORM_ITERATORS_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
-#include "config_begin.hpp"
+#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
+
#include <boost/container/detail/type_traits.hpp>
#include <iterator>
@@ -33,10 +34,10 @@ struct operator_arrow_proxy
: m_value(px)
{}
+ typedef PseudoReference element_type;
+
PseudoReference* operator->() const { return &m_value; }
- // This function is needed for MWCW and BCC, which won't call operator->
- // again automatically per 13.3.1.2 para 8
-// operator T*() const { return &m_value; }
+
mutable PseudoReference m_value;
};
@@ -47,10 +48,10 @@ struct operator_arrow_proxy<T&>
: m_value(px)
{}
+ typedef T element_type;
+
T* operator->() const { return const_cast<T*>(&m_value); }
- // This function is needed for MWCW and BCC, which won't call operator->
- // again automatically per 13.3.1.2 para 8
-// operator T*() const { return &m_value; }
+
T &m_value;
};
diff --git a/boost/container/detail/tree.hpp b/boost/container/detail/tree.hpp
index 3ab1536204..e59bca0887 100644
--- a/boost/container/detail/tree.hpp
+++ b/boost/container/detail/tree.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
+// (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)
//
@@ -11,23 +11,35 @@
#ifndef BOOST_CONTAINER_TREE_HPP
#define BOOST_CONTAINER_TREE_HPP
-#include "config_begin.hpp"
+#if defined(_MSC_VER)
+# 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/move.hpp>
-#include <boost/intrusive/pointer_traits.hpp>
-#include <boost/type_traits/has_trivial_destructor.hpp>
-#include <boost/detail/no_exceptions_support.hpp>
-#include <boost/intrusive/rbtree.hpp>
-
#include <boost/container/detail/utilities.hpp>
+#include <boost/container/detail/iterators.hpp>
#include <boost/container/detail/algorithms.hpp>
#include <boost/container/detail/node_alloc_holder.hpp>
#include <boost/container/detail/destroyers.hpp>
#include <boost/container/detail/pair.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <boost/container/allocator_traits.hpp>
+#include <boost/container/options.hpp>
+
+//
+#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>
+//
+#include <boost/move/utility_core.hpp>
+#include <boost/type_traits/has_trivial_destructor.hpp>
+#include <boost/core/no_exceptions_support.hpp>
+//
#ifndef BOOST_CONTAINER_PERFECT_FORWARDING
#include <boost/container/detail/preprocessor.hpp>
#endif
@@ -41,7 +53,7 @@ namespace container {
namespace container_detail {
template<class Key, class Value, class KeyCompare, class KeyOfValue>
-struct value_compare_impl
+struct tree_value_compare
: public KeyCompare
{
typedef Value value_type;
@@ -49,8 +61,12 @@ struct value_compare_impl
typedef KeyOfValue key_of_value;
typedef Key key_type;
- value_compare_impl(const key_compare &kcomp)
- : key_compare(kcomp)
+ explicit tree_value_compare(const key_compare &kcomp)
+ : KeyCompare(kcomp)
+ {}
+
+ tree_value_compare()
+ : KeyCompare()
{}
const key_compare &key_comp() const
@@ -80,47 +96,78 @@ struct value_compare_impl
{ return key_compare::operator()(this->key_forward(key1), this->key_forward(key2)); }
};
-template<class VoidPointer>
-struct rbtree_hook
+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 container_detail::bi::make_set_base_hook
< container_detail::bi::void_pointer<VoidPointer>
, container_detail::bi::link_mode<container_detail::bi::normal_link>
- , container_detail::bi::optimize_size<true>
+ , container_detail::bi::optimize_size<OptimizeSize>
+ >::type type;
+};
+
+template<class VoidPointer, bool OptimizeSize>
+struct intrusive_tree_hook<VoidPointer, boost::container::avl_tree, OptimizeSize>
+{
+ typedef typename container_detail::bi::make_avl_set_base_hook
+ < container_detail::bi::void_pointer<VoidPointer>
+ , container_detail::bi::link_mode<container_detail::bi::normal_link>
+ , container_detail::bi::optimize_size<OptimizeSize>
+ >::type type;
+};
+
+template<class VoidPointer, bool OptimizeSize>
+struct intrusive_tree_hook<VoidPointer, boost::container::scapegoat_tree, OptimizeSize>
+{
+ typedef typename container_detail::bi::make_bs_set_base_hook
+ < container_detail::bi::void_pointer<VoidPointer>
+ , container_detail::bi::link_mode<container_detail::bi::normal_link>
+ >::type type;
+};
+
+template<class VoidPointer, bool OptimizeSize>
+struct intrusive_tree_hook<VoidPointer, boost::container::splay_tree, OptimizeSize>
+{
+ typedef typename container_detail::bi::make_bs_set_base_hook
+ < container_detail::bi::void_pointer<VoidPointer>
+ , container_detail::bi::link_mode<container_detail::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 rbtree_internal_data_type
+struct tree_internal_data_type
{
typedef T type;
};
template<class T1, class T2>
-struct rbtree_internal_data_type< std::pair<T1, T2> >
+struct tree_internal_data_type< std::pair<T1, T2> >
{
typedef pair<T1, T2> type;
};
-
//The node to be store in the tree
-template <class T, class VoidPointer>
-struct rbtree_node
- : public rbtree_hook<VoidPointer>::type
+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(rbtree_node)
- rbtree_node();
+ //BOOST_COPYABLE_AND_MOVABLE(tree_node)
+ tree_node();
public:
- typedef typename rbtree_hook<VoidPointer>::type hook_type;
-
+ typedef typename intrusive_tree_hook
+ <VoidPointer, tree_type_value, OptimizeSize>::type hook_type;
typedef T value_type;
- typedef typename rbtree_internal_data_type<T>::type internal_type;
+ typedef typename tree_internal_data_type<T>::type internal_type;
- typedef rbtree_node<T, VoidPointer> node_type;
+ typedef tree_node< T, VoidPointer
+ , tree_type_value, OptimizeSize> node_type;
T &get_data()
{
@@ -173,56 +220,261 @@ struct rbtree_node
{ 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:
+ insert_equal_end_hint_functor(Icont &icont)
+ : icont_(icont)
+ {}
+
+ void operator()(Node &n)
+ { this->icont_.insert_equal(this->icont_.cend(), n); }
+};
+
+template<class Node, class Icont>
+class push_back_functor
+{
+ Icont &icont_;
+
+ public:
+ push_back_functor(Icont &icont)
+ : icont_(icont)
+ {}
+
+ void operator()(Node &n)
+ { this->icont_.push_back(n); }
+};
+
}//namespace container_detail {
namespace container_detail {
-template<class A, class ValueCompare>
-struct intrusive_rbtree_type
+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 container_detail::bi::make_rbtree
+ <NodeType
+ ,container_detail::bi::compare<NodeCompareType>
+ ,container_detail::bi::base_hook<HookType>
+ ,container_detail::bi::constant_time_size<true>
+ ,container_detail::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 container_detail::bi::make_avltree
+ <NodeType
+ ,container_detail::bi::compare<NodeCompareType>
+ ,container_detail::bi::base_hook<HookType>
+ ,container_detail::bi::constant_time_size<true>
+ ,container_detail::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 container_detail::bi::make_sgtree
+ <NodeType
+ ,container_detail::bi::compare<NodeCompareType>
+ ,container_detail::bi::base_hook<HookType>
+ ,container_detail::bi::floating_point<true>
+ ,container_detail::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 container_detail::bi::make_splaytree
+ <NodeType
+ ,container_detail::bi::compare<NodeCompareType>
+ ,container_detail::bi::base_hook<HookType>
+ ,container_detail::bi::constant_time_size<true>
+ ,container_detail::bi::size_type<SizeType>
+ >::type type;
+};
+
+template<class A, class ValueCompare, boost::container::tree_type_enum tree_type_value, bool OptimizeSize>
+struct intrusive_tree_type
+{
+ private:
typedef typename boost::container::
allocator_traits<A>::value_type value_type;
typedef typename boost::container::
allocator_traits<A>::void_pointer void_pointer;
typedef typename boost::container::
allocator_traits<A>::size_type size_type;
- typedef typename container_detail::rbtree_node
- <value_type, void_pointer> node_type;
+ typedef typename container_detail::tree_node
+ < value_type, void_pointer
+ , tree_type_value, OptimizeSize> node_type;
typedef node_compare<ValueCompare, node_type> node_compare_type;
- typedef typename container_detail::bi::make_rbtree
- <node_type
- ,container_detail::bi::compare<node_compare_type>
- ,container_detail::bi::base_hook<typename rbtree_hook<void_pointer>::type>
- ,container_detail::bi::constant_time_size<true>
- ,container_detail::bi::size_type<size_type>
- >::type container_type;
- typedef container_type type ;
+ //Deducing the hook type from node_type (e.g. node_type::hook_type) would
+ //provoke an early instantiation of node_type that could ruin recursive
+ //tree definitions, so retype the complete type to avoid any problem.
+ typedef typename intrusive_tree_hook
+ <void_pointer, tree_type_value
+ , OptimizeSize>::type hook_type;
+ public:
+ typedef typename intrusive_tree_dispatch
+ < node_type, 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>
+ static void rebalance(Icont &) {}
+};
+
+template<boost::container::tree_type_enum tree_type_value>
+struct intrusive_tree_proxy<tree_type_value, true>
+{
+ template<class Icont>
+ static void rebalance(Icont &c)
+ { c.rebalance(); }
};
} //namespace container_detail {
namespace container_detail {
+//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_type;
+ typedef typename AllocHolder::NodePtr node_ptr_type;
+
+ public:
+ RecyclingCloner(AllocHolder &holder, intrusive_container &itree)
+ : m_holder(holder), m_icont(itree)
+ {}
+
+ static void do_assign(node_ptr_type &p, const node_type &other, bool_<true>)
+ { p->do_assign(other.m_data); }
+
+ static void do_assign(node_ptr_type &p, const node_type &other, bool_<false>)
+ { p->do_move_assign(const_cast<node_type &>(other).m_data); }
+
+ node_ptr_type operator()(const node_type &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 KeyValueCompare, class Node>
+//where KeyValueCompare is tree_value_compare<Key, Value, KeyCompare, KeyOfValue>
+struct key_node_compare
+ : private KeyValueCompare
+{
+ explicit key_node_compare(const KeyValueCompare &comp)
+ : KeyValueCompare(comp)
+ {}
+
+ template<class T>
+ struct is_node
+ {
+ static const bool value = is_same<T, Node>::value;
+ };
+
+ template<class T>
+ typename enable_if_c<is_node<T>::value, const typename KeyValueCompare::value_type &>::type
+ key_forward(const T &node) const
+ { return node.get_data(); }
+
+ template<class T>
+ typename enable_if_c<!is_node<T>::value, const T &>::type
+ key_forward(const T &key) const
+ { return key; }
+
+ template<class KeyType, class KeyType2>
+ bool operator()(const KeyType &key1, const KeyType2 &key2) const
+ { return KeyValueCompare::operator()(this->key_forward(key1), this->key_forward(key2)); }
+};
+
template <class Key, class Value, class KeyOfValue,
- class KeyCompare, class A>
-class rbtree
+ class KeyCompare, class A,
+ class Options = tree_assoc_defaults>
+class tree
: protected container_detail::node_alloc_holder
< A
- , typename container_detail::intrusive_rbtree_type
- <A, value_compare_impl<Key, Value, KeyCompare, KeyOfValue>
- >::type
- , KeyCompare
+ , typename container_detail::intrusive_tree_type
+ < A, tree_value_compare<Key, Value, KeyCompare, KeyOfValue> //ValComp
+ , Options::tree_type, Options::optimize_size>::type
>
{
- typedef typename container_detail::intrusive_rbtree_type
- < A, value_compare_impl
- <Key, Value, KeyCompare, KeyOfValue>
- >::type Icont;
- typedef container_detail::node_alloc_holder
- <A, Icont, KeyCompare> AllocHolder;
+ typedef tree_value_compare
+ <Key, Value, KeyCompare, KeyOfValue> ValComp;
+ typedef typename container_detail::intrusive_tree_type
+ < A, ValComp, Options::tree_type
+ , Options::optimize_size>::type Icont;
+ typedef container_detail::node_alloc_holder
+ <A, Icont> AllocHolder;
typedef typename AllocHolder::NodePtr NodePtr;
- typedef rbtree < Key, Value, KeyOfValue
- , KeyCompare, A> ThisType;
+ typedef tree < Key, Value, KeyOfValue
+ , KeyCompare, A, Options> ThisType;
typedef typename AllocHolder::NodeAlloc NodeAlloc;
typedef typename AllocHolder::ValAlloc ValAlloc;
typedef typename AllocHolder::Node Node;
@@ -232,82 +484,9 @@ class rbtree
typedef typename AllocHolder::allocator_v1 allocator_v1;
typedef typename AllocHolder::allocator_v2 allocator_v2;
typedef typename AllocHolder::alloc_version alloc_version;
+ typedef intrusive_tree_proxy<Options::tree_type> intrusive_tree_proxy_t;
- class RecyclingCloner;
- friend class RecyclingCloner;
-
- class RecyclingCloner
- {
- public:
- RecyclingCloner(AllocHolder &holder, Icont &irbtree)
- : m_holder(holder), m_icont(irbtree)
- {}
-
- NodePtr operator()(const Node &other) const
- {
- if(NodePtr p = m_icont.unlink_leftmost_without_rebalance()){
- //First recycle a node (this can't throw)
- try{
- //This can throw
- p->do_assign(other.m_data);
- return p;
- }
- 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);
- }
- throw;
- }
- }
- else{
- return m_holder.create_node(other.m_data);
- }
- }
-
- AllocHolder &m_holder;
- Icont &m_icont;
- };
-
- class RecyclingMoveCloner;
- friend class RecyclingMoveCloner;
-
- class RecyclingMoveCloner
- {
- public:
- RecyclingMoveCloner(AllocHolder &holder, Icont &irbtree)
- : m_holder(holder), m_icont(irbtree)
- {}
-
- NodePtr operator()(const Node &other) const
- {
- if(NodePtr p = m_icont.unlink_leftmost_without_rebalance()){
- //First recycle a node (this can't throw)
- try{
- //This can throw
- p->do_move_assign(const_cast<Node &>(other).m_data);
- return p;
- }
- 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);
- }
- throw;
- }
- }
- else{
- return m_holder.create_node(other.m_data);
- }
- }
-
- AllocHolder &m_holder;
- Icont &m_icont;
- };
-
- BOOST_COPYABLE_AND_MOVABLE(rbtree)
+ BOOST_COPYABLE_AND_MOVABLE(tree)
public:
@@ -315,8 +494,7 @@ class rbtree
typedef Value value_type;
typedef A allocator_type;
typedef KeyCompare key_compare;
- typedef value_compare_impl< Key, Value
- , KeyCompare, KeyOfValue> value_compare;
+ typedef ValComp value_compare;
typedef typename boost::container::
allocator_traits<A>::pointer pointer;
typedef typename boost::container::
@@ -329,190 +507,147 @@ class rbtree
allocator_traits<A>::size_type size_type;
typedef typename boost::container::
allocator_traits<A>::difference_type difference_type;
- typedef difference_type rbtree_difference_type;
- typedef pointer rbtree_pointer;
- typedef const_pointer rbtree_const_pointer;
- typedef reference rbtree_reference;
- typedef const_reference rbtree_const_reference;
+ typedef difference_type tree_difference_type;
+ typedef pointer tree_pointer;
+ typedef const_pointer tree_const_pointer;
+ typedef reference tree_reference;
+ typedef const_reference tree_const_reference;
typedef NodeAlloc stored_allocator_type;
private:
- template<class KeyValueCompare>
- struct key_node_compare
- : private KeyValueCompare
- {
- key_node_compare(const KeyValueCompare &comp)
- : KeyValueCompare(comp)
- {}
-
- template<class T>
- struct is_node
- {
- static const bool value = is_same<T, Node>::value;
- };
-
- template<class T>
- typename enable_if_c<is_node<T>::value, const value_type &>::type
- key_forward(const T &node) const
- { return node.get_data(); }
-
- template<class T>
- typename enable_if_c<!is_node<T>::value, const T &>::type
- key_forward(const T &key) const
- { return key; }
-
- template<class KeyType, class KeyType2>
- bool operator()(const KeyType &key1, const KeyType2 &key2) const
- { return KeyValueCompare::operator()(this->key_forward(key1), this->key_forward(key2)); }
- };
-
- typedef key_node_compare<value_compare> KeyNodeCompare;
+ typedef key_node_compare<value_compare, Node> KeyNodeCompare;
public:
- //rbtree const_iterator
- class const_iterator
- : public std::iterator
- < std::bidirectional_iterator_tag
- , value_type , rbtree_difference_type
- , rbtree_const_pointer , rbtree_const_reference>
- {
- protected:
- typedef typename Icont::iterator iiterator;
- iiterator m_it;
- explicit const_iterator(iiterator it) : m_it(it){}
- void prot_incr() { ++m_it; }
- void prot_decr() { --m_it; }
-
- private:
- iiterator get()
- { return this->m_it; }
-
- public:
- friend class rbtree <Key, Value, KeyOfValue, KeyCompare, A>;
- typedef rbtree_difference_type difference_type;
+ typedef container_detail::iterator<iiterator, false> iterator;
+ typedef container_detail::iterator<iiterator, true > const_iterator;
+ typedef container_detail::reverse_iterator<iterator> reverse_iterator;
+ typedef container_detail::reverse_iterator<const_iterator> const_reverse_iterator;
- //Constructors
- const_iterator()
- : m_it()
- {}
-
- //Pointer like operators
- const_reference operator*() const
- { return m_it->get_data(); }
-
- const_pointer operator->() const
- { return const_pointer(&m_it->get_data()); }
-
- //Increment / Decrement
- const_iterator& operator++()
- { prot_incr(); return *this; }
-
- const_iterator operator++(int)
- { iiterator tmp = m_it; ++*this; return const_iterator(tmp); }
-
- const_iterator& operator--()
- { prot_decr(); return *this; }
-
- const_iterator operator--(int)
- { iiterator tmp = m_it; --*this; return const_iterator(tmp); }
+ tree()
+ : AllocHolder(ValComp(key_compare()))
+ {}
- //Comparison operators
- bool operator== (const const_iterator& r) const
- { return m_it == r.m_it; }
+ explicit tree(const key_compare& comp, const allocator_type& a = allocator_type())
+ : AllocHolder(a, ValComp(comp))
+ {}
- bool operator!= (const const_iterator& r) const
- { return m_it != r.m_it; }
- };
+ explicit tree(const allocator_type& a)
+ : AllocHolder(a)
+ {}
- //rbtree iterator
- class iterator : public const_iterator
+ template <class InputIterator>
+ tree(bool unique_insertion, InputIterator first, InputIterator last, const key_compare& comp,
+ const allocator_type& a
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename container_detail::enable_if_c
+ < container_detail::is_input_iterator<InputIterator>::value
+ || container_detail::is_same<alloc_version, allocator_v1>::value
+ >::type * = 0
+ #endif
+ )
+ : AllocHolder(a, value_compare(comp))
{
- private:
- explicit iterator(iiterator it)
- : const_iterator(it)
- {}
-
- iiterator get()
- { return this->m_it; }
-
- public:
- friend class rbtree <Key, Value, KeyOfValue, KeyCompare, A>;
- typedef rbtree_pointer pointer;
- typedef rbtree_reference reference;
-
- //Constructors
- iterator(){}
-
- //Pointer like operators
- reference operator*() const
- { return this->m_it->get_data(); }
- pointer operator->() const
- { return boost::intrusive::pointer_traits<pointer>::pointer_to(this->m_it->get_data()); }
-
- //Increment / Decrement
- iterator& operator++()
- { this->prot_incr(); return *this; }
-
- iterator operator++(int)
- { iiterator tmp = this->m_it; ++*this; return iterator(tmp); }
-
- iterator& operator--()
- { this->prot_decr(); return *this; }
-
- iterator operator--(int)
- { iterator tmp = *this; --*this; return tmp; }
- };
-
- typedef std::reverse_iterator<iterator> reverse_iterator;
- typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
-
- rbtree()
- : AllocHolder(key_compare())
- {}
+ //Use cend() as hint to achieve linear time for
+ //ordered ranges as required by the standard
+ //for the constructor
+ const const_iterator end_it(this->cend());
+ if(unique_insertion){
+ for ( ; first != last; ++first){
+ this->insert_unique(end_it, *first);
+ }
+ }
+ else{
+ for ( ; first != last; ++first){
+ this->insert_equal(end_it, *first);
+ }
+ }
+ }
- rbtree(const key_compare& comp, const allocator_type& a = allocator_type())
- : AllocHolder(a, comp)
- {}
+ template <class InputIterator>
+ tree(bool unique_insertion, InputIterator first, InputIterator last, const key_compare& comp,
+ const allocator_type& a
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename container_detail::enable_if_c
+ < !(container_detail::is_input_iterator<InputIterator>::value
+ || container_detail::is_same<alloc_version, allocator_v1>::value)
+ >::type * = 0
+ #endif
+ )
+ : AllocHolder(a, value_compare(comp))
+ {
+ if(unique_insertion){
+ //Use cend() as hint to achieve linear time for
+ //ordered ranges as required by the standard
+ //for the constructor
+ const const_iterator end_it(this->cend());
+ for ( ; first != last; ++first){
+ this->insert_unique(end_it, *first);
+ }
+ }
+ else{
+ //Optimized allocation and construction
+ this->allocate_many_and_construct
+ ( first, std::distance(first, last)
+ , insert_equal_end_hint_functor<Node, Icont>(this->icont()));
+ }
+ }
template <class InputIterator>
- rbtree(InputIterator first, InputIterator last, const key_compare& comp,
- const allocator_type& a, bool unique_insertion)
- : AllocHolder(a, comp)
+ tree( ordered_range_t, InputIterator first, InputIterator last
+ , const key_compare& comp = key_compare(), const allocator_type& a = allocator_type()
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename container_detail::enable_if_c
+ < container_detail::is_input_iterator<InputIterator>::value
+ || container_detail::is_same<alloc_version, allocator_v1>::value
+ >::type * = 0
+ #endif
+ )
+ : AllocHolder(a, value_compare(comp))
{
- typedef typename std::iterator_traits<InputIterator>::iterator_category ItCat;
- priv_create_and_insert_nodes(first, last, unique_insertion, alloc_version(), ItCat());
+ for ( ; first != last; ++first){
+ this->push_back_impl(*first);
+ }
}
template <class InputIterator>
- rbtree( ordered_range_t, InputIterator first, InputIterator last
- , const key_compare& comp = key_compare(), const allocator_type& a = allocator_type())
- : AllocHolder(a, comp)
+ tree( ordered_range_t, InputIterator first, InputIterator last
+ , const key_compare& comp = key_compare(), const allocator_type& a = allocator_type()
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename container_detail::enable_if_c
+ < !(container_detail::is_input_iterator<InputIterator>::value
+ || container_detail::is_same<alloc_version, allocator_v1>::value)
+ >::type * = 0
+ #endif
+ )
+ : AllocHolder(a, value_compare(comp))
{
- typedef typename std::iterator_traits<InputIterator>::iterator_category ItCat;
- priv_create_and_insert_ordered_nodes(first, last, alloc_version(), ItCat());
+ //Optimized allocation and construction
+ this->allocate_many_and_construct
+ ( first, std::distance(first, last)
+ , container_detail::push_back_functor<Node, Icont>(this->icont()));
}
- rbtree(const rbtree& x)
- : AllocHolder(x, x.key_comp())
+ tree(const tree& x)
+ : AllocHolder(x, x.value_comp())
{
this->icont().clone_from
(x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc()));
}
- rbtree(BOOST_RV_REF(rbtree) x)
- : AllocHolder(::boost::move(static_cast<AllocHolder&>(x)), x.key_comp())
+ tree(BOOST_RV_REF(tree) x)
+ : AllocHolder(::boost::move(static_cast<AllocHolder&>(x)), x.value_comp())
{}
- rbtree(const rbtree& x, const allocator_type &a)
- : AllocHolder(a, x.key_comp())
+ tree(const tree& x, const allocator_type &a)
+ : AllocHolder(a, x.value_comp())
{
this->icont().clone_from
(x.icont(), typename AllocHolder::cloner(*this), Destroyer(this->node_alloc()));
}
- rbtree(BOOST_RV_REF(rbtree) x, const allocator_type &a)
- : AllocHolder(a, x.key_comp())
+ tree(BOOST_RV_REF(tree) x, const allocator_type &a)
+ : AllocHolder(a, x.value_comp())
{
if(this->node_alloc() == x.node_alloc()){
this->icont().swap(x.icont());
@@ -523,10 +658,10 @@ class rbtree
}
}
- ~rbtree()
+ ~tree()
{} //AllocHolder clears the tree
- rbtree& operator=(BOOST_COPY_ASSIGN_REF(rbtree) x)
+ tree& operator=(BOOST_COPY_ASSIGN_REF(tree) x)
{
if (&x != this){
NodeAlloc &this_alloc = this->get_stored_allocator();
@@ -545,7 +680,7 @@ class rbtree
//Now recreate the source tree reusing nodes stored by other_tree
this->icont().clone_from
(x.icont()
- , RecyclingCloner(*this, other_tree)
+ , RecyclingCloner<AllocHolder, false>(*this, other_tree)
, Destroyer(this->node_alloc()));
//If there are remaining nodes, destroy them
@@ -557,43 +692,47 @@ class rbtree
return *this;
}
- rbtree& operator=(BOOST_RV_REF(rbtree) x)
+ tree& operator=(BOOST_RV_REF(tree) x)
{
- if (&x != this){
- NodeAlloc &this_alloc = this->node_alloc();
- NodeAlloc &x_alloc = x.node_alloc();
- //If allocators are equal we can just swap pointers
- if(this_alloc == x_alloc){
- //Destroy and swap pointers
- this->clear();
- this->icont() = ::boost::move(x.icont());
- //Move allocator if needed
- this->AllocHolder::move_assign_alloc(x);
- }
- //If unequal allocators, then 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
- (x.icont()
- , RecyclingMoveCloner(*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);
- }
+ 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
+ (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:
+ public:
// accessors:
value_compare value_comp() const
{ return this->icont().value_comp().value_comp(); }
@@ -704,8 +843,10 @@ class rbtree
iterator insert_unique_commit(const value_type& v, insert_commit_data &data)
{
NodePtr tmp = AllocHolder::create_node(v);
- iiterator it(this->icont().insert_unique_commit(*tmp, data));
- return iterator(it);
+ 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>
@@ -713,8 +854,10 @@ class rbtree
(BOOST_FWD_REF(MovableConvertible) mv, insert_commit_data &data)
{
NodePtr tmp = AllocHolder::create_node(boost::forward<MovableConvertible>(mv));
- iiterator it(this->icont().insert_unique_commit(*tmp, data));
- return iterator(it);
+ scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc());
+ iterator ret(this->icont().insert_unique_commit(*tmp, data));
+ destroy_deallocator.release();
+ return ret;
}
std::pair<iterator,bool> insert_unique(const value_type& v)
@@ -722,10 +865,10 @@ class rbtree
insert_commit_data data;
std::pair<iterator,bool> ret =
this->insert_unique_check(KeyOfValue()(v), data);
- if(!ret.second)
- return ret;
- return std::pair<iterator,bool>
- (this->insert_unique_commit(v, data), true);
+ if(ret.second){
+ ret.first = this->insert_unique_commit(v, data);
+ }
+ return ret;
}
template<class MovableConvertible>
@@ -734,13 +877,22 @@ class rbtree
insert_commit_data data;
std::pair<iterator,bool> ret =
this->insert_unique_check(KeyOfValue()(mv), data);
- if(!ret.second)
- return ret;
- return std::pair<iterator,bool>
- (this->insert_unique_commit(boost::forward<MovableConvertible>(mv), data), true);
+ if(ret.second){
+ ret.first = this->insert_unique_commit(boost::forward<MovableConvertible>(mv), data);
+ }
+ return ret;
}
private:
+
+ template<class MovableConvertible>
+ void push_back_impl(BOOST_FWD_REF(MovableConvertible) mv)
+ {
+ NodePtr tmp(AllocHolder::create_node(boost::forward<MovableConvertible>(mv)));
+ //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();
@@ -786,15 +938,21 @@ class rbtree
template <class... Args>
iterator emplace_equal(Args&&... args)
{
- NodePtr p(AllocHolder::create_node(boost::forward<Args>(args)...));
- return iterator(this->icont().insert_equal(this->icont().end(), *p));
+ 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, Args&&... args)
{
- NodePtr p(AllocHolder::create_node(boost::forward<Args>(args)...));
- return iterator(this->icont().insert_equal(hint.get(), *p));
+ 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;
}
#else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
@@ -818,16 +976,22 @@ class rbtree
BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
iterator emplace_equal(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
{ \
- NodePtr p(AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \
- return iterator(this->icont().insert_equal(this->icont().end(), *p)); \
+ NodePtr tmp(AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \
+ scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc()); \
+ iterator ret(this->icont().insert_equal(this->icont().end(), *tmp)); \
+ destroy_deallocator.release(); \
+ return ret; \
} \
\
BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
iterator emplace_hint_equal(const_iterator hint \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
{ \
- NodePtr p(AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \
- return iterator(this->icont().insert_equal(hint.get(), *p)); \
+ NodePtr tmp(AllocHolder::create_node(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \
+ scoped_destroy_deallocator<NodeAlloc> destroy_deallocator(tmp, this->node_alloc()); \
+ iterator ret(this->icont().insert_equal(hint.get(), *tmp)); \
+ destroy_deallocator.release(); \
+ return ret; \
} \
//!
#define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
@@ -859,53 +1023,53 @@ class rbtree
template <class InputIterator>
void insert_unique(InputIterator first, InputIterator last)
{
- if(this->empty()){
- //Insert with end hint, to achieve linear
- //complexity if [first, last) is ordered
- const_iterator hint(this->cend());
- for( ; first != last; ++first)
- hint = this->insert_unique(hint, *first);
- }
- else{
- for( ; first != last; ++first)
- this->insert_unique(*first);
- }
+ for( ; first != last; ++first)
+ this->insert_unique(*first);
}
iterator insert_equal(const value_type& v)
{
- NodePtr p(AllocHolder::create_node(v));
- return iterator(this->icont().insert_equal(this->icont().end(), *p));
+ 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) mv)
{
- NodePtr p(AllocHolder::create_node(boost::forward<MovableConvertible>(mv)));
- return iterator(this->icont().insert_equal(this->icont().end(), *p));
+ NodePtr tmp(AllocHolder::create_node(boost::forward<MovableConvertible>(mv)));
+ 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;
}
iterator insert_equal(const_iterator hint, const value_type& v)
{
- NodePtr p(AllocHolder::create_node(v));
- return iterator(this->icont().insert_equal(hint.get(), *p));
+ NodePtr tmp(AllocHolder::create_node(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;
}
template<class MovableConvertible>
iterator insert_equal(const_iterator hint, BOOST_FWD_REF(MovableConvertible) mv)
{
- NodePtr p(AllocHolder::create_node(boost::forward<MovableConvertible>(mv)));
- return iterator(this->icont().insert_equal(hint.get(), *p));
+ NodePtr tmp(AllocHolder::create_node(boost::forward<MovableConvertible>(mv)));
+ 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 InputIterator>
void insert_equal(InputIterator first, InputIterator last)
{
- //Insert with end hint, to achieve linear
- //complexity if [first, last) is ordered
- const_iterator hint(this->cend());
for( ; first != last; ++first)
- hint = this->insert_equal(hint, *first);
+ this->insert_equal(*first);
}
iterator erase(const_iterator position)
@@ -920,7 +1084,8 @@ class rbtree
void clear()
{ AllocHolder::clear(alloc_version()); }
- // set operations:
+ // 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
iterator find(const key_type& k)
{ return iterator(this->icont().find(k, KeyNodeCompare(value_comp()))); }
@@ -943,187 +1108,60 @@ class rbtree
{ return const_iterator(this->non_const_icont().upper_bound(k, KeyNodeCompare(value_comp()))); }
std::pair<iterator,iterator> equal_range(const key_type& k)
- {
+ {
std::pair<iiterator, iiterator> ret =
this->icont().equal_range(k, KeyNodeCompare(value_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(value_comp()));
return std::pair<const_iterator,const_iterator>
(const_iterator(ret.first), const_iterator(ret.second));
}
- private:
- //Iterator range version
- template<class InpIterator>
- void priv_create_and_insert_nodes
- (InpIterator beg, InpIterator end, bool unique, allocator_v1, std::input_iterator_tag)
+ std::pair<iterator,iterator> lower_bound_range(const key_type& k)
{
- if(unique){
- for (; beg != end; ++beg){
- this->insert_unique(*beg);
- }
- }
- else{
- for (; beg != end; ++beg){
- this->insert_equal(*beg);
- }
- }
- }
-
- template<class InpIterator>
- void priv_create_and_insert_nodes
- (InpIterator beg, InpIterator end, bool unique, allocator_v2, std::input_iterator_tag)
- { //Just forward to the default one
- priv_create_and_insert_nodes(beg, end, unique, allocator_v1(), std::input_iterator_tag());
+ std::pair<iiterator, iiterator> ret =
+ this->icont().lower_bound_range(k, KeyNodeCompare(value_comp()));
+ return std::pair<iterator,iterator>(iterator(ret.first), iterator(ret.second));
}
- class insertion_functor;
- friend class insertion_functor;
-
- class insertion_functor
- {
- Icont &icont_;
-
- public:
- insertion_functor(Icont &icont)
- : icont_(icont)
- {}
-
- void operator()(Node &n)
- { this->icont_.insert_equal(this->icont_.cend(), n); }
- };
-
-
- template<class FwdIterator>
- void priv_create_and_insert_nodes
- (FwdIterator beg, FwdIterator end, bool unique, allocator_v2, std::forward_iterator_tag)
+ std::pair<const_iterator, const_iterator> lower_bound_range(const key_type& k) const
{
- if(beg != end){
- if(unique){
- priv_create_and_insert_nodes(beg, end, unique, allocator_v2(), std::input_iterator_tag());
- }
- else{
- //Optimized allocation and construction
- this->allocate_many_and_construct
- (beg, std::distance(beg, end), insertion_functor(this->icont()));
- }
- }
+ std::pair<iiterator, iiterator> ret =
+ this->non_const_icont().lower_bound_range(k, KeyNodeCompare(value_comp()));
+ return std::pair<const_iterator,const_iterator>
+ (const_iterator(ret.first), const_iterator(ret.second));
}
- //Iterator range version
- template<class InpIterator>
- void priv_create_and_insert_ordered_nodes
- (InpIterator beg, InpIterator end, allocator_v1, std::input_iterator_tag)
- {
- const_iterator cend_n(this->cend());
- for (; beg != end; ++beg){
- this->insert_before(cend_n, *beg);
- }
- }
+ void rebalance()
+ { intrusive_tree_proxy_t::rebalance(this->icont()); }
- template<class InpIterator>
- void priv_create_and_insert_ordered_nodes
- (InpIterator beg, InpIterator end, allocator_v2, std::input_iterator_tag)
- { //Just forward to the default one
- priv_create_and_insert_ordered_nodes(beg, end, allocator_v1(), std::input_iterator_tag());
- }
+ friend bool operator==(const tree& x, const tree& y)
+ { return x.size() == y.size() && std::equal(x.begin(), x.end(), y.begin()); }
- class back_insertion_functor;
- friend class back_insertion_functor;
+ friend bool operator<(const tree& x, const tree& y)
+ { return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
- class back_insertion_functor
- {
- Icont &icont_;
+ friend bool operator!=(const tree& x, const tree& y)
+ { return !(x == y); }
- public:
- back_insertion_functor(Icont &icont)
- : icont_(icont)
- {}
+ friend bool operator>(const tree& x, const tree& y)
+ { return y < x; }
- void operator()(Node &n)
- { this->icont_.push_back(n); }
- };
+ friend bool operator<=(const tree& x, const tree& y)
+ { return !(y < x); }
+ friend bool operator>=(const tree& x, const tree& y)
+ { return !(x < y); }
- template<class FwdIterator>
- void priv_create_and_insert_ordered_nodes
- (FwdIterator beg, FwdIterator end, allocator_v2, std::forward_iterator_tag)
- {
- if(beg != end){
- //Optimized allocation and construction
- this->allocate_many_and_construct
- (beg, std::distance(beg, end), back_insertion_functor(this->icont()));
- }
- }
+ friend void swap(tree& x, tree& y)
+ { x.swap(y); }
};
-template <class Key, class Value, class KeyOfValue,
- class KeyCompare, class A>
-inline bool
-operator==(const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x,
- const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& y)
-{
- return x.size() == y.size() &&
- std::equal(x.begin(), x.end(), y.begin());
-}
-
-template <class Key, class Value, class KeyOfValue,
- class KeyCompare, class A>
-inline bool
-operator<(const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x,
- const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& y)
-{
- return std::lexicographical_compare(x.begin(), x.end(),
- y.begin(), y.end());
-}
-
-template <class Key, class Value, class KeyOfValue,
- class KeyCompare, class A>
-inline bool
-operator!=(const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x,
- const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& y) {
- return !(x == y);
-}
-
-template <class Key, class Value, class KeyOfValue,
- class KeyCompare, class A>
-inline bool
-operator>(const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x,
- const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& y) {
- return y < x;
-}
-
-template <class Key, class Value, class KeyOfValue,
- class KeyCompare, class A>
-inline bool
-operator<=(const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x,
- const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& y) {
- return !(y < x);
-}
-
-template <class Key, class Value, class KeyOfValue,
- class KeyCompare, class A>
-inline bool
-operator>=(const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x,
- const rbtree<Key,Value,KeyOfValue,KeyCompare,A>& y) {
- return !(x < y);
-}
-
-
-template <class Key, class Value, class KeyOfValue,
- class KeyCompare, class A>
-inline void
-swap(rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x,
- rbtree<Key,Value,KeyOfValue,KeyCompare,A>& y)
-{
- x.swap(y);
-}
-
} //namespace container_detail {
} //namespace container {
/*
@@ -1132,9 +1170,9 @@ swap(rbtree<Key,Value,KeyOfValue,KeyCompare,A>& x,
template <class K, class V, class KOV,
class C, class A>
struct has_trivial_destructor_after_move
- <boost::container::container_detail::rbtree<K, V, KOV, C, A> >
+ <boost::container::container_detail::tree<K, V, KOV, C, A> >
{
- static const bool value = has_trivial_destructor<A>::value && has_trivial_destructor<C>::value;
+ static const bool value = has_trivial_destructor_after_move<A>::value && has_trivial_destructor_after_move<C>::value;
};
*/
} //namespace boost {
diff --git a/boost/container/detail/type_traits.hpp b/boost/container/detail/type_traits.hpp
index 0e096e54e3..9ff361454a 100644
--- a/boost/container/detail/type_traits.hpp
+++ b/boost/container/detail/type_traits.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
// (C) Copyright John Maddock 2000.
-// (C) Copyright Ion Gaztanaga 2005-2012.
+// (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
@@ -15,13 +15,12 @@
#ifndef BOOST_CONTAINER_CONTAINER_DETAIL_TYPE_TRAITS_HPP
#define BOOST_CONTAINER_CONTAINER_DETAIL_TYPE_TRAITS_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
-#include "config_begin.hpp"
-
-#include <boost/move/move.hpp>
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
namespace boost {
namespace container {
@@ -90,7 +89,7 @@ struct remove_reference<T&>
typedef T type;
};
-#ifndef BOOST_NO_RVALUE_REFERENCES
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template<class T>
struct remove_reference<T&&>
@@ -100,6 +99,15 @@ struct remove_reference<T&&>
#else
+} // namespace container_detail {
+} //namespace container {
+
+template<class T>
+class rv;
+
+namespace container {
+namespace container_detail {
+
template<class T>
struct remove_reference< ::boost::rv<T> >
{
@@ -164,6 +172,10 @@ template <class T>
struct add_const_reference<T&>
{ typedef T& type; };
+template <class T>
+struct add_const
+{ typedef const T type; };
+
template <typename T, typename U>
struct is_same
{
@@ -201,6 +213,21 @@ struct remove_ref_const
typedef typename remove_const< typename remove_reference<T>::type >::type type;
};
+template <class T>
+struct make_unsigned
+{
+ typedef T type;
+};
+
+template <> struct make_unsigned<bool> {};
+template <> struct make_unsigned<signed char> {typedef unsigned char type;};
+template <> struct make_unsigned<signed short> {typedef unsigned short type;};
+template <> struct make_unsigned<signed int> {typedef unsigned int type;};
+template <> struct make_unsigned<signed long> {typedef unsigned long type;};
+#ifdef BOOST_HAS_LONG_LONG
+template <> struct make_unsigned<signed long long> {typedef unsigned long long type;};
+#endif
+
} // namespace container_detail
} //namespace container {
} //namespace boost {
diff --git a/boost/container/detail/utilities.hpp b/boost/container/detail/utilities.hpp
index 152b5e162e..25f035df50 100644
--- a/boost/container/detail/utilities.hpp
+++ b/boost/container/detail/utilities.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
+// (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)
//
@@ -11,29 +11,101 @@
#ifndef BOOST_CONTAINER_DETAIL_UTILITIES_HPP
#define BOOST_CONTAINER_DETAIL_UTILITIES_HPP
-#include "config_begin.hpp"
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+
#include <cstdio>
-#include <boost/type_traits/is_fundamental.hpp>
+#include <cstring> //for ::memmove / ::memcpy
#include <boost/type_traits/is_pointer.hpp>
#include <boost/type_traits/is_enum.hpp>
-#include <boost/type_traits/is_member_pointer.hpp>
#include <boost/type_traits/is_class.hpp>
-#include <boost/move/move.hpp>
+#include <boost/type_traits/is_integral.hpp>
+#include <boost/type_traits/is_floating_point.hpp>
+#include <boost/type_traits/is_copy_constructible.hpp>
+#include <boost/type_traits/has_trivial_destructor.hpp>
+#include <boost/type_traits/has_trivial_copy.hpp>
+#include <boost/type_traits/has_trivial_assign.hpp>
+#include <boost/type_traits/is_pod.hpp>
+#include <boost/move/core.hpp>
+#include <boost/move/utility_core.hpp>
+#include <boost/move/iterator.hpp>
+#include <boost/assert.hpp>
+#include <boost/container/throw_exception.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <boost/container/allocator_traits.hpp>
-#include <algorithm>
+#include <boost/core/no_exceptions_support.hpp>
+#include <boost/container/detail/memory_util.hpp>
+#include <boost/intrusive/pointer_traits.hpp>
+#include <boost/aligned_storage.hpp>
+#include <iterator>
+#include <utility> //std::distance
namespace boost {
namespace container {
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// swap
+//
+//////////////////////////////////////////////////////////////////////////////
+
+namespace container_swap {
+
+template<class T, bool IsClass = boost::is_class<T>::value >
+struct has_member_swap
+{
+ static const bool value = boost::container::container_detail::
+ has_member_function_callable_with_swap<T, T &>::value;
+};
+
+template<class T>
+struct has_member_swap<T, false>
+{
+ static const bool value = false;
+};
+
+} //namespace container_swap {
+
+template<class T> inline
+typename container_detail::enable_if_c
+ <container_swap::has_member_swap<T>::value, void>::type
+swap_dispatch(T &left, T &right) //swap using member swap
+{
+ left.swap(right); // may throw
+}
+
+template<class T> inline
+typename container_detail::enable_if_c
+ <!container_swap::has_member_swap<T>::value/* && boost::has_move_emulation_enabled<T>::value*/, void>::type
+ swap_dispatch(T &left, T &right)
+{
+ T temp(boost::move(left)); // may throw
+ left = boost::move(right); // may throw
+ right = boost::move(temp); // may throw
+}
+/*
+template<class T> inline
+typename container_detail::enable_if_c
+ <!container_swap::has_member_swap<T>::value && !boost::has_move_emulation_enabled<T>::value, void>::type
+ swap_dispatch(T &left, T &right)
+{
+ using std::swap;
+ swap(left, right); // may throw
+}
+*/
namespace container_detail {
template <typename T>
inline T* addressof(T& obj)
{
return static_cast<T*>(
- static_cast<void*>(
- const_cast<char*>(
+ static_cast<void*>(
+ const_cast<char*>(
&reinterpret_cast<const char&>(obj)
)));
}
@@ -46,42 +118,73 @@ template<class T>
const T &min_value(const T &a, const T &b)
{ return a < b ? a : b; }
-template <class SizeType>
-SizeType
- get_next_capacity(const SizeType max_size
- ,const SizeType capacity
- ,const SizeType n)
+enum NextCapacityOption { NextCapacityDouble, NextCapacity60Percent };
+
+template<class SizeType, NextCapacityOption Option>
+struct next_capacity_calculator;
+
+template<class SizeType>
+struct next_capacity_calculator<SizeType, NextCapacityDouble>
{
-// if (n > max_size - capacity)
-// throw std::length_error("get_next_capacity");
+ static SizeType get(const SizeType max_size
+ ,const SizeType capacity
+ ,const SizeType n)
+ {
+ const SizeType remaining = max_size - capacity;
+ if ( remaining < n )
+ boost::container::throw_length_error("get_next_capacity, allocator's max_size reached");
+ const SizeType additional = max_value(n, capacity);
+ return ( remaining < additional ) ? max_size : ( capacity + additional );
+ }
+};
- const SizeType m3 = max_size/3;
- if (capacity < m3)
- return capacity + max_value(3*(capacity+1)/5, n);
+template<class SizeType>
+struct next_capacity_calculator<SizeType, NextCapacity60Percent>
+{
+ static SizeType get(const SizeType max_size
+ ,const SizeType capacity
+ ,const SizeType n)
+ {
+ const SizeType remaining = max_size - capacity;
+ if ( remaining < n )
+ boost::container::throw_length_error("get_next_capacity, allocator's max_size reached");
+ const SizeType m3 = max_size/3;
- if (capacity < m3*2)
- return capacity + max_value((capacity+1)/2, n);
+ if (capacity < m3)
+ return capacity + max_value(3*(capacity+1)/5, n);
- return max_size;
-}
+ if (capacity < m3*2)
+ return capacity + max_value((capacity+1)/2, n);
+ return max_size;
+ }
+};
template <class T>
inline T* to_raw_pointer(T* p)
{ return p; }
template <class Pointer>
-inline typename Pointer::element_type*
+inline typename boost::intrusive::pointer_traits<Pointer>::element_type*
to_raw_pointer(const Pointer &p)
{ return boost::container::container_detail::to_raw_pointer(p.operator->()); }
-//!To avoid ADL problems with swap
template <class T>
-inline void do_swap(T& x, T& y)
-{
- using std::swap;
- swap(x, y);
-}
+inline T* iterator_to_pointer(T* i)
+{ return i; }
+
+template <class Iterator>
+inline typename std::iterator_traits<Iterator>::pointer
+ iterator_to_pointer(const Iterator &i)
+{ return i.operator->(); }
+
+template <class Iterator>
+inline
+ typename boost::intrusive::pointer_traits
+ <typename std::iterator_traits<Iterator>::pointer>::element_type*
+ iterator_to_raw_pointer(const Iterator &i)
+{ return (to_raw_pointer)((iterator_to_pointer)(i)); }
+
template<class AllocatorType>
inline void swap_alloc(AllocatorType &, AllocatorType &, container_detail::false_type)
@@ -90,7 +193,7 @@ inline void swap_alloc(AllocatorType &, AllocatorType &, container_detail::false
template<class AllocatorType>
inline void swap_alloc(AllocatorType &l, AllocatorType &r, container_detail::true_type)
-{ container_detail::do_swap(l, r); }
+{ boost::container::swap_dispatch(l, r); }
template<class AllocatorType>
inline void assign_alloc(AllocatorType &, const AllocatorType &, container_detail::false_type)
@@ -122,101 +225,340 @@ struct ct_rounded_size
{
enum { value = ((OrigSize-1)/RoundTo+1)*RoundTo };
};
-/*
-template <class _TypeT>
-struct __rw_is_enum
+
+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;
+};
+
+/////////////////////////
+// predeclarations
+/////////////////////////
+
+#ifndef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
+
+template<class Pointer>
+class vector_iterator;
+
+template<class Pointer>
+class vector_const_iterator;
+
+#endif //BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
+
+} //namespace container_detail {
+} //namespace container {
+
+namespace interprocess {
+
+template <class PointedType, class DifferenceType, class OffsetType, std::size_t OffsetAlignment>
+class offset_ptr;
+
+} //namespace interprocess {
+
+namespace container {
+
+namespace container_detail {
+
+/////////////////////////
+//vector_[const_]iterator
+/////////////////////////
+
+#ifndef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
+
+template<class Pointer>
+struct are_elements_contiguous<boost::container::container_detail::vector_iterator<Pointer> >
{
- struct _C_no { };
- struct _C_yes { int _C_dummy [2]; };
+ static const bool value = true;
+};
- struct _C_indirect {
- // prevent classes with user-defined conversions from matching
+template<class Pointer>
+struct are_elements_contiguous<boost::container::container_detail::vector_const_iterator<Pointer> >
+{
+ static const bool value = true;
+};
+
+#endif //BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
- // use double to prevent float->int gcc conversion warnings
- _C_indirect (double);
+/////////////////////////
+// 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;
};
-// nested struct gets rid of bogus gcc errors
-struct _C_nest {
- // supply first argument to prevent HP aCC warnings
- static _C_no _C_is (int, ...);
- static _C_yes _C_is (int, _C_indirect);
+template <typename I, typename O>
+struct are_contiguous_and_same
+{
+ static const bool is_same_io =
+ is_same< typename remove_const< typename ::std::iterator_traits<I>::value_type >::type
+ , typename ::std::iterator_traits<O>::value_type
+ >::value;
+ static const bool value = is_same_io &&
+ are_elements_contiguous<I>::value &&
+ are_elements_contiguous<O>::value;
+};
- static _TypeT _C_make_T ();
+template <typename I, typename O>
+struct is_memtransfer_copy_assignable
+{
+ static const bool value = are_contiguous_and_same<I, O>::value &&
+ boost::has_trivial_assign< typename ::std::iterator_traits<I>::value_type >::value;
};
-enum {
- _C_val = sizeof (_C_yes) == sizeof (_C_nest::_C_is (0, _C_nest::_C_make_T ()))
- && !::boost::is_fundamental<_TypeT>::value
+template <typename I, typename O>
+struct is_memtransfer_copy_constructible
+{
+ static const bool value = are_contiguous_and_same<I, O>::value &&
+ boost::has_trivial_copy< typename ::std::iterator_traits<I>::value_type >::value;
};
+template <typename I, typename O, typename R>
+struct enable_if_memtransfer_copy_constructible
+ : public enable_if_c<container_detail::is_memtransfer_copy_constructible<I, O>::value, R>
+{};
+
+template <typename I, typename O, typename R>
+struct disable_if_memtransfer_copy_constructible
+ : public enable_if_c<!container_detail::is_memtransfer_copy_constructible<I, O>::value, R>
+{};
+
+template <typename I, typename O, typename R>
+struct enable_if_memtransfer_copy_assignable
+ : public enable_if_c<container_detail::is_memtransfer_copy_assignable<I, O>::value, R>
+{};
+
+template <typename I, typename O, typename R>
+struct disable_if_memtransfer_copy_assignable
+ : public enable_if_c<!container_detail::is_memtransfer_copy_assignable<I, O>::value, R>
+{};
+
+template
+ <typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+inline F memmove(I f, I l, F r) BOOST_CONTAINER_NOEXCEPT
+{
+ typedef typename std::iterator_traits<I>::value_type value_type;
+ typename std::iterator_traits<I>::difference_type n = std::distance(f, l);
+ ::memmove((iterator_to_raw_pointer)(r), (iterator_to_raw_pointer)(f), sizeof(value_type)*n);
+ std::advance(r, n);
+ return r;
+}
+
+template
+ <typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+F memmove_n(I f, typename std::iterator_traits<I>::difference_type n, F r) BOOST_CONTAINER_NOEXCEPT
+{
+ typedef typename std::iterator_traits<I>::value_type value_type;
+ ::memmove((iterator_to_raw_pointer)(r), (iterator_to_raw_pointer)(f), sizeof(value_type)*n);
+ std::advance(r, n);
+ return r;
+}
+
+template
+ <typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+I memmove_n_source(I f, typename std::iterator_traits<I>::difference_type n, F r) BOOST_CONTAINER_NOEXCEPT
+{
+ typedef typename std::iterator_traits<I>::value_type value_type;
+ ::memmove((iterator_to_raw_pointer)(r), (iterator_to_raw_pointer)(f), sizeof(value_type)*n);
+ std::advance(f, n);
+ return f;
+}
+
+template
+ <typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+I memmove_n_source_dest(I f, typename std::iterator_traits<I>::difference_type n, F &r) BOOST_CONTAINER_NOEXCEPT
+{
+ typedef typename std::iterator_traits<I>::value_type value_type;
+ ::memmove((iterator_to_raw_pointer)(r), (iterator_to_raw_pointer)(f), sizeof(value_type)*n);
+ std::advance(f, n);
+ std::advance(r, n);
+ return f;
+}
+
+template <typename O>
+struct is_memzero_initializable
+{
+ typedef typename ::std::iterator_traits<O>::value_type value_type;
+ static const bool value = are_elements_contiguous<O>::value &&
+ ( ::boost::is_integral<value_type>::value || ::boost::is_enum<value_type>::value
+ #if defined(BOOST_CONTAINER_MEMZEROED_POINTER_IS_NULL)
+ || ::boost::is_pointer<value_type>::value
+ #endif
+ #if defined(BOOST_CONTAINER_MEMZEROED_FLOATING_POINT_IS_ZERO)
+ || ::boost::is_floating_point<value_type>::value
+ #endif
+ #if defined(BOOST_CONTAINER_MEMZEROED_FLOATING_POINT_IS_ZERO) && defined(BOOST_CONTAINER_MEMZEROED_POINTER_IS_NULL)
+ || ::boost::is_pod<value_type>::value
+ #endif
+ );
};
-*/
-template<class T>
-struct move_const_ref_type
- : if_c
-// < ::boost::is_fundamental<T>::value || ::boost::is_pointer<T>::value || ::boost::is_member_pointer<T>::value || ::boost::is_enum<T>::value
- < !::boost::is_class<T>::value
- ,const T &
- ,BOOST_CATCH_CONST_RLVALUE(T)
- >
+template <typename O, typename R>
+struct enable_if_memzero_initializable
+ : public enable_if_c<container_detail::is_memzero_initializable<O>::value, R>
+{};
+
+template <typename O, typename R>
+struct disable_if_memzero_initializable
+ : public enable_if_c<!container_detail::is_memzero_initializable<O>::value, R>
{};
} //namespace container_detail {
+
//////////////////////////////////////////////////////////////////////////////
//
// uninitialized_move_alloc
//
//////////////////////////////////////////////////////////////////////////////
+
//! <b>Effects</b>:
//! \code
-//! for (; first != last; ++result, ++first)
-//! allocator_traits::construct(a, &*result, boost::move(*first));
+//! for (; f != l; ++r, ++f)
+//! allocator_traits::construct(a, &*r, boost::move(*f));
//! \endcode
//!
-//! <b>Returns</b>: result
+//! <b>Returns</b>: r
template
<typename A,
typename I, // I models InputIterator
typename F> // F models ForwardIterator
-F uninitialized_move_alloc(A &a, I f, I l, F r)
+inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F, F>::type
+ uninitialized_move_alloc(A &a, I f, I l, F r)
{
- while (f != l) {
- allocator_traits<A>::construct(a, container_detail::to_raw_pointer(&*r), boost::move(*f));
- ++f; ++r;
+ F back = r;
+ BOOST_TRY{
+ while (f != l) {
+ allocator_traits<A>::construct(a, container_detail::iterator_to_raw_pointer(r), boost::move(*f));
+ ++f; ++r;
+ }
}
+ BOOST_CATCH(...){
+ for (; back != r; ++back){
+ allocator_traits<A>::destroy(a, container_detail::iterator_to_raw_pointer(back));
+ }
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
return r;
}
+template
+ <typename A,
+ typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+inline typename container_detail::enable_if_memtransfer_copy_constructible<I, F, F>::type
+ uninitialized_move_alloc(A &, I f, I l, F r) BOOST_CONTAINER_NOEXCEPT
+{ return container_detail::memmove(f, l, r); }
+
//////////////////////////////////////////////////////////////////////////////
//
-// uninitialized_copy_alloc
+// uninitialized_move_alloc_n
//
//////////////////////////////////////////////////////////////////////////////
//! <b>Effects</b>:
//! \code
-//! for (; first != last; ++result, ++first)
-//! allocator_traits::construct(a, &*result, *first);
+//! for (; n--; ++r, ++f)
+//! allocator_traits::construct(a, &*r, boost::move(*f));
//! \endcode
//!
-//! <b>Returns</b>: result
+//! <b>Returns</b>: r
template
<typename A,
typename I, // I models InputIterator
typename F> // F models ForwardIterator
-F uninitialized_copy_alloc(A &a, I f, I l, F r)
+inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F, F>::type
+ uninitialized_move_alloc_n(A &a, I f, typename std::iterator_traits<I>::difference_type n, F r)
{
- while (f != l) {
- allocator_traits<A>::construct(a, container_detail::to_raw_pointer(&*r), *f);
- ++f; ++r;
+ F back = r;
+ BOOST_TRY{
+ while (n--) {
+ allocator_traits<A>::construct(a, container_detail::iterator_to_raw_pointer(r), boost::move(*f));
+ ++f; ++r;
+ }
}
+ BOOST_CATCH(...){
+ for (; back != r; ++back){
+ allocator_traits<A>::destroy(a, container_detail::iterator_to_raw_pointer(back));
+ }
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
return r;
}
+template
+ <typename A,
+ typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+inline typename container_detail::enable_if_memtransfer_copy_constructible<I, F, F>::type
+ uninitialized_move_alloc_n(A &, I f, typename std::iterator_traits<I>::difference_type n, F r) BOOST_CONTAINER_NOEXCEPT
+{ return container_detail::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 A,
+ typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F, I>::type
+ uninitialized_move_alloc_n_source(A &a, I f, typename std::iterator_traits<I>::difference_type n, F r)
+{
+ F back = r;
+ BOOST_TRY{
+ while (n--) {
+ allocator_traits<A>::construct(a, container_detail::iterator_to_raw_pointer(r), boost::move(*f));
+ ++f; ++r;
+ }
+ }
+ BOOST_CATCH(...){
+ for (; back != r; ++back){
+ allocator_traits<A>::destroy(a, container_detail::iterator_to_raw_pointer(back));
+ }
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ return f;
+}
+
+template
+ <typename A,
+ typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+inline typename container_detail::enable_if_memtransfer_copy_constructible<I, F, I>::type
+ uninitialized_move_alloc_n_source(A &, I f, typename std::iterator_traits<I>::difference_type n, F r) BOOST_CONTAINER_NOEXCEPT
+{ return container_detail::memmove_n_source(f, n, r); }
+
//////////////////////////////////////////////////////////////////////////////
//
// uninitialized_copy_alloc
@@ -225,58 +567,701 @@ F uninitialized_copy_alloc(A &a, I f, I l, F r)
//! <b>Effects</b>:
//! \code
-//! for (; first != last; ++result, ++first)
-//! allocator_traits::construct(a, &*result, *first);
+//! for (; f != l; ++r, ++f)
+//! allocator_traits::construct(a, &*r, *f);
+//! \endcode
+//!
+//! <b>Returns</b>: r
+template
+ <typename A,
+ typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F, F>::type
+ uninitialized_copy_alloc(A &a, I f, I l, F r)
+{
+ F back = r;
+ BOOST_TRY{
+ while (f != l) {
+ allocator_traits<A>::construct(a, container_detail::iterator_to_raw_pointer(r), *f);
+ ++f; ++r;
+ }
+ }
+ BOOST_CATCH(...){
+ for (; back != r; ++back){
+ allocator_traits<A>::destroy(a, container_detail::iterator_to_raw_pointer(back));
+ }
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ return r;
+}
+
+template
+ <typename A,
+ typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+inline typename container_detail::enable_if_memtransfer_copy_constructible<I, F, F>::type
+ uninitialized_copy_alloc(A &, I f, I l, F r) BOOST_CONTAINER_NOEXCEPT
+{ return container_detail::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>: result
+//! <b>Returns</b>: r
+template
+ <typename A,
+ typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F, F>::type
+ uninitialized_copy_alloc_n(A &a, I f, typename std::iterator_traits<I>::difference_type n, F r)
+{
+ F back = r;
+ BOOST_TRY{
+ while (n--) {
+ allocator_traits<A>::construct(a, container_detail::iterator_to_raw_pointer(r), *f);
+ ++f; ++r;
+ }
+ }
+ BOOST_CATCH(...){
+ for (; back != r; ++back){
+ allocator_traits<A>::destroy(a, container_detail::iterator_to_raw_pointer(back));
+ }
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ return r;
+}
+
+template
+ <typename A,
+ typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+inline typename container_detail::enable_if_memtransfer_copy_constructible<I, F, F>::type
+ uninitialized_copy_alloc_n(A &, I f, typename std::iterator_traits<I>::difference_type n, F r) BOOST_CONTAINER_NOEXCEPT
+{ return container_detail::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 A,
+ typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+inline typename container_detail::disable_if_memtransfer_copy_constructible<I, F, I>::type
+ uninitialized_copy_alloc_n_source(A &a, I f, typename std::iterator_traits<I>::difference_type n, F r)
+{
+ F back = r;
+ BOOST_TRY{
+ while (n--) {
+ allocator_traits<A>::construct(a, container_detail::iterator_to_raw_pointer(r), *f);
+ ++f; ++r;
+ }
+ }
+ BOOST_CATCH(...){
+ for (; back != r; ++back){
+ allocator_traits<A>::destroy(a, container_detail::iterator_to_raw_pointer(back));
+ }
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ return f;
+}
+
+template
+ <typename A,
+ typename I, // I models InputIterator
+ typename F> // F models ForwardIterator
+inline typename container_detail::enable_if_memtransfer_copy_constructible<I, F, I>::type
+ uninitialized_copy_alloc_n_source(A &, I f, typename std::iterator_traits<I>::difference_type n, F r) BOOST_CONTAINER_NOEXCEPT
+{ return container_detail::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 A,
+ typename F> // F models ForwardIterator
+inline typename container_detail::disable_if_memzero_initializable<F, F>::type
+ uninitialized_value_init_alloc_n(A &a, typename allocator_traits<A>::difference_type n, F r)
+{
+ F back = r;
+ BOOST_TRY{
+ while (n--) {
+ allocator_traits<A>::construct(a, container_detail::iterator_to_raw_pointer(r));
+ ++r;
+ }
+ }
+ BOOST_CATCH(...){
+ for (; back != r; ++back){
+ allocator_traits<A>::destroy(a, container_detail::iterator_to_raw_pointer(back));
+ }
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ return r;
+}
+
+template
+ <typename A,
+ typename F> // F models ForwardIterator
+inline typename container_detail::enable_if_memzero_initializable<F, F>::type
+ uninitialized_value_init_alloc_n(A &, typename allocator_traits<A>::difference_type n, F r)
+{
+ typedef typename std::iterator_traits<F>::value_type value_type;
+ ::memset((void*)container_detail::iterator_to_raw_pointer(r), 0, sizeof(value_type)*n);
+ std::advance(r, n);
+ 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 A,
+ typename F> // F models ForwardIterator
+inline F uninitialized_default_init_alloc_n(A &a, typename allocator_traits<A>::difference_type n, F r)
+{
+ F back = r;
+ BOOST_TRY{
+ while (n--) {
+ allocator_traits<A>::construct(a, container_detail::iterator_to_raw_pointer(r), default_init);
+ ++r;
+ }
+ }
+ BOOST_CATCH(...){
+ for (; back != r; ++back){
+ allocator_traits<A>::destroy(a, container_detail::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 A,
typename F, // F models ForwardIterator
typename T>
-void uninitialized_fill_alloc(A &a, F f, F l, const T &t)
+inline void uninitialized_fill_alloc(A &a, F f, F l, const T &t)
+{
+ F back = f;
+ BOOST_TRY{
+ while (f != l) {
+ allocator_traits<A>::construct(a, container_detail::iterator_to_raw_pointer(f), t);
+ ++f;
+ }
+ }
+ BOOST_CATCH(...){
+ for (; back != l; ++back){
+ allocator_traits<A>::destroy(a, container_detail::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 A,
+ typename T,
+ typename F> // F models ForwardIterator
+inline F uninitialized_fill_alloc_n(A &a, const T &v, typename allocator_traits<A>::difference_type n, F r)
+{
+ F back = r;
+ BOOST_TRY{
+ while (n--) {
+ allocator_traits<A>::construct(a, container_detail::iterator_to_raw_pointer(r), v);
+ ++r;
+ }
+ }
+ BOOST_CATCH(...){
+ for (; back != r; ++back){
+ allocator_traits<A>::destroy(a, container_detail::iterator_to_raw_pointer(back));
+ }
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+ return r;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// copy
+//
+//////////////////////////////////////////////////////////////////////////////
+
+template
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, F>::type
+ copy(I f, I l, F r)
{
while (f != l) {
- allocator_traits<A>::construct(a, container_detail::to_raw_pointer(&*f), t);
- ++f;
+ *r = *f;
+ ++f; ++r;
}
+ return r;
}
+template
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline typename container_detail::enable_if_memtransfer_copy_assignable<I, F, F>::type
+ copy(I f, I l, F r) BOOST_CONTAINER_NOEXCEPT
+{ return container_detail::memmove(f, l, r); }
+
//////////////////////////////////////////////////////////////////////////////
//
-// uninitialized_copy_or_move_alloc
+// copy_n
//
//////////////////////////////////////////////////////////////////////////////
template
-<typename A
-,typename I // I models InputIterator
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, F>::type
+ copy_n(I f, typename std::iterator_traits<I>::difference_type n, F r)
+{
+ while (n--) {
+ *r = *f;
+ ++f; ++r;
+ }
+ return r;
+}
+
+template
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline typename container_detail::enable_if_memtransfer_copy_assignable<I, F, F>::type
+ copy_n(I f, typename std::iterator_traits<I>::difference_type n, F r) BOOST_CONTAINER_NOEXCEPT
+{ return container_detail::memmove_n(f, n, r); }
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// copy_n_source
+//
+//////////////////////////////////////////////////////////////////////////////
+
+template
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, I>::type
+ copy_n_source(I f, typename std::iterator_traits<I>::difference_type n, F r)
+{
+ while (n--) {
+ *r = *f;
+ ++f; ++r;
+ }
+ return f;
+}
+
+template
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline typename container_detail::enable_if_memtransfer_copy_assignable<I, F, I>::type
+ copy_n_source(I f, typename std::iterator_traits<I>::difference_type n, F r) BOOST_CONTAINER_NOEXCEPT
+{ return container_detail::memmove_n_source(f, n, r); }
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// copy_n_source_dest
+//
+//////////////////////////////////////////////////////////////////////////////
+
+template
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, I>::type
+ copy_n_source_dest(I f, typename std::iterator_traits<I>::difference_type n, F &r)
+{
+ while (n--) {
+ *r = *f;
+ ++f; ++r;
+ }
+ return f;
+}
+
+template
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline typename container_detail::enable_if_memtransfer_copy_assignable<I, F, I>::type
+ copy_n_source_dest(I f, typename std::iterator_traits<I>::difference_type n, F &r) BOOST_CONTAINER_NOEXCEPT
+{ return container_detail::memmove_n_source_dest(f, n, r); }
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// move
+//
+//////////////////////////////////////////////////////////////////////////////
+
+template
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, F>::type
+ move(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 container_detail::enable_if_memtransfer_copy_assignable<I, F, F>::type
+ move(I f, I l, F r) BOOST_CONTAINER_NOEXCEPT
+{ return container_detail::memmove(f, l, r); }
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// move_n
+//
+//////////////////////////////////////////////////////////////////////////////
+
+template
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, F>::type
+ move_n(I f, typename std::iterator_traits<I>::difference_type n, F r)
+{
+ while (n--) {
+ *r = ::boost::move(*f);
+ ++f; ++r;
+ }
+ return r;
+}
+
+template
+<typename I, // I models InputIterator
+typename F> // F models ForwardIterator
+inline typename container_detail::enable_if_memtransfer_copy_assignable<I, F, F>::type
+ move_n(I f, typename std::iterator_traits<I>::difference_type n, F r) BOOST_CONTAINER_NOEXCEPT
+{ return container_detail::memmove_n(f, n, r); }
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// move_n_source
+//
+//////////////////////////////////////////////////////////////////////////////
+
+template
+<typename I // I models InputIterator
,typename F> // F models ForwardIterator
-F uninitialized_copy_or_move_alloc
- (A &a, I f, I l, F r
- ,typename boost::container::container_detail::enable_if
- < boost::move_detail::is_move_iterator<I> >::type* = 0)
+inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, I>::type
+ move_n_source(I f, typename std::iterator_traits<I>::difference_type n, F r)
{
- return ::boost::container::uninitialized_move_alloc(a, f, l, r);
+ while (n--) {
+ *r = ::boost::move(*f);
+ ++f; ++r;
+ }
+ return f;
}
template
-<typename A
-,typename I // I models InputIterator
+<typename I // I models InputIterator
+,typename F> // F models ForwardIterator
+inline typename container_detail::enable_if_memtransfer_copy_assignable<I, F, I>::type
+ move_n_source(I f, typename std::iterator_traits<I>::difference_type n, F r) BOOST_CONTAINER_NOEXCEPT
+{ return container_detail::memmove_n_source(f, n, r); }
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// move_n_source_dest
+//
+//////////////////////////////////////////////////////////////////////////////
+
+template
+<typename I // I models InputIterator
,typename F> // F models ForwardIterator
-F uninitialized_copy_or_move_alloc
- (A &a, I f, I l, F r
- ,typename boost::container::container_detail::disable_if
- < boost::move_detail::is_move_iterator<I> >::type* = 0)
+inline typename container_detail::disable_if_memtransfer_copy_assignable<I, F, I>::type
+ move_n_source_dest(I f, typename std::iterator_traits<I>::difference_type n, F &r)
{
- return ::boost::container::uninitialized_copy_alloc(a, f, l, r);
+ while (n--) {
+ *r = ::boost::move(*f);
+ ++f; ++r;
+ }
+ return f;
}
+template
+<typename I // I models InputIterator
+,typename F> // F models ForwardIterator
+inline typename container_detail::enable_if_memtransfer_copy_assignable<I, F, I>::type
+ move_n_source_dest(I f, typename std::iterator_traits<I>::difference_type n, F &r) BOOST_CONTAINER_NOEXCEPT
+{ return container_detail::memmove_n_source_dest(f, n, r); }
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// destroy_n
+//
+//////////////////////////////////////////////////////////////////////////////
+
+template
+ <typename A
+ ,typename I> // I models InputIterator
+inline void destroy_alloc_n(A &a, I f, typename std::iterator_traits<I>::difference_type n
+ ,typename boost::container::container_detail::enable_if_c
+ < !boost::has_trivial_destructor<typename std::iterator_traits<I>::value_type>::value >::type* = 0)
+{
+ while(n--){
+ allocator_traits<A>::destroy(a, container_detail::iterator_to_raw_pointer(f++));
+ }
+}
+
+template
+ <typename A
+ ,typename I> // I models InputIterator
+inline void destroy_alloc_n(A &, I, typename std::iterator_traits<I>::difference_type
+ ,typename boost::container::container_detail::enable_if_c
+ < boost::has_trivial_destructor<typename std::iterator_traits<I>::value_type>::value >::type* = 0)
+{}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// deep_swap_alloc_n
+//
+//////////////////////////////////////////////////////////////////////////////
+
+template
+ <std::size_t MaxTmpBytes
+ ,typename A
+ ,typename F // F models ForwardIterator
+ ,typename G // G models ForwardIterator
+ >
+inline typename container_detail::disable_if_memtransfer_copy_assignable<F, G, void>::type
+ deep_swap_alloc_n( A &a, F short_range_f, typename allocator_traits<A>::size_type n_i
+ , G large_range_f, typename allocator_traits<A>::size_type n_j)
+{
+ typename allocator_traits<A>::size_type n = 0;
+ for (; n != n_i ; ++short_range_f, ++large_range_f, ++n){
+ boost::container::swap_dispatch(*short_range_f, *large_range_f);
+ }
+ boost::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 A
+ ,typename F // F models ForwardIterator
+ ,typename G // G models ForwardIterator
+ >
+inline typename container_detail::enable_if_c
+ < container_detail::is_memtransfer_copy_assignable<F, G>::value && (MaxTmpBytes <= DeepSwapAllocNMaxStorage) && false
+ , void>::type
+ deep_swap_alloc_n( A &a, F short_range_f, typename allocator_traits<A>::size_type n_i
+ , G large_range_f, typename allocator_traits<A>::size_type n_j)
+{
+ typedef typename allocator_traits<A>::value_type value_type;
+ typedef typename boost::aligned_storage
+ <MaxTmpBytes, container_detail::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*>(container_detail::iterator_to_raw_pointer(large_range_f));
+ void *const short_ptr = static_cast<void*>(container_detail::iterator_to_raw_pointer(short_range_f));
+ void *const stora_ptr = static_cast<void*>(container_detail::iterator_to_raw_pointer(storage));
+ ::memcpy(stora_ptr, large_ptr, n_i_bytes);
+ ::memcpy(large_ptr, short_ptr, n_i_bytes);
+ ::memcpy(short_ptr, stora_ptr, n_i_bytes);
+ std::advance(large_range_f, n_i);
+ std::advance(short_range_f, n_i);
+ boost::container::uninitialized_move_alloc_n(a, large_range_f, n_j - n_i, short_range_f); // may throw
+ boost::container::destroy_alloc_n(a, large_range_f, n_j - n_i);
+}
+
+template
+ <std::size_t MaxTmpBytes
+ ,typename A
+ ,typename F // F models ForwardIterator
+ ,typename G // G models ForwardIterator
+ >
+inline typename container_detail::enable_if_c
+ < container_detail::is_memtransfer_copy_assignable<F, G>::value && true//(MaxTmpBytes > DeepSwapAllocNMaxStorage)
+ , void>::type
+ deep_swap_alloc_n( A &a, F short_range_f, typename allocator_traits<A>::size_type n_i
+ , G large_range_f, typename allocator_traits<A>::size_type n_j)
+{
+ typedef typename allocator_traits<A>::value_type value_type;
+ typedef typename boost::aligned_storage
+ <DeepSwapAllocNMaxStorage, container_detail::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*>(container_detail::iterator_to_raw_pointer(large_range_f)));
+ char *short_ptr = static_cast<char*>(static_cast<void*>(container_detail::iterator_to_raw_pointer(short_range_f)));
+ char *stora_ptr = static_cast<char*>(static_cast<void*>(&storage));
+
+ 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{
+ ::memcpy(stora_ptr, large_ptr, sizeof_storage);
+ ::memcpy(large_ptr, short_ptr, sizeof_storage);
+ ::memcpy(short_ptr, stora_ptr, sizeof_storage);
+ large_ptr += sizeof_storage;
+ short_ptr += sizeof_storage;
+ BOOST_CONTAINER_FALLTHOUGH
+ case 3:
+ ::memcpy(stora_ptr, large_ptr, sizeof_storage);
+ ::memcpy(large_ptr, short_ptr, sizeof_storage);
+ ::memcpy(short_ptr, stora_ptr, sizeof_storage);
+ large_ptr += sizeof_storage;
+ short_ptr += sizeof_storage;
+ BOOST_CONTAINER_FALLTHOUGH
+ case 2:
+ ::memcpy(stora_ptr, large_ptr, sizeof_storage);
+ ::memcpy(large_ptr, short_ptr, sizeof_storage);
+ ::memcpy(short_ptr, stora_ptr, sizeof_storage);
+ large_ptr += sizeof_storage;
+ short_ptr += sizeof_storage;
+ BOOST_CONTAINER_FALLTHOUGH
+ case 1:
+ ::memcpy(stora_ptr, large_ptr, sizeof_storage);
+ ::memcpy(large_ptr, short_ptr, sizeof_storage);
+ ::memcpy(short_ptr, stora_ptr, sizeof_storage);
+ large_ptr += sizeof_storage;
+ short_ptr += sizeof_storage;
+ } while(--n);
+ }
+ ::memcpy(stora_ptr, large_ptr, szt_rem);
+ ::memcpy(large_ptr, short_ptr, szt_rem);
+ ::memcpy(short_ptr, stora_ptr, szt_rem);
+ std::advance(large_range_f, n_i);
+ std::advance(short_range_f, n_i);
+ 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 A
+ ,typename I // F models InputIterator
+ ,typename O // G models OutputIterator
+ >
+void copy_assign_range_alloc_n( A &a, I inp_start, typename allocator_traits<A>::size_type n_i
+ , O out_start, typename allocator_traits<A>::size_type n_o )
+{
+ 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 A
+ ,typename I // F models InputIterator
+ ,typename O // G models OutputIterator
+ >
+void move_assign_range_alloc_n( A &a, I inp_start, typename allocator_traits<A>::size_type n_i
+ , O out_start, typename allocator_traits<A>::size_type n_o )
+{
+ 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 {
-
#include <boost/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINER_DETAIL_UTILITIES_HPP
diff --git a/boost/container/detail/value_init.hpp b/boost/container/detail/value_init.hpp
index ec1a99c56d..68f9678358 100644
--- a/boost/container/detail/value_init.hpp
+++ b/boost/container/detail/value_init.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012.
+// (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
@@ -13,11 +13,11 @@
#ifndef BOOST_CONTAINER_DETAIL_VALUE_INIT_HPP
#define BOOST_CONTAINER_DETAIL_VALUE_INIT_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
-#include "config_begin.hpp"
+#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
namespace boost {
diff --git a/boost/container/detail/variadic_templates_tools.hpp b/boost/container/detail/variadic_templates_tools.hpp
index d903dfa04c..b07fe3050e 100644
--- a/boost/container/detail/variadic_templates_tools.hpp
+++ b/boost/container/detail/variadic_templates_tools.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost
+// (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)
//
@@ -11,12 +11,13 @@
#ifndef BOOST_CONTAINER_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
#define BOOST_CONTAINER_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
-#include "config_begin.hpp"
+#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
+
#include <boost/container/detail/type_traits.hpp>
#include <cstddef> //std::size_t
diff --git a/boost/container/detail/version_type.hpp b/boost/container/detail/version_type.hpp
index e47ba26f12..2eabc62483 100644
--- a/boost/container/detail/version_type.hpp
+++ b/boost/container/detail/version_type.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
+// (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)
//
@@ -16,7 +16,12 @@
#ifndef BOOST_CONTAINER_DETAIL_VERSION_TYPE_HPP
#define BOOST_CONTAINER_DETAIL_VERSION_TYPE_HPP
-#include "config_begin.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/mpl.hpp>
#include <boost/container/detail/type_traits.hpp>
@@ -80,13 +85,19 @@ struct version<T, true>
template <class T>
struct version
: public container_detail::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 container_detail {
} //namespace container {
} //namespace boost{
-#include "config_end.hpp"
+#include <boost/container/detail/config_end.hpp>
#endif //#define BOOST_CONTAINER_DETAIL_VERSION_TYPE_HPP
diff --git a/boost/container/detail/workaround.hpp b/boost/container/detail/workaround.hpp
index c4440743fc..55ebe339ce 100644
--- a/boost/container/detail/workaround.hpp
+++ b/boost/container/detail/workaround.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
+// (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)
//
@@ -11,26 +11,62 @@
#ifndef BOOST_CONTAINER_DETAIL_WORKAROUND_HPP
#define BOOST_CONTAINER_DETAIL_WORKAROUND_HPP
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
#include <boost/container/detail/config_begin.hpp>
-#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)\
+#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_NOEXCEPT)
- #define BOOST_CONTAINER_NOEXCEPT
+#if defined(BOOST_NO_CXX11_NOEXCEPT)
+ #if defined(BOOST_MSVC)
+ #define BOOST_CONTAINER_NOEXCEPT throw()
+ #else
+ #define BOOST_CONTAINER_NOEXCEPT
+ #endif
#define BOOST_CONTAINER_NOEXCEPT_IF(x)
#else
#define BOOST_CONTAINER_NOEXCEPT noexcept
#define BOOST_CONTAINER_NOEXCEPT_IF(x) noexcept(x)
#endif
-#if !defined(BOOST_NO_VARIADIC_TEMPLATES) && defined(__GXX_EXPERIMENTAL_CXX0X__)\
+#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_FALLTHOUGH)
+ #define BOOST_CONTAINER_FALLTHOUGH
+#else
+ #define BOOST_CONTAINER_FALLTHOUGH BOOST_FALLTHOUGH;
+#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)
+
#include <boost/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINER_DETAIL_WORKAROUND_HPP
diff --git a/boost/container/flat_map.hpp b/boost/container/flat_map.hpp
index 0142500860..e7ff31a30b 100644
--- a/boost/container/flat_map.hpp
+++ b/boost/container/flat_map.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
+// (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)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_CONTAINER_FLAT_MAP_HPP
#define BOOST_CONTAINER_FLAT_MAP_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -22,37 +22,24 @@
#include <utility>
#include <functional>
#include <memory>
-#include <stdexcept>
#include <boost/container/detail/flat_tree.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/allocator_traits.hpp>
-#include <boost/move/move.hpp>
+#include <boost/container/throw_exception.hpp>
+#include <boost/move/utility_core.hpp>
+#include <boost/move/detail/move_helpers.hpp>
+#include <boost/move/traits.hpp>
+#include <boost/core/no_exceptions_support.hpp>
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+#include <initializer_list>
+#endif
-#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
-namespace boost {
-namespace container {
-#else
namespace boost {
namespace container {
-#endif
-
-/// @cond
-// Forward declarations of operators == and <, needed for friend declarations.
-#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
-template <class Key, class T, class Pred = std::less< std::pair< Key, T> >, class A = std::allocator<T> >
-#else
-template <class Key, class T, class Pred, class A>
-#endif
-class flat_map;
-template <class Key, class T, class Pred, class A>
-inline bool operator==(const flat_map<Key,T,Pred,A>& x,
- const flat_map<Key,T,Pred,A>& y);
-
-template <class Key, class T, class Pred, class A>
-inline bool operator<(const flat_map<Key,T,Pred,A>& x,
- const flat_map<Key,T,Pred,A>& y);
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
namespace container_detail{
@@ -69,8 +56,7 @@ static D force_copy(S s)
} //namespace container_detail{
-
-/// @endcond
+#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
@@ -82,109 +68,132 @@ static D force_copy(S s)
//! 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>).
//!
-//! Pred is the ordering function for Keys (e.g. <i>std::less<Key></i>).
+//! Compare is the ordering function for Keys (e.g. <i>std::less<Key></i>).
//!
-//! A is the allocator to allocate the value_types
+//! Allocator is the allocator to allocate the value_types
//! (e.g. <i>allocator< std::pair<Key, T> ></i>).
//!
//! flat_map is similar to std::map but it's implemented like an ordered vector.
//! This means that inserting a new element into a flat_map invalidates
//! previous iterators and references
//!
-//! Erasing an element of a flat_map invalidates iterators and references
+//! Erasing an element invalidates 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 Allocator is the allocator to allocate the <code>value_type</code>s
+//! (e.g. <i>allocator< std::pair<Key, T> > </i>).
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
-template <class Key, class T, class Pred = std::less< std::pair< Key, T> >, class A = std::allocator<T> >
+template <class Key, class T, class Compare = std::less<Key>, class Allocator = std::allocator< std::pair< Key, T> > >
#else
-template <class Key, class T, class Pred, class A>
+template <class Key, class T, class Compare, class Allocator>
#endif
class flat_map
{
- /// @cond
+ #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 container_detail::flat_tree<Key,
std::pair<Key, T>,
container_detail::select1st< std::pair<Key, T> >,
- Pred,
- A> tree_t;
+ Compare,
+ Allocator> tree_t;
//This is the real tree stored here. It's based on a movable pair
typedef container_detail::flat_tree<Key,
container_detail::pair<Key, T>,
container_detail::select1st<container_detail::pair<Key, T> >,
- Pred,
- typename allocator_traits<A>::template portable_rebind_alloc
+ Compare,
+ typename allocator_traits<Allocator>::template portable_rebind_alloc
<container_detail::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::pointer impl_pointer;
- typedef typename impl_tree_t::const_pointer impl_const_pointer;
- typedef typename impl_tree_t::reference impl_reference;
- typedef typename impl_tree_t::const_reference impl_const_reference;
- typedef typename impl_tree_t::value_compare impl_value_compare;
- typedef typename impl_tree_t::iterator impl_iterator;
typedef typename impl_tree_t::const_iterator impl_const_iterator;
- typedef typename impl_tree_t::reverse_iterator impl_reverse_iterator;
- typedef typename impl_tree_t::const_reverse_iterator impl_const_reverse_iterator;
typedef typename impl_tree_t::allocator_type impl_allocator_type;
- typedef allocator_traits<A> allocator_traits_type;
-
-
-
- /// @endcond
+ typedef container_detail::flat_tree_value_compare
+ < Compare
+ , container_detail::select1st< std::pair<Key, T> >
+ , std::pair<Key, T> > value_compare_impl;
+ typedef typename container_detail::get_flat_tree_iterators
+ <typename allocator_traits<Allocator>::pointer>::iterator iterator_impl;
+ typedef typename container_detail::get_flat_tree_iterators
+ <typename allocator_traits<Allocator>::pointer>::const_iterator const_iterator_impl;
+ typedef typename container_detail::get_flat_tree_iterators
+ <typename allocator_traits<Allocator>::pointer>::reverse_iterator reverse_iterator_impl;
+ typedef typename container_detail::get_flat_tree_iterators
+ <typename allocator_traits<Allocator>::pointer>::const_reverse_iterator const_reverse_iterator_impl;
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public:
- // typedefs:
- typedef Key key_type;
- typedef T mapped_type;
- typedef typename std::pair<key_type, mapped_type> value_type;
- typedef typename allocator_traits_type::pointer pointer;
- typedef typename allocator_traits_type::const_pointer const_pointer;
- typedef typename allocator_traits_type::reference reference;
- typedef typename allocator_traits_type::const_reference const_reference;
- typedef typename impl_tree_t::size_type size_type;
- typedef typename impl_tree_t::difference_type difference_type;
-
- typedef container_detail::flat_tree_value_compare
- < Pred
- , container_detail::select1st< std::pair<Key, T> >
- , std::pair<Key, T> > value_compare;
- typedef Pred key_compare;
- typedef typename container_detail::
- get_flat_tree_iterators<pointer>::iterator iterator;
- typedef typename container_detail::
- get_flat_tree_iterators<pointer>::const_iterator const_iterator;
- typedef typename container_detail::
- get_flat_tree_iterators
- <pointer>::reverse_iterator reverse_iterator;
- typedef typename container_detail::
- get_flat_tree_iterators
- <pointer>::const_reverse_iterator const_reverse_iterator;
- typedef A allocator_type;
-
- //!Standard extension
- typedef A stored_allocator_type;
-
- //!Standard extension for C++03 compilers with non-movable std::pair
- typedef impl_value_type movable_value_type;
+ //////////////////////////////////////////////
+ //
+ // types
+ //
+ //////////////////////////////////////////////
+ typedef Key key_type;
+ typedef T mapped_type;
+ typedef std::pair<Key, T> value_type;
+ 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 BOOST_CONTAINER_IMPDEF(Allocator) stored_allocator_type;
+ typedef BOOST_CONTAINER_IMPDEF(value_compare_impl) value_compare;
+ typedef Compare key_compare;
+ typedef BOOST_CONTAINER_IMPDEF(iterator_impl) iterator;
+ typedef BOOST_CONTAINER_IMPDEF(const_iterator_impl) const_iterator;
+ typedef BOOST_CONTAINER_IMPDEF(reverse_iterator_impl) reverse_iterator;
+ typedef BOOST_CONTAINER_IMPDEF(const_reverse_iterator_impl) const_reverse_iterator;
+ typedef BOOST_CONTAINER_IMPDEF(impl_value_type) movable_value_type;
public:
+ //////////////////////////////////////////////
+ //
+ // construct/copy/destroy
+ //
+ //////////////////////////////////////////////
+
//! <b>Effects</b>: Default constructs an empty flat_map.
//!
//! <b>Complexity</b>: Constant.
flat_map()
- : m_flat_tree() {}
+ : m_flat_tree()
+ {
+ //Allocator type must be std::pair<Key, T>
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
+ }
//! <b>Effects</b>: Constructs an empty flat_map using the specified
//! comparison object and allocator.
//!
//! <b>Complexity</b>: Constant.
- explicit flat_map(const Pred& comp, const allocator_type& a = allocator_type())
- : m_flat_tree(comp, container_detail::force<impl_allocator_type>(a)) {}
+ explicit flat_map(const Compare& comp, const allocator_type& a = allocator_type())
+ : m_flat_tree(comp, container_detail::force<impl_allocator_type>(a))
+ {
+ //Allocator type must be std::pair<Key, T>
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
+ }
+
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified allocator.
+ //!
+ //! <b>Complexity</b>: Constant.
+ explicit flat_map(const allocator_type& a)
+ : m_flat_tree(container_detail::force<impl_allocator_type>(a))
+ {
+ //Allocator type must be std::pair<Key, T>
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
+ }
//! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
//! allocator, and inserts elements from the range [first ,last ).
@@ -192,10 +201,13 @@ class flat_map
//! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
//! comp and otherwise N logN, where N is last - first.
template <class InputIterator>
- flat_map(InputIterator first, InputIterator last, const Pred& comp = Pred(),
+ flat_map(InputIterator first, InputIterator last, const Compare& comp = Compare(),
const allocator_type& a = allocator_type())
- : m_flat_tree(comp, container_detail::force<impl_allocator_type>(a))
- { m_flat_tree.insert_unique(first, last); }
+ : m_flat_tree(true, first, last, comp, container_detail::force<impl_allocator_type>(a))
+ {
+ //Allocator type must be std::pair<Key, T>
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
+ }
//! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
//! allocator, and inserts elements from the ordered unique range [first ,last). This function
@@ -209,15 +221,55 @@ class flat_map
//! <b>Note</b>: Non-standard extension.
template <class InputIterator>
flat_map( ordered_unique_range_t, InputIterator first, InputIterator last
- , const Pred& comp = Pred(), const allocator_type& a = allocator_type())
+ , const Compare& comp = Compare(), const allocator_type& a = allocator_type())
: m_flat_tree(ordered_range, first, last, comp, a)
- {}
+ {
+ //Allocator type must be std::pair<Key, T>
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
+ }
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
+ //! allocator, and inserts elements from the range [il.begin() ,il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
+ //! comp and otherwise N logN, where N is last - first.
+ flat_map(std::initializer_list<value_type> il, const Compare& comp = Compare(),
+ const allocator_type& a = allocator_type())
+ : m_flat_tree(true, il.begin(), il.end(), comp, container_detail::force<impl_allocator_type>(a))
+ {
+ //Allocator type must be std::pair<Key, T>
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
+ }
+
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified 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.
+ flat_map(ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp = Compare(),
+ const allocator_type& a = allocator_type())
+ : m_flat_tree(ordered_range, il.begin(), il.end(), comp, a)
+ {
+ //Allocator type must be std::pair<Key, T>
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
+ }
+#endif
//! <b>Effects</b>: Copy constructs a flat_map.
//!
//! <b>Complexity</b>: Linear in x.size().
flat_map(const flat_map& x)
- : m_flat_tree(x.m_flat_tree) {}
+ : m_flat_tree(x.m_flat_tree)
+ {
+ //Allocator type must be std::pair<Key, T>
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
+ }
//! <b>Effects</b>: Move constructs a flat_map.
//! Constructs *this using x's resources.
@@ -227,14 +279,20 @@ class flat_map
//! <b>Postcondition</b>: x is emptied.
flat_map(BOOST_RV_REF(flat_map) x)
: m_flat_tree(boost::move(x.m_flat_tree))
- {}
+ {
+ //Allocator type must be std::pair<Key, T>
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
+ }
//! <b>Effects</b>: Copy constructs a flat_map using the specified allocator.
//!
//! <b>Complexity</b>: Linear in x.size().
flat_map(const flat_map& x, const allocator_type &a)
: m_flat_tree(x.m_flat_tree, a)
- {}
+ {
+ //Allocator type must be std::pair<Key, T>
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
+ }
//! <b>Effects</b>: Move constructs a flat_map using the specified allocator.
//! Constructs *this using x's resources.
@@ -242,7 +300,10 @@ class flat_map
//! <b>Complexity</b>: Constant if x.get_allocator() == a, linear otherwise.
flat_map(BOOST_RV_REF(flat_map) x, const allocator_type &a)
: m_flat_tree(boost::move(x.m_flat_tree), a)
- {}
+ {
+ //Allocator type must be std::pair<Key, T>
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
+ }
//! <b>Effects</b>: Makes *this a copy of x.
//!
@@ -253,45 +314,65 @@ class flat_map
//! <b>Effects</b>: Move constructs a flat_map.
//! Constructs *this using x's resources.
//!
- //! <b>Complexity</b>: Construct.
+ //! <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>Postcondition</b>: x is emptied.
- flat_map& operator=(BOOST_RV_REF(flat_map) mx)
- { m_flat_tree = boost::move(mx.m_flat_tree); return *this; }
+ //! <b>Complexity</b>: Constant if allocator_traits_type::
+ //! propagate_on_container_move_assignment is true or
+ //! this->get>allocator() == x.get_allocator(). Linear otherwise.
+ flat_map& operator=(BOOST_RV_REF(flat_map) x)
+ BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value)
+ { m_flat_tree = boost::move(x.m_flat_tree); return *this; }
- //! <b>Effects</b>: Returns the comparison object out
- //! of which a was constructed.
- //!
- //! <b>Complexity</b>: Constant.
- key_compare key_comp() const
- { return container_detail::force_copy<key_compare>(m_flat_tree.key_comp()); }
-
- //! <b>Effects</b>: Returns an object of value_compare constructed out
- //! of the comparison object.
- //!
- //! <b>Complexity</b>: Constant.
- value_compare value_comp() const
- { return value_compare(container_detail::force_copy<key_compare>(m_flat_tree.key_comp())); }
+#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.
- allocator_type get_allocator() const
+ allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<allocator_type>(m_flat_tree.get_allocator()); }
- const stored_allocator_type &get_stored_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_CONTAINER_NOEXCEPT
{ return container_detail::force<stored_allocator_type>(m_flat_tree.get_stored_allocator()); }
- 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 BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force<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.
- iterator begin()
+ iterator begin() BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<iterator>(m_flat_tree.begin()); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
@@ -299,7 +380,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_iterator begin() const
+ const_iterator begin() const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<const_iterator>(m_flat_tree.begin()); }
//! <b>Effects</b>: Returns an iterator to the end of the container.
@@ -307,7 +388,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- iterator end()
+ iterator end() BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<iterator>(m_flat_tree.end()); }
//! <b>Effects</b>: Returns a const_iterator to the end of the container.
@@ -315,7 +396,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_iterator end() const
+ const_iterator end() const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<const_iterator>(m_flat_tree.end()); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
@@ -324,7 +405,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- reverse_iterator rbegin()
+ reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<reverse_iterator>(m_flat_tree.rbegin()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
@@ -333,7 +414,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reverse_iterator rbegin() const
+ const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<const_reverse_iterator>(m_flat_tree.rbegin()); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the end
@@ -342,7 +423,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- reverse_iterator rend()
+ reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<reverse_iterator>(m_flat_tree.rend()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
@@ -351,7 +432,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reverse_iterator rend() const
+ const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<const_reverse_iterator>(m_flat_tree.rend()); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
@@ -359,7 +440,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_iterator cbegin() const
+ const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<const_iterator>(m_flat_tree.cbegin()); }
//! <b>Effects</b>: Returns a const_iterator to the end of the container.
@@ -367,7 +448,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_iterator cend() const
+ const_iterator cend() const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<const_iterator>(m_flat_tree.cend()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
@@ -376,7 +457,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reverse_iterator crbegin() const
+ const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<const_reverse_iterator>(m_flat_tree.crbegin()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
@@ -385,15 +466,21 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reverse_iterator crend() const
+ const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::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.
- bool empty() const
+ bool empty() const BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.empty(); }
//! <b>Effects</b>: Returns the number of the elements contained in the container.
@@ -401,7 +488,7 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- size_type size() const
+ size_type size() const BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.size(); }
//! <b>Effects</b>: Returns the largest possible size of the container.
@@ -409,14 +496,50 @@ class flat_map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- size_type max_size() const
+ size_type max_size() const BOOST_CONTAINER_NOEXCEPT
{ 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.
+ size_type capacity() const BOOST_CONTAINER_NOEXCEPT
+ { return m_flat_tree.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 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)
+ { 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().
+ 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.
+ //! Returns: Allocator reference to the mapped_type corresponding to x in *this.
//!
//! Complexity: Logarithmic.
mapped_type &operator[](const key_type& k);
@@ -424,46 +547,106 @@ class flat_map
//! Effects: If there is no key equivalent to x in the flat_map, inserts
//! value_type(move(x), T()) into the flat_map (the key is move-constructed)
//!
- //! Returns: A reference to the mapped_type corresponding to x in *this.
+ //! Returns: Allocator reference to the mapped_type corresponding to x in *this.
//!
//! Complexity: Logarithmic.
mapped_type &operator[](key_type &&k) ;
#else
- BOOST_MOVE_CONVERSION_AWARE_CATCH( operator[] , key_type, mapped_type&, priv_subscript)
+ BOOST_MOVE_CONVERSION_AWARE_CATCH( operator[] , key_type, mapped_type&, this->priv_subscript)
#endif
- //! Returns: A reference to the element whose key is equivalent to x.
+ //! Returns: Allocator 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 std::out_of_range("key not found");
+ 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.
+ //! Returns: Allocator 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 std::out_of_range("key not found");
+ throw_out_of_range("flat_map::at key not found");
}
return i->second;
}
- //! <b>Effects</b>: Swaps the contents of *this and x.
+ //////////////////////////////////////////////
+ //
+ // modifiers
+ //
+ //////////////////////////////////////////////
+
+ #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || 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>Throws</b>: Nothing.
+ //! <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>: Constant.
- void swap(flat_map& x)
- { m_flat_tree.swap(x.m_flat_tree); }
+ //! <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>
+ std::pair<iterator,bool> emplace(Args&&... args)
+ { return container_detail::force_copy< std::pair<iterator, bool> >(m_flat_tree.emplace_unique(boost::forward<Args>(args)...)); }
+
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! 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>
+ iterator emplace_hint(const_iterator hint, Args&&... args)
+ {
+ return container_detail::force_copy<iterator>
+ (m_flat_tree.emplace_hint_unique( container_detail::force_copy<impl_const_iterator>(hint)
+ , boost::forward<Args>(args)...));
+ }
+
+ #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
+
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
+ std::pair<iterator,bool> emplace(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
+ { return container_detail::force_copy< std::pair<iterator, bool> > \
+ (m_flat_tree.emplace_unique(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); } \
+ \
+ BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
+ iterator emplace_hint(const_iterator hint \
+ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
+ { return container_detail::force_copy<iterator>(m_flat_tree.emplace_hint_unique \
+ (container_detail::force_copy<impl_const_iterator>(hint) \
+ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); } \
+ //!
+ #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
+ #include BOOST_PP_LOCAL_ITERATE()
+
+ #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
//! <b>Effects</b>: Inserts x if and only if there is no element in the container
//! with key equivalent to the key of x.
@@ -523,10 +706,10 @@ class flat_map
//! right before p) plus insertion linear to the elements with bigger keys than x.
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
- iterator insert(const_iterator position, const value_type& x)
+ iterator insert(const_iterator p, const value_type& x)
{
return container_detail::force_copy<iterator>(
- m_flat_tree.insert_unique( container_detail::force_copy<impl_const_iterator>(position)
+ m_flat_tree.insert_unique( container_detail::force_copy<impl_const_iterator>(p)
, container_detail::force<impl_value_type>(x)));
}
@@ -539,10 +722,10 @@ class flat_map
//! right before p) plus insertion linear to the elements with bigger keys than x.
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
- iterator insert(const_iterator position, BOOST_RV_REF(value_type) x)
+ iterator insert(const_iterator p, BOOST_RV_REF(value_type) x)
{
return container_detail::force_copy<iterator>
- (m_flat_tree.insert_unique( container_detail::force_copy<impl_const_iterator>(position)
+ (m_flat_tree.insert_unique( container_detail::force_copy<impl_const_iterator>(p)
, boost::move(container_detail::force<impl_value_type>(x))));
}
@@ -555,10 +738,10 @@ class flat_map
//! right before p) plus insertion linear to the elements with bigger keys than x.
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
- iterator insert(const_iterator position, BOOST_RV_REF(movable_value_type) x)
+ iterator insert(const_iterator p, BOOST_RV_REF(movable_value_type) x)
{
return container_detail::force_copy<iterator>(
- m_flat_tree.insert_unique(container_detail::force_copy<impl_const_iterator>(position), boost::move(x)));
+ m_flat_tree.insert_unique(container_detail::force_copy<impl_const_iterator>(p), boost::move(x)));
}
//! <b>Requires</b>: first, last are not iterators into *this.
@@ -587,82 +770,54 @@ class flat_map
//! search time plus N*size() insertion time.
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
+ //!
+ //! <b>Note</b>: Non-standard extension.
template <class InputIterator>
void insert(ordered_unique_range_t, InputIterator first, InputIterator last)
{ m_flat_tree.insert_unique(ordered_unique_range, first, last); }
- #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || 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.
+#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>: Logarithmic search time plus linear insertion
- //! to the elements with bigger keys than x.
+ //! <b>Complexity</b>: At most N log(size()+N) (N is the distance from il.first() to il.end())
+ //! search time plus N*size() insertion time.
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
- template <class... Args>
- std::pair<iterator,bool> emplace(Args&&... args)
- { return container_detail::force_copy< std::pair<iterator, bool> >(m_flat_tree.emplace_unique(boost::forward<Args>(args)...)); }
+ void insert(std::initializer_list<value_type> il)
+ { m_flat_tree.insert_unique(il.begin(), il.end()); }
- //! <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>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate and must be
+ //! unique values.
//!
- //! <b>Returns</b>: An iterator pointing to the element with key equivalent
- //! to the key of x.
+ //! <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>: Logarithmic search time (constant if x is inserted
- //! right before p) plus insertion linear to the elements with bigger keys than x.
+ //! <b>Complexity</b>: At most N log(size()+N) (N is the distance from first to last)
+ //! search time plus N*size() insertion time.
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
- template <class... Args>
- iterator emplace_hint(const_iterator hint, Args&&... args)
- {
- return container_detail::force_copy<iterator>
- (m_flat_tree.emplace_hint_unique( container_detail::force_copy<impl_const_iterator>(hint)
- , boost::forward<Args>(args)...));
- }
-
- #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
-
- #define BOOST_PP_LOCAL_MACRO(n) \
- BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
- std::pair<iterator,bool> emplace(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
- { return container_detail::force_copy< std::pair<iterator, bool> > \
- (m_flat_tree.emplace_unique(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); } \
- \
- BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
- iterator emplace_hint(const_iterator hint \
- BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
- { return container_detail::force_copy<iterator>(m_flat_tree.emplace_hint_unique \
- (container_detail::force_copy<impl_const_iterator>(hint) \
- BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); } \
//!
- #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
- #include BOOST_PP_LOCAL_ITERATE()
-
- #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
+ //! <b>Note</b>: Non-standard extension.
+ void insert(ordered_unique_range_t, std::initializer_list<value_type> il)
+ { m_flat_tree.insert_unique(ordered_unique_range, il.begin(), il.end()); }
+#endif
- //! <b>Effects</b>: Erases the element pointed to by position.
+ //! <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 position
+ //! <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 position)
+ iterator erase(const_iterator p)
{
return container_detail::force_copy<iterator>
- (m_flat_tree.erase(container_detail::force_copy<impl_const_iterator>(position)));
+ (m_flat_tree.erase(container_detail::force_copy<impl_const_iterator>(p)));
}
//! <b>Effects</b>: Erases all elements in the container with key equivalent to x.
@@ -689,22 +844,47 @@ class flat_map
, container_detail::force_copy<impl_const_iterator>(last)));
}
+ //! <b>Effects</b>: Swaps the contents of *this and x.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ void swap(flat_map& x)
+ { 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().
- void clear()
+ void clear() BOOST_CONTAINER_NOEXCEPT
{ m_flat_tree.clear(); }
- //! <b>Effects</b>: Tries to deallocate the excess of memory created
- // with previous allocations. The size of the vector is unchanged
+ //////////////////////////////////////////////
+ //
+ // observers
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Returns the comparison object out
+ //! of which a was constructed.
//!
- //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
+ //! <b>Complexity</b>: Constant.
+ key_compare key_comp() const
+ { return container_detail::force_copy<key_compare>(m_flat_tree.key_comp()); }
+
+ //! <b>Effects</b>: Returns an object of value_compare constructed out
+ //! of the comparison object.
//!
- //! <b>Complexity</b>: Linear to size().
- void shrink_to_fit()
- { m_flat_tree.shrink_to_fit(); }
+ //! <b>Complexity</b>: Constant.
+ value_compare value_comp() const
+ { return value_compare(container_detail::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.
@@ -713,7 +893,7 @@ class flat_map
iterator find(const key_type& x)
{ return container_detail::force_copy<iterator>(m_flat_tree.find(x)); }
- //! <b>Returns</b>: A const_iterator pointing to an element with the key
+ //! <b>Returns</b>: Allocator const_iterator pointing to an element with the key
//! equivalent to x, or end() if such an element is not found.
//!
//! <b>Complexity</b>: Logarithmic.s
@@ -724,7 +904,7 @@ class flat_map
//!
//! <b>Complexity</b>: log(size())+count(k)
size_type count(const key_type& x) const
- { return m_flat_tree.find(x) == m_flat_tree.end() ? 0 : 1; }
+ { 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.
@@ -733,7 +913,7 @@ class flat_map
iterator lower_bound(const key_type& x)
{ return container_detail::force_copy<iterator>(m_flat_tree.lower_bound(x)); }
- //! <b>Returns</b>: A const iterator pointing to the first element with key not
+ //! <b>Returns</b>: Allocator 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
@@ -747,7 +927,7 @@ class flat_map
iterator upper_bound(const key_type& x)
{ return container_detail::force_copy<iterator>(m_flat_tree.upper_bound(x)); }
- //! <b>Returns</b>: A const iterator pointing to the first element with key not
+ //! <b>Returns</b>: Allocator 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
@@ -758,43 +938,57 @@ class flat_map
//!
//! <b>Complexity</b>: Logarithmic
std::pair<iterator,iterator> equal_range(const key_type& x)
- { return container_detail::force_copy<std::pair<iterator,iterator> >(m_flat_tree.equal_range(x)); }
+ { return container_detail::force_copy<std::pair<iterator,iterator> >(m_flat_tree.lower_bound_range(x)); }
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
//!
//! <b>Complexity</b>: Logarithmic
std::pair<const_iterator,const_iterator> equal_range(const key_type& x) const
- { return container_detail::force_copy<std::pair<const_iterator,const_iterator> >(m_flat_tree.equal_range(x)); }
+ { return container_detail::force_copy<std::pair<const_iterator,const_iterator> >(m_flat_tree.lower_bound_range(x)); }
- //! <b>Effects</b>: Number of elements for which memory has been allocated.
- //! capacity() is always greater than or equal to size().
+ //! <b>Effects</b>: Returns true if x and y are equal
//!
- //! <b>Throws</b>: Nothing.
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator==(const flat_map& x, const flat_map& y)
+ { return x.size() == y.size() && std::equal(x.begin(), x.end(), y.begin()); }
+
+ //! <b>Effects</b>: Returns true if x and y are unequal
//!
- //! <b>Complexity</b>: Constant.
- size_type capacity() const
- { return m_flat_tree.capacity(); }
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator!=(const flat_map& x, const flat_map& y)
+ { return !(x == y); }
- //! <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>Effects</b>: Returns true if x is less than y
//!
- //! <b>Throws</b>: If memory allocation allocation throws or T's copy constructor throws.
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator<(const flat_map& x, const flat_map& y)
+ { return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
+
+ //! <b>Effects</b>: Returns true if x is greater than y
//!
- //! <b>Note</b>: If capacity() is less than "count", iterators and references to
- //! to values might be invalidated.
- void reserve(size_type count)
- { m_flat_tree.reserve(count); }
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator>(const flat_map& x, const flat_map& y)
+ { return y < x; }
- /// @cond
- template <class K1, class T1, class C1, class A1>
- friend bool operator== (const flat_map<K1, T1, C1, A1>&,
- const flat_map<K1, T1, C1, A1>&);
- template <class K1, class T1, class C1, class A1>
- friend bool operator< (const flat_map<K1, T1, C1, A1>&,
- const flat_map<K1, T1, C1, A1>&);
+ //! <b>Effects</b>: Returns true if x is equal or less than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator<=(const flat_map& x, const flat_map& y)
+ { return !(y < x); }
+ //! <b>Effects</b>: Returns true if x is equal or greater than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator>=(const flat_map& x, const flat_map& y)
+ { return !(x < y); }
+
+ //! <b>Effects</b>: x.swap(y)
+ //!
+ //! <b>Complexity</b>: Constant.
+ 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)
{
@@ -817,74 +1011,24 @@ class flat_map
}
return (*i).second;
}
- /// @endcond
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
};
-template <class Key, class T, class Pred, class A>
-inline bool operator==(const flat_map<Key,T,Pred,A>& x,
- const flat_map<Key,T,Pred,A>& y)
- { return x.m_flat_tree == y.m_flat_tree; }
-
-template <class Key, class T, class Pred, class A>
-inline bool operator<(const flat_map<Key,T,Pred,A>& x,
- const flat_map<Key,T,Pred,A>& y)
- { return x.m_flat_tree < y.m_flat_tree; }
-
-template <class Key, class T, class Pred, class A>
-inline bool operator!=(const flat_map<Key,T,Pred,A>& x,
- const flat_map<Key,T,Pred,A>& y)
- { return !(x == y); }
-
-template <class Key, class T, class Pred, class A>
-inline bool operator>(const flat_map<Key,T,Pred,A>& x,
- const flat_map<Key,T,Pred,A>& y)
- { return y < x; }
-
-template <class Key, class T, class Pred, class A>
-inline bool operator<=(const flat_map<Key,T,Pred,A>& x,
- const flat_map<Key,T,Pred,A>& y)
- { return !(y < x); }
-
-template <class Key, class T, class Pred, class A>
-inline bool operator>=(const flat_map<Key,T,Pred,A>& x,
- const flat_map<Key,T,Pred,A>& y)
- { return !(x < y); }
-
-template <class Key, class T, class Pred, class A>
-inline void swap(flat_map<Key,T,Pred,A>& x,
- flat_map<Key,T,Pred,A>& y)
- { x.swap(y); }
-
-/// @cond
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
} //namespace container {
-/*
+
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
-template <class K, class T, class C, class A>
-struct has_trivial_destructor_after_move<boost::container::flat_map<K, T, C, A> >
+template <class K, class T, class C, class Allocator>
+struct has_trivial_destructor_after_move<boost::container::flat_map<K, T, C, Allocator> >
{
- static const bool value = has_trivial_destructor<A>::value && has_trivial_destructor<C>::value;
+ static const bool value = has_trivial_destructor_after_move<Allocator>::value && has_trivial_destructor_after_move<C>::value;
};
-*/
-namespace container {
-// Forward declaration of operators < and ==, needed for friend declaration.
-#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
-template <class Key, class T, class Pred = std::less< std::pair< Key, T> >, class A = std::allocator<T> >
-#else
-template <class Key, class T, class Pred, class A>
-#endif
-class flat_multimap;
-
-template <class Key, class T, class Pred, class A>
-inline bool operator==(const flat_multimap<Key,T,Pred,A>& x,
- const flat_multimap<Key,T,Pred,A>& y);
+namespace container {
-template <class Key, class T, class Pred, class A>
-inline bool operator<(const flat_multimap<Key,T,Pred,A>& x,
- const flat_multimap<Key,T,Pred,A>& y);
-/// @endcond
+#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
@@ -896,96 +1040,130 @@ inline bool operator<(const flat_multimap<Key,T,Pred,A>& x,
//! 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>).
//!
-//! Pred is the ordering function for Keys (e.g. <i>std::less<Key></i>).
+//! Compare is the ordering function for Keys (e.g. <i>std::less<Key></i>).
//!
-//! A is the allocator to allocate the value_types
+//! Allocator is the allocator to allocate the value_types
//! (e.g. <i>allocator< std::pair<Key, T> ></i>).
+//!
+//! flat_multimap is similar to std::multimap but it's implemented like an ordered vector.
+//! This means that inserting a new element into a flat_map invalidates
+//! previous iterators and references
+//!
+//! Erasing an element invalidates 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 Allocator is the allocator to allocate the <code>value_type</code>s
+//! (e.g. <i>allocator< std::pair<Key, T> > </i>).
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
-template <class Key, class T, class Pred = std::less< std::pair< Key, T> >, class A = std::allocator<T> >
+template <class Key, class T, class Compare = std::less<Key>, class Allocator = std::allocator< std::pair< Key, T> > >
#else
-template <class Key, class T, class Pred, class A>
+template <class Key, class T, class Compare, class Allocator>
#endif
class flat_multimap
{
- /// @cond
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
BOOST_COPYABLE_AND_MOVABLE(flat_multimap)
typedef container_detail::flat_tree<Key,
std::pair<Key, T>,
container_detail::select1st< std::pair<Key, T> >,
- Pred,
- A> tree_t;
+ Compare,
+ Allocator> tree_t;
//This is the real tree stored here. It's based on a movable pair
typedef container_detail::flat_tree<Key,
container_detail::pair<Key, T>,
container_detail::select1st<container_detail::pair<Key, T> >,
- Pred,
- typename allocator_traits<A>::template portable_rebind_alloc
+ Compare,
+ typename allocator_traits<Allocator>::template portable_rebind_alloc
<container_detail::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::pointer impl_pointer;
- typedef typename impl_tree_t::const_pointer impl_const_pointer;
- typedef typename impl_tree_t::reference impl_reference;
- typedef typename impl_tree_t::const_reference impl_const_reference;
- typedef typename impl_tree_t::value_compare impl_value_compare;
- typedef typename impl_tree_t::iterator impl_iterator;
typedef typename impl_tree_t::const_iterator impl_const_iterator;
- typedef typename impl_tree_t::reverse_iterator impl_reverse_iterator;
- typedef typename impl_tree_t::const_reverse_iterator impl_const_reverse_iterator;
typedef typename impl_tree_t::allocator_type impl_allocator_type;
- typedef allocator_traits<A> allocator_traits_type;
-
- /// @endcond
+ typedef container_detail::flat_tree_value_compare
+ < Compare
+ , container_detail::select1st< std::pair<Key, T> >
+ , std::pair<Key, T> > value_compare_impl;
+ typedef typename container_detail::get_flat_tree_iterators
+ <typename allocator_traits<Allocator>::pointer>::iterator iterator_impl;
+ typedef typename container_detail::get_flat_tree_iterators
+ <typename allocator_traits<Allocator>::pointer>::const_iterator const_iterator_impl;
+ typedef typename container_detail::get_flat_tree_iterators
+ <typename allocator_traits<Allocator>::pointer>::reverse_iterator reverse_iterator_impl;
+ typedef typename container_detail::get_flat_tree_iterators
+ <typename allocator_traits<Allocator>::pointer>::const_reverse_iterator const_reverse_iterator_impl;
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public:
- // typedefs:
- typedef Key key_type;
- typedef T mapped_type;
- typedef Pred key_compare;
- typedef typename std::pair<key_type, mapped_type> value_type;
- typedef typename allocator_traits_type::pointer pointer;
- typedef typename allocator_traits_type::const_pointer const_pointer;
- typedef typename allocator_traits_type::reference reference;
- typedef typename allocator_traits_type::const_reference const_reference;
- typedef typename impl_tree_t::size_type size_type;
- typedef typename impl_tree_t::difference_type difference_type;
- typedef container_detail::flat_tree_value_compare
- < Pred
- , container_detail::select1st< std::pair<Key, T> >
- , std::pair<Key, T> > value_compare;
-
- typedef typename container_detail::
- get_flat_tree_iterators<pointer>::iterator iterator;
- typedef typename container_detail::
- get_flat_tree_iterators<pointer>::const_iterator const_iterator;
- typedef typename container_detail::
- get_flat_tree_iterators
- <pointer>::reverse_iterator reverse_iterator;
- typedef typename container_detail::
- get_flat_tree_iterators
- <pointer>::const_reverse_iterator const_reverse_iterator;
- typedef A allocator_type;
- //Non-standard extension
- typedef A stored_allocator_type;
- //!Standard extension for C++03 compilers with non-movable std::pair
- typedef impl_value_type movable_value_type;
+ //////////////////////////////////////////////
+ //
+ // types
+ //
+ //////////////////////////////////////////////
+ typedef Key key_type;
+ typedef T mapped_type;
+ typedef std::pair<Key, T> value_type;
+ 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 BOOST_CONTAINER_IMPDEF(Allocator) stored_allocator_type;
+ typedef BOOST_CONTAINER_IMPDEF(value_compare_impl) value_compare;
+ typedef Compare key_compare;
+ typedef BOOST_CONTAINER_IMPDEF(iterator_impl) iterator;
+ typedef BOOST_CONTAINER_IMPDEF(const_iterator_impl) const_iterator;
+ typedef BOOST_CONTAINER_IMPDEF(reverse_iterator_impl) reverse_iterator;
+ typedef BOOST_CONTAINER_IMPDEF(const_reverse_iterator_impl) const_reverse_iterator;
+ typedef BOOST_CONTAINER_IMPDEF(impl_value_type) movable_value_type;
+
+ //////////////////////////////////////////////
+ //
+ // construct/copy/destroy
+ //
+ //////////////////////////////////////////////
//! <b>Effects</b>: Default constructs an empty flat_map.
//!
//! <b>Complexity</b>: Constant.
flat_multimap()
- : m_flat_tree() {}
+ : m_flat_tree()
+ {
+ //Allocator type must be std::pair<Key, T>
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
+ }
//! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison
//! object and allocator.
//!
//! <b>Complexity</b>: Constant.
- explicit flat_multimap(const Pred& comp,
+ explicit flat_multimap(const Compare& comp,
const allocator_type& a = allocator_type())
- : m_flat_tree(comp, container_detail::force<impl_allocator_type>(a)) { }
+ : m_flat_tree(comp, container_detail::force<impl_allocator_type>(a))
+ {
+ //Allocator type must be std::pair<Key, T>
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
+ }
+
+ //! <b>Effects</b>: Constructs an empty flat_multimap using the specified allocator.
+ //!
+ //! <b>Complexity</b>: Constant.
+ explicit flat_multimap(const allocator_type& a)
+ : m_flat_tree(container_detail::force<impl_allocator_type>(a))
+ {
+ //Allocator type must be std::pair<Key, T>
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
+ }
//! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object
//! and allocator, and inserts elements from the range [first ,last ).
@@ -994,10 +1172,13 @@ class flat_multimap
//! comp and otherwise N logN, where N is last - first.
template <class InputIterator>
flat_multimap(InputIterator first, InputIterator last,
- const Pred& comp = Pred(),
+ const Compare& comp = Compare(),
const allocator_type& a = allocator_type())
- : m_flat_tree(comp, container_detail::force<impl_allocator_type>(a))
- { m_flat_tree.insert_equal(first, last); }
+ : m_flat_tree(false, first, last, comp, container_detail::force<impl_allocator_type>(a))
+ {
+ //Allocator type must be std::pair<Key, T>
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
+ }
//! <b>Effects</b>: Constructs an empty flat_multimap using the specified comparison object and
//! allocator, and inserts elements from the ordered range [first ,last). This function
@@ -1010,16 +1191,54 @@ class flat_multimap
//! <b>Note</b>: Non-standard extension.
template <class InputIterator>
flat_multimap(ordered_range_t, InputIterator first, InputIterator last,
- const Pred& comp = Pred(),
+ const Compare& comp = Compare(),
const allocator_type& a = allocator_type())
: m_flat_tree(ordered_range, first, last, comp, a)
- {}
+ {
+ //Allocator type must be std::pair<Key, T>
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
+ }
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Constructs an empty flat_map using the specified comparison object and
+ //! allocator, and inserts elements from the range [il.begin(), il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
+ //! comp and otherwise N logN, where N is last - first.
+ flat_multimap(std::initializer_list<value_type> il, const Compare& comp = Compare(), const allocator_type& a = allocator_type())
+ : m_flat_tree(false, il.begin(), il.end(), comp, container_detail::force<impl_allocator_type>(a))
+ {
+ //Allocator type must be std::pair<Key, T>
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
+ }
+
+ //! <b>Effects</b>: Constructs an empty flat_multimap using the specified 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.
+ flat_multimap(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp = Compare(),
+ const allocator_type& a = allocator_type())
+ : m_flat_tree(ordered_range, il.begin(), il.end(), comp, a)
+ {
+ //Allocator type must be std::pair<Key, T>
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
+ }
+#endif
//! <b>Effects</b>: Copy constructs a flat_multimap.
//!
//! <b>Complexity</b>: Linear in x.size().
flat_multimap(const flat_multimap& x)
- : m_flat_tree(x.m_flat_tree) { }
+ : m_flat_tree(x.m_flat_tree)
+ {
+ //Allocator type must be std::pair<Key, T>
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
+ }
//! <b>Effects</b>: Move constructs a flat_multimap. Constructs *this using x's resources.
//!
@@ -1028,14 +1247,20 @@ class flat_multimap
//! <b>Postcondition</b>: x is emptied.
flat_multimap(BOOST_RV_REF(flat_multimap) x)
: m_flat_tree(boost::move(x.m_flat_tree))
- { }
+ {
+ //Allocator type must be std::pair<Key, T>
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
+ }
//! <b>Effects</b>: Copy constructs a flat_multimap using the specified allocator.
//!
//! <b>Complexity</b>: Linear in x.size().
flat_multimap(const flat_multimap& x, const allocator_type &a)
: m_flat_tree(x.m_flat_tree, a)
- {}
+ {
+ //Allocator type must be std::pair<Key, T>
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
+ }
//! <b>Effects</b>: Move constructs a flat_multimap using the specified allocator.
//! Constructs *this using x's resources.
@@ -1043,7 +1268,10 @@ class flat_multimap
//! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise.
flat_multimap(BOOST_RV_REF(flat_multimap) x, const allocator_type &a)
: m_flat_tree(boost::move(x.m_flat_tree), a)
- { }
+ {
+ //Allocator type must be std::pair<Key, T>
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<Key, T>, typename Allocator::value_type>::value));
+ }
//! <b>Effects</b>: Makes *this a copy of x.
//!
@@ -1054,42 +1282,61 @@ class flat_multimap
//! <b>Effects</b>: this->swap(x.get()).
//!
//! <b>Complexity</b>: Constant.
- flat_multimap& operator=(BOOST_RV_REF(flat_multimap) mx)
- { m_flat_tree = boost::move(mx.m_flat_tree); return *this; }
-
- //! <b>Effects</b>: Returns the comparison object out
- //! of which a was constructed.
- //!
- //! <b>Complexity</b>: Constant.
- key_compare key_comp() const
- { return container_detail::force_copy<key_compare>(m_flat_tree.key_comp()); }
+ flat_multimap& operator=(BOOST_RV_REF(flat_multimap) x)
+ BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value)
+ { m_flat_tree = boost::move(x.m_flat_tree); return *this; }
- //! <b>Effects</b>: Returns an object of value_compare constructed out
- //! of the comparison object.
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Assign content of il to *this
//!
- //! <b>Complexity</b>: Constant.
- value_compare value_comp() const
- { return value_compare(container_detail::force_copy<key_compare>(m_flat_tree.key_comp())); }
+ //! <b>Complexity</b>: Linear in il.size().
+ 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.
- allocator_type get_allocator() const
+ allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<allocator_type>(m_flat_tree.get_allocator()); }
- const stored_allocator_type &get_stored_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_CONTAINER_NOEXCEPT
{ return container_detail::force<stored_allocator_type>(m_flat_tree.get_stored_allocator()); }
- 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 BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force<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.
- iterator begin()
+ iterator begin() BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<iterator>(m_flat_tree.begin()); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
@@ -1097,7 +1344,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_iterator begin() const
+ const_iterator begin() const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<const_iterator>(m_flat_tree.begin()); }
//! <b>Effects</b>: Returns an iterator to the end of the container.
@@ -1105,7 +1352,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- iterator end()
+ iterator end() BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<iterator>(m_flat_tree.end()); }
//! <b>Effects</b>: Returns a const_iterator to the end of the container.
@@ -1113,7 +1360,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_iterator end() const
+ const_iterator end() const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<const_iterator>(m_flat_tree.end()); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
@@ -1122,7 +1369,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- reverse_iterator rbegin()
+ reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<reverse_iterator>(m_flat_tree.rbegin()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
@@ -1131,7 +1378,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reverse_iterator rbegin() const
+ const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<const_reverse_iterator>(m_flat_tree.rbegin()); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the end
@@ -1140,7 +1387,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- reverse_iterator rend()
+ reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<reverse_iterator>(m_flat_tree.rend()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
@@ -1149,7 +1396,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reverse_iterator rend() const
+ const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<const_reverse_iterator>(m_flat_tree.rend()); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
@@ -1157,7 +1404,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_iterator cbegin() const
+ const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<const_iterator>(m_flat_tree.cbegin()); }
//! <b>Effects</b>: Returns a const_iterator to the end of the container.
@@ -1165,7 +1412,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_iterator cend() const
+ const_iterator cend() const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<const_iterator>(m_flat_tree.cend()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
@@ -1174,7 +1421,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reverse_iterator crbegin() const
+ const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::force_copy<const_reverse_iterator>(m_flat_tree.crbegin()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
@@ -1183,15 +1430,21 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reverse_iterator crend() const
+ const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::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.
- bool empty() const
+ bool empty() const BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.empty(); }
//! <b>Effects</b>: Returns the number of the elements contained in the container.
@@ -1199,7 +1452,7 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- size_type size() const
+ size_type size() const BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.size(); }
//! <b>Effects</b>: Returns the largest possible size of the container.
@@ -1207,16 +1460,97 @@ class flat_multimap
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- size_type max_size() const
+ size_type max_size() const BOOST_CONTAINER_NOEXCEPT
{ return m_flat_tree.max_size(); }
- //! <b>Effects</b>: Swaps the contents of *this and 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.
- void swap(flat_multimap& x)
- { m_flat_tree.swap(x.m_flat_tree); }
+ size_type capacity() const BOOST_CONTAINER_NOEXCEPT
+ { return m_flat_tree.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 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)
+ { 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().
+ void shrink_to_fit()
+ { m_flat_tree.shrink_to_fit(); }
+
+ //////////////////////////////////////////////
+ //
+ // modifiers
+ //
+ //////////////////////////////////////////////
+
+ #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... 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>
+ iterator emplace(Args&&... args)
+ { return container_detail::force_copy<iterator>(m_flat_tree.emplace_equal(boost::forward<Args>(args)...)); }
+
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! 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>
+ iterator emplace_hint(const_iterator hint, Args&&... args)
+ {
+ return container_detail::force_copy<iterator>(m_flat_tree.emplace_hint_equal
+ (container_detail::force_copy<impl_const_iterator>(hint), boost::forward<Args>(args)...));
+ }
+
+ #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
+
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
+ iterator emplace(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
+ { return container_detail::force_copy<iterator>(m_flat_tree.emplace_equal \
+ (BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); } \
+ \
+ BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
+ iterator emplace_hint(const_iterator hint \
+ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
+ { return container_detail::force_copy<iterator>(m_flat_tree.emplace_hint_equal \
+ (container_detail::force_copy<impl_const_iterator>(hint) \
+ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); } \
+ //!
+ #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
+ #include BOOST_PP_LOCAL_ITERATE()
+
+ #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
//! <b>Effects</b>: Inserts x and returns the iterator pointing to the
//! newly inserted element.
@@ -1262,10 +1596,10 @@ class flat_multimap
//! to the elements with bigger keys than x.
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
- iterator insert(const_iterator position, const value_type& x)
+ iterator insert(const_iterator p, const value_type& x)
{
return container_detail::force_copy<iterator>
- (m_flat_tree.insert_equal( container_detail::force_copy<impl_const_iterator>(position)
+ (m_flat_tree.insert_equal( container_detail::force_copy<impl_const_iterator>(p)
, container_detail::force<impl_value_type>(x)));
}
@@ -1280,10 +1614,10 @@ class flat_multimap
//! to the elements with bigger keys than x.
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
- iterator insert(const_iterator position, BOOST_RV_REF(value_type) x)
+ iterator insert(const_iterator p, BOOST_RV_REF(value_type) x)
{
return container_detail::force_copy<iterator>
- (m_flat_tree.insert_equal(container_detail::force_copy<impl_const_iterator>(position)
+ (m_flat_tree.insert_equal(container_detail::force_copy<impl_const_iterator>(p)
, boost::move(x)));
}
@@ -1298,10 +1632,10 @@ class flat_multimap
//! to the elements with bigger keys than x.
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
- iterator insert(const_iterator position, BOOST_RV_REF(impl_value_type) x)
+ iterator insert(const_iterator p, BOOST_RV_REF(impl_value_type) x)
{
return container_detail::force_copy<iterator>(
- m_flat_tree.insert_equal(container_detail::force_copy<impl_const_iterator>(position), boost::move(x)));
+ m_flat_tree.insert_equal(container_detail::force_copy<impl_const_iterator>(p), boost::move(x)));
}
//! <b>Requires</b>: first, last are not iterators into *this.
@@ -1328,77 +1662,52 @@ class flat_multimap
//! search time plus N*size() insertion time.
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
+ //!
+ //! <b>Note</b>: Non-standard extension.
template <class InputIterator>
void insert(ordered_range_t, InputIterator first, InputIterator last)
{ m_flat_tree.insert_equal(ordered_range, first, last); }
- #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
-
- //! <b>Effects</b>: Inserts an object of type T constructed with
- //! std::forward<Args>(args)... and returns the iterator pointing to the
- //! newly inserted element.
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()) .
//!
- //! <b>Complexity</b>: Logarithmic search time plus linear insertion
- //! to the elements with bigger keys than x.
+ //! <b>Complexity</b>: At most N log(size()+N) (N is the distance from first to last)
+ //! search time plus N*size() insertion time.
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
- template <class... Args>
- iterator emplace(Args&&... args)
- { return container_detail::force_copy<iterator>(m_flat_tree.emplace_equal(boost::forward<Args>(args)...)); }
+ void insert(std::initializer_list<value_type> il)
+ { m_flat_tree.insert_equal(il.begin(), il.end()); }
- //! <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>Requires</b>: [il.begin(), il.end()) must be ordered according to the predicate.
//!
- //! <b>Returns</b>: An iterator pointing to the element with key equivalent
- //! to the key of x.
+ //! <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>: 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>Complexity</b>: At most N log(size()+N) (N is the distance from first to last)
+ //! search time plus N*size() insertion time.
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
- template <class... Args>
- iterator emplace_hint(const_iterator hint, Args&&... args)
- {
- return container_detail::force_copy<iterator>(m_flat_tree.emplace_hint_equal
- (container_detail::force_copy<impl_const_iterator>(hint), boost::forward<Args>(args)...));
- }
-
- #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
-
- #define BOOST_PP_LOCAL_MACRO(n) \
- BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
- iterator emplace(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
- { return container_detail::force_copy<iterator>(m_flat_tree.emplace_equal \
- (BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); } \
- \
- BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
- iterator emplace_hint(const_iterator hint \
- BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
- { return container_detail::force_copy<iterator>(m_flat_tree.emplace_hint_equal \
- (container_detail::force_copy<impl_const_iterator>(hint) \
- BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); } \
//!
- #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
- #include BOOST_PP_LOCAL_ITERATE()
-
- #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
+ //! <b>Note</b>: Non-standard extension.
+ void insert(ordered_range_t, std::initializer_list<value_type> il)
+ { m_flat_tree.insert_equal(ordered_range, il.begin(), il.end()); }
+#endif
- //! <b>Effects</b>: Erases the element pointed to by position.
+ //! <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 position
+ //! <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 position)
+ iterator erase(const_iterator p)
{
return container_detail::force_copy<iterator>(
- m_flat_tree.erase(container_detail::force_copy<impl_const_iterator>(position)));
+ m_flat_tree.erase(container_detail::force_copy<impl_const_iterator>(p)));
}
//! <b>Effects</b>: Erases all elements in the container with key equivalent to x.
@@ -1425,22 +1734,47 @@ class flat_multimap
, container_detail::force_copy<impl_const_iterator>(last)));
}
+ //! <b>Effects</b>: Swaps the contents of *this and x.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ void swap(flat_multimap& x)
+ { 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().
- void clear()
+ void clear() BOOST_CONTAINER_NOEXCEPT
{ m_flat_tree.clear(); }
- //! <b>Effects</b>: Tries to deallocate the excess of memory created
- // with previous allocations. The size of the vector is unchanged
+ //////////////////////////////////////////////
+ //
+ // observers
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Returns the comparison object out
+ //! of which a was constructed.
//!
- //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
+ //! <b>Complexity</b>: Constant.
+ key_compare key_comp() const
+ { return container_detail::force_copy<key_compare>(m_flat_tree.key_comp()); }
+
+ //! <b>Effects</b>: Returns an object of value_compare constructed out
+ //! of the comparison object.
//!
- //! <b>Complexity</b>: Linear to size().
- void shrink_to_fit()
- { m_flat_tree.shrink_to_fit(); }
+ //! <b>Complexity</b>: Constant.
+ value_compare value_comp() const
+ { return value_compare(container_detail::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.
@@ -1467,9 +1801,9 @@ class flat_multimap
//!
//! <b>Complexity</b>: Logarithmic
iterator lower_bound(const key_type& x)
- {return container_detail::force_copy<iterator>(m_flat_tree.lower_bound(x)); }
+ { return container_detail::force_copy<iterator>(m_flat_tree.lower_bound(x)); }
- //! <b>Returns</b>: A const iterator pointing to the first element with key
+ //! <b>Returns</b>: Allocator 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
@@ -1483,7 +1817,7 @@ class flat_multimap
iterator upper_bound(const key_type& x)
{return container_detail::force_copy<iterator>(m_flat_tree.upper_bound(x)); }
- //! <b>Returns</b>: A const iterator pointing to the first element with key
+ //! <b>Returns</b>: Allocator 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
@@ -1499,93 +1833,69 @@ class flat_multimap
//! <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
+ std::pair<const_iterator,const_iterator> equal_range(const key_type& x) const
{ return container_detail::force_copy<std::pair<const_iterator,const_iterator> >(m_flat_tree.equal_range(x)); }
- //! <b>Effects</b>: Number of elements for which memory has been allocated.
- //! capacity() is always greater than or equal to size().
- //!
- //! <b>Throws</b>: Nothing.
+ //! <b>Effects</b>: Returns true if x and y are equal
//!
- //! <b>Complexity</b>: Constant.
- size_type capacity() const
- { return m_flat_tree.capacity(); }
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator==(const flat_multimap& x, const flat_multimap& y)
+ { return x.size() == y.size() && std::equal(x.begin(), x.end(), y.begin()); }
- //! <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>Effects</b>: Returns true if x and y are unequal
//!
- //! <b>Throws</b>: If memory allocation allocation throws or T's copy constructor throws.
- //!
- //! <b>Note</b>: If capacity() is less than "count", iterators and references to
- //! to values might be invalidated.
- void reserve(size_type count)
- { m_flat_tree.reserve(count); }
-
- /// @cond
- template <class K1, class T1, class C1, class A1>
- friend bool operator== (const flat_multimap<K1, T1, C1, A1>& x,
- const flat_multimap<K1, T1, C1, A1>& y);
-
- template <class K1, class T1, class C1, class A1>
- friend bool operator< (const flat_multimap<K1, T1, C1, A1>& x,
- const flat_multimap<K1, T1, C1, A1>& y);
- /// @endcond
-};
-
-template <class Key, class T, class Pred, class A>
-inline bool operator==(const flat_multimap<Key,T,Pred,A>& x,
- const flat_multimap<Key,T,Pred,A>& y)
- { return x.m_flat_tree == y.m_flat_tree; }
-
-template <class Key, class T, class Pred, class A>
-inline bool operator<(const flat_multimap<Key,T,Pred,A>& x,
- const flat_multimap<Key,T,Pred,A>& y)
- { return x.m_flat_tree < y.m_flat_tree; }
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator!=(const flat_multimap& x, const flat_multimap& y)
+ { return !(x == y); }
-template <class Key, class T, class Pred, class A>
-inline bool operator!=(const flat_multimap<Key,T,Pred,A>& x,
- const flat_multimap<Key,T,Pred,A>& y)
- { return !(x == y); }
+ //! <b>Effects</b>: Returns true if x is less than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator<(const flat_multimap& x, const flat_multimap& y)
+ { return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
-template <class Key, class T, class Pred, class A>
-inline bool operator>(const flat_multimap<Key,T,Pred,A>& x,
- const flat_multimap<Key,T,Pred,A>& 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_multimap& x, const flat_multimap& y)
{ return y < x; }
-template <class Key, class T, class Pred, class A>
-inline bool operator<=(const flat_multimap<Key,T,Pred,A>& x,
- const flat_multimap<Key,T,Pred,A>& 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_multimap& x, const flat_multimap& y)
{ return !(y < x); }
-template <class Key, class T, class Pred, class A>
-inline bool operator>=(const flat_multimap<Key,T,Pred,A>& x,
- const flat_multimap<Key,T,Pred,A>& 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_multimap& x, const flat_multimap& y)
{ return !(x < y); }
-template <class Key, class T, class Pred, class A>
-inline void swap(flat_multimap<Key,T,Pred,A>& x, flat_multimap<Key,T,Pred,A>& y)
+ //! <b>Effects</b>: x.swap(y)
+ //!
+ //! <b>Complexity</b>: Constant.
+ friend void swap(flat_multimap& x, flat_multimap& y)
{ x.swap(y); }
+};
}}
-/// @cond
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
namespace boost {
-/*
+
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
-template <class K, class T, class C, class A>
-struct has_trivial_destructor_after_move< boost::container::flat_multimap<K, T, C, A> >
+template <class K, class T, class C, class Allocator>
+struct has_trivial_destructor_after_move< boost::container::flat_multimap<K, T, C, Allocator> >
{
- static const bool value = has_trivial_destructor<A>::value && has_trivial_destructor<C>::value;
+ static const bool value = has_trivial_destructor_after_move<Allocator>::value && has_trivial_destructor_after_move<C>::value;
};
-*/
+
} //namespace boost {
-/// @endcond
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
#include <boost/container/detail/config_end.hpp>
diff --git a/boost/container/flat_set.hpp b/boost/container/flat_set.hpp
index 09c95eb2f5..1307f3492f 100644
--- a/boost/container/flat_set.hpp
+++ b/boost/container/flat_set.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
+// (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)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_CONTAINER_FLAT_SET_HPP
#define BOOST_CONTAINER_FLAT_SET_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -24,39 +24,19 @@
#include <memory>
#include <boost/container/detail/flat_tree.hpp>
#include <boost/container/detail/mpl.hpp>
-#include <boost/move/move.hpp>
+#include <boost/container/allocator_traits.hpp>
+#include <boost/move/utility_core.hpp>
+#include <boost/move/detail/move_helpers.hpp>
+#include <boost/move/traits.hpp>
-#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
-namespace boost {
-namespace container {
-#else
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+#include <initializer_list>
+#endif
namespace boost {
namespace container {
-#endif
-
-/// @cond
-// Forward declarations of operators < and ==, needed for friend declaration.
-
-#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
-template <class T, class Pred = std::less<T>, class A = std::allocator<T> >
-#else
-template <class T, class Pred, class A>
-#endif
-class flat_set;
-
-template <class T, class Pred, class A>
-inline bool operator==(const flat_set<T,Pred,A>& x,
- const flat_set<T,Pred,A>& y);
-
-template <class T, class Pred, class A>
-inline bool operator<(const flat_set<T,Pred,A>& x,
- const flat_set<T,Pred,A>& y);
-/// @endcond
//! flat_set is a Sorted Associative Container that stores objects of type Key.
-//! flat_set is a Simple Associative Container, meaning that its value type,
-//! as well as its key type, is Key. It is also a Unique Associative Container,
-//! meaning that no two elements are the same.
+//! 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 like an ordered vector.
//! This means that inserting a new element into a flat_set invalidates
@@ -64,71 +44,95 @@ inline bool operator<(const flat_set<T,Pred,A>& x,
//!
//! Erasing an element of a flat_set invalidates 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 Allocator is the allocator to be used to allocate memory for this container
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
-template <class T, class Pred = std::less<T>, class A = std::allocator<T> >
+template <class Key, class Compare = std::less<Key>, class Allocator = std::allocator<Key> >
#else
-template <class T, class Pred, class A>
+template <class Key, class Compare, class Allocator>
#endif
class flat_set
+ ///@cond
+ : public container_detail::flat_tree<Key, Key, container_detail::identity<Key>, Compare, Allocator>
+ ///@endcond
{
- /// @cond
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
BOOST_COPYABLE_AND_MOVABLE(flat_set)
- typedef container_detail::flat_tree<T, T, container_detail::identity<T>, Pred, A> tree_t;
- tree_t m_flat_tree; // flat tree representing flat_set
- typedef typename container_detail::
- move_const_ref_type<T>::type insert_const_ref_type;
- /// @endcond
+ typedef container_detail::flat_tree<Key, Key, container_detail::identity<Key>, Compare, Allocator> 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;
public:
+ //////////////////////////////////////////////
+ //
+ // construct/copy/destroy
+ //
+ //////////////////////////////////////////////
- // typedefs:
- typedef typename tree_t::key_type key_type;
- typedef typename tree_t::value_type value_type;
- typedef typename tree_t::pointer pointer;
- typedef typename tree_t::const_pointer const_pointer;
- typedef typename tree_t::reference reference;
- typedef typename tree_t::const_reference const_reference;
- typedef typename tree_t::key_compare key_compare;
- typedef typename tree_t::value_compare value_compare;
- typedef typename tree_t::iterator iterator;
- typedef typename tree_t::const_iterator const_iterator;
- typedef typename tree_t::reverse_iterator reverse_iterator;
- typedef typename tree_t::const_reverse_iterator const_reverse_iterator;
- typedef typename tree_t::size_type size_type;
- typedef typename tree_t::difference_type difference_type;
- typedef typename tree_t::allocator_type allocator_type;
- typedef typename tree_t::stored_allocator_type stored_allocator_type;
-
- //! <b>Effects</b>: Default constructs an empty flat_set.
+ //! <b>Effects</b>: Default constructs an empty container.
//!
//! <b>Complexity</b>: Constant.
explicit flat_set()
- : m_flat_tree()
+ : base_t()
{}
- //! <b>Effects</b>: Constructs an empty flat_set using the specified
+ //! <b>Effects</b>: Constructs an empty container using the specified
//! comparison object and allocator.
//!
//! <b>Complexity</b>: Constant.
- explicit flat_set(const Pred& comp,
+ explicit flat_set(const Compare& comp,
const allocator_type& a = allocator_type())
- : m_flat_tree(comp, a)
+ : base_t(comp, a)
{}
- //! <b>Effects</b>: Constructs an empty set using the specified comparison object and
+ //! <b>Effects</b>: Constructs an empty container using the specified allocator.
+ //!
+ //! <b>Complexity</b>: Constant.
+ explicit flat_set(const allocator_type& a)
+ : base_t(a)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty container using the specified comparison object and
//! allocator, and inserts elements from the range [first ,last ).
//!
//! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
//! comp and otherwise N logN, where N is last - first.
template <class InputIterator>
flat_set(InputIterator first, InputIterator last,
- const Pred& comp = Pred(),
+ const Compare& comp = Compare(),
const allocator_type& a = allocator_type())
- : m_flat_tree(comp, a)
- { m_flat_tree.insert_unique(first, last); }
+ : base_t(true, first, last, comp, a)
+ {}
- //! <b>Effects</b>: Constructs an empty flat_set using the specified comparison object and
+ //! <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.
//!
@@ -140,173 +144,207 @@ class flat_set
//! <b>Note</b>: Non-standard extension.
template <class InputIterator>
flat_set(ordered_unique_range_t, InputIterator first, InputIterator last,
- const Pred& comp = Pred(),
+ const Compare& comp = Compare(),
const allocator_type& a = allocator_type())
- : m_flat_tree(ordered_range, first, last, comp, a)
+ : base_t(ordered_range, first, last, comp, a)
{}
- //! <b>Effects</b>: Copy constructs a set.
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Constructs an empty container using the specified comparison object and
+ //! allocator, and inserts elements from the range [il.begin(), il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
+ //! comp and otherwise N logN, where N is il.begin() - il.end().
+ flat_set(std::initializer_list<value_type> il, const Compare& comp = Compare(),
+ const allocator_type& a = allocator_type())
+ : base_t(true, il.begin(), il.end(), comp, a)
+ {
+
+ }
+
+ //! <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.
+ flat_set(ordered_unique_range_t, std::initializer_list<value_type> il,
+ const Compare& comp = Compare(), const allocator_type& a = allocator_type())
+ : base_t(ordered_range, il.begin(), il.end(), comp, a)
+ {
+
+ }
+#endif
+
+ //! <b>Effects</b>: Copy constructs the container.
//!
//! <b>Complexity</b>: Linear in x.size().
flat_set(const flat_set& x)
- : m_flat_tree(x.m_flat_tree)
+ : base_t(static_cast<const base_t&>(x))
{}
- //! <b>Effects</b>: Move constructs a set. Constructs *this using x's resources.
+ //! <b>Effects</b>: Move constructs thecontainer. Constructs *this using mx's resources.
//!
//! <b>Complexity</b>: Constant.
//!
- //! <b>Postcondition</b>: x is emptied.
+ //! <b>Postcondition</b>: mx is emptied.
flat_set(BOOST_RV_REF(flat_set) mx)
- : m_flat_tree(boost::move(mx.m_flat_tree))
+ : base_t(boost::move(static_cast<base_t&>(mx)))
{}
- //! <b>Effects</b>: Copy constructs a set using the specified allocator.
+ //! <b>Effects</b>: Copy constructs a container using the specified allocator.
//!
//! <b>Complexity</b>: Linear in x.size().
flat_set(const flat_set& x, const allocator_type &a)
- : m_flat_tree(x.m_flat_tree, 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>Effects</b>: Move constructs a container using the specified allocator.
+ //! Constructs *this using mx's resources.
//!
//! <b>Complexity</b>: Constant if a == mx.get_allocator(), linear otherwise
flat_set(BOOST_RV_REF(flat_set) mx, const allocator_type &a)
- : m_flat_tree(boost::move(mx.m_flat_tree), a)
+ : base_t(boost::move(static_cast<base_t&>(mx)), a)
{}
//! <b>Effects</b>: Makes *this a copy of x.
//!
//! <b>Complexity</b>: Linear in x.size().
flat_set& operator=(BOOST_COPY_ASSIGN_REF(flat_set) x)
- { m_flat_tree = x.m_flat_tree; return *this; }
-
- //! <b>Effects</b>: Makes *this a copy of the previous value of xx.
- //!
- //! <b>Complexity</b>: Linear in x.size().
- flat_set& operator=(BOOST_RV_REF(flat_set) mx)
- { m_flat_tree = boost::move(mx.m_flat_tree); return *this; }
+ { return static_cast<flat_set&>(this->base_t::operator=(static_cast<const base_t&>(x))); }
+
+ //! <b>Throws</b>: If allocator_traits_type::propagate_on_container_move_assignment
+ //! 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.
+ flat_set& operator=(BOOST_RV_REF(flat_set) x)
+ BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value)
+ { return static_cast<flat_set&>(this->base_t::operator=(boost::move(static_cast<base_t&>(x)))); }
+
+#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
- //! <b>Effects</b>: Returns the comparison object out
- //! of which a was constructed.
+ #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.
- key_compare key_comp() const
- { return m_flat_tree.key_comp(); }
+ allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT;
- //! <b>Effects</b>: Returns an object of value_compare constructed out
- //! of the comparison object.
+ //! <b>Effects</b>: Returns a reference to the internal allocator.
+ //!
+ //! <b>Throws</b>: Nothing
//!
//! <b>Complexity</b>: Constant.
- value_compare value_comp() const
- { return m_flat_tree.key_comp(); }
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT;
- //! <b>Effects</b>: Returns a copy of the Allocator that
- //! was passed to the object's constructor.
+ //! <b>Effects</b>: Returns a reference to the internal allocator.
+ //!
+ //! <b>Throws</b>: Nothing
//!
//! <b>Complexity</b>: Constant.
- allocator_type get_allocator() const
- { return m_flat_tree.get_allocator(); }
-
- const stored_allocator_type &get_stored_allocator() const
- { return m_flat_tree.get_stored_allocator(); }
-
- stored_allocator_type &get_stored_allocator()
- { return m_flat_tree.get_stored_allocator(); }
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT;
//! <b>Effects</b>: Returns an iterator to the first element contained in the container.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- iterator begin()
- { return m_flat_tree.begin(); }
+ iterator begin() BOOST_CONTAINER_NOEXCEPT;
//! <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
- { return m_flat_tree.begin(); }
+ const_iterator begin() const BOOST_CONTAINER_NOEXCEPT;
- //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
+ //! <b>Effects</b>: Returns an iterator to the end of the container.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_iterator cbegin() const
- { return m_flat_tree.cbegin(); }
+ iterator end() BOOST_CONTAINER_NOEXCEPT;
- //! <b>Effects</b>: Returns an iterator to the end of the container.
+ //! <b>Effects</b>: Returns a const_iterator to the end of the container.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- iterator end()
- { return m_flat_tree.end(); }
+ const_iterator end() const BOOST_CONTAINER_NOEXCEPT;
- //! <b>Effects</b>: Returns a const_iterator to the end of the container.
+ //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
+ //! of the reversed container.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_iterator end() const
- { return m_flat_tree.end(); }
+ reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT;
- //! <b>Effects</b>: Returns a const_iterator to the end of the container.
+ //! <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_iterator cend() const
- { return m_flat_tree.cend(); }
+ const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT;
- //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
+ //! <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 rbegin()
- { return m_flat_tree.rbegin(); }
+ reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT;
- //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
+ //! <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 rbegin() const
- { return m_flat_tree.rbegin(); }
+ const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT;
- //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
- //! of the reversed container.
+ //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reverse_iterator crbegin() const
- { return m_flat_tree.crbegin(); }
+ const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT;
- //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
- //! of the reversed container.
+ //! <b>Effects</b>: Returns a const_iterator to the end of the container.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- reverse_iterator rend()
- { return m_flat_tree.rend(); }
+ const_iterator cend() const BOOST_CONTAINER_NOEXCEPT;
- //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the 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.
- const_reverse_iterator rend() const
- { return m_flat_tree.rend(); }
+ const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT;
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
//! of the reversed container.
@@ -314,42 +352,68 @@ class flat_set
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reverse_iterator crend() const
- { return m_flat_tree.crend(); }
+ const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT;
//! <b>Effects</b>: Returns true if the container contains no elements.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- bool empty() const
- { return m_flat_tree.empty(); }
+ bool empty() const BOOST_CONTAINER_NOEXCEPT;
//! <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
- { return m_flat_tree.size(); }
+ size_type size() const BOOST_CONTAINER_NOEXCEPT;
//! <b>Effects</b>: Returns the largest possible size of the container.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- size_type max_size() const
- { return m_flat_tree.max_size(); }
+ size_type max_size() const BOOST_CONTAINER_NOEXCEPT;
- //! <b>Effects</b>: Swaps the contents of *this and 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.
- void swap(flat_set& x)
- { m_flat_tree.swap(x.m_flat_tree); }
+ size_type capacity() const BOOST_CONTAINER_NOEXCEPT;
- //! <b>Effects</b>: Inserts x if and only if there is no element in the container
+ //! <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 Key'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_CONTAINER_PERFECT_FORWARDING) || 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
@@ -360,17 +424,57 @@ class flat_set
//! 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(insert_const_ref_type x)
- { return priv_insert(x); }
+ template <class... Args>
+ std::pair<iterator,bool> emplace(Args&&... args)
+ { return this->base_t::emplace_unique(boost::forward<Args>(args)...); }
- #if defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- std::pair<iterator, bool> insert(T &x)
- { return this->insert(const_cast<const T &>(x)); }
+ //! <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>
+ iterator emplace_hint(const_iterator p, Args&&... args)
+ { return this->base_t::emplace_hint_unique(p, boost::forward<Args>(args)...); }
- template<class U>
- std::pair<iterator, bool> insert(const U &u, typename container_detail::enable_if_c<container_detail::is_same<T, U>::value && !::boost::has_move_emulation_enabled<U>::value >::type* =0)
- { return priv_insert(u); }
- #endif
+ #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
+
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
+ std::pair<iterator,bool> emplace(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
+ { return this->base_t::emplace_unique(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); }\
+ \
+ BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
+ iterator emplace_hint(const_iterator p \
+ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
+ { return this->base_t::emplace_hint_unique \
+ (p BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); } \
+ //!
+ #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
+ #include BOOST_PP_LOCAL_ITERATE()
+
+ #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
+
+ #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.
@@ -383,9 +487,15 @@ class flat_set
//! to the elements with bigger keys than x.
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
- std::pair<iterator,bool> insert(BOOST_RV_REF(value_type) x)
- { return m_flat_tree.insert_unique(boost::move(x)); }
+ 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.
@@ -397,17 +507,7 @@ class flat_set
//! 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, insert_const_ref_type x)
- { return priv_insert(p, x); }
-
- #if defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- iterator insert(const_iterator position, T &x)
- { return this->insert(position, const_cast<const T &>(x)); }
-
- template<class U>
- iterator insert(const_iterator position, const U &u, typename container_detail::enable_if_c<container_detail::is_same<T, U>::value && !::boost::has_move_emulation_enabled<U>::value >::type* =0)
- { return priv_insert(position, u); }
- #endif
+ 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.
@@ -418,8 +518,10 @@ class flat_set
//! 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 position, BOOST_RV_REF(value_type) x)
- { return m_flat_tree.insert_unique(position, boost::move(x)); }
+ 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.
//!
@@ -432,7 +534,7 @@ class flat_set
//! <b>Note</b>: If an element is inserted it might invalidate elements.
template <class InputIterator>
void insert(InputIterator first, InputIterator last)
- { m_flat_tree.insert_unique(first, last); }
+ { this->base_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
@@ -447,72 +549,46 @@ class flat_set
//! <b>Note</b>: Non-standard extension. If an element is inserted it might invalidate elements.
template <class InputIterator>
void insert(ordered_unique_range_t, InputIterator first, InputIterator last)
- { m_flat_tree.insert_unique(ordered_unique_range, first, last); }
+ { this->base_t::insert_unique(ordered_unique_range, first, last); }
- #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || 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.
+#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>: Logarithmic search time plus linear insertion
- //! to the elements with bigger keys than x.
+ //! <b>Complexity</b>: At most N log(size()+N) (N is the distance from il.begin() to il.end())
+ //! search time plus N*size() insertion time.
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
- template <class... Args>
- std::pair<iterator,bool> emplace(Args&&... args)
- { return m_flat_tree.emplace_unique(boost::forward<Args>(args)...); }
+ void insert(std::initializer_list<value_type> il)
+ { this->base_t::insert_unique(il.begin(), il.end()); }
- //! <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>Requires</b>: Range [il.begin(), il.end()) must be ordered according to the predicate
+ //! and must be unique values.
//!
- //! <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>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>Note</b>: If an element is inserted it might invalidate elements.
- template <class... Args>
- iterator emplace_hint(const_iterator hint, Args&&... args)
- { return m_flat_tree.emplace_hint_unique(hint, boost::forward<Args>(args)...); }
-
- #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
-
- #define BOOST_PP_LOCAL_MACRO(n) \
- BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
- std::pair<iterator,bool> emplace(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
- { return m_flat_tree.emplace_unique(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); } \
- \
- BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
- iterator emplace_hint(const_iterator hint \
- BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
- { return m_flat_tree.emplace_hint_unique \
- (hint BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); } \
+ //! <b>Complexity</b>: At most N log(size()+N) (N is the distance from il.begin() to il.end())
+ //! search time plus N*size() insertion time.
//!
- #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
- #include BOOST_PP_LOCAL_ITERATE()
+ //! <b>Note</b>: Non-standard extension. If an element is inserted it might invalidate elements.
+ void insert(ordered_unique_range_t, std::initializer_list<value_type> il)
+ { this->base_t::insert_unique(ordered_unique_range, il.begin(), il.end()); }
+#endif
- #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- //! <b>Effects</b>: Erases the element pointed to by position.
+ //! <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 position
+ //! <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 position)
- { return m_flat_tree.erase(position); }
+ iterator erase(const_iterator p);
//! <b>Effects</b>: Erases all elements in the container with key equivalent to x.
//!
@@ -520,8 +596,7 @@ class flat_set
//!
//! <b>Complexity</b>: Logarithmic search time plus erasure time
//! linear to the elements with bigger keys.
- size_type erase(const key_type& x)
- { return m_flat_tree.erase(x); }
+ size_type erase(const key_type& x);
//! <b>Effects</b>: Erases all the elements in the range [first, last).
//!
@@ -531,254 +606,239 @@ class flat_set
//!
//! <b>Complexity</b>: Logarithmic search time plus erasure time
//! linear to the elements with bigger keys.
- iterator erase(const_iterator first, const_iterator last)
- { return m_flat_tree.erase(first, last); }
+ 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);
//! <b>Effects</b>: erase(a.begin(),a.end()).
//!
//! <b>Postcondition</b>: size() == 0.
//!
//! <b>Complexity</b>: linear in size().
- void clear()
- { m_flat_tree.clear(); }
+ void clear() BOOST_CONTAINER_NOEXCEPT;
- //! <b>Effects</b>: Tries to deallocate the excess of memory created
- // with previous allocations. The size of the vector is unchanged
+ //! <b>Effects</b>: Returns the comparison object out
+ //! of which a was constructed.
//!
- //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
+ //! <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>: Linear to size().
- void shrink_to_fit()
- { m_flat_tree.shrink_to_fit(); }
+ //! <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)
- { return m_flat_tree.find(x); }
+ iterator find(const key_type& x);
- //! <b>Returns</b>: A const_iterator pointing to an element with the key
+ //! <b>Returns</b>: Allocator const_iterator pointing to an element with the key
//! equivalent to x, or end() if such an element is not found.
//!
- //! <b>Complexity</b>: Logarithmic.s
- const_iterator find(const key_type& x) const
- { return m_flat_tree.find(x); }
+ //! <b>Complexity</b>: Logarithmic.
+ const_iterator find(const key_type& 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)
size_type count(const key_type& x) const
- { return m_flat_tree.find(x) == m_flat_tree.end() ? 0 : 1; }
+ { return static_cast<size_type>(this->base_t::find(x) != this->base_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)
- { return m_flat_tree.lower_bound(x); }
+ iterator lower_bound(const key_type& x);
- //! <b>Returns</b>: A const iterator pointing to the first element with key not
+ //! <b>Returns</b>: Allocator 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
- { return m_flat_tree.lower_bound(x); }
+ const_iterator lower_bound(const key_type& 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)
- { return m_flat_tree.upper_bound(x); }
+ iterator upper_bound(const key_type& x);
- //! <b>Returns</b>: A const iterator pointing to the first element with key not
+ //! <b>Returns</b>: Allocator 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
- { return m_flat_tree.upper_bound(x); }
+ const_iterator upper_bound(const key_type& 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
- std::pair<const_iterator, const_iterator>
- equal_range(const key_type& x) const
- { return m_flat_tree.equal_range(x); }
+ std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const
+ { return this->base_t::lower_bound_range(x); }
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
//!
//! <b>Complexity</b>: Logarithmic
- std::pair<iterator,iterator>
- equal_range(const key_type& x)
- { return m_flat_tree.equal_range(x); }
+ std::pair<iterator,iterator> equal_range(const key_type& x)
+ { return this->base_t::lower_bound_range(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.
- size_type capacity() const
- { return m_flat_tree.capacity(); }
+ #if defined(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.
- //! 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>Effects</b>: Returns true if x and y are equal
//!
- //! <b>Throws</b>: If memory allocation allocation throws or T's copy constructor throws.
- //!
- //! <b>Note</b>: If capacity() is less than "count", iterators and references to
- //! to values might be invalidated.
- void reserve(size_type count)
- { m_flat_tree.reserve(count); }
-
- /// @cond
- template <class K1, class C1, class A1>
- friend bool operator== (const flat_set<K1,C1,A1>&, const flat_set<K1,C1,A1>&);
-
- template <class K1, class C1, class A1>
- friend bool operator< (const flat_set<K1,C1,A1>&, const flat_set<K1,C1,A1>&);
-
- private:
- std::pair<iterator, bool> priv_insert(const T &x)
- { return m_flat_tree.insert_unique(x); }
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator==(const flat_set& x, const flat_set& y);
- iterator priv_insert(const_iterator p, const T &x)
- { return m_flat_tree.insert_unique(p, x); }
- /// @endcond
-};
+ //! <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);
-template <class T, class Pred, class A>
-inline bool operator==(const flat_set<T,Pred,A>& x,
- const flat_set<T,Pred,A>& y)
- { return x.m_flat_tree == y.m_flat_tree; }
+ //! <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);
-template <class T, class Pred, class A>
-inline bool operator<(const flat_set<T,Pred,A>& x,
- const flat_set<T,Pred,A>& y)
- { return x.m_flat_tree < y.m_flat_tree; }
+ //! <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);
-template <class T, class Pred, class A>
-inline bool operator!=(const flat_set<T,Pred,A>& x,
- const flat_set<T,Pred,A>& y)
- { return !(x == 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);
-template <class T, class Pred, class A>
-inline bool operator>(const flat_set<T,Pred,A>& x,
- const flat_set<T,Pred,A>& y)
- { return y < x; }
+ //! <b>Effects</b>: Returns true if x is equal or greater than y
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator>=(const flat_set& x, const flat_set& y);
-template <class T, class Pred, class A>
-inline bool operator<=(const flat_set<T,Pred,A>& x,
- const flat_set<T,Pred,A>& y)
- { return !(y < x); }
+ //! <b>Effects</b>: x.swap(y)
+ //!
+ //! <b>Complexity</b>: Constant.
+ friend void swap(flat_set& x, flat_set& y);
-template <class T, class Pred, class A>
-inline bool operator>=(const flat_set<T,Pred,A>& x,
- const flat_set<T,Pred,A>& y)
- { return !(x < y); }
+ #endif //#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
-template <class T, class Pred, class A>
-inline void swap(flat_set<T,Pred,A>& x, flat_set<T,Pred,A>& y)
- { x.swap(y); }
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ private:
+ template<class KeyType>
+ std::pair<iterator, bool> priv_insert(BOOST_FWD_REF(KeyType) x)
+ { return this->base_t::insert_unique(::boost::forward<KeyType>(x)); }
+
+ template<class KeyType>
+ iterator priv_insert(const_iterator p, BOOST_FWD_REF(KeyType) x)
+ { return this->base_t::insert_unique(p, ::boost::forward<KeyType>(x)); }
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+};
-/// @cond
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
} //namespace container {
-/*
+
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
-template <class T, class C, class A>
-struct has_trivial_destructor_after_move<boost::container::flat_set<T, C, A> >
+template <class Key, class C, class Allocator>
+struct has_trivial_destructor_after_move<boost::container::flat_set<Key, C, Allocator> >
{
- static const bool value = has_trivial_destructor<A>::value &&has_trivial_destructor<C>::value;
+ static const bool value = has_trivial_destructor_after_move<Allocator>::value &&has_trivial_destructor_after_move<C>::value;
};
-*/
-namespace container {
-
-// Forward declaration of operators < and ==, needed for friend declaration.
-
-#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
-template <class T, class Pred = std::less<T>, class A = std::allocator<T> >
-#else
-template <class T, class Pred, class A>
-#endif
-class flat_multiset;
-template <class T, class Pred, class A>
-inline bool operator==(const flat_multiset<T,Pred,A>& x,
- const flat_multiset<T,Pred,A>& y);
+namespace container {
-template <class T, class Pred, class A>
-inline bool operator<(const flat_multiset<T,Pred,A>& x,
- const flat_multiset<T,Pred,A>& y);
-/// @endcond
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//! flat_multiset is a Sorted Associative Container that stores objects of type Key.
-//! flat_multiset is a Simple Associative Container, meaning that its value type,
-//! as well as its key type, is Key.
-//! flat_Multiset can store multiple copies of the same key value.
+//!
+//! flat_multiset can store multiple copies of the same key value.
//!
//! flat_multiset is similar to std::multiset but it's implemented like an ordered vector.
//! This means that inserting a new element into a flat_multiset invalidates
//! previous iterators and references
//!
-//! Erasing an element of a flat_multiset invalidates iterators and references
-//! pointing to elements that come after (their keys are equal or bigger) the erased element.
+//! Erasing an element invalidates 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 Allocator is the allocator to be used to allocate memory for this container
#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
-template <class T, class Pred = std::less<T>, class A = std::allocator<T> >
+template <class Key, class Compare = std::less<Key>, class Allocator = std::allocator<Key> >
#else
-template <class T, class Pred, class A>
+template <class Key, class Compare, class Allocator>
#endif
class flat_multiset
+ ///@cond
+ : public container_detail::flat_tree<Key, Key, container_detail::identity<Key>, Compare, Allocator>
+ ///@endcond
{
- /// @cond
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
BOOST_COPYABLE_AND_MOVABLE(flat_multiset)
- typedef container_detail::flat_tree<T, T, container_detail::identity<T>, Pred, A> tree_t;
- tree_t m_flat_tree; // flat tree representing flat_multiset
- typedef typename container_detail::
- move_const_ref_type<T>::type insert_const_ref_type;
- /// @endcond
+ typedef container_detail::flat_tree<Key, Key, container_detail::identity<Key>, Compare, Allocator> base_t;
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public:
- // typedefs:
- typedef typename tree_t::key_type key_type;
- typedef typename tree_t::value_type value_type;
- typedef typename tree_t::pointer pointer;
- typedef typename tree_t::const_pointer const_pointer;
- typedef typename tree_t::reference reference;
- typedef typename tree_t::const_reference const_reference;
- typedef typename tree_t::key_compare key_compare;
- typedef typename tree_t::value_compare value_compare;
- typedef typename tree_t::iterator iterator;
- typedef typename tree_t::const_iterator const_iterator;
- typedef typename tree_t::reverse_iterator reverse_iterator;
- typedef typename tree_t::const_reverse_iterator const_reverse_iterator;
- typedef typename tree_t::size_type size_type;
- typedef typename tree_t::difference_type difference_type;
- typedef typename tree_t::allocator_type allocator_type;
- typedef typename tree_t::stored_allocator_type stored_allocator_type;
-
- //! <b>Effects</b>: Default constructs an empty flat_multiset.
- //!
- //! <b>Complexity</b>: Constant.
+ //////////////////////////////////////////////
+ //
+ // 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;
+
+ //! @copydoc ::boost::container::flat_set::flat_set()
explicit flat_multiset()
- : m_flat_tree()
+ : base_t()
{}
- explicit flat_multiset(const Pred& comp,
+ //! @copydoc ::boost::container::flat_set::flat_set(const Compare&, const allocator_type&)
+ explicit flat_multiset(const Compare& comp,
const allocator_type& a = allocator_type())
- : m_flat_tree(comp, a) {}
+ : base_t(comp, a)
+ {}
+ //! @copydoc ::boost::container::flat_set::flat_set(const allocator_type&)
+ explicit flat_multiset(const allocator_type& a)
+ : base_t(a)
+ {}
+
+ //! @copydoc ::boost::container::flat_set::flat_set(InputIterator, InputIterator, const Compare& comp, const allocator_type&)
template <class InputIterator>
flat_multiset(InputIterator first, InputIterator last,
- const Pred& comp = Pred(),
+ const Compare& comp = Compare(),
const allocator_type& a = allocator_type())
- : m_flat_tree(comp, a)
- { m_flat_tree.insert_equal(first, last); }
+ : base_t(false, first, last, comp, a)
+ {}
//! <b>Effects</b>: Constructs an empty flat_multiset using the specified comparison object and
//! allocator, and inserts elements from the ordered range [first ,last ). This function
@@ -791,215 +851,185 @@ class flat_multiset
//! <b>Note</b>: Non-standard extension.
template <class InputIterator>
flat_multiset(ordered_range_t, InputIterator first, InputIterator last,
- const Pred& comp = Pred(),
+ const Compare& comp = Compare(),
const allocator_type& a = allocator_type())
- : m_flat_tree(ordered_range, first, last, comp, a)
+ : base_t(ordered_range, first, last, comp, a)
{}
- //! <b>Effects</b>: Copy constructs a flat_multiset.
- //!
- //! <b>Complexity</b>: Linear in x.size().
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! @copydoc ::boost::container::flat_set::flat_set(std::initializer_list<value_type>, const Compare& comp, const allocator_type&)
+ flat_multiset(std::initializer_list<value_type> il, const Compare& comp = Compare(),
+ const allocator_type& a = allocator_type())
+ : base_t(false, il.begin(), il.end(), comp, a)
+ {}
+
+ //! @copydoc ::boost::container::flat_set::flat_set(ordered_unique_range_t, std::initializer_list<value_type>, const Compare& comp, const allocator_type&)
+ flat_multiset(ordered_unique_range_t, std::initializer_list<value_type> il,
+ const Compare& comp = Compare(), const allocator_type& a = allocator_type())
+ : base_t(ordered_range, il.begin(), il.end(), comp, a)
+ {}
+#endif
+
+ //! @copydoc ::boost::container::flat_set::flat_set(const flat_set &)
flat_multiset(const flat_multiset& x)
- : m_flat_tree(x.m_flat_tree)
+ : base_t(static_cast<const base_t&>(x))
{}
- //! <b>Effects</b>: Move constructs a flat_multiset. Constructs *this using x's resources.
- //!
- //! <b>Complexity</b>: Constant.
- //!
- //! <b>Postcondition</b>: x is emptied.
+ //! @copydoc ::boost::container::flat_set(flat_set &&)
flat_multiset(BOOST_RV_REF(flat_multiset) mx)
- : m_flat_tree(boost::move(mx.m_flat_tree))
+ : base_t(boost::move(static_cast<base_t&>(mx)))
{}
- //! <b>Effects</b>: Copy constructs a flat_multiset using the specified allocator.
- //!
- //! <b>Complexity</b>: Linear in x.size().
+ //! @copydoc ::boost::container::flat_set(const flat_set &, const allocator_type &)
flat_multiset(const flat_multiset& x, const allocator_type &a)
- : m_flat_tree(x.m_flat_tree, a)
+ : base_t(static_cast<const base_t&>(x), a)
{}
- //! <b>Effects</b>: Move constructs a flat_multiset using the specified allocator.
- //! Constructs *this using x's resources.
- //!
- //! <b>Complexity</b>: Constant if a == mx.get_allocator(), linear otherwise
+ //! @copydoc ::boost::container::flat_set(flat_set &&, const allocator_type &)
flat_multiset(BOOST_RV_REF(flat_multiset) mx, const allocator_type &a)
- : m_flat_tree(boost::move(mx.m_flat_tree), a)
+ : base_t(boost::move(static_cast<base_t&>(mx)), a)
{}
- //! <b>Effects</b>: Makes *this a copy of x.
- //!
- //! <b>Complexity</b>: Linear in x.size().
+ //! @copydoc ::boost::container::flat_set::operator=(const flat_set &)
flat_multiset& operator=(BOOST_COPY_ASSIGN_REF(flat_multiset) x)
- { m_flat_tree = x.m_flat_tree; return *this; }
+ { return static_cast<flat_multiset&>(this->base_t::operator=(static_cast<const base_t&>(x))); }
- //! <b>Effects</b>: Makes *this a copy of x.
- //!
- //! <b>Complexity</b>: Linear in x.size().
+ //! @copydoc ::boost::container::flat_set::operator=(flat_set &&)
flat_multiset& operator=(BOOST_RV_REF(flat_multiset) mx)
- { m_flat_tree = boost::move(mx.m_flat_tree); return *this; }
+ BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value)
+ { return static_cast<flat_multiset&>(this->base_t::operator=(boost::move(static_cast<base_t&>(mx)))); }
+
+#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
- //! <b>Effects</b>: Returns the comparison object out
- //! of which a was constructed.
- //!
- //! <b>Complexity</b>: Constant.
- key_compare key_comp() const
- { return m_flat_tree.key_comp(); }
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- //! <b>Effects</b>: Returns an object of value_compare constructed out
- //! of the comparison object.
- //!
- //! <b>Complexity</b>: Constant.
- value_compare value_comp() const
- { return m_flat_tree.key_comp(); }
+ //! @copydoc ::boost::container::flat_set::get_allocator()
+ allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT;
- //! <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
- { return m_flat_tree.get_allocator(); }
+ //! @copydoc ::boost::container::flat_set::get_stored_allocator()
+ stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT;
- const stored_allocator_type &get_stored_allocator() const
- { return m_flat_tree.get_stored_allocator(); }
+ //! @copydoc ::boost::container::flat_set::get_stored_allocator() const
+ const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT;
- stored_allocator_type &get_stored_allocator()
- { return m_flat_tree.get_stored_allocator(); }
+ //! @copydoc ::boost::container::flat_set::begin()
+ iterator begin() BOOST_CONTAINER_NOEXCEPT;
- //! <b>Effects</b>: Returns an iterator to the first element contained in the container.
- //!
- //! <b>Throws</b>: Nothing.
- //!
- //! <b>Complexity</b>: Constant.
- iterator begin()
- { return m_flat_tree.begin(); }
+ //! @copydoc ::boost::container::flat_set::begin() const
+ 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 begin() const
- { return m_flat_tree.begin(); }
+ //! @copydoc ::boost::container::flat_set::cbegin() const
+ const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT;
- //! <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
- { return m_flat_tree.cbegin(); }
+ //! @copydoc ::boost::container::flat_set::end()
+ iterator end() BOOST_CONTAINER_NOEXCEPT;
- //! <b>Effects</b>: Returns an iterator to the end of the container.
- //!
- //! <b>Throws</b>: Nothing.
- //!
- //! <b>Complexity</b>: Constant.
- iterator end()
- { return m_flat_tree.end(); }
+ //! @copydoc ::boost::container::flat_set::end() const
+ const_iterator end() const BOOST_CONTAINER_NOEXCEPT;
- //! <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
- { return m_flat_tree.end(); }
+ //! @copydoc ::boost::container::flat_set::cend() const
+ const_iterator cend() const BOOST_CONTAINER_NOEXCEPT;
- //! <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
- { return m_flat_tree.cend(); }
+ //! @copydoc ::boost::container::flat_set::rbegin()
+ reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT;
- //! <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()
- { return m_flat_tree.rbegin(); }
+ //! @copydoc ::boost::container::flat_set::rbegin() const
+ const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT;
- //! <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
- { return m_flat_tree.rbegin(); }
+ //! @copydoc ::boost::container::flat_set::crbegin() const
+ const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT;
- //! <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
- { return m_flat_tree.crbegin(); }
+ //! @copydoc ::boost::container::flat_set::rend()
+ reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT;
- //! <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()
- { return m_flat_tree.rend(); }
+ //! @copydoc ::boost::container::flat_set::rend() const
+ const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT;
- //! <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
- { return m_flat_tree.rend(); }
+ //! @copydoc ::boost::container::flat_set::crend() const
+ const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT;
- //! <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
- { return m_flat_tree.crend(); }
+ //! @copydoc ::boost::container::flat_set::empty() const
+ bool empty() const BOOST_CONTAINER_NOEXCEPT;
- //! <b>Effects</b>: Returns true if the container contains no elements.
- //!
- //! <b>Throws</b>: Nothing.
- //!
- //! <b>Complexity</b>: Constant.
- bool empty() const
- { return m_flat_tree.empty(); }
+ //! @copydoc ::boost::container::flat_set::size() const
+ size_type size() const BOOST_CONTAINER_NOEXCEPT;
- //! <b>Effects</b>: Returns the number of the elements contained in the container.
+ //! @copydoc ::boost::container::flat_set::max_size() const
+ size_type max_size() const BOOST_CONTAINER_NOEXCEPT;
+
+ //! @copydoc ::boost::container::flat_set::capacity() const
+ size_type capacity() const BOOST_CONTAINER_NOEXCEPT;
+
+ //! @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_CONTAINER_PERFECT_FORWARDING) || 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>Throws</b>: Nothing.
+ //! <b>Complexity</b>: Logarithmic search time plus linear insertion
+ //! to the elements with bigger keys than x.
//!
- //! <b>Complexity</b>: Constant.
- size_type size() const
- { return m_flat_tree.size(); }
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ template <class... Args>
+ iterator emplace(Args&&... args)
+ { return this->base_t::emplace_equal(boost::forward<Args>(args)...); }
- //! <b>Effects</b>: Returns the largest possible size of the container.
+ //! <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>Throws</b>: Nothing.
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
//!
- //! <b>Complexity</b>: Constant.
- size_type max_size() const
- { return m_flat_tree.max_size(); }
-
- //! <b>Effects</b>: Swaps the contents of *this and 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>Throws</b>: Nothing.
+ //! <b>Note</b>: If an element is inserted it might invalidate elements.
+ template <class... Args>
+ iterator emplace_hint(const_iterator p, Args&&... args)
+ { return this->base_t::emplace_hint_equal(p, boost::forward<Args>(args)...); }
+
+ #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
+
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
+ iterator emplace(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
+ { return this->base_t::emplace_equal(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); } \
+ \
+ BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
+ iterator emplace_hint(const_iterator p \
+ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
+ { return this->base_t::emplace_hint_equal \
+ (p BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); } \
//!
- //! <b>Complexity</b>: Constant.
- void swap(flat_multiset& x)
- { m_flat_tree.swap(x.m_flat_tree); }
+ #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
+ #include BOOST_PP_LOCAL_ITERATE()
+ #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
+
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! <b>Effects</b>: Inserts x and returns the iterator pointing to the
//! newly inserted element.
//!
@@ -1007,17 +1037,7 @@ class flat_multiset
//! to the elements with bigger keys than x.
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
- iterator insert(insert_const_ref_type x)
- { return priv_insert(x); }
-
- #if defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- iterator insert(T &x)
- { return this->insert(const_cast<const T &>(x)); }
-
- template<class U>
- iterator insert(const U &u, typename container_detail::enable_if_c<container_detail::is_same<T, U>::value && !::boost::has_move_emulation_enabled<U>::value >::type* =0)
- { return priv_insert(u); }
- #endif
+ 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.
@@ -1026,9 +1046,12 @@ class flat_multiset
//! to the elements with bigger keys than x.
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
- iterator insert(BOOST_RV_REF(value_type) x)
- { return m_flat_tree.insert_equal(boost::move(x)); }
+ 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.
//!
@@ -1039,18 +1062,7 @@ class flat_multiset
//! 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, insert_const_ref_type x)
- { return priv_insert(p, x); }
-
- #if defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- iterator insert(const_iterator position, T &x)
- { return this->insert(position, const_cast<const T &>(x)); }
-
- template<class U>
- iterator insert( const_iterator position, const U &u
- , typename container_detail::enable_if_c<container_detail::is_same<T, U>::value && !::boost::has_move_emulation_enabled<U>::value >::type* =0)
- { return priv_insert(position, u); }
- #endif
+ 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.
@@ -1062,8 +1074,10 @@ class flat_multiset
//! 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 position, BOOST_RV_REF(value_type) x)
- { return m_flat_tree.insert_equal(position, boost::move(x)); }
+ 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.
//!
@@ -1075,7 +1089,7 @@ class flat_multiset
//! <b>Note</b>: If an element is inserted it might invalidate elements.
template <class InputIterator>
void insert(InputIterator first, InputIterator last)
- { m_flat_tree.insert_equal(first, last); }
+ { this->base_t::insert_equal(first, last); }
//! <b>Requires</b>: first, last are not iterators into *this and
//! must be ordered according to the predicate.
@@ -1089,253 +1103,145 @@ class flat_multiset
//! <b>Note</b>: Non-standard extension. If an element is inserted it might invalidate elements.
template <class InputIterator>
void insert(ordered_range_t, InputIterator first, InputIterator last)
- { m_flat_tree.insert_equal(ordered_range, first, last); }
-
- #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ { this->base_t::insert_equal(ordered_range, first, last); }
- //! <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.
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: inserts each element from the range [il.begin(), il.end()).
//!
- //! <b>Complexity</b>: Logarithmic search time plus linear insertion
- //! to the elements with bigger keys than x.
+ //! <b>Complexity</b>: At most N log(size()+N) (N is the distance from first to last)
+ //! search time plus N*size() insertion time.
//!
//! <b>Note</b>: If an element is inserted it might invalidate elements.
- template <class... Args>
- iterator emplace(Args&&... args)
- { return m_flat_tree.emplace_equal(boost::forward<Args>(args)...); }
+ void insert(std::initializer_list<value_type> il)
+ { this->base_t::insert_equal(il.begin(), il.end()); }
- //! <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>Requires</b>: Range [il.begin(), il.end()) must be ordered according to the predicate.
//!
- //! <b>Returns</b>: An iterator pointing to the element with key equivalent
- //! to the key of x.
+ //! <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>: Logarithmic search time (constant if x is inserted
- //! right before p) plus insertion linear to the elements with bigger keys than x.
+ //! <b>Complexity</b>: At most N log(size()+N) (N is the distance from il.begin() to il.end())
+ //! search time plus N*size() insertion time.
//!
- //! <b>Note</b>: If an element is inserted it might invalidate elements.
- template <class... Args>
- iterator emplace_hint(const_iterator hint, Args&&... args)
- { return m_flat_tree.emplace_hint_equal(hint, boost::forward<Args>(args)...); }
+ //! <b>Note</b>: Non-standard extension. If an element is inserted it might invalidate elements.
+ void insert(ordered_range_t, std::initializer_list<value_type> il)
+ { this->base_t::insert_equal(ordered_range, il.begin(), il.end()); }
+#endif
- #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- #define BOOST_PP_LOCAL_MACRO(n) \
- BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
- iterator emplace(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
- { return m_flat_tree.emplace_equal(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); } \
- \
- BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
- iterator emplace_hint(const_iterator hint \
- BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
- { return m_flat_tree.emplace_hint_equal \
- (hint BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); } \
- //!
- #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
- #include BOOST_PP_LOCAL_ITERATE()
+ //! @copydoc ::boost::container::flat_set::erase(const_iterator)
+ iterator erase(const_iterator p);
- #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
+ //! @copydoc ::boost::container::flat_set::erase(const key_type&)
+ size_type erase(const key_type& x);
- //! <b>Effects</b>: Erases the element pointed to by position.
- //!
- //! <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 position
- //!
- //! <b>Note</b>: Invalidates elements with keys
- //! not less than the erased element.
- iterator erase(const_iterator position)
- { return m_flat_tree.erase(position); }
+ //! @copydoc ::boost::container::flat_set::erase(const_iterator,const_iterator)
+ iterator erase(const_iterator first, const_iterator last);
- //! <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)
- { return m_flat_tree.erase(x); }
+ //! @copydoc ::boost::container::flat_set::swap
+ void swap(flat_multiset& 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)
- { return m_flat_tree.erase(first, last); }
+ //! @copydoc ::boost::container::flat_set::clear
+ void clear() BOOST_CONTAINER_NOEXCEPT;
- //! <b>Effects</b>: erase(a.begin(),a.end()).
- //!
- //! <b>Postcondition</b>: size() == 0.
- //!
- //! <b>Complexity</b>: linear in size().
- void clear()
- { m_flat_tree.clear(); }
+ //! @copydoc ::boost::container::flat_set::key_comp
+ key_compare key_comp() const;
- //! <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().
- void shrink_to_fit()
- { m_flat_tree.shrink_to_fit(); }
+ //! @copydoc ::boost::container::flat_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)
- { return m_flat_tree.find(x); }
+ //! @copydoc ::boost::container::flat_set::find(const key_type& )
+ 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.s
- const_iterator find(const key_type& x) const
- { return m_flat_tree.find(x); }
+ //! @copydoc ::boost::container::flat_set::find(const key_type& ) const
+ const_iterator find(const key_type& 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
- { return m_flat_tree.count(x); }
+ //! @copydoc ::boost::container::flat_set::count(const key_type& ) const
+ size_type count(const key_type& 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)
- { return m_flat_tree.lower_bound(x); }
+ //! @copydoc ::boost::container::flat_set::lower_bound(const key_type& )
+ 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.
+ //! @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>: Logarithmic
- const_iterator lower_bound(const key_type& x) const
- { return m_flat_tree.lower_bound(x); }
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator==(const flat_multiset& x, const flat_multiset& y);
- //! <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>Effects</b>: Returns true if x and y are unequal
//!
- //! <b>Complexity</b>: Logarithmic
- iterator upper_bound(const key_type& x)
- { return m_flat_tree.upper_bound(x); }
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator!=(const flat_multiset& x, const flat_multiset& y);
- //! <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>Effects</b>: Returns true if x is less than y
//!
- //! <b>Complexity</b>: Logarithmic
- const_iterator upper_bound(const key_type& x) const
- { return m_flat_tree.upper_bound(x); }
+ //! <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>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
+ //! <b>Effects</b>: Returns true if x is greater than y
//!
- //! <b>Complexity</b>: Logarithmic
- std::pair<const_iterator, const_iterator>
- equal_range(const key_type& x) const
- { return m_flat_tree.equal_range(x); }
+ //! <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>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
+ //! <b>Effects</b>: Returns true if x is equal or less than y
//!
- //! <b>Complexity</b>: Logarithmic
- std::pair<iterator,iterator>
- equal_range(const key_type& x)
- { return m_flat_tree.equal_range(x); }
+ //! <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>: Number of elements for which memory has been allocated.
- //! capacity() is always greater than or equal to size().
+ //! <b>Effects</b>: Returns true if x is equal or greater than y
//!
- //! <b>Throws</b>: Nothing.
+ //! <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.
- size_type capacity() const
- { return m_flat_tree.capacity(); }
+ friend void swap(flat_multiset& x, flat_multiset& y);
- //! <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 constructor throws.
- //!
- //! <b>Note</b>: If capacity() is less than "count", iterators and references to
- //! to values might be invalidated.
- void reserve(size_type count)
- { m_flat_tree.reserve(count); }
-
- /// @cond
- template <class K1, class C1, class A1>
- friend bool operator== (const flat_multiset<K1,C1,A1>&,
- const flat_multiset<K1,C1,A1>&);
- template <class K1, class C1, class A1>
- friend bool operator< (const flat_multiset<K1,C1,A1>&,
- const flat_multiset<K1,C1,A1>&);
- private:
- iterator priv_insert(const T &x)
- { return m_flat_tree.insert_equal(x); }
+ #endif //#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
- iterator priv_insert(const_iterator p, const T &x)
- { return m_flat_tree.insert_equal(p, x); }
- /// @endcond
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ private:
+ template <class KeyType>
+ iterator priv_insert(BOOST_FWD_REF(KeyType) x)
+ { return this->base_t::insert_equal(::boost::forward<KeyType>(x)); }
+
+ template <class KeyType>
+ iterator priv_insert(const_iterator p, BOOST_FWD_REF(KeyType) x)
+ { return this->base_t::insert_equal(p, ::boost::forward<KeyType>(x)); }
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
};
-template <class T, class Pred, class A>
-inline bool operator==(const flat_multiset<T,Pred,A>& x,
- const flat_multiset<T,Pred,A>& y)
- { return x.m_flat_tree == y.m_flat_tree; }
-
-template <class T, class Pred, class A>
-inline bool operator<(const flat_multiset<T,Pred,A>& x,
- const flat_multiset<T,Pred,A>& y)
- { return x.m_flat_tree < y.m_flat_tree; }
-
-template <class T, class Pred, class A>
-inline bool operator!=(const flat_multiset<T,Pred,A>& x,
- const flat_multiset<T,Pred,A>& y)
- { return !(x == y); }
-
-template <class T, class Pred, class A>
-inline bool operator>(const flat_multiset<T,Pred,A>& x,
- const flat_multiset<T,Pred,A>& y)
- { return y < x; }
-
-template <class T, class Pred, class A>
-inline bool operator<=(const flat_multiset<T,Pred,A>& x,
- const flat_multiset<T,Pred,A>& y)
- { return !(y < x); }
-
-template <class T, class Pred, class A>
-inline bool operator>=(const flat_multiset<T,Pred,A>& x,
- const flat_multiset<T,Pred,A>& y)
-{ return !(x < y); }
-
-template <class T, class Pred, class A>
-inline void swap(flat_multiset<T,Pred,A>& x, flat_multiset<T,Pred,A>& y)
- { x.swap(y); }
-
-/// @cond
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
} //namespace container {
-/*
+
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
-template <class T, class C, class A>
-struct has_trivial_destructor_after_move<boost::container::flat_multiset<T, C, A> >
+template <class Key, class C, class Allocator>
+struct has_trivial_destructor_after_move<boost::container::flat_multiset<Key, C, Allocator> >
{
- static const bool value = has_trivial_destructor<A>::value && has_trivial_destructor<C>::value;
+ static const bool value = has_trivial_destructor_after_move<Allocator>::value && has_trivial_destructor_after_move<C>::value;
};
-*/
+
namespace container {
-/// @endcond
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
}}
diff --git a/boost/container/list.hpp b/boost/container/list.hpp
index c3e3562988..33cc6ee0f8 100644
--- a/boost/container/list.hpp
+++ b/boost/container/list.hpp
@@ -1,16 +1,16 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
+// (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_LIST_HPP_
-#define BOOST_CONTAINER_LIST_HPP_
+#ifndef BOOST_CONTAINER_LIST_HPP
+#define BOOST_CONTAINER_LIST_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -18,13 +18,16 @@
#include <boost/container/detail/workaround.hpp>
#include <boost/container/container_fwd.hpp>
#include <boost/container/detail/version_type.hpp>
-#include <boost/move/move.hpp>
-#include <boost/move/move_helpers.hpp>
+#include <boost/container/detail/iterators.hpp>
+#include <boost/container/detail/mpl.hpp>
+#include <boost/container/throw_exception.hpp>
+#include <boost/move/utility_core.hpp>
+#include <boost/move/iterator.hpp>
+#include <boost/move/detail/move_helpers.hpp>
+#include <boost/move/traits.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/container/detail/utilities.hpp>
#include <boost/container/detail/algorithms.hpp>
-#include <boost/type_traits/has_trivial_destructor.hpp>
-#include <boost/container/detail/mpl.hpp>
#include <boost/intrusive/list.hpp>
#include <boost/assert.hpp>
#include <boost/container/detail/node_alloc_holder.hpp>
@@ -35,23 +38,20 @@
#include <boost/container/detail/preprocessor.hpp>
#endif
-#include <stdexcept>
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+#include <initializer_list>
+#endif
+
#include <iterator>
#include <utility>
#include <memory>
#include <functional>
#include <algorithm>
-#include <stdexcept>
-#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
namespace boost {
namespace container {
-#else
-namespace boost {
-namespace container {
-#endif
-/// @cond
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
namespace container_detail {
template<class VoidPointer>
@@ -69,14 +69,27 @@ struct list_node
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 A>
+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<A> allocator_traits_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
@@ -95,7 +108,7 @@ struct intrusive_list_type
};
} //namespace container_detail {
-/// @endcond
+#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
@@ -107,29 +120,31 @@ struct intrusive_list_type
//! 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 A = std::allocator<T> >
+template <class T, class Allocator = std::allocator<T> >
#else
-template <class T, class A>
+template <class T, class Allocator>
#endif
class list
: protected container_detail::node_alloc_holder
- <A, typename container_detail::intrusive_list_type<A>::type>
+ <Allocator, typename container_detail::intrusive_list_type<Allocator>::type>
{
- /// @cond
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
typedef typename
- container_detail::intrusive_list_type<A>::type Icont;
- typedef list <T, A> ThisType;
- typedef container_detail::node_alloc_holder<A, Icont> AllocHolder;
- typedef typename AllocHolder::NodePtr NodePtr;
- typedef typename AllocHolder::NodeAlloc NodeAlloc;
- typedef typename AllocHolder::ValAlloc ValAlloc;
- typedef typename AllocHolder::Node Node;
- typedef container_detail::allocator_destroyer<NodeAlloc> Destroyer;
- typedef typename AllocHolder::allocator_v1 allocator_v1;
- typedef typename AllocHolder::allocator_v2 allocator_v2;
- typedef typename AllocHolder::alloc_version alloc_version;
- typedef boost::container::allocator_traits<A> allocator_traits_type;
+ container_detail::intrusive_list_type<Allocator>::type Icont;
+ typedef container_detail::node_alloc_holder<Allocator, Icont> AllocHolder;
+ typedef typename AllocHolder::NodePtr NodePtr;
+ typedef typename AllocHolder::NodeAlloc NodeAlloc;
+ typedef typename AllocHolder::ValAlloc ValAlloc;
+ typedef typename AllocHolder::Node Node;
+ typedef container_detail::allocator_destroyer<NodeAlloc> Destroyer;
+ typedef typename AllocHolder::allocator_v1 allocator_v1;
+ typedef typename AllocHolder::allocator_v2 allocator_v2;
+ typedef typename AllocHolder::alloc_version alloc_version;
+ typedef boost::container::allocator_traits<Allocator> allocator_traits_type;
class equal_to_value
{
@@ -159,141 +174,39 @@ class list
bool operator()(const Node &a) const
{ return static_cast<const Pred&>(*this)(a.m_data); }
};
- /// @endcond
- public:
- //! The type of object, T, stored in the list
- typedef T value_type;
- //! Pointer to T
- typedef typename allocator_traits_type::pointer pointer;
- //! Const pointer to T
- typedef typename allocator_traits_type::const_pointer const_pointer;
- //! Reference to T
- typedef typename allocator_traits_type::reference reference;
- //! Const reference to T
- typedef typename allocator_traits_type::const_reference const_reference;
- //! An unsigned integral type
- typedef typename allocator_traits_type::size_type size_type;
- //! A signed integral type
- typedef typename allocator_traits_type::difference_type difference_type;
- //! The allocator type
- typedef A allocator_type;
- //! Non-standard extension: the stored allocator type
- typedef NodeAlloc stored_allocator_type;
-
- /// @cond
- private:
BOOST_COPYABLE_AND_MOVABLE(list)
- typedef difference_type list_difference_type;
- typedef pointer list_pointer;
- typedef const_pointer list_const_pointer;
- typedef reference list_reference;
- typedef const_reference list_const_reference;
- /// @endcond
-
- public:
- //! Const iterator used to iterate through a list.
- class const_iterator
- /// @cond
- : public std::iterator<std::bidirectional_iterator_tag,
- value_type, list_difference_type,
- list_const_pointer, list_const_reference>
- {
-
- protected:
- typename Icont::iterator m_it;
- explicit const_iterator(typename Icont::iterator it) : m_it(it){}
- void prot_incr() { ++m_it; }
- void prot_decr() { --m_it; }
-
- private:
- typename Icont::iterator get()
- { return this->m_it; }
-
- public:
- friend class list<T, A>;
- typedef list_difference_type difference_type;
-
- //Constructors
- const_iterator()
- : m_it()
- {}
-
- //Pointer like operators
- const_reference operator*() const
- { return m_it->m_data; }
-
- const_pointer operator->() const
- { return const_pointer(&m_it->m_data); }
-
- //Increment / Decrement
- const_iterator& operator++()
- { prot_incr(); return *this; }
-
- const_iterator operator++(int)
- { typename Icont::iterator tmp = m_it; ++*this; return const_iterator(tmp); }
-
- const_iterator& operator--()
- { prot_decr(); return *this; }
-
- const_iterator operator--(int)
- { typename Icont::iterator tmp = m_it; --*this; return const_iterator(tmp); }
-
- //Comparison operators
- bool operator== (const const_iterator& r) const
- { return m_it == r.m_it; }
-
- bool operator!= (const const_iterator& r) const
- { return m_it != r.m_it; }
- }
- /// @endcond
- ;
-
- //! Iterator used to iterate through a list
- class iterator
- /// @cond
- : public const_iterator
- {
-
- private:
- explicit iterator(typename Icont::iterator it)
- : const_iterator(it)
- {}
-
- typename Icont::iterator get()
- { return this->m_it; }
-
- public:
- friend class list<T, A>;
- typedef list_pointer pointer;
- typedef list_reference reference;
-
- //Constructors
- iterator(){}
- //Pointer like operators
- reference operator*() const { return this->m_it->m_data; }
- pointer operator->() const { return pointer(&this->m_it->m_data); }
+ typedef container_detail::iterator<typename Icont::iterator, false> iterator_impl;
+ typedef container_detail::iterator<typename Icont::iterator, true> const_iterator_impl;
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
- //Increment / Decrement
- iterator& operator++()
- { this->prot_incr(); return *this; }
-
- iterator operator++(int)
- { typename Icont::iterator tmp = this->m_it; ++*this; return iterator(tmp); }
-
- iterator& operator--()
- { this->prot_decr(); return *this; }
-
- iterator operator--(int)
- { iterator tmp = *this; --*this; return tmp; }
- };
- /// @endcond
-
- //! Iterator used to iterate backwards through a list.
- typedef std::reverse_iterator<iterator> reverse_iterator;
- //! Const iterator used to iterate backwards through a list.
- typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+ 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(container_detail::reverse_iterator<iterator>) reverse_iterator;
+ typedef BOOST_CONTAINER_IMPDEF(container_detail::reverse_iterator<const_iterator>) const_reverse_iterator;
+
+ //////////////////////////////////////////////
+ //
+ // construct/copy/destroy
+ //
+ //////////////////////////////////////////////
//! <b>Effects</b>: Default constructs a list.
//!
@@ -306,32 +219,32 @@ class list
//! <b>Effects</b>: Constructs a list taking the allocator as parameter.
//!
- //! <b>Throws</b>: If allocator_type's copy constructor throws.
+ //! <b>Throws</b>: Nothing
//!
//! <b>Complexity</b>: Constant.
- explicit list(const allocator_type &a)
+ explicit list(const allocator_type &a) BOOST_CONTAINER_NOEXCEPT
: AllocHolder(a)
{}
//! <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 or copy constructor
+ //! <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(A())
+ : 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 or copy constructor
+ //! <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 A& a = A())
+ list(size_type n, const T& value, const Allocator& a = Allocator())
: AllocHolder(a)
{ this->insert(this->cbegin(), n, value); }
@@ -339,7 +252,7 @@ class list
//!
//! <b>Postcondition</b>: x == *this.
//!
- //! <b>Throws</b>: If allocator_type's default constructor or copy constructor throws.
+ //! <b>Throws</b>: If allocator_type's default constructor throws.
//!
//! <b>Complexity</b>: Linear to the elements x contains.
list(const list& x)
@@ -386,52 +299,205 @@ class list
//! <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 or copy constructor
- //! throws or T's constructor taking an dereferenced InIt throws.
+ //! <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 A &a = A())
+ 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()
+ ~list() BOOST_CONTAINER_NOEXCEPT
{} //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();
+ container_detail::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_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::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 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 container_detail::enable_if_c
+ < !container_detail::is_convertible<InpIt, size_type>::value
+ >::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 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
+ allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT
{ return allocator_type(this->node_alloc()); }
- const stored_allocator_type &get_stored_allocator() const
- { return this->node_alloc(); }
-
- 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.
+ stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT
{ return this->node_alloc(); }
- //! <b>Effects</b>: Erases all the elements of the list.
+ //! <b>Effects</b>: Returns a reference to the internal allocator.
//!
- //! <b>Throws</b>: Nothing.
+ //! <b>Throws</b>: Nothing
//!
- //! <b>Complexity</b>: Linear to the number of elements in the list.
- void clear()
- { AllocHolder::clear(alloc_version()); }
+ //! <b>Complexity</b>: Constant.
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT
+ { 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()
+ iterator begin() BOOST_CONTAINER_NOEXCEPT
{ return iterator(this->icont().begin()); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the list.
@@ -439,7 +505,7 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_iterator begin() const
+ const_iterator begin() const BOOST_CONTAINER_NOEXCEPT
{ return this->cbegin(); }
//! <b>Effects</b>: Returns an iterator to the end of the list.
@@ -447,7 +513,7 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- iterator end()
+ iterator end() BOOST_CONTAINER_NOEXCEPT
{ return iterator(this->icont().end()); }
//! <b>Effects</b>: Returns a const_iterator to the end of the list.
@@ -455,7 +521,7 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_iterator end() const
+ const_iterator end() const BOOST_CONTAINER_NOEXCEPT
{ return this->cend(); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
@@ -464,7 +530,7 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- reverse_iterator rbegin()
+ reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT
{ return reverse_iterator(end()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
@@ -473,7 +539,7 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reverse_iterator rbegin() const
+ const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT
{ return this->crbegin(); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the end
@@ -482,7 +548,7 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- reverse_iterator rend()
+ reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT
{ return reverse_iterator(begin()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
@@ -491,7 +557,7 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reverse_iterator rend() const
+ const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT
{ return this->crend(); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the list.
@@ -499,7 +565,7 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_iterator cbegin() const
+ const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT
{ return const_iterator(this->non_const_icont().begin()); }
//! <b>Effects</b>: Returns a const_iterator to the end of the list.
@@ -507,7 +573,7 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_iterator cend() const
+ const_iterator cend() const BOOST_CONTAINER_NOEXCEPT
{ return const_iterator(this->non_const_icont().end()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
@@ -516,7 +582,7 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reverse_iterator crbegin() const
+ const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT
{ return const_reverse_iterator(this->cend()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
@@ -525,15 +591,21 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reverse_iterator crend() const
+ const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT
{ 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
+ bool empty() const BOOST_CONTAINER_NOEXCEPT
{ return !this->size(); }
//! <b>Effects</b>: Returns the number of the elements contained in the list.
@@ -541,7 +613,7 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- size_type size() const
+ size_type size() const BOOST_CONTAINER_NOEXCEPT
{ return this->icont().size(); }
//! <b>Effects</b>: Returns the largest possible size of the list.
@@ -549,64 +621,41 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- size_type max_size() const
+ size_type max_size() const BOOST_CONTAINER_NOEXCEPT
{ return AllocHolder::max_size(); }
- #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 mx 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 mx to this new element.
+ //! <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>Throws</b>: If memory allocation throws, or T's copy 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
+ //! <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>: Removes the first element from the list.
+ //! <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>: Nothing.
+ //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
//!
- //! <b>Complexity</b>: Amortized constant time.
- void pop_front()
- { this->erase(this->cbegin()); }
+ //! <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);
+ }
+ }
- //! <b>Effects</b>: Removes the last element from the list.
- //!
- //! <b>Throws</b>: Nothing.
- //!
- //! <b>Complexity</b>: Amortized constant time.
- void pop_back()
- { const_iterator tmp = this->cend(); this->erase(--tmp); }
+ //////////////////////////////////////////////
+ //
+ // element access
+ //
+ //////////////////////////////////////////////
//! <b>Requires</b>: !empty()
//!
@@ -616,7 +665,7 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- reference front()
+ reference front() BOOST_CONTAINER_NOEXCEPT
{ return *this->begin(); }
//! <b>Requires</b>: !empty()
@@ -627,7 +676,7 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reference front() const
+ const_reference front() const BOOST_CONTAINER_NOEXCEPT
{ return *this->begin(); }
//! <b>Requires</b>: !empty()
@@ -638,7 +687,7 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- reference back()
+ reference back() BOOST_CONTAINER_NOEXCEPT
{ return *(--this->end()); }
//! <b>Requires</b>: !empty()
@@ -649,176 +698,14 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reference back() const
+ const_reference back() const BOOST_CONTAINER_NOEXCEPT
{ return *(--this->end()); }
- //! <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 iend = this->cend();
- size_type len = this->size();
-
- if(len > new_size){
- size_type to_erase = len - new_size;
- while(to_erase--){
- --iend;
- }
- this->erase(iend, this->cend());
- }
- else{
- this->priv_create_and_insert_nodes(iend, new_size - len, x);
- }
- }
-
- //! <b>Effects</b>: Inserts or erases elements at the end such that
- //! the size becomes n. New elements are default constructed.
- //!
- //! <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 iend = this->end();
- size_type len = this->size();
-
- if(len > new_size){
- size_type to_erase = len - new_size;
- const_iterator ifirst;
- if(to_erase < len/2u){
- ifirst = iend;
- while(to_erase--){
- --ifirst;
- }
- }
- else{
- ifirst = this->begin();
- size_type to_skip = len - to_erase;
- while(to_skip--){
- ++ifirst;
- }
- }
- this->erase(ifirst, iend);
- }
- else{
- this->priv_create_and_insert_nodes(this->cend(), new_size - len);
- }
- }
-
- //! <b>Effects</b>: Swaps the contents of *this and x.
- //!
- //! <b>Throws</b>: Nothing.
- //!
- //! <b>Complexity</b>: Constant.
- void swap(ThisType& x)
- { AllocHolder::swap(x); }
-
- //! <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.
- ThisType& operator=(BOOST_COPY_ASSIGN_REF(ThisType) x)
- {
- if (&x != this){
- NodeAlloc &this_alloc = this->node_alloc();
- const NodeAlloc &x_alloc = x.node_alloc();
- container_detail::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 mx'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_type's copy constructor throws.
- //!
- //! <b>Complexity</b>: Constant.
- ThisType& operator=(BOOST_RV_REF(ThisType) x)
- {
- if (&x != this){
- NodeAlloc &this_alloc = this->node_alloc();
- NodeAlloc &x_alloc = x.node_alloc();
- //If allocators are equal we can just swap pointers
- if(this_alloc == x_alloc){
- //Destroy and swap pointers
- this->clear();
- this->icont() = boost::move(x.icont());
- //Move allocator if needed
- this->AllocHolder::move_assign_alloc(x);
- }
- //If unequal allocators, then do a one by one move
- else{
- typedef typename std::iterator_traits<iterator>::iterator_category ItCat;
- this->assign( boost::make_move_iterator(x.begin())
- , boost::make_move_iterator(x.end()));
- }
- }
- return *this;
- }
-
- //! <b>Requires</b>: p must be a valid iterator of *this.
- //!
- //! <b>Effects</b>: Inserts n copies of x before p.
- //!
- //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
- //!
- //! <b>Complexity</b>: Linear to n.
- void insert(const_iterator p, size_type n, const T& x)
- { this->priv_create_and_insert_nodes(p, n, x); }
-
- //! <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>Throws</b>: If memory allocation throws, T's constructor from a
- //! dereferenced InpIt throws.
- //!
- //! <b>Complexity</b>: Linear to std::distance [first, last).
- template <class InpIt>
- void insert(const_iterator p, InpIt first, InpIt last)
- {
- const bool aux_boolean = container_detail::is_convertible<InpIt, size_type>::value;
- typedef container_detail::bool_<aux_boolean> Result;
- this->priv_insert_dispatch(p, first, last, Result());
- }
-
- #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 x's copy constructor throws.
- //!
- //! <b>Complexity</b>: Amortized constant time.
- 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 mx's resources.
- //!
- //! <b>Throws</b>: If memory allocation throws.
- //!
- //! <b>Complexity</b>: Amortized constant time.
- iterator insert(const_iterator position, T &&x);
- #else
- BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator)
- #endif
+ //////////////////////////////////////////////
+ //
+ // modifiers
+ //
+ //////////////////////////////////////////////
#if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
@@ -831,9 +718,7 @@ class list
//! <b>Complexity</b>: Constant
template <class... Args>
void emplace_back(Args&&... args)
- {
- this->emplace(this->cend(), boost::forward<Args>(args)...);
- }
+ { 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.
@@ -844,9 +729,7 @@ class list
//! <b>Complexity</b>: Constant
template <class... Args>
void emplace_front(Args&&... args)
- {
- this->emplace(this->cbegin(), boost::forward<Args>(args)...);
- }
+ { 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.
@@ -893,6 +776,172 @@ class list
#endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
+ #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 mx 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 mx 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 mx'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 p, size_type n, const T& x)
+ {
+ typedef constant_iterator<value_type, difference_type> cvalue_iterator;
+ return this->insert(p, 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 std::distance [first, last).
+ template <class InpIt>
+ iterator insert(const_iterator p, InpIt first, InpIt last
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename container_detail::enable_if_c
+ < !container_detail::is_convertible<InpIt, size_type>::value
+ && (container_detail::is_input_iterator<InpIt>::value
+ || container_detail::is_same<alloc_version, allocator_v1>::value
+ )
+ >::type * = 0
+ #endif
+ )
+ {
+ 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 p, FwdIt first, FwdIt last
+ , typename container_detail::enable_if_c
+ < !container_detail::is_convertible<FwdIt, size_type>::value
+ && !(container_detail::is_input_iterator<FwdIt>::value
+ || container_detail::is_same<alloc_version, allocator_v1>::value
+ )
+ >::type * = 0
+ )
+ {
+ //Optimized allocation and construction
+ insertion_functor func(this->icont(), p.get());
+ iterator before_p(p.get());
+ --before_p;
+ this->allocate_many_and_construct(first, std::distance(first, last), func);
+ 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 std::distance [il.begin(), il.end()).
+ iterator insert(const_iterator p, std::initializer_list<value_type> il)
+ { 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_CONTAINER_NOEXCEPT
+ { 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_CONTAINER_NOEXCEPT
+ { 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 p.
@@ -900,7 +949,7 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Amortized constant time.
- iterator erase(const_iterator p)
+ iterator erase(const_iterator p) BOOST_CONTAINER_NOEXCEPT
{ 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.
@@ -910,129 +959,187 @@ class list
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Linear to the distance between first and last.
- iterator erase(const_iterator first, const_iterator last)
+ iterator erase(const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT
{ return iterator(AllocHolder::erase_range(first.get(), last.get(), alloc_version())); }
- //! <b>Effects</b>: Assigns the n copies of val to *this.
+ //! <b>Effects</b>: Swaps the contents of *this and x.
//!
- //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
+ //! <b>Throws</b>: Nothing.
//!
- //! <b>Complexity</b>: Linear to n.
- void assign(size_type n, const T& val)
- { this->priv_fill_assign(n, val); }
+ //! <b>Complexity</b>: Constant.
+ void swap(list& x)
+ { AllocHolder::swap(x); }
- //! <b>Effects</b>: Assigns the the range [first, last) to *this.
+ //! <b>Effects</b>: Erases all the elements of the list.
//!
- //! <b>Throws</b>: If memory allocation throws or
- //! T's constructor from dereferencing InpIt throws.
+ //! <b>Throws</b>: Nothing.
//!
- //! <b>Complexity</b>: Linear to n.
- template <class InpIt>
- void assign(InpIt first, InpIt last)
- {
- const bool aux_boolean = container_detail::is_convertible<InpIt, size_type>::value;
- typedef container_detail::bool_<aux_boolean> Result;
- this->priv_assign_dispatch(first, last, Result());
- }
+ //! <b>Complexity</b>: Linear to the number of elements in the list.
+ void clear() BOOST_CONTAINER_NOEXCEPT
+ { AllocHolder::clear(alloc_version()); }
+
+ //////////////////////////////////////////////
+ //
+ // slist operations
+ //
+ //////////////////////////////////////////////
//! <b>Requires</b>: p must point to an element contained
- //! by the list. x != *this
+ //! 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>: std::runtime_error if this' allocator and x's allocator
- //! are not equal.
+ //! <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, ThisType& x) BOOST_CONTAINER_NOEXCEPT
+ void splice(const_iterator p, list& x) BOOST_CONTAINER_NOEXCEPT
{
- BOOST_ASSERT((NodeAlloc&)*this == (NodeAlloc&)x);
+ 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_CONTAINER_NOEXCEPT
+ { 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 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>: std::runtime_error if this' allocator and x's allocator
- //! are not equal.
+ //! <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, ThisType &x, const_iterator i) BOOST_CONTAINER_NOEXCEPT
+ void splice(const_iterator p, list &x, const_iterator i) BOOST_CONTAINER_NOEXCEPT
{
- BOOST_ASSERT((NodeAlloc&)*this == (NodeAlloc&)x);
+ //BOOST_ASSERT(this != &x);
+ 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 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_CONTAINER_NOEXCEPT
+ { 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 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>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, ThisType &x, const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT
+ void splice(const_iterator p, list &x, const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT
{
- BOOST_ASSERT((NodeAlloc&)*this == (NodeAlloc&)x);
+ 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.
- //! n == std::distance(first, last)
+ //! this' allocator and x's allocator shall compare equal.
//!
//! <b>Effects</b>: Transfers the range pointed by first and last from list x to this list,
//! before the the element pointed by p. No destructors or copy constructors are called.
//!
- //! <b>Throws</b>: std::runtime_error if this' allocator and x's allocator
- //! are not equal.
+ //! <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_CONTAINER_NOEXCEPT
+ { this->splice(p, static_cast<list&>(x), first, last); }
+
+ //! <b>Requires</b>: p must point to an element contained
+ //! by this list. first and last must point to elements contained in list x.
+ //! n == std::distance(first, last). this' allocator and x's allocator shall compare equal
+ //!
+ //! <b>Effects</b>: Transfers the range pointed by first and last from list x to this list,
+ //! before the the element pointed by p. No destructors or copy constructors are called.
+ //!
+ //! <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, ThisType &x, const_iterator first, const_iterator last, size_type n) BOOST_CONTAINER_NOEXCEPT
+ //!
+ //! <b>Note</b>: Non-standard extension
+ void splice(const_iterator p, list &x, const_iterator first, const_iterator last, size_type n) BOOST_CONTAINER_NOEXCEPT
{
- BOOST_ASSERT((NodeAlloc&)*this == (NodeAlloc&)x);
+ BOOST_ASSERT(this->node_alloc() == x.node_alloc());
this->icont().splice(p.get(), x.icont(), first.get(), last.get(), n);
}
- //! <b>Effects</b>: Reverses the order of elements in the list.
+ //! <b>Requires</b>: p must point to an element contained
+ //! by this list. first and last must point to elements contained in list x.
+ //! n == std::distance(first, last). this' allocator and x's allocator shall compare equal
//!
- //! <b>Throws</b>: Nothing.
+ //! <b>Effects</b>: Transfers the range pointed by first and last from list x to this list,
+ //! before the the element pointed by p. No destructors or copy constructors are called.
//!
- //! <b>Complexity</b>: This function is linear time.
+ //! <b>Throws</b>: Nothing
//!
- //! <b>Note</b>: Iterators and references are not invalidated
- void reverse()
- { this->icont().reverse(); }
+ //! <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_CONTAINER_NOEXCEPT
+ { 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>: Nothing.
+ //! <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)
- { remove_if(equal_to_value(value)); }
+ { this->remove_if(equal_to_value(value)); }
//! <b>Effects</b>: Removes all the elements for which a specified
//! predicate is satisfied.
@@ -1053,9 +1160,9 @@ class list
//! <b>Effects</b>: Removes adjacent duplicate elements or adjacent
//! elements that are equal from the list.
//!
- //! <b>Throws</b>: Nothing.
+ //! <b>Throws</b>: If comparison throws.
//!
- //! <b>Complexity</b>: Linear time (size()-1 comparisons calls to pred()).
+ //! <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.
@@ -1067,7 +1174,7 @@ class list
//!
//! <b>Throws</b>: If pred throws.
//!
- //! <b>Complexity</b>: Linear time (size()-1 comparisons equality comparisons).
+ //! <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.
@@ -1085,13 +1192,27 @@ class list
//! 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>: Nothing.
+ //! <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<T, A>& x)
+ void merge(list &x)
{ this->merge(x, value_less()); }
+ //! <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.
@@ -1100,31 +1221,45 @@ class list
//! 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>: Nothing.
+ //! <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, StrictWeakOrdering comp)
+ void merge(list &x, const StrictWeakOrdering &comp)
{
- if((NodeAlloc&)*this == (NodeAlloc&)x){
- this->icont().merge(x.icont(),
- ValueCompareToNodeCompare<StrictWeakOrdering>(comp));
- }
- else{
- throw std::runtime_error("list::merge called with unequal allocators");
- }
+ BOOST_ASSERT(this->node_alloc() == x.node_alloc());
+ this->icont().merge(x.icont(),
+ ValueCompareToNodeCompare<StrictWeakOrdering>(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>: Nothing.
+ //! <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()
@@ -1133,7 +1268,7 @@ class list
//! <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>: Nothing.
+ //! <b>Throws</b>: If comp throws.
//!
//! <b>Notes</b>: Iterators and references are not invalidated.
//!
@@ -1148,9 +1283,103 @@ class list
this->icont().sort(ValueCompareToNodeCompare<StrictWeakOrdering>(comp));
}
- /// @cond
+ //! <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_CONTAINER_NOEXCEPT
+ { this->icont().reverse(); }
+
+ //! <b>Effects</b>: Returns true if x and y are equal
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator==(const list& x, const list& y)
+ {
+ if(x.size() != y.size()){
+ return false;
+ }
+ typedef typename list::const_iterator const_iterator;
+ const_iterator end1 = x.end();
+
+ const_iterator i1 = x.begin();
+ const_iterator i2 = y.begin();
+ while (i1 != end1 && *i1 == *i2) {
+ ++i1;
+ ++i2;
+ }
+ return i1 == end1;
+ }
+
+ //! <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 std::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:
+ 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)
{
NodePtr tmp = AllocHolder::create_node(x);
@@ -1163,50 +1392,26 @@ class list
return iterator(this->icont().insert(p.get(), *tmp));
}
- void priv_push_back (const T &x)
+ 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)
+ 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)); }
- //Iterator range version
- template<class InpIterator>
- void priv_create_and_insert_nodes
- (const_iterator pos, InpIterator beg, InpIterator end)
- {
- typedef typename std::iterator_traits<InpIterator>::iterator_category ItCat;
- priv_create_and_insert_nodes(pos, beg, end, alloc_version(), ItCat());
- }
-
- template<class InpIterator>
- void priv_create_and_insert_nodes
- (const_iterator pos, InpIterator beg, InpIterator end, allocator_v1, std::input_iterator_tag)
- {
- for (; beg != end; ++beg){
- this->icont().insert(pos.get(), *this->create_node_from_it(beg));
- }
- }
-
- template<class InpIterator>
- void priv_create_and_insert_nodes
- (const_iterator pos, InpIterator beg, InpIterator end, allocator_v2, std::input_iterator_tag)
- { //Just forward to the default one
- priv_create_and_insert_nodes(pos, beg, end, allocator_v1(), std::input_iterator_tag());
- }
-
class insertion_functor;
friend class insertion_functor;
class insertion_functor
{
Icont &icont_;
- typename Icont::const_iterator pos_;
+ typedef typename Icont::const_iterator iconst_iterator;
+ const iconst_iterator pos_;
public:
insertion_functor(Icont &icont, typename Icont::const_iterator pos)
@@ -1214,77 +1419,10 @@ class list
{}
void operator()(Node &n)
- { this->icont_.insert(pos_, n); }
- };
-
-
- template<class FwdIterator>
- void priv_create_and_insert_nodes
- (const_iterator pos, FwdIterator beg, FwdIterator end, allocator_v2, std::forward_iterator_tag)
- {
- if(beg != end){
- //Optimized allocation and construction
- this->allocate_many_and_construct
- (beg, std::distance(beg, end), insertion_functor(this->icont(), pos.get()));
+ {
+ this->icont_.insert(pos_, n);
}
- }
-
- //Default constructed version
- void priv_create_and_insert_nodes(const_iterator pos, size_type n)
- {
- typedef default_construct_iterator<value_type, difference_type> default_iterator;
- this->priv_create_and_insert_nodes(pos, default_iterator(n), default_iterator());
- }
-
- //Copy constructed version
- void priv_create_and_insert_nodes(const_iterator pos, size_type n, const T& x)
- {
- typedef constant_iterator<value_type, difference_type> cvalue_iterator;
- this->priv_create_and_insert_nodes(pos, cvalue_iterator(x, n), cvalue_iterator());
- }
-
- //Dispatch to detect iterator range or integer overloads
- template <class InputIter>
- void priv_insert_dispatch(const_iterator p,
- InputIter first, InputIter last,
- container_detail::false_)
- { this->priv_create_and_insert_nodes(p, first, last); }
-
- template<class Integer>
- void priv_insert_dispatch(const_iterator p, Integer n, Integer x, container_detail::true_)
- { this->insert(p, (size_type)n, x); }
-
- void priv_fill_assign(size_type n, const T& val)
- {
- iterator i = this->begin(), iend = this->end();
-
- for ( ; i != iend && n > 0; ++i, --n)
- *i = val;
- if (n > 0){
- this->priv_create_and_insert_nodes(this->cend(), n, val);
- }
- else{
- this->erase(i, cend());
- }
- }
-
- template <class Integer>
- void priv_assign_dispatch(Integer n, Integer val, container_detail::true_)
- { this->priv_fill_assign((size_type) n, (T) val); }
-
- template <class InputIter>
- void priv_assign_dispatch(InputIter first2, InputIter last2, container_detail::false_)
- {
- iterator first1 = this->begin();
- iterator last1 = this->end();
- for ( ; first1 != last1 && first2 != last2; ++first1, ++first2)
- *first1 = *first2;
- if (first2 == last2)
- this->erase(first1, last1);
- else{
- this->priv_create_and_insert_nodes(last1, first2, last2);
- }
- }
+ };
//Functors for member algorithm defaults
struct value_less
@@ -1298,83 +1436,27 @@ class list
bool operator()(const value_type &a, const value_type &b) const
{ return a == b; }
};
- /// @endcond
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
};
-template <class T, class A>
-inline bool operator==(const list<T,A>& x, const list<T,A>& y)
-{
- if(x.size() != y.size()){
- return false;
- }
- typedef typename list<T,A>::const_iterator const_iterator;
- const_iterator end1 = x.end();
-
- const_iterator i1 = x.begin();
- const_iterator i2 = y.begin();
- while (i1 != end1 && *i1 == *i2) {
- ++i1;
- ++i2;
- }
- return i1 == end1;
-}
-
-template <class T, class A>
-inline bool operator<(const list<T,A>& x,
- const list<T,A>& y)
-{
- return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
-}
-
-template <class T, class A>
-inline bool operator!=(const list<T,A>& x, const list<T,A>& y)
-{
- return !(x == y);
-}
-
-template <class T, class A>
-inline bool operator>(const list<T,A>& x, const list<T,A>& y)
-{
- return y < x;
-}
-
-template <class T, class A>
-inline bool operator<=(const list<T,A>& x, const list<T,A>& y)
-{
- return !(y < x);
-}
-
-template <class T, class A>
-inline bool operator>=(const list<T,A>& x, const list<T,A>& y)
-{
- return !(x < y);
-}
-
-template <class T, class A>
-inline void swap(list<T, A>& x, list<T, A>& y)
-{
- x.swap(y);
-}
-
-/// @cond
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
} //namespace container {
-/*
+
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
-template <class T, class A>
-struct has_trivial_destructor_after_move<boost::container::list<T, A> >
-{
- static const bool value = has_trivial_destructor<A>::value;
-};
-*/
+template <class T, class Allocator>
+struct has_trivial_destructor_after_move<boost::container::list<T, Allocator> >
+ : public ::boost::has_trivial_destructor_after_move<Allocator>
+{};
+
namespace container {
-/// @endcond
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
}}
#include <boost/container/detail/config_end.hpp>
-#endif // BOOST_CONTAINER_LIST_HPP_
+#endif // BOOST_CONTAINER_LIST_HPP
diff --git a/boost/container/map.hpp b/boost/container/map.hpp
index 91cbd35429..6abfa1a346 100644
--- a/boost/container/map.hpp
+++ b/boost/container/map.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
+// (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)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_CONTAINER_MAP_HPP
#define BOOST_CONTAINER_MAP_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -22,7 +22,6 @@
#include <utility>
#include <functional>
#include <memory>
-#include <stdexcept>
#include <boost/container/detail/tree.hpp>
#include <boost/container/detail/value_init.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp>
@@ -30,121 +29,127 @@
#include <boost/container/detail/utilities.hpp>
#include <boost/container/detail/pair.hpp>
#include <boost/container/detail/type_traits.hpp>
-#include <boost/move/move.hpp>
-#include <boost/move/move_helpers.hpp>
+#include <boost/container/throw_exception.hpp>
+#include <boost/move/utility_core.hpp>
+#include <boost/move/detail/move_helpers.hpp>
+#include <boost/move/traits.hpp>
#include <boost/static_assert.hpp>
#include <boost/container/detail/value_init.hpp>
+#include <boost/core/no_exceptions_support.hpp>
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+#include <initializer_list>
+#endif
-#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
-namespace boost {
-namespace container {
-#else
namespace boost {
namespace container {
-#endif
-/// @cond
-// Forward declarations of operators == and <, needed for friend declarations.
-template <class Key, class T, class Pred, class A>
-inline bool operator==(const map<Key,T,Pred,A>& x,
- const map<Key,T,Pred,A>& y);
-
-template <class Key, class T, class Pred, class A>
-inline bool operator<(const map<Key,T,Pred,A>& x,
- const map<Key,T,Pred,A>& y);
-/// @endcond
+#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. For a
-//! map<Key,T> the key_type is Key and the value_type is std::pair<const Key,T>.
-//!
-//! Pred is the ordering function for Keys (e.g. <i>std::less<Key></i>).
+//! 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>.
//!
-//! A is the allocator to allocate the value_types
-//! (e.g. <i>allocator< std::pair<const Key, T> > </i>).
-#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
-template <class Key, class T, class Pred = std::less< std::pair< const Key, T> >, class A = std::allocator<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 MapOptions is an packed option type generated using using boost::container::tree_assoc_options.
+template < class Key, class T, class Compare = std::less<Key>
+ , class Allocator = std::allocator< std::pair< const Key, T> >, class MapOptions = tree_assoc_defaults >
#else
-template <class Key, class T, class Pred, class A>
+template <class Key, class T, class Compare, class Allocator, class MapOptions>
#endif
class map
+ ///@cond
+ : public container_detail::tree
+ < Key, std::pair<const Key, T>
+ , container_detail::select1st< std::pair<const Key, T> >
+ , Compare, Allocator, MapOptions>
+ ///@endcond
{
- /// @cond
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
BOOST_COPYABLE_AND_MOVABLE(map)
- typedef container_detail::rbtree<Key,
- std::pair<const Key, T>,
- container_detail::select1st< std::pair<const Key, T> >,
- Pred,
- A> tree_t;
- tree_t m_tree; // red-black tree representing map
- /// @endcond
+ typedef std::pair<const Key, T> value_type_impl;
+ typedef container_detail::tree
+ <Key, value_type_impl, container_detail::select1st<value_type_impl>, Compare, Allocator, MapOptions> base_t;
+ typedef container_detail::pair <Key, T> movable_value_type_impl;
+ typedef container_detail::tree_value_compare
+ < Key, value_type_impl, Compare, container_detail::select1st<value_type_impl>
+ > value_compare_impl;
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public:
-
- // typedefs:
- typedef typename tree_t::key_type key_type;
- typedef typename tree_t::value_type value_type;
- typedef typename tree_t::pointer pointer;
- typedef typename tree_t::const_pointer const_pointer;
- typedef typename tree_t::reference reference;
- typedef typename tree_t::const_reference const_reference;
- typedef T mapped_type;
- typedef Pred key_compare;
- typedef typename tree_t::iterator iterator;
- typedef typename tree_t::const_iterator const_iterator;
- typedef typename tree_t::reverse_iterator reverse_iterator;
- typedef typename tree_t::const_reverse_iterator const_reverse_iterator;
- typedef typename tree_t::size_type size_type;
- typedef typename tree_t::difference_type difference_type;
- typedef typename tree_t::allocator_type allocator_type;
- typedef typename tree_t::stored_allocator_type stored_allocator_type;
- typedef std::pair<key_type, mapped_type> nonconst_value_type;
- typedef container_detail::pair
- <key_type, mapped_type> nonconst_impl_value_type;
-
- /// @cond
- class value_compare_impl
- : public Pred,
- public std::binary_function<value_type, value_type, bool>
- {
- friend class map<Key,T,Pred,A>;
- protected :
- value_compare_impl(const Pred &c) : Pred(c) {}
- public:
- bool operator()(const value_type& x, const value_type& y) const {
- return Pred::operator()(x.first, y.first);
- }
- };
- /// @endcond
- typedef value_compare_impl value_compare;
+ //////////////////////////////////////////////
+ //
+ // types
+ //
+ //////////////////////////////////////////////
+
+ typedef Key key_type;
+ typedef ::boost::container::allocator_traits<Allocator> allocator_traits_type;
+ typedef T mapped_type;
+ typedef std::pair<const Key, T> value_type;
+ typedef typename boost::container::allocator_traits<Allocator>::pointer pointer;
+ typedef typename boost::container::allocator_traits<Allocator>::const_pointer const_pointer;
+ typedef typename boost::container::allocator_traits<Allocator>::reference reference;
+ 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;
+
+ //////////////////////////////////////////////
+ //
+ // construct/copy/destroy
+ //
+ //////////////////////////////////////////////
//! <b>Effects</b>: Default constructs an empty map.
//!
//! <b>Complexity</b>: Constant.
map()
- : m_tree()
+ : base_t()
{
//Allocator type must be std::pair<CONST Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename A::value_type>::value));
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
}
//! <b>Effects</b>: Constructs an empty map using the specified comparison object
//! and allocator.
//!
//! <b>Complexity</b>: Constant.
- explicit map(const Pred& comp,
+ explicit map(const Compare& comp,
const allocator_type& a = allocator_type())
- : m_tree(comp, a)
+ : base_t(comp, a)
{
//Allocator type must be std::pair<CONST Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename A::value_type>::value));
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
+ }
+
+ //! <b>Effects</b>: Constructs an empty map using the specified allocator.
+ //!
+ //! <b>Complexity</b>: Constant.
+ explicit map(const allocator_type& a)
+ : base_t(a)
+ {
+ //Allocator type must be std::pair<CONST Key, T>
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
}
//! <b>Effects</b>: Constructs an empty map using the specified comparison object and
@@ -153,12 +158,12 @@ class map
//! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
//! comp and otherwise N logN, where N is last - first.
template <class InputIterator>
- map(InputIterator first, InputIterator last, const Pred& comp = Pred(),
+ map(InputIterator first, InputIterator last, const Compare& comp = Compare(),
const allocator_type& a = allocator_type())
- : m_tree(first, last, comp, a, true)
+ : base_t(true, first, last, comp, a)
{
//Allocator type must be std::pair<CONST Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename A::value_type>::value));
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
}
//! <b>Effects</b>: Constructs an empty map using the specified comparison object and
@@ -169,23 +174,47 @@ class map
//! unique values.
//!
//! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
template <class InputIterator>
map( ordered_unique_range_t, InputIterator first, InputIterator last
- , const Pred& comp = Pred(), const allocator_type& a = allocator_type())
- : m_tree(ordered_range, first, last, comp, a)
+ , const Compare& comp = Compare(), const allocator_type& a = allocator_type())
+ : base_t(ordered_range, first, last, comp, a)
+ {
+ //Allocator type must be std::pair<CONST Key, T>
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
+ }
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Constructs an empty map 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
+ //! comp and otherwise N logN, where N is il.first() - il.end().
+ map(std::initializer_list<value_type> il, const Compare& comp = Compare(), const allocator_type& a = allocator_type())
+ : base_t(true, il.begin(), il.end(), comp, a)
{
//Allocator type must be std::pair<CONST Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename A::value_type>::value));
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
}
+ map(ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp = Compare(),
+ const allocator_type& a = allocator_type())
+ : base_t(ordered_range, il.begin(), il.end(), comp, a)
+ {
+ //Allocator type must be std::pair<CONST Key, T>
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
+ }
+#endif
+
//! <b>Effects</b>: Copy constructs a map.
//!
//! <b>Complexity</b>: Linear in x.size().
map(const map& x)
- : m_tree(x.m_tree)
+ : base_t(static_cast<const base_t&>(x))
{
//Allocator type must be std::pair<CONST Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename A::value_type>::value));
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
}
//! <b>Effects</b>: Move constructs a map. Constructs *this using x's resources.
@@ -194,20 +223,20 @@ class map
//!
//! <b>Postcondition</b>: x is emptied.
map(BOOST_RV_REF(map) x)
- : m_tree(boost::move(x.m_tree))
+ : base_t(boost::move(static_cast<base_t&>(x)))
{
//Allocator type must be std::pair<CONST Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename A::value_type>::value));
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
}
//! <b>Effects</b>: Copy constructs a map using the specified allocator.
//!
//! <b>Complexity</b>: Linear in x.size().
map(const map& x, const allocator_type &a)
- : m_tree(x.m_tree, a)
+ : base_t(static_cast<const base_t&>(x), a)
{
//Allocator type must be std::pair<CONST Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename A::value_type>::value));
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
}
//! <b>Effects</b>: Move constructs a map using the specified allocator.
@@ -217,98 +246,108 @@ class map
//!
//! <b>Postcondition</b>: x is emptied.
map(BOOST_RV_REF(map) x, const allocator_type &a)
- : m_tree(boost::move(x.m_tree), a)
+ : base_t(boost::move(static_cast<base_t&>(x)), a)
{
//Allocator type must be std::pair<CONST Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename A::value_type>::value));
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
}
//! <b>Effects</b>: Makes *this a copy of x.
//!
//! <b>Complexity</b>: Linear in x.size().
map& operator=(BOOST_COPY_ASSIGN_REF(map) x)
- { m_tree = x.m_tree; return *this; }
+ { return static_cast<map&>(this->base_t::operator=(static_cast<const base_t&>(x))); }
//! <b>Effects</b>: this->swap(x.get()).
//!
- //! <b>Complexity</b>: Constant.
+ //! <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.
map& operator=(BOOST_RV_REF(map) x)
- { m_tree = boost::move(x.m_tree); return *this; }
+ BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value)
+ { return static_cast<map&>(this->base_t::operator=(boost::move(static_cast<base_t&>(x)))); }
- //! <b>Effects</b>: Returns the comparison object out
- //! of which a was constructed.
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Assign content of il to *this.
//!
- //! <b>Complexity</b>: Constant.
- key_compare key_comp() const
- { return m_tree.key_comp(); }
+ map& operator=(std::initializer_list<value_type> il)
+ {
+ this->clear();
+ insert(il.begin(), il.end());
+ return *this;
+ }
+#endif
- //! <b>Effects</b>: Returns an object of value_compare constructed out
- //! of the comparison object.
- //!
- //! <b>Complexity</b>: Constant.
- value_compare value_comp() const
- { return value_compare(m_tree.key_comp()); }
+ #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
- { return m_tree.get_allocator(); }
+ allocator_type get_allocator() const;
- const stored_allocator_type &get_stored_allocator() const
- { return m_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.
+ stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT;
- stored_allocator_type &get_stored_allocator()
- { return m_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.
+ const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT;
//! <b>Effects</b>: Returns an iterator to the first element contained in the container.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- iterator begin()
- { return m_tree.begin(); }
+ iterator begin() BOOST_CONTAINER_NOEXCEPT;
//! <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
- { return this->cbegin(); }
+ const_iterator begin() const BOOST_CONTAINER_NOEXCEPT;
//! <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
- { return m_tree.begin(); }
+ const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT;
//! <b>Effects</b>: Returns an iterator to the end of the container.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- iterator end()
- { return m_tree.end(); }
+ iterator end() BOOST_CONTAINER_NOEXCEPT;
//! <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
- { return this->cend(); }
+ const_iterator end() const BOOST_CONTAINER_NOEXCEPT;
//! <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
- { return m_tree.end(); }
+ const_iterator cend() const BOOST_CONTAINER_NOEXCEPT;
//! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
//! of the reversed container.
@@ -316,8 +355,7 @@ class map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- reverse_iterator rbegin()
- { return m_tree.rbegin(); }
+ reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT;
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
//! of the reversed container.
@@ -325,8 +363,7 @@ class map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reverse_iterator rbegin() const
- { return this->crbegin(); }
+ const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT;
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
//! of the reversed container.
@@ -334,8 +371,7 @@ class map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reverse_iterator crbegin() const
- { return m_tree.rbegin(); }
+ const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT;
//! <b>Effects</b>: Returns a reverse_iterator pointing to the end
//! of the reversed container.
@@ -343,8 +379,7 @@ class map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- reverse_iterator rend()
- { return m_tree.rend(); }
+ reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT;
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
//! of the reversed container.
@@ -352,8 +387,7 @@ class map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reverse_iterator rend() const
- { return this->crend(); }
+ const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT;
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
//! of the reversed container.
@@ -361,38 +395,36 @@ class map
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reverse_iterator crend() const
- { return m_tree.rend(); }
+ const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT;
//! <b>Effects</b>: Returns true if the container contains no elements.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- bool empty() const
- { return m_tree.empty(); }
+ bool empty() const BOOST_CONTAINER_NOEXCEPT;
//! <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
- { return m_tree.size(); }
+ size_type size() const BOOST_CONTAINER_NOEXCEPT;
//! <b>Effects</b>: Returns the largest possible size of the container.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- size_type max_size() const
- { return m_tree.max_size(); }
+ size_type max_size() const BOOST_CONTAINER_NOEXCEPT;
+
+ #endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! Effects: If there is no key equivalent to x in the map, inserts
//! value_type(x, T()) into the map.
//!
- //! Returns: A reference to the mapped_type corresponding to x in *this.
+ //! Returns: Allocator reference to the mapped_type corresponding to x in *this.
//!
//! Complexity: Logarithmic.
mapped_type& operator[](const key_type &k);
@@ -400,45 +432,43 @@ class map
//! Effects: If there is no key equivalent to x in the map, inserts
//! value_type(boost::move(x), T()) into the map (the key is move-constructed)
//!
- //! Returns: A reference to the mapped_type corresponding to x in *this.
+ //! Returns: Allocator reference to the mapped_type corresponding to x in *this.
//!
//! Complexity: Logarithmic.
mapped_type& operator[](key_type &&k);
#else
- BOOST_MOVE_CONVERSION_AWARE_CATCH( operator[] , key_type, mapped_type&, priv_subscript)
+ BOOST_MOVE_CONVERSION_AWARE_CATCH( operator[] , key_type, mapped_type&, this->priv_subscript)
#endif
- //! Returns: A reference to the element whose key is equivalent to x.
+ //! Returns: Allocator 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 std::out_of_range("key not found");
+ throw_out_of_range("map::at key not found");
}
return i->second;
}
- //! Returns: A reference to the element whose key is equivalent to x.
+ //! Returns: Allocator 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 std::out_of_range("key not found");
+ throw_out_of_range("map::at key not found");
}
return i->second;
}
- //! <b>Effects</b>: Swaps the contents of *this and x.
- //!
- //! <b>Throws</b>: Nothing.
- //!
- //! <b>Complexity</b>: Constant.
- void swap(map& x)
- { m_tree.swap(x.m_tree); }
+ //////////////////////////////////////////////
+ //
+ // 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.
@@ -449,7 +479,7 @@ class map
//!
//! <b>Complexity</b>: Logarithmic.
std::pair<iterator,bool> insert(const value_type& x)
- { return m_tree.insert_unique(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.
@@ -460,7 +490,7 @@ class map
//!
//! <b>Complexity</b>: Logarithmic.
std::pair<iterator,bool> insert(const nonconst_value_type& x)
- { return m_tree.insert_unique(x); }
+ { return this->base_t::insert_unique(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.
@@ -471,7 +501,7 @@ class map
//!
//! <b>Complexity</b>: Logarithmic.
std::pair<iterator,bool> insert(BOOST_RV_REF(nonconst_value_type) x)
- { return m_tree.insert_unique(boost::move(x)); }
+ { return this->base_t::insert_unique(boost::move(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.
@@ -481,8 +511,8 @@ class map
//! points to the element with key equivalent to the key of x.
//!
//! <b>Complexity</b>: Logarithmic.
- std::pair<iterator,bool> insert(BOOST_RV_REF(nonconst_impl_value_type) x)
- { return m_tree.insert_unique(boost::move(x)); }
+ std::pair<iterator,bool> insert(BOOST_RV_REF(movable_value_type) x)
+ { return this->base_t::insert_unique(boost::move(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.
@@ -493,7 +523,7 @@ class map
//!
//! <b>Complexity</b>: Logarithmic.
std::pair<iterator,bool> insert(BOOST_RV_REF(value_type) x)
- { return m_tree.insert_unique(boost::move(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.
@@ -504,8 +534,8 @@ class map
//!
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
//! is inserted right before p.
- iterator insert(iterator position, const value_type& x)
- { return m_tree.insert_unique(position, x); }
+ 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.
@@ -516,8 +546,8 @@ class map
//!
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
//! is inserted right before p.
- iterator insert(iterator position, BOOST_RV_REF(nonconst_value_type) x)
- { return m_tree.insert_unique(position, boost::move(x)); }
+ iterator insert(const_iterator p, BOOST_RV_REF(nonconst_value_type) x)
+ { return this->base_t::insert_unique(p, boost::move(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.
@@ -528,8 +558,8 @@ class map
//!
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
//! is inserted right before p.
- iterator insert(iterator position, BOOST_RV_REF(nonconst_impl_value_type) x)
- { return m_tree.insert_unique(position, boost::move(x)); }
+ iterator insert(const_iterator p, BOOST_RV_REF(movable_value_type) x)
+ { return this->base_t::insert_unique(p, 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.
@@ -537,8 +567,8 @@ class map
//! <b>Returns</b>: An iterator pointing to the element with key equivalent to the key of x.
//!
//! <b>Complexity</b>: Logarithmic.
- iterator insert(iterator position, const nonconst_value_type& x)
- { return m_tree.insert_unique(position, x); }
+ iterator insert(const_iterator p, const nonconst_value_type& x)
+ { return this->base_t::insert_unique(p, 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.
@@ -546,8 +576,8 @@ class map
//! <b>Returns</b>: An iterator pointing to the element with key equivalent to the key of x.
//!
//! <b>Complexity</b>: Logarithmic.
- iterator insert(iterator position, BOOST_RV_REF(value_type) x)
- { return m_tree.insert_unique(position, boost::move(x)); }
+ 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.
//!
@@ -557,7 +587,16 @@ class map
//! <b>Complexity</b>: At most N log(size()+N) (N is the distance from first to last)
template <class InputIterator>
void insert(InputIterator first, InputIterator last)
- { m_tree.insert_unique(first, 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())
+ void insert(std::initializer_list<value_type> il)
+ { this->base_t::insert_unique(il.begin(), il.end()); }
+#endif
#if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
@@ -574,7 +613,7 @@ class map
//! is inserted right before p.
template <class... Args>
std::pair<iterator,bool> emplace(Args&&... args)
- { return m_tree.emplace_unique(boost::forward<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
@@ -587,20 +626,20 @@ class map
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
//! is inserted right before p.
template <class... Args>
- iterator emplace_hint(const_iterator hint, Args&&... args)
- { return m_tree.emplace_hint_unique(hint, boost::forward<Args>(args)...); }
+ iterator emplace_hint(const_iterator p, Args&&... args)
+ { return this->base_t::emplace_hint_unique(p, boost::forward<Args>(args)...); }
#else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
#define BOOST_PP_LOCAL_MACRO(n) \
BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
std::pair<iterator,bool> emplace(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
- { return m_tree.emplace_unique(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); } \
+ { return this->base_t::emplace_unique(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); }\
\
BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
- iterator emplace_hint(const_iterator hint \
+ iterator emplace_hint(const_iterator p \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
- { return m_tree.emplace_hint_unique(hint \
+ { return this->base_t::emplace_hint_unique(p \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _));} \
//!
#define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
@@ -608,116 +647,165 @@ class map
#endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
- //! <b>Effects</b>: Erases the element pointed to by position.
+ #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 position)
- { return m_tree.erase(position); }
+ iterator erase(const_iterator p) BOOST_CONTAINER_NOEXCEPT;
//! <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)
- { return m_tree.erase(x); }
+ size_type erase(const key_type& x) BOOST_CONTAINER_NOEXCEPT;
//! <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)
- { return m_tree.erase(first, last); }
+ iterator erase(const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT;
+
+ //! <b>Effects</b>: Swaps the contents of *this and x.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ void swap(map& x);
//! <b>Effects</b>: erase(a.begin(),a.end()).
//!
//! <b>Postcondition</b>: size() == 0.
//!
//! <b>Complexity</b>: linear in size().
- void clear()
- { m_tree.clear(); }
+ void clear() BOOST_CONTAINER_NOEXCEPT;
+
+ //! <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)
- { return m_tree.find(x); }
+ iterator find(const key_type& x);
- //! <b>Returns</b>: A const_iterator pointing to an element with the key
+ //! <b>Returns</b>: Allocator 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
- { return m_tree.find(x); }
+ const_iterator find(const key_type& 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)
size_type count(const key_type& x) const
- { return m_tree.find(x) == m_tree.end() ? 0 : 1; }
+ { 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)
- { return m_tree.lower_bound(x); }
+ iterator lower_bound(const key_type& x);
- //! <b>Returns</b>: A const iterator pointing to the first element with key not
+ //! <b>Returns</b>: Allocator 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
- { return m_tree.lower_bound(x); }
+ const_iterator lower_bound(const key_type& 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)
- { return m_tree.upper_bound(x); }
+ iterator upper_bound(const key_type& x);
- //! <b>Returns</b>: A const iterator pointing to the first element with key not
+ //! <b>Returns</b>: Allocator 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
- { return m_tree.upper_bound(x); }
+ const_iterator upper_bound(const key_type& 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)
- { return m_tree.equal_range(x); }
+ 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
- { return m_tree.equal_range(x); }
-
- /// @cond
- template <class K1, class T1, class C1, class A1>
- friend bool operator== (const map<K1, T1, C1, A1>&,
- const map<K1, T1, C1, A1>&);
- template <class K1, class T1, class C1, class A1>
- friend bool operator< (const map<K1, T1, C1, A1>&,
- const map<K1, T1, C1, A1>&);
+ std::pair<const_iterator,const_iterator> equal_range(const key_type& 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:
mapped_type& priv_subscript(const key_type &k)
{
//we can optimize this
- iterator i = lower_bound(k);
+ iterator i = this->lower_bound(k);
// i->first is greater than or equivalent to k.
- if (i == end() || key_comp()(k, (*i).first)){
+ if (i == this->end() || this->key_comp()(k, (*i).first)){
container_detail::value_init<mapped_type> m;
- nonconst_impl_value_type val(k, boost::move(m.m_t));
+ movable_value_type val(k, boost::move(m.m_t));
i = insert(i, boost::move(val));
}
return (*i).second;
@@ -727,78 +815,37 @@ class map
{
key_type &k = mk;
//we can optimize this
- iterator i = lower_bound(k);
+ iterator i = this->lower_bound(k);
// i->first is greater than or equivalent to k.
- if (i == end() || key_comp()(k, (*i).first)){
+ if (i == this->end() || this->key_comp()(k, (*i).first)){
container_detail::value_init<mapped_type> m;
- nonconst_impl_value_type val(boost::move(k), boost::move(m.m_t));
+ movable_value_type val(boost::move(k), boost::move(m.m_t));
i = insert(i, boost::move(val));
}
return (*i).second;
}
- /// @endcond
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
};
-template <class Key, class T, class Pred, class A>
-inline bool operator==(const map<Key,T,Pred,A>& x,
- const map<Key,T,Pred,A>& y)
- { return x.m_tree == y.m_tree; }
-
-template <class Key, class T, class Pred, class A>
-inline bool operator<(const map<Key,T,Pred,A>& x,
- const map<Key,T,Pred,A>& y)
- { return x.m_tree < y.m_tree; }
-
-template <class Key, class T, class Pred, class A>
-inline bool operator!=(const map<Key,T,Pred,A>& x,
- const map<Key,T,Pred,A>& y)
- { return !(x == y); }
-
-template <class Key, class T, class Pred, class A>
-inline bool operator>(const map<Key,T,Pred,A>& x,
- const map<Key,T,Pred,A>& y)
- { return y < x; }
-
-template <class Key, class T, class Pred, class A>
-inline bool operator<=(const map<Key,T,Pred,A>& x,
- const map<Key,T,Pred,A>& y)
- { return !(y < x); }
-
-template <class Key, class T, class Pred, class A>
-inline bool operator>=(const map<Key,T,Pred,A>& x,
- const map<Key,T,Pred,A>& y)
- { return !(x < y); }
-
-template <class Key, class T, class Pred, class A>
-inline void swap(map<Key,T,Pred,A>& x, map<Key,T,Pred,A>& y)
- { x.swap(y); }
-
-/// @cond
-// Forward declaration of operators < and ==, needed for friend declaration.
-
-template <class Key, class T, class Pred, class A>
-inline bool operator==(const multimap<Key,T,Pred,A>& x,
- const multimap<Key,T,Pred,A>& y);
-
-template <class Key, class T, class Pred, class A>
-inline bool operator<(const multimap<Key,T,Pred,A>& x,
- const multimap<Key,T,Pred,A>& y);
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
} //namespace container {
-/*
+
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
-template <class K, class T, class C, class A>
-struct has_trivial_destructor_after_move<boost::container::map<K, T, C, A> >
+template <class K, class T, class C, class Allocator>
+struct has_trivial_destructor_after_move<boost::container::map<K, T, C, Allocator> >
{
- static const bool value = has_trivial_destructor<A>::value && has_trivial_destructor<C>::value;
+ static const bool value = has_trivial_destructor_after_move<Allocator>::value && has_trivial_destructor_after_move<C>::value;
};
-*/
+
namespace container {
-/// @endcond
+#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
@@ -806,91 +853,103 @@ namespace container {
//! supports bidirectional iterators.
//!
//! A multimap satisfies all of the requirements of a container and of a reversible
-//! container and of an associative container. For a
-//! map<Key,T> the key_type is Key and the value_type is std::pair<const Key,T>.
+//! 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>.
//!
-//! Pred is the ordering function for Keys (e.g. <i>std::less<Key></i>).
-//!
-//! A is the allocator to allocate the value_types
-//!(e.g. <i>allocator< std::pair<<b>const</b> Key, T> ></i>).
-#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
-template <class Key, class T, class Pred = std::less< std::pair< const Key, T> >, class A = std::allocator<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 MultiMapOptions is an packed option type generated using using boost::container::tree_assoc_options.
+template < class Key, class T, class Compare = std::less<Key>
+ , class Allocator = std::allocator< std::pair< const Key, T> >, class MultiMapOptions = tree_assoc_defaults>
#else
-template <class Key, class T, class Pred, class A>
+template <class Key, class T, class Compare, class Allocator, class MultiMapOptions>
#endif
class multimap
+ ///@cond
+ : public container_detail::tree
+ < Key, std::pair<const Key, T>
+ , container_detail::select1st< std::pair<const Key, T> >
+ , Compare, Allocator, MultiMapOptions>
+ ///@endcond
{
- /// @cond
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
BOOST_COPYABLE_AND_MOVABLE(multimap)
- typedef container_detail::rbtree<Key,
- std::pair<const Key, T>,
- container_detail::select1st< std::pair<const Key, T> >,
- Pred,
- A> tree_t;
- tree_t m_tree; // red-black tree representing map
- typedef typename container_detail::
- move_const_ref_type<Key>::type insert_key_const_ref_type;
- /// @endcond
- public:
+ typedef std::pair<const Key, T> value_type_impl;
+ typedef container_detail::tree
+ <Key, value_type_impl, container_detail::select1st<value_type_impl>, Compare, Allocator, MultiMapOptions> base_t;
+ typedef container_detail::pair <Key, T> movable_value_type_impl;
+ typedef container_detail::tree_value_compare
+ < Key, value_type_impl, Compare, container_detail::select1st<value_type_impl>
+ > value_compare_impl;
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
- // typedefs:
- typedef typename tree_t::key_type key_type;
- typedef typename tree_t::value_type value_type;
- typedef typename tree_t::pointer pointer;
- typedef typename tree_t::const_pointer const_pointer;
- typedef typename tree_t::reference reference;
- typedef typename tree_t::const_reference const_reference;
- typedef T mapped_type;
- typedef Pred key_compare;
- typedef typename tree_t::iterator iterator;
- typedef typename tree_t::const_iterator const_iterator;
- typedef typename tree_t::reverse_iterator reverse_iterator;
- typedef typename tree_t::const_reverse_iterator const_reverse_iterator;
- typedef typename tree_t::size_type size_type;
- typedef typename tree_t::difference_type difference_type;
- typedef typename tree_t::allocator_type allocator_type;
- typedef typename tree_t::stored_allocator_type stored_allocator_type;
- typedef std::pair<key_type, mapped_type> nonconst_value_type;
- typedef container_detail::pair
- <key_type, mapped_type> nonconst_impl_value_type;
-
- /// @cond
- class value_compare_impl
- : public Pred,
- public std::binary_function<value_type, value_type, bool>
- {
- friend class multimap<Key,T,Pred,A>;
- protected :
- value_compare_impl(const Pred &c) : Pred(c) {}
- public:
- bool operator()(const value_type& x, const value_type& y) const {
- return Pred::operator()(x.first, y.first);
- }
- };
- /// @endcond
- typedef value_compare_impl value_compare;
+ public:
+ //////////////////////////////////////////////
+ //
+ // types
+ //
+ //////////////////////////////////////////////
+
+ typedef Key key_type;
+ typedef T mapped_type;
+ typedef std::pair<const Key, T> value_type;
+ typedef typename boost::container::allocator_traits<Allocator>::pointer pointer;
+ typedef typename boost::container::allocator_traits<Allocator>::const_pointer const_pointer;
+ typedef typename boost::container::allocator_traits<Allocator>::reference reference;
+ 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;
+
+ //////////////////////////////////////////////
+ //
+ // construct/copy/destroy
+ //
+ //////////////////////////////////////////////
//! <b>Effects</b>: Default constructs an empty multimap.
//!
//! <b>Complexity</b>: Constant.
multimap()
- : m_tree()
+ : base_t()
{
//Allocator type must be std::pair<CONST Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename A::value_type>::value));
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
+ }
+
+ //! <b>Effects</b>: Constructs an empty multimap using the specified allocator.
+ //!
+ //! <b>Complexity</b>: Constant.
+ explicit multimap(const Compare& comp, const allocator_type& a = allocator_type())
+ : base_t(comp, a)
+ {
+ //Allocator type must be std::pair<CONST Key, T>
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
}
//! <b>Effects</b>: Constructs an empty multimap using the specified comparison
//! object and allocator.
//!
//! <b>Complexity</b>: Constant.
- explicit multimap(const Pred& comp, const allocator_type& a = allocator_type())
- : m_tree(comp, a)
+ explicit multimap(const allocator_type& a)
+ : base_t(a)
{
//Allocator type must be std::pair<CONST Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename A::value_type>::value));
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
}
//! <b>Effects</b>: Constructs an empty multimap using the specified comparison object
@@ -900,12 +959,12 @@ class multimap
//! comp and otherwise N logN, where N is last - first.
template <class InputIterator>
multimap(InputIterator first, InputIterator last,
- const Pred& comp = Pred(),
+ const Compare& comp = Compare(),
const allocator_type& a = allocator_type())
- : m_tree(first, last, comp, a, false)
+ : base_t(false, first, last, comp, a)
{
//Allocator type must be std::pair<CONST Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename A::value_type>::value));
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
}
//! <b>Effects</b>: Constructs an empty multimap using the specified comparison object and
@@ -915,20 +974,45 @@ class multimap
//! <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>
- multimap(ordered_range_t ordered_range, InputIterator first, InputIterator last, const Pred& comp = Pred(),
+ multimap(ordered_range_t, InputIterator first, InputIterator last, const Compare& comp = Compare(),
const allocator_type& a = allocator_type())
- : m_tree(ordered_range, first, last, comp, a)
+ : base_t(ordered_range, first, last, comp, a)
{}
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Constructs an empty multimap using the specified comparison object and
+ //! allocator, and inserts elements from the range [il.begin(), il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
+ //! comp and otherwise N logN, where N is il.first() - il.end().
+ multimap(std::initializer_list<value_type> il, const Compare& comp = Compare(),
+ const allocator_type& a = allocator_type())
+ : base_t(false, il.begin(), il.end(), comp, a)
+ {
+ //Allocator type must be std::pair<CONST Key, T>
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
+ }
+
+ multimap(ordered_range_t, std::initializer_list<value_type> il, const Compare& comp = Compare(),
+ const allocator_type& a = allocator_type())
+ : base_t(ordered_range, il.begin(), il.end(), comp, a)
+ {
+ //Allocator type must be std::pair<CONST Key, T>
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
+ }
+#endif
+
//! <b>Effects</b>: Copy constructs a multimap.
//!
//! <b>Complexity</b>: Linear in x.size().
multimap(const multimap& x)
- : m_tree(x.m_tree)
+ : base_t(static_cast<const base_t&>(x))
{
//Allocator type must be std::pair<CONST Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename A::value_type>::value));
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
}
//! <b>Effects</b>: Move constructs a multimap. Constructs *this using x's resources.
@@ -937,20 +1021,20 @@ class multimap
//!
//! <b>Postcondition</b>: x is emptied.
multimap(BOOST_RV_REF(multimap) x)
- : m_tree(boost::move(x.m_tree))
+ : base_t(boost::move(static_cast<base_t&>(x)))
{
//Allocator type must be std::pair<CONST Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename A::value_type>::value));
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
}
//! <b>Effects</b>: Copy constructs a multimap.
//!
//! <b>Complexity</b>: Linear in x.size().
multimap(const multimap& x, const allocator_type &a)
- : m_tree(x.m_tree, a)
+ : base_t(static_cast<const base_t&>(x), a)
{
//Allocator type must be std::pair<CONST Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename A::value_type>::value));
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
}
//! <b>Effects</b>: Move constructs a multimap using the specified allocator.
@@ -959,212 +1043,166 @@ class multimap
//!
//! <b>Postcondition</b>: x is emptied.
multimap(BOOST_RV_REF(multimap) x, const allocator_type &a)
- : m_tree(boost::move(x.m_tree), a)
+ : base_t(boost::move(static_cast<base_t&>(x)), a)
{
//Allocator type must be std::pair<CONST Key, T>
- BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename A::value_type>::value));
+ BOOST_STATIC_ASSERT((container_detail::is_same<std::pair<const Key, T>, typename Allocator::value_type>::value));
}
//! <b>Effects</b>: Makes *this a copy of x.
//!
//! <b>Complexity</b>: Linear in x.size().
multimap& operator=(BOOST_COPY_ASSIGN_REF(multimap) x)
- { m_tree = x.m_tree; return *this; }
+ { 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.
multimap& operator=(BOOST_RV_REF(multimap) x)
- { m_tree = boost::move(x.m_tree); return *this; }
+ { return static_cast<multimap&>(this->base_t::operator=(boost::move(static_cast<base_t&>(x)))); }
- //! <b>Effects</b>: Returns the comparison object out
- //! of which a was constructed.
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Assign content of il to *this.
//!
- //! <b>Complexity</b>: Constant.
- key_compare key_comp() const
- { return m_tree.key_comp(); }
+ multimap& operator=(std::initializer_list<value_type> il)
+ {
+ this->clear();
+ insert(il.begin(), il.end());
+ return *this;
+ }
+#endif
- //! <b>Effects</b>: Returns an object of value_compare constructed out
- //! of the comparison object.
- //!
- //! <b>Complexity</b>: Constant.
- value_compare value_comp() const
- { return value_compare(m_tree.key_comp()); }
+ #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
- { return m_tree.get_allocator(); }
+ //! @copydoc ::boost::container::set::get_allocator()
+ allocator_type get_allocator() const;
- const stored_allocator_type &get_stored_allocator() const
- { return m_tree.get_stored_allocator(); }
+ //! @copydoc ::boost::container::set::get_stored_allocator()
+ stored_allocator_type &get_stored_allocator();
- stored_allocator_type &get_stored_allocator()
- { return m_tree.get_stored_allocator(); }
+ //! @copydoc ::boost::container::set::get_stored_allocator() const
+ 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()
- { return m_tree.begin(); }
+ //! @copydoc ::boost::container::set::begin()
+ 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
- { return this->cbegin(); }
+ //! @copydoc ::boost::container::set::begin() const
+ 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
- { return m_tree.begin(); }
+ //! @copydoc ::boost::container::set::cbegin() const
+ 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()
- { return m_tree.end(); }
+ //! @copydoc ::boost::container::set::end()
+ iterator end() BOOST_CONTAINER_NOEXCEPT;
- //! <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
- { return this->cend(); }
+ //! @copydoc ::boost::container::set::end() const
+ const_iterator end() const BOOST_CONTAINER_NOEXCEPT;
- //! <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
- { return m_tree.end(); }
+ //! @copydoc ::boost::container::set::cend() const
+ const_iterator cend() const BOOST_CONTAINER_NOEXCEPT;
- //! <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()
- { return m_tree.rbegin(); }
+ //! @copydoc ::boost::container::set::rbegin()
+ reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT;
- //! <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
- { return this->crbegin(); }
+ //! @copydoc ::boost::container::set::rbegin() const
+ const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT;
- //! <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
- { return m_tree.rbegin(); }
+ //! @copydoc ::boost::container::set::crbegin() const
+ const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT;
- //! <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()
- { return m_tree.rend(); }
+ //! @copydoc ::boost::container::set::rend()
+ reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT;
- //! <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
- { return this->crend(); }
+ //! @copydoc ::boost::container::set::rend() const
+ const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT;
- //! <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
- { return m_tree.rend(); }
+ //! @copydoc ::boost::container::set::crend() const
+ const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT;
- //! <b>Effects</b>: Returns true if the container contains no elements.
- //!
- //! <b>Throws</b>: Nothing.
- //!
- //! <b>Complexity</b>: Constant.
- bool empty() const
- { return m_tree.empty(); }
+ //! @copydoc ::boost::container::set::empty() const
+ bool empty() const;
- //! <b>Effects</b>: Returns the number of the elements contained in the container.
+ //! @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_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... in the container.
+ //! p is a hint pointing to where the insert should start to search.
//!
- //! <b>Throws</b>: Nothing.
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
//!
- //! <b>Complexity</b>: Constant.
- size_type size() const
- { return m_tree.size(); }
+ //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
+ //! is inserted right before p.
+ template <class... Args>
+ iterator emplace(Args&&... args)
+ { return this->base_t::emplace_equal(boost::forward<Args>(args)...); }
- //! <b>Effects</b>: Returns the largest possible size of the container.
+ //! <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>Throws</b>: Nothing.
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
//!
- //! <b>Complexity</b>: Constant.
- size_type max_size() const
- { return m_tree.max_size(); }
+ //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
+ //! is inserted right before p.
+ template <class... Args>
+ iterator emplace_hint(const_iterator p, Args&&... args)
+ { return this->base_t::emplace_hint_equal(p, boost::forward<Args>(args)...); }
- //! <b>Effects</b>: Swaps the contents of *this and x.
- //!
- //! <b>Throws</b>: Nothing.
+ #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
+
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
+ iterator emplace(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
+ { return this->base_t::emplace_equal(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); } \
+ \
+ BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
+ iterator emplace_hint(const_iterator p \
+ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
+ { return this->base_t::emplace_hint_equal(p \
+ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _));} \
//!
- //! <b>Complexity</b>: Constant.
- void swap(multimap& x)
- { m_tree.swap(x.m_tree); }
+ #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
+ #include BOOST_PP_LOCAL_ITERATE()
+
+ #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
//! <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)
- { return m_tree.insert_equal(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.
iterator insert(const nonconst_value_type& x)
- { return m_tree.insert_equal(x); }
+ { return this->base_t::insert_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.
iterator insert(BOOST_RV_REF(nonconst_value_type) x)
- { return m_tree.insert_equal(boost::move(x)); }
+ { return this->base_t::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.
- iterator insert(BOOST_RV_REF(nonconst_impl_value_type) x)
- { return m_tree.insert_equal(boost::move(x)); }
+ iterator insert(BOOST_RV_REF(movable_value_type) x)
+ { return this->base_t::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.
@@ -1174,8 +1212,8 @@ class multimap
//!
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
//! is inserted right before p.
- iterator insert(iterator position, const value_type& x)
- { return m_tree.insert_equal(position, x); }
+ 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.
@@ -1185,8 +1223,8 @@ class multimap
//!
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
//! is inserted right before p.
- iterator insert(iterator position, const nonconst_value_type& x)
- { return m_tree.insert_equal(position, x); }
+ iterator insert(const_iterator p, const nonconst_value_type& x)
+ { return this->base_t::insert_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.
@@ -1196,8 +1234,8 @@ class multimap
//!
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
//! is inserted right before p.
- iterator insert(iterator position, BOOST_RV_REF(nonconst_value_type) x)
- { return m_tree.insert_equal(position, boost::move(x)); }
+ iterator insert(const_iterator p, BOOST_RV_REF(nonconst_value_type) x)
+ { return this->base_t::insert_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.
@@ -1207,8 +1245,8 @@ class multimap
//!
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
//! is inserted right before p.
- iterator insert(iterator position, BOOST_RV_REF(nonconst_impl_value_type) x)
- { return m_tree.insert_equal(position, boost::move(x)); }
+ iterator insert(const_iterator p, BOOST_RV_REF(movable_value_type) x)
+ { return this->base_t::insert_equal(p, boost::move(x)); }
//! <b>Requires</b>: first, last are not iterators into *this.
//!
@@ -1217,209 +1255,148 @@ class multimap
//! <b>Complexity</b>: At most N log(size()+N) (N is the distance from first to last)
template <class InputIterator>
void insert(InputIterator first, InputIterator last)
- { m_tree.insert_equal(first, last); }
-
- #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ { this->base_t::insert_equal(first, last); }
- //! <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.
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: inserts each element from the range [il.begin(), il.end().
//!
- //! <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>
- iterator emplace(Args&&... args)
- { return m_tree.emplace_equal(boost::forward<Args>(args)...); }
+ //! <b>Complexity</b>: At most N log(size()+N) (N is the distance from il.begin() to il.end())
+ void insert(std::initializer_list<value_type> il)
+ { this->base_t::insert_equal(il.begin(), il.end()); }
+#endif
- //! <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>
- iterator emplace_hint(const_iterator hint, Args&&... args)
- { return m_tree.emplace_hint_equal(hint, boost::forward<Args>(args)...); }
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
+ //! @copydoc ::boost::container::set::erase(const_iterator)
+ iterator erase(const_iterator p);
- #define BOOST_PP_LOCAL_MACRO(n) \
- BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
- iterator emplace(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
- { return m_tree.emplace_equal(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); } \
- \
- BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
- iterator emplace_hint(const_iterator hint \
- BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
- { return m_tree.emplace_hint_equal(hint \
- BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _));} \
- //!
- #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
- #include BOOST_PP_LOCAL_ITERATE()
+ //! @copydoc ::boost::container::set::erase(const key_type&)
+ size_type erase(const key_type& x);
- #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
+ //! @copydoc ::boost::container::set::erase(const_iterator,const_iterator)
+ iterator erase(const_iterator first, const_iterator last);
- //! <b>Effects</b>: Erases the element pointed to by position.
- //!
- //! <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 position)
- { return m_tree.erase(position); }
+ //! @copydoc ::boost::container::set::swap
+ void swap(flat_multiset& x);
- //! <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)
- { return m_tree.erase(x); }
+ //! @copydoc ::boost::container::set::clear
+ void clear() BOOST_CONTAINER_NOEXCEPT;
- //! <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)
- { return m_tree.erase(first, last); }
+ //! @copydoc ::boost::container::set::key_comp
+ key_compare key_comp() const;
- //! <b>Effects</b>: erase(a.begin(),a.end()).
- //!
- //! <b>Postcondition</b>: size() == 0.
- //!
- //! <b>Complexity</b>: linear in size().
- void clear()
- { m_tree.clear(); }
+ //! @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)
- { return m_tree.find(x); }
+ iterator find(const key_type& x);
- //! <b>Returns</b>: A const iterator pointing to an element with the key
+ //! <b>Returns</b>: Allocator 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
- { return m_tree.find(x); }
+ const_iterator find(const key_type& 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
- { return m_tree.count(x); }
+ size_type count(const key_type& 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)
- {return m_tree.lower_bound(x); }
+ iterator lower_bound(const key_type& x);
- //! <b>Returns</b>: A const iterator pointing to the first element with key not
+ //! <b>Returns</b>: Allocator 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
- { return m_tree.lower_bound(x); }
+ const_iterator lower_bound(const key_type& 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)
- { return m_tree.upper_bound(x); }
+ iterator upper_bound(const key_type& x);
- //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
+ //! <b>Returns</b>: Allocator 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
- std::pair<iterator,iterator> equal_range(const key_type& x)
- { return m_tree.equal_range(x); }
+ const_iterator upper_bound(const key_type& x) const;
- //! <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>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
//!
//! <b>Complexity</b>: Logarithmic
- const_iterator upper_bound(const key_type& x) const
- { return m_tree.upper_bound(x); }
+ 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
- { return m_tree.equal_range(x); }
-
- /// @cond
- template <class K1, class T1, class C1, class A1>
- friend bool operator== (const multimap<K1, T1, C1, A1>& x,
- const multimap<K1, T1, C1, A1>& y);
-
- template <class K1, class T1, class C1, class A1>
- friend bool operator< (const multimap<K1, T1, C1, A1>& x,
- const multimap<K1, T1, C1, A1>& y);
- /// @endcond
-};
+ std::pair<const_iterator,const_iterator> equal_range(const key_type& x) const;
-template <class Key, class T, class Pred, class A>
-inline bool operator==(const multimap<Key,T,Pred,A>& x,
- const multimap<Key,T,Pred,A>& y)
-{ return x.m_tree == y.m_tree; }
+ //! <b>Effects</b>: Rebalances the tree. It's a no-op for Red-Black and AVL trees.
+ //!
+ //! <b>Complexity</b>: Linear
+ void rebalance();
-template <class Key, class T, class Pred, class A>
-inline bool operator<(const multimap<Key,T,Pred,A>& x,
- const multimap<Key,T,Pred,A>& y)
-{ return x.m_tree < y.m_tree; }
+ //! <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);
-template <class Key, class T, class Pred, class A>
-inline bool operator!=(const multimap<Key,T,Pred,A>& x,
- const multimap<Key,T,Pred,A>& y)
-{ return !(x == 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);
-template <class Key, class T, class Pred, class A>
-inline bool operator>(const multimap<Key,T,Pred,A>& x,
- const multimap<Key,T,Pred,A>& y)
-{ return y < x; }
+ //! <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);
-template <class Key, class T, class Pred, class A>
-inline bool operator<=(const multimap<Key,T,Pred,A>& x,
- const multimap<Key,T,Pred,A>& y)
-{ return !(y < x); }
+ //! <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);
-template <class Key, class T, class Pred, class A>
-inline bool operator>=(const multimap<Key,T,Pred,A>& x,
- const multimap<Key,T,Pred,A>& y)
-{ return !(x < y); }
+ //! <b>Effects</b>: x.swap(y)
+ //!
+ //! <b>Complexity</b>: Constant.
+ friend void swap(multimap& x, multimap& y);
-template <class Key, class T, class Pred, class A>
-inline void swap(multimap<Key,T,Pred,A>& x, multimap<Key,T,Pred,A>& y)
-{ x.swap(y); }
+ #endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+};
-/// @cond
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
} //namespace container {
-/*
+
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
-template <class K, class T, class C, class A>
-struct has_trivial_destructor_after_move<boost::container::multimap<K, T, C, A> >
+template <class K, class T, class C, class Allocator>
+struct has_trivial_destructor_after_move<boost::container::multimap<K, T, C, Allocator> >
{
- static const bool value = has_trivial_destructor<A>::value && has_trivial_destructor<C>::value;
+ static const bool value = has_trivial_destructor_after_move<Allocator>::value && has_trivial_destructor_after_move<C>::value;
};
-*/
+
namespace container {
-/// @endcond
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
}}
diff --git a/boost/container/node_allocator.hpp b/boost/container/node_allocator.hpp
new file mode 100644
index 0000000000..8004339eb8
--- /dev/null
+++ b/boost/container/node_allocator.hpp
@@ -0,0 +1,344 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# 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/alloc_lib_auto_link.hpp>
+#include <boost/container/detail/singleton.hpp>
+
+#include <boost/assert.hpp>
+#include <boost/utility/addressof.hpp>
+#include <boost/static_assert.hpp>
+#include <memory>
+#include <algorithm>
+#include <cstddef>
+
+namespace boost {
+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::
+ container_detail::unvoid<T>::type & reference;
+ typedef const typename ::boost::container::
+ container_detail::unvoid<T>::type & const_reference;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+
+ typedef boost::container::container_detail::
+ version_type<self_t, Version> version;
+
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ typedef boost::container::container_detail::
+ basic_multiallocation_chain<void*> multiallocation_chain_void;
+ typedef boost::container::container_detail::
+ 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>&);
+
+ //!Not assignable from other node_allocator
+ node_allocator& operator=(const node_allocator&);
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ public:
+
+ //!Default constructor
+ node_allocator() BOOST_CONTAINER_NOEXCEPT
+ {}
+
+ //!Copy constructor from other node_allocator.
+ node_allocator(const node_allocator &) BOOST_CONTAINER_NOEXCEPT
+ {}
+
+ //!Copy constructor from related node_allocator.
+ template<class T2>
+ node_allocator
+ (const node_allocator<T2, NodesPerBlock
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ , Version
+ #endif
+ > &) BOOST_CONTAINER_NOEXCEPT
+ {}
+
+ //!Destructor
+ ~node_allocator() BOOST_CONTAINER_NOEXCEPT
+ {}
+
+ //!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(count > this->max_size())
+ boost::container::throw_bad_alloc();
+
+ if(Version == 1 && count == 1){
+ typedef container_detail::shared_node_pool
+ <sizeof(T), NodesPerBlock> shared_pool_t;
+ typedef container_detail::singleton_default<shared_pool_t> singleton_t;
+ return pointer(static_cast<T*>(singleton_t::instance().allocate_node()));
+ }
+ else{
+ void *ret = boost_cont_malloc(count*sizeof(T));
+ if(!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_CONTAINER_NOEXCEPT
+ {
+ (void)count;
+ if(Version == 1 && count == 1){
+ typedef container_detail::shared_node_pool
+ <sizeof(T), NodesPerBlock> shared_pool_t;
+ typedef container_detail::singleton_default<shared_pool_t> singleton_t;
+ singleton_t::instance().deallocate_node(ptr);
+ }
+ else{
+ boost_cont_free(ptr);
+ }
+ }
+
+ //!Deallocates all free blocks of the pool
+ static void deallocate_free_blocks() BOOST_CONTAINER_NOEXCEPT
+ {
+ typedef container_detail::shared_node_pool
+ <sizeof(T), NodesPerBlock> shared_pool_t;
+ typedef container_detail::singleton_default<shared_pool_t> singleton_t;
+ singleton_t::instance().deallocate_free_blocks();
+ }
+
+ std::pair<pointer, bool>
+ allocation_command(allocation_type command,
+ size_type limit_size,
+ size_type preferred_size,
+ size_type &received_size, pointer reuse = pointer())
+ {
+ BOOST_STATIC_ASSERT(( Version > 1 ));
+ std::pair<pointer, bool> ret =
+ priv_allocation_command(command, limit_size, preferred_size, received_size, reuse);
+ if(!ret.first && !(command & BOOST_CONTAINER_NOTHROW_ALLOCATION))
+ boost::container::throw_bad_alloc();
+ return ret;
+ }
+
+ //!Returns maximum the number of objects the previously allocated memory
+ //!pointed by p can hold.
+ size_type size(pointer p) const BOOST_CONTAINER_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT(( Version > 1 ));
+ return boost_cont_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 container_detail::shared_node_pool
+ <sizeof(T), NodesPerBlock> shared_pool_t;
+ typedef container_detail::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 container_detail::shared_node_pool
+ <sizeof(T), NodesPerBlock> shared_pool_t;
+ typedef container_detail::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_CONTAINER_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT(( Version > 1 ));
+ typedef container_detail::shared_node_pool
+ <sizeof(T), NodesPerBlock> shared_pool_t;
+ typedef container_detail::singleton_default<shared_pool_t> singleton_t;
+ singleton_t::instance().deallocate_node(p);
+ }
+
+ void deallocate_individual(multiallocation_chain &chain) BOOST_CONTAINER_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT(( Version > 1 ));
+ typedef container_detail::shared_node_pool
+ <sizeof(T), NodesPerBlock> shared_pool_t;
+ typedef container_detail::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 ));
+ boost_cont_memchain ch;
+ BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
+ if(!boost_cont_multialloc_nodes(n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch)){
+ 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 ));
+ boost_cont_memchain ch;
+ boost_cont_multialloc_arrays(n_elements, elem_sizes, sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch);
+ if(BOOST_CONTAINER_MEMCHAIN_EMPTY(&ch)){
+ 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_CONTAINER_NOEXCEPT
+ {
+ BOOST_STATIC_ASSERT(( Version > 1 ));
+ void *first = &*chain.begin();
+ void *last = &*chain.last();
+ size_t num = chain.size();
+ boost_cont_memchain ch;
+ BOOST_CONTAINER_MEMCHAIN_INIT_FROM(&ch, first, last, num);
+ boost_cont_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_CONTAINER_NOEXCEPT
+ {}
+
+ //!An allocator always compares to true, as memory allocated with one
+ //!instance can be deallocated by another instance
+ friend bool operator==(const node_allocator &, const node_allocator &) BOOST_CONTAINER_NOEXCEPT
+ { return true; }
+
+ //!An allocator always compares to false, as memory allocated with one
+ //!instance can be deallocated by another instance
+ friend bool operator!=(const node_allocator &, const node_allocator &) BOOST_CONTAINER_NOEXCEPT
+ { return false; }
+
+ private:
+ std::pair<pointer, bool> priv_allocation_command
+ (allocation_type command, std::size_t limit_size
+ ,std::size_t preferred_size,std::size_t &received_size, void *reuse_ptr)
+ {
+ boost_cont_command_ret_t ret = {0 , 0};
+ if(limit_size > this->max_size() || preferred_size > this->max_size()){
+ //ret.first = 0;
+ return std::pair<pointer, bool>(pointer(), false);
+ }
+ std::size_t l_size = limit_size*sizeof(T);
+ std::size_t p_size = preferred_size*sizeof(T);
+ std::size_t r_size;
+ {
+ ret = boost_cont_allocation_command(command, sizeof(T), l_size, p_size, &r_size, reuse_ptr);
+ }
+ received_size = r_size/sizeof(T);
+ return std::pair<pointer, bool>(static_cast<pointer>(ret.first), !!ret.second);
+ }
+};
+
+} //namespace container {
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_CONTAINER_POOLED_NODE_ALLOCATOR_HPP
diff --git a/boost/container/options.hpp b/boost/container/options.hpp
new file mode 100644
index 0000000000..c36ad30143
--- /dev/null
+++ b/boost/container/options.hpp
@@ -0,0 +1,76 @@
+/////////////////////////////////////////////////////////////////////////////
+//
+// (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
+
+#if defined(_MSC_VER)
+# 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 {
+
+#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;
+};
+
+#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;
+};
+
+} //namespace container {
+} //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_CONTAINER_OPTIONS_HPP
diff --git a/boost/container/scoped_allocator.hpp b/boost/container/scoped_allocator.hpp
index 7da71bdf81..0a2987194f 100644
--- a/boost/container/scoped_allocator.hpp
+++ b/boost/container/scoped_allocator.hpp
@@ -6,7 +6,7 @@
//
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2011-2012. Distributed under the Boost
+// (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)
//
@@ -17,7 +17,7 @@
#ifndef BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_HPP
#define BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_HPP
-#if (defined MSC_VER) && (_MSC_VER >= 1200)
+#if defined (_MSC_VER)
# pragma once
#endif
@@ -30,8 +30,8 @@
#include <boost/container/detail/utilities.hpp>
#include <utility>
#include <boost/container/detail/pair.hpp>
-#include <boost/move/move.hpp>
-
+#include <boost/move/utility_core.hpp>
+#include <boost/core/no_exceptions_support.hpp>
namespace boost { namespace container {
@@ -46,11 +46,11 @@ namespace boost { namespace container {
//! and if T is used in a context where a container must call such a constructor, then the program is
//! ill-formed.
//!
-//! [Example:
-//! template <class T, class A = allocator<T> >
+//! <code>
+//! template <class T, class Allocator = allocator<T> >
//! class Z {
//! public:
-//! typedef A allocator_type;
+//! typedef Allocator allocator_type;
//!
//! // Default constructor with optional allocator suffix
//! Z(const allocator_type& a = allocator_type());
@@ -61,10 +61,10 @@ namespace boost { namespace container {
//! };
//!
//! // Specialize trait for class template Z
-//! template <class T, class A = allocator<T> >
-//! struct constructible_with_allocator_suffix<Z<T,A> >
+//! template <class T, class Allocator = allocator<T> >
+//! struct constructible_with_allocator_suffix<Z<T,Allocator> >
//! : ::boost::true_type { };
-//! -- end example]
+//! </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
@@ -80,7 +80,7 @@ struct constructible_with_allocator_suffix
{};
//! <b>Remark</b>: if a specialization is derived from true_type, indicates that T may be constructed
-//! with allocator_arg and T::allocator_type as its first two constructor arguments.
+//! 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.
//!
@@ -90,32 +90,32 @@ struct constructible_with_allocator_suffix
//! 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.
//!
-//! [Example:
-//! template <class T, class A = allocator<T> >
+//! <code>
+//! template <class T, class Allocator = allocator<T> >
//! class Y {
//! public:
-//! typedef A allocator_type;
-//!
+//! 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>
+//! template<class ...Args>
//! Y(allocator_arg_t, const allocator_type& a, Args&&... args);
//! };
-//!
+//!
//! // Specialize trait for class template Y
-//! template <class T, class A = allocator<T> >
-//! struct constructible_with_allocator_prefix<Y<T,A> >
+//! template <class T, class Allocator = allocator<T> >
+//! struct constructible_with_allocator_prefix<Y<T,Allocator> >
//! : ::boost::true_type { };
-//!
-//! -- end example]
+//!
+//! </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
@@ -130,7 +130,7 @@ struct constructible_with_allocator_prefix
: ::boost::false_type
{};
-///@cond
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
namespace container_detail {
@@ -159,7 +159,7 @@ struct uses_allocator_imp
} //namespace container_detail {
-///@endcond
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//! <b>Remark</b>: Automatically detects if T has a nested allocator_type that is convertible from
//! Alloc. Meets the BinaryTypeTrait requirements ([meta.rqmts] 20.4.1). A program may
@@ -173,7 +173,7 @@ struct uses_allocator
: boost::integral_constant<bool, container_detail::uses_allocator_imp<T, Alloc>::value>
{};
-///@cond
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
namespace container_detail {
@@ -259,7 +259,7 @@ namespace container_detail {
//! Thanks Mathias!
//With variadic templates, we need a single class to implement the trait
- #if !defined(BOOST_NO_VARIADIC_TEMPLATES)
+ #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template<class T, class ...Args>
struct is_constructible_impl
@@ -290,9 +290,9 @@ namespace container_detail {
: is_constructible<T, allocator_arg_t, InnerAlloc, Args...>
{};
- #else // #if !defined(BOOST_NO_VARIADIC_TEMPLATES)
+ #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
- //Without variadic templates, we need to use de preprocessor to generate
+ //Without variadic templates, we need to use the preprocessor to generate
//some specializations.
#define BOOST_CONTAINER_MAX_IS_CONSTRUCTIBLE_PARAMETERS \
@@ -382,14 +382,14 @@ namespace container_detail {
>
{};*/
- #endif // #if !defined(BOOST_NO_VARIADIC_TEMPLATES)
+ #endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#else // #if !defined(BOOST_NO_SFINAE_EXPR)
//Without advanced SFINAE expressions, we can't use is_constructible
//so backup to constructible_with_allocator_xxx
- #if !defined(BOOST_NO_VARIADIC_TEMPLATES)
+ #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template < class T, class InnerAlloc, class ...Args>
struct is_constructible_with_allocator_prefix
@@ -401,7 +401,7 @@ namespace container_detail {
: constructible_with_allocator_suffix<T>
{};*/
- #else // #if !defined(BOOST_NO_VARIADIC_TEMPLATES)
+ #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template < class T
, class InnerAlloc
@@ -423,11 +423,11 @@ namespace container_detail {
: constructible_with_allocator_suffix<T>
{};*/
- #endif // #if !defined(BOOST_NO_VARIADIC_TEMPLATES)
+ #endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#endif // #if !defined(BOOST_NO_SFINAE_EXPR)
-#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template < typename OutermostAlloc
, typename InnerAlloc
@@ -489,7 +489,7 @@ inline void dispatch_uses_allocator
(outermost_alloc, p, ::boost::forward<Args>(args)...);
}
-#else //#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
+#else //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#define BOOST_PP_LOCAL_MACRO(n) \
template < typename OutermostAlloc \
@@ -564,9 +564,9 @@ inline void dispatch_uses_allocator(boost::false_type uses_allocator
#define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
-#endif //#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
+#endif //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
-#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <typename OuterAlloc, class ...InnerAllocs>
class scoped_allocator_adaptor_base
@@ -583,7 +583,10 @@ class scoped_allocator_adaptor_base
};
typedef OuterAlloc outer_allocator_type;
- typedef scoped_allocator_adaptor<InnerAllocs...> inner_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 boost::integral_constant<
bool,
outer_traits_type::propagate_on_container_copy_assignment::value ||
@@ -634,7 +637,7 @@ class scoped_allocator_adaptor_base
, m_inner(other.inner_allocator())
{}
- protected:
+ public:
struct internal_type_t{};
template <class OuterA2>
@@ -663,23 +666,41 @@ class scoped_allocator_adaptor_base
return *this;
}
- inner_allocator_type& inner_allocator()
+ void swap(scoped_allocator_adaptor_base &r)
+ {
+ boost::container::swap_dispatch(this->outer_allocator(), r.outer_allocator());
+ boost::container::swap_dispatch(this->m_inner, r.inner_allocator());
+ }
+
+ friend void swap(scoped_allocator_adaptor_base &l, scoped_allocator_adaptor_base &r)
+ { l.swap(r); }
+
+ inner_allocator_type& inner_allocator() BOOST_CONTAINER_NOEXCEPT
{ return m_inner; }
- inner_allocator_type const& inner_allocator() const
+ inner_allocator_type const& inner_allocator() const BOOST_CONTAINER_NOEXCEPT
{ return m_inner; }
- outer_allocator_type & outer_allocator()
+ outer_allocator_type & outer_allocator() BOOST_CONTAINER_NOEXCEPT
{ return static_cast<outer_allocator_type&>(*this); }
- const outer_allocator_type &outer_allocator() const
+ const outer_allocator_type &outer_allocator() const BOOST_CONTAINER_NOEXCEPT
{ 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_VARIADIC_TEMPLATES)
+#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
@@ -723,6 +744,12 @@ class scoped_allocator_adaptor_base<OuterAlloc, true
( BOOST_PP_SUB(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, n) \
, BOOST_CONTAINER_PP_IDENTITY, nat) \
> inner_allocator_type; \
+ typedef scoped_allocator_adaptor<OuterAlloc, BOOST_PP_ENUM_PARAMS(n, Q) \
+ BOOST_PP_ENUM_TRAILING \
+ ( BOOST_PP_SUB(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, n) \
+ , BOOST_CONTAINER_PP_IDENTITY, nat) \
+ > scoped_allocator_type; \
+ typedef allocator_traits<inner_allocator_type> inner_traits_type; \
typedef boost::integral_constant< \
bool, \
outer_traits_type::propagate_on_container_copy_assignment::value || \
@@ -782,7 +809,7 @@ class scoped_allocator_adaptor_base<OuterAlloc, true
, m_inner(other.inner_allocator()) \
{} \
\
- protected: \
+ public: \
struct internal_type_t{}; \
\
template <class OuterA2> \
@@ -810,6 +837,15 @@ class scoped_allocator_adaptor_base<OuterAlloc, true
return *this; \
} \
\
+ void swap(scoped_allocator_adaptor_base &r) \
+ { \
+ boost::container::swap_dispatch(this->outer_allocator(), r.outer_allocator()); \
+ boost::container::swap_dispatch(this->m_inner, r.inner_allocator()); \
+ } \
+ \
+ friend void swap(scoped_allocator_adaptor_base &l, scoped_allocator_adaptor_base &r) \
+ { l.swap(r); } \
+ \
inner_allocator_type& inner_allocator() \
{ return m_inner; } \
\
@@ -822,6 +858,14 @@ class scoped_allocator_adaptor_base<OuterAlloc, true
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; \
}; \
@@ -829,13 +873,13 @@ class scoped_allocator_adaptor_base<OuterAlloc, true
#define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
-#endif //#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
+#endif //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
//Specialization for adaptor without any InnerAlloc
template <typename OuterAlloc>
class scoped_allocator_adaptor_base
< OuterAlloc
- #if defined(BOOST_NO_VARIADIC_TEMPLATES)
+ #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
, true
BOOST_PP_ENUM_TRAILING(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, BOOST_CONTAINER_PP_IDENTITY, nat)
#endif
@@ -850,7 +894,7 @@ class scoped_allocator_adaptor_base
{
typedef scoped_allocator_adaptor_base
<typename allocator_traits<OuterAlloc>::template portable_rebind_alloc<U>::type
- #if defined(BOOST_NO_VARIADIC_TEMPLATES)
+ #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
, true
BOOST_PP_ENUM_TRAILING(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, BOOST_CONTAINER_PP_IDENTITY, container_detail::nat)
#endif
@@ -860,6 +904,8 @@ class scoped_allocator_adaptor_base
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::
@@ -887,7 +933,7 @@ class scoped_allocator_adaptor_base
scoped_allocator_adaptor_base
(const scoped_allocator_adaptor_base<
OuterA2
- #if defined(BOOST_NO_VARIADIC_TEMPLATES)
+ #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
, true
BOOST_PP_ENUM_TRAILING(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, BOOST_CONTAINER_PP_IDENTITY, container_detail::nat)
#endif
@@ -899,7 +945,7 @@ class scoped_allocator_adaptor_base
scoped_allocator_adaptor_base
(BOOST_RV_REF_BEG scoped_allocator_adaptor_base<
OuterA2
- #if defined(BOOST_NO_VARIADIC_TEMPLATES)
+ #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
, true
BOOST_PP_ENUM_TRAILING(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, BOOST_CONTAINER_PP_IDENTITY, container_detail::nat)
#endif
@@ -907,14 +953,14 @@ class scoped_allocator_adaptor_base
: outer_allocator_type(other.outer_allocator())
{}
- protected:
+ 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)
{
@@ -928,6 +974,14 @@ class scoped_allocator_adaptor_base
return *this;
}
+ void swap(scoped_allocator_adaptor_base &r)
+ {
+ boost::container::swap_dispatch(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); }
@@ -939,14 +993,25 @@ class scoped_allocator_adaptor_base
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 container_detail {
-///@endcond
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//Scoped allocator
-#if !defined(BOOST_NO_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
#if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST)
@@ -973,14 +1038,14 @@ class scoped_allocator_adaptor_base
//! 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, `OUTERMOST(x)` is x if x does not have
- //! an `outer_allocator()` member function and
- //! `OUTERMOST(x.outer_allocator())` otherwise; `OUTERMOST_ALLOC_TRAITS(x)` is
- //! `allocator_traits<decltype(OUTERMOST(x))>`.
+ //! 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>: `OUTERMOST(x)` and
- //! `OUTERMOST_ALLOC_TRAITS(x)` are recursive operations. It is incumbent upon
- //! the definition of `outer_allocator()` to ensure that the recursion terminates.
+ //! [<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
@@ -992,7 +1057,7 @@ class scoped_allocator_adaptor_base
#endif // #if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST)
-#else // #if !defined(BOOST_NO_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+#else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
template <typename OuterAlloc
BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, class Q)
@@ -1001,7 +1066,7 @@ class scoped_allocator_adaptor
#endif
: public container_detail::scoped_allocator_adaptor_base
<OuterAlloc
- #if !defined(BOOST_NO_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, InnerAllocs...
#else
, true BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
@@ -1011,24 +1076,25 @@ class scoped_allocator_adaptor
BOOST_COPYABLE_AND_MOVABLE(scoped_allocator_adaptor)
public:
- /// @cond
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
typedef container_detail::scoped_allocator_adaptor_base
<OuterAlloc
- #if !defined(BOOST_NO_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, InnerAllocs...
#else
, true BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
#endif
> base_type;
- typedef typename base_type::internal_type_t internal_type_t;
- /// @endcond
+ 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: `scoped_allocator_adaptor<OuterAlloc>` if `sizeof...(InnerAllocs)` is zero; otherwise,
- //! `scoped_allocator_adaptor<InnerAllocs...>`.
+ //! 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;
@@ -1036,29 +1102,29 @@ class scoped_allocator_adaptor
typedef typename outer_traits_type::const_pointer const_pointer;
typedef typename outer_traits_type::void_pointer void_pointer;
typedef typename outer_traits_type::const_void_pointer const_void_pointer;
- //! Type: `true_type` if `allocator_traits<A>::propagate_on_container_copy_assignment::value` is
- //! true for any `A` in the set of `OuterAlloc` and `InnerAllocs...`; otherwise, false_type.
+ //! Type: <code>true_type</code> if <code>allocator_traits<Allocator>::propagate_on_container_copy_assignment::value</code> is
+ //! true for any <code>Allocator</code> in the set of <code>OuterAlloc</code> and <code>InnerAllocs...</code>; otherwise, false_type.
typedef typename base_type::
propagate_on_container_copy_assignment propagate_on_container_copy_assignment;
- //! Type: `true_type` if `allocator_traits<A>::propagate_on_container_move_assignment::value` is
- //! true for any `A` in the set of `OuterAlloc` and `InnerAllocs...`; otherwise, false_type.
+ //! Type: <code>true_type</code> if <code>allocator_traits<Allocator>::propagate_on_container_move_assignment::value</code> is
+ //! true for any <code>Allocator</code> in the set of <code>OuterAlloc</code> and <code>InnerAllocs...</code>; otherwise, false_type.
typedef typename base_type::
propagate_on_container_move_assignment propagate_on_container_move_assignment;
- //! Type: `true_type` if `allocator_traits<A>::propagate_on_container_swap::value` is true for any
- //! `A` in the set of `OuterAlloc` and `InnerAllocs...`; otherwise, false_type.
+ //! Type: <code>true_type</code> if <code>allocator_traits<Allocator>::propagate_on_container_swap::value</code> is true for any
+ //! <code>Allocator</code> in the set of <code>OuterAlloc</code> and <code>InnerAllocs...</code>; otherwise, false_type.
typedef typename base_type::
propagate_on_container_swap propagate_on_container_swap;
//! Type: Rebinds scoped allocator to
- //! `typedef scoped_allocator_adaptor
+ //! <code>typedef scoped_allocator_adaptor
//! < typename outer_traits_type::template portable_rebind_alloc<U>::type
- //! , InnerAllocs... >`
+ //! , InnerAllocs... ></code>
template <class U>
struct rebind
{
typedef scoped_allocator_adaptor
< typename outer_traits_type::template portable_rebind_alloc<U>::type
- #if !defined(BOOST_NO_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, InnerAllocs...
#else
BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
@@ -1086,7 +1152,7 @@ class scoped_allocator_adaptor
: base_type(::boost::move(other.base()))
{}
- #if !defined(BOOST_NO_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! <b>Requires</b>: OuterAlloc shall be constructible from OuterA2.
//!
@@ -1097,7 +1163,7 @@ class scoped_allocator_adaptor
scoped_allocator_adaptor(BOOST_FWD_REF(OuterA2) outerAlloc, const InnerAllocs & ...innerAllocs)
: base_type(::boost::forward<OuterA2>(outerAlloc), innerAllocs...)
{}
- #else // #if !defined(BOOST_NO_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
#define BOOST_PP_LOCAL_MACRO(n) \
template <class OuterA2> \
@@ -1111,14 +1177,14 @@ class scoped_allocator_adaptor
#define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
- #endif // #if !defined(BOOST_NO_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ #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
- #if !defined(BOOST_NO_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, InnerAllocs...
#else
BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
@@ -1133,7 +1199,7 @@ class scoped_allocator_adaptor
//! rvalue from other.
template <class OuterA2>
scoped_allocator_adaptor(BOOST_RV_REF_BEG scoped_allocator_adaptor<OuterA2
- #if !defined(BOOST_NO_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, InnerAllocs...
#else
BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
@@ -1143,120 +1209,117 @@ class scoped_allocator_adaptor
{}
scoped_allocator_adaptor &operator=(BOOST_COPY_ASSIGN_REF(scoped_allocator_adaptor) other)
- {
- base_type::operator=(static_cast<const base_type &>(other));
- return *this;
- }
+ { 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)
- {
- base_type::operator=(boost::move(static_cast<scoped_allocator_adaptor&>(other)));
- return *this;
- }
+ { return static_cast<scoped_allocator_adaptor&>(base_type::operator=(boost::move(static_cast<base_type&>(other)))); }
+
+ #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>:
- //! `static_cast<OuterAlloc&>(*this)`.
- outer_allocator_type & outer_allocator()
- { return *this; }
+ //! <code>static_cast<OuterAlloc&>(*this)</code>.
+ outer_allocator_type & outer_allocator() BOOST_CONTAINER_NOEXCEPT;
//! <b>Returns</b>:
- //! `static_cast<const OuterAlloc&>(*this)`.
- const outer_allocator_type &outer_allocator() const
- { return *this; }
+ //! <code>static_cast<const OuterAlloc&>(*this)</code>.
+ const outer_allocator_type &outer_allocator() const BOOST_CONTAINER_NOEXCEPT;
//! <b>Returns</b>:
- //! *this if `sizeof...(InnerAllocs)` is zero; otherwise, inner.
- inner_allocator_type& inner_allocator()
- { return base_type::inner_allocator(); }
+ //! *this if <code>sizeof...(InnerAllocs)</code> is zero; otherwise, inner.
+ inner_allocator_type& inner_allocator() BOOST_CONTAINER_NOEXCEPT;
//! <b>Returns</b>:
- //! *this if `sizeof...(InnerAllocs)` is zero; otherwise, inner.
- inner_allocator_type const& inner_allocator() const
- { return base_type::inner_allocator(); }
+ //! *this if <code>sizeof...(InnerAllocs)</code> is zero; otherwise, inner.
+ inner_allocator_type const& inner_allocator() const BOOST_CONTAINER_NOEXCEPT;
+
+ #endif //BOOST_CONTAINER_DOXYGEN_INVOKED
//! <b>Returns</b>:
- //! `allocator_traits<OuterAlloc>::max_size(outer_allocator())`.
- size_type max_size() const
+ //! <code>allocator_traits<OuterAlloc>::max_size(outer_allocator())</code>.
+ size_type max_size() const BOOST_CONTAINER_NOEXCEPT
{
return outer_traits_type::max_size(this->outer_allocator());
}
//! <b>Effects</b>:
- //! calls `OUTERMOST_ALLOC_TRAITS(*this)::destroy(OUTERMOST(*this), p)`.
+ //! calls <code>OUTERMOST_ALLOC_TRAITS(*this)::destroy(OUTERMOST(*this), p)</code>.
template <class T>
- void destroy(T* p)
+ void destroy(T* p) BOOST_CONTAINER_NOEXCEPT
{
allocator_traits<typename outermost_allocator<OuterAlloc>::type>
::destroy(get_outermost_allocator(this->outer_allocator()), p);
}
//! <b>Returns</b>:
- //! `allocator_traits<OuterAlloc>::allocate(outer_allocator(), n)`.
+ //! <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>:
- //! `allocator_traits<OuterAlloc>::allocate(outer_allocator(), n, hint)`.
+ //! <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>:
- //! `allocator_traits<OuterAlloc>::deallocate(outer_allocator(), p, n)`.
+ //! <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);
}
- //! <b>Returns</b>: A new scoped_allocator_adaptor object where each allocator
+ #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
+ //! <b>Returns</b>: Allocator new scoped_allocator_adaptor object where each allocator
//! A in the adaptor is initialized from the result of calling
- //! `allocator_traits<A>::select_on_container_copy_construction()` on
+ //! <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
- {
- return scoped_allocator_adaptor
- (internal_type_t()
- ,outer_traits_type::select_on_container_copy_construction(this->outer_allocator())
- ,outer_traits_type::select_on_container_copy_construction(this->inner_allocator())
- );
- }
- /// @cond
+ 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; }
- /// @endcond
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
- #if !defined(BOOST_NO_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! <b>Effects</b>:
- //! 1) If `uses_allocator<T, inner_allocator_type>::value` is false calls
- //! `OUTERMOST_ALLOC_TRAITS(*this)::construct
- //! (OUTERMOST(*this), p, std::forward<Args>(args)...)`.
+ //! 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 `uses_allocator<T, inner_allocator_type>::value` is true and
- //! `is_constructible<T, allocator_arg_t, inner_allocator_type, Args...>::value` is true, calls
- //! `OUTERMOST_ALLOC_TRAITS(*this)::construct(OUTERMOST(*this), p, allocator_arg,
- //! inner_allocator(), std::forward<Args>(args)...)`.
+ //! 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, `is_constructible` can't
+ //! [<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
- //! `is_constructible<T, Args..., inner_allocator_type>::value` is true, calls
- //! `OUTERMOST_ALLOC_TRAITS(*this)::construct(OUTERMOST(*this), p,
- //! std::forward<Args>(args)..., inner_allocator())`.
+ //! <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, `is_constructible` can't be
+ //! [<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_suffix<T>::value`. -end note]
+ //! <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 `uses_allocator` evaluates
+ //! [<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>
@@ -1274,7 +1337,7 @@ class scoped_allocator_adaptor
, p, ::boost::forward<Args>(args)...);
}
- #else // #if !defined(BOOST_NO_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ #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.
@@ -1295,7 +1358,7 @@ class scoped_allocator_adaptor
#define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
- #endif // #if !defined(BOOST_NO_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ #endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
template <class T1, class T2>
void construct(std::pair<T1,T2>* p)
@@ -1312,7 +1375,7 @@ class scoped_allocator_adaptor
template <class T1, class T2, class U, class V>
void construct(container_detail::pair<T1, T2>* p, BOOST_FWD_REF(U) x, BOOST_FWD_REF(V) y)
{ this->construct_pair(p, ::boost::forward<U>(x), ::boost::forward<V>(y)); }
-
+
template <class T1, class T2, class U, class V>
void construct(std::pair<T1, T2>* p, const std::pair<U, V>& x)
{ this->construct_pair(p, x); }
@@ -1321,7 +1384,7 @@ class scoped_allocator_adaptor
void construct( container_detail::pair<T1, T2>* p
, const container_detail::pair<U, V>& x)
{ this->construct_pair(p, x); }
-
+
template <class T1, class T2, class U, class V>
void construct( std::pair<T1, T2>* p
, BOOST_RV_REF_BEG std::pair<U, V> BOOST_RV_REF_END x)
@@ -1332,74 +1395,79 @@ class scoped_allocator_adaptor
, BOOST_RV_REF_BEG container_detail::pair<U, V> BOOST_RV_REF_END x)
{ this->construct_pair(p, x); }
- /// @cond
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
template <class Pair>
void construct_pair(Pair* p)
{
this->construct(container_detail::addressof(p->first));
- try {
+ BOOST_TRY{
this->construct(container_detail::addressof(p->second));
}
- catch (...) {
+ BOOST_CATCH(...){
this->destroy(container_detail::addressof(p->first));
- throw;
+ BOOST_RETHROW
}
+ BOOST_CATCH_END
}
template <class Pair, class U, class V>
void construct_pair(Pair* p, BOOST_FWD_REF(U) x, BOOST_FWD_REF(V) y)
{
this->construct(container_detail::addressof(p->first), ::boost::forward<U>(x));
- try {
+ BOOST_TRY{
this->construct(container_detail::addressof(p->second), ::boost::forward<V>(y));
}
- catch (...) {
+ BOOST_CATCH(...){
this->destroy(container_detail::addressof(p->first));
- throw;
+ BOOST_RETHROW
}
+ BOOST_CATCH_END
}
template <class Pair, class Pair2>
void construct_pair(Pair* p, const Pair2& pr)
{
this->construct(container_detail::addressof(p->first), pr.first);
- try {
+ BOOST_TRY{
this->construct(container_detail::addressof(p->second), pr.second);
}
- catch (...) {
+ BOOST_CATCH(...){
this->destroy(container_detail::addressof(p->first));
- throw;
+ BOOST_RETHROW
}
+ BOOST_CATCH_END
}
template <class Pair, class Pair2>
void construct_pair(Pair* p, BOOST_RV_REF(Pair2) pr)
{
this->construct(container_detail::addressof(p->first), ::boost::move(pr.first));
- try {
+ BOOST_TRY{
this->construct(container_detail::addressof(p->second), ::boost::move(pr.second));
}
- catch (...) {
+ BOOST_CATCH(...){
this->destroy(container_detail::addressof(p->first));
- throw;
+ BOOST_RETHROW
}
+ BOOST_CATCH_END
}
//template <class T1, class T2, class... Args1, class... Args2>
//void construct(pair<T1, T2>* p, piecewise_construct_t, tuple<Args1...> x, tuple<Args2...> y);
- private:
+ 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)
{}
- /// @endcond
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
};
template <typename OuterA1, typename OuterA2
- #if !defined(BOOST_NO_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, typename... InnerAllocs
#else
BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, class Q)
@@ -1407,21 +1475,21 @@ template <typename OuterA1, typename OuterA2
>
inline bool operator==(
const scoped_allocator_adaptor<OuterA1
- #if !defined(BOOST_NO_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
,InnerAllocs...
#else
BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
#endif
>& a,
const scoped_allocator_adaptor<OuterA2
- #if !defined(BOOST_NO_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
,InnerAllocs...
#else
BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
#endif
>& b)
{
- #if !defined(BOOST_NO_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ #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 =
@@ -1434,7 +1502,7 @@ inline bool operator==(
}
template <typename OuterA1, typename OuterA2
- #if !defined(BOOST_NO_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
, typename... InnerAllocs
#else
BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, class Q)
@@ -1442,14 +1510,14 @@ template <typename OuterA1, typename OuterA2
>
inline bool operator!=(
const scoped_allocator_adaptor<OuterA1
- #if !defined(BOOST_NO_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
,InnerAllocs...
#else
BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
#endif
>& a,
const scoped_allocator_adaptor<OuterA2
- #if !defined(BOOST_NO_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
,InnerAllocs...
#else
BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
diff --git a/boost/container/scoped_allocator_fwd.hpp b/boost/container/scoped_allocator_fwd.hpp
index 0814a50699..f19e27e885 100644
--- a/boost/container/scoped_allocator_fwd.hpp
+++ b/boost/container/scoped_allocator_fwd.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2011-2012. Distributed under the Boost
+// (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)
//
@@ -11,23 +11,27 @@
#ifndef BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_FWD_HPP
#define BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_FWD_HPP
-#if (defined MSC_VER) && (_MSC_VER >= 1200)
+//! \file
+//! This header file forward declares boost::container::scoped_allocator_adaptor
+//! and defines the following types:
+
+#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
-#if defined(BOOST_NO_VARIADIC_TEMPLATES)
+#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#include <boost/container/detail/preprocessor.hpp>
#include <boost/container/detail/type_traits.hpp>
#endif
namespace boost { namespace container {
-///@cond
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
-#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
+#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST)
@@ -45,7 +49,7 @@ namespace boost { namespace container {
#endif // #if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST)
-#else // #if !defined(BOOST_NO_VARIADIC_TEMPLATES)
+#else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <typename OuterAlloc
BOOST_PP_ENUM_TRAILING( BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS
@@ -55,7 +59,7 @@ class scoped_allocator_adaptor;
#endif
-///@endcond
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//! The allocator_arg_t struct is an empty structure type used as a unique type to
//! disambiguate constructor and function overloading. Specifically, several types
diff --git a/boost/container/set.hpp b/boost/container/set.hpp
index 09ada20033..3e2c2aad0d 100644
--- a/boost/container/set.hpp
+++ b/boost/container/set.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
+// (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)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_CONTAINER_SET_HPP
#define BOOST_CONTAINER_SET_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -23,32 +23,23 @@
#include <functional>
#include <memory>
-#include <boost/move/move.hpp>
+#include <boost/move/utility_core.hpp>
+#include <boost/move/detail/move_helpers.hpp>
+#include <boost/move/traits.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/tree.hpp>
-#include <boost/move/move.hpp>
+#include <boost/move/utility_core.hpp>
#ifndef BOOST_CONTAINER_PERFECT_FORWARDING
#include <boost/container/detail/preprocessor.hpp>
#endif
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+#include <initializer_list>
+#endif
-#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
-namespace boost {
-namespace container {
-#else
namespace boost {
namespace container {
-#endif
-/// @cond
-// Forward declarations of operators < and ==, needed for friend declaration.
-template <class T, class Pred, class A>
-inline bool operator==(const set<T,Pred,A>& x,
- const set<T,Pred,A>& y);
-
-template <class T, class Pred, class A>
-inline bool operator<(const set<T,Pred,A>& x,
- const set<T,Pred,A>& y);
-/// @endcond
+#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.
@@ -57,57 +48,79 @@ inline bool operator<(const set<T,Pred,A>& x,
//! 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.
-#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
-template <class T, class Pred = std::less<T>, class A = std::allocator<T> >
+//!
+//! \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 SetOptions is an packed option type generated using using boost::container::tree_assoc_options.
+template <class Key, class Compare = std::less<Key>, class Allocator = std::allocator<Key>, class SetOptions = tree_assoc_defaults >
#else
-template <class T, class Pred, class A>
+template <class Key, class Compare, class Allocator, class SetOptions>
#endif
class set
+ ///@cond
+ : public container_detail::tree
+ < Key, Key, container_detail::identity<Key>, Compare, Allocator, SetOptions>
+ ///@endcond
{
- /// @cond
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
BOOST_COPYABLE_AND_MOVABLE(set)
- typedef container_detail::rbtree<T, T,
- container_detail::identity<T>, Pred, A> tree_t;
- tree_t m_tree; // red-black tree representing set
- typedef typename container_detail::
- move_const_ref_type<T>::type insert_const_ref_type;
- /// @endcond
+ typedef container_detail::tree
+ < Key, Key, container_detail::identity<Key>, Compare, Allocator, SetOptions> base_t;
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public:
-
- // typedefs:
- typedef typename tree_t::key_type key_type;
- typedef typename tree_t::value_type value_type;
- typedef typename tree_t::pointer pointer;
- typedef typename tree_t::const_pointer const_pointer;
- typedef typename tree_t::reference reference;
- typedef typename tree_t::const_reference const_reference;
- typedef Pred key_compare;
- typedef Pred value_compare;
- typedef typename tree_t::iterator iterator;
- typedef typename tree_t::const_iterator const_iterator;
- typedef typename tree_t::reverse_iterator reverse_iterator;
- typedef typename tree_t::const_reverse_iterator const_reverse_iterator;
- typedef typename tree_t::size_type size_type;
- typedef typename tree_t::difference_type difference_type;
- typedef typename tree_t::allocator_type allocator_type;
- typedef typename tree_t::stored_allocator_type stored_allocator_type;
+ //////////////////////////////////////////////
+ //
+ // 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;
+
+ //////////////////////////////////////////////
+ //
+ // construct/copy/destroy
+ //
+ //////////////////////////////////////////////
//! <b>Effects</b>: Default constructs an empty set.
//!
//! <b>Complexity</b>: Constant.
set()
- : m_tree()
+ : base_t()
{}
//! <b>Effects</b>: Constructs an empty set using the specified comparison object
//! and allocator.
//!
//! <b>Complexity</b>: Constant.
- explicit set(const Pred& comp,
+ explicit set(const Compare& comp,
const allocator_type& a = allocator_type())
- : m_tree(comp, a)
+ : base_t(comp, a)
+ {}
+
+ //! <b>Effects</b>: Constructs an empty set using the specified allocator object.
+ //!
+ //! <b>Complexity</b>: Constant.
+ explicit set(const allocator_type& a)
+ : base_t(a)
{}
//! <b>Effects</b>: Constructs an empty set using the specified comparison object and
@@ -116,9 +129,9 @@ class set
//! <b>Complexity</b>: Linear in N if the range [first ,last ) is already sorted using
//! comp and otherwise N logN, where N is last - first.
template <class InputIterator>
- set(InputIterator first, InputIterator last, const Pred& comp = Pred(),
+ set(InputIterator first, InputIterator last, const Compare& comp = Compare(),
const allocator_type& a = allocator_type())
- : m_tree(first, last, comp, a, true)
+ : base_t(true, first, last, comp, a)
{}
//! <b>Effects</b>: Constructs an empty set using the specified comparison object and
@@ -129,17 +142,44 @@ class set
//! unique values.
//!
//! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
template <class InputIterator>
set( ordered_unique_range_t, InputIterator first, InputIterator last
- , const Pred& comp = Pred(), const allocator_type& a = allocator_type())
- : m_tree(ordered_range, first, last, comp, a)
+ , const Compare& comp = Compare(), const allocator_type& a = allocator_type())
+ : base_t(ordered_range, first, last, comp, a)
+ {}
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Constructs an empty set using the specified comparison object and
+ //! allocator, and inserts elements from the range [il.begin(), il.end()).
+ //!
+ //! <b>Complexity</b>: Linear in N if the range [il.begin(), il.end()) is already sorted using
+ //! comp and otherwise N logN, where N is il.begin() - il.end().
+ set(std::initializer_list<value_type> il, const Compare& comp = Compare(), const allocator_type& a = allocator_type())
+ : base_t(true, il.begin(), il.end(), comp, a)
+ {}
+
+ //! <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.
+ set(ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp = Compare(), const allocator_type& a = allocator_type())
+ : base_t(ordered_range, il.begin(), il.end(), comp, a)
{}
+#endif
//! <b>Effects</b>: Copy constructs a set.
//!
//! <b>Complexity</b>: Linear in x.size().
set(const set& x)
- : m_tree(x.m_tree)
+ : base_t(static_cast<const base_t&>(x))
{}
//! <b>Effects</b>: Move constructs a set. Constructs *this using x's resources.
@@ -148,14 +188,14 @@ class set
//!
//! <b>Postcondition</b>: x is emptied.
set(BOOST_RV_REF(set) x)
- : m_tree(boost::move(x.m_tree))
+ : base_t(boost::move(static_cast<base_t&>(x)))
{}
//! <b>Effects</b>: Copy constructs a set using the specified allocator.
//!
//! <b>Complexity</b>: Linear in x.size().
set(const set& x, const allocator_type &a)
- : m_tree(x.m_tree, a)
+ : base_t(static_cast<const base_t&>(x), a)
{}
//! <b>Effects</b>: Move constructs a set using the specified allocator.
@@ -163,140 +203,143 @@ class set
//!
//! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise.
set(BOOST_RV_REF(set) x, const allocator_type &a)
- : m_tree(boost::move(x.m_tree), a)
+ : base_t(boost::move(static_cast<base_t&>(x)), a)
{}
//! <b>Effects</b>: Makes *this a copy of x.
//!
//! <b>Complexity</b>: Linear in x.size().
set& operator=(BOOST_COPY_ASSIGN_REF(set) x)
- { m_tree = x.m_tree; return *this; }
+ { return static_cast<set&>(this->base_t::operator=(static_cast<const base_t&>(x))); }
//! <b>Effects</b>: this->swap(x.get()).
//!
- //! <b>Complexity</b>: Constant.
+ //! <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.
set& operator=(BOOST_RV_REF(set) x)
- { m_tree = boost::move(x.m_tree); return *this; }
+ BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value)
+ { return static_cast<set&>(this->base_t::operator=(boost::move(static_cast<base_t&>(x)))); }
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ set& operator=(std::initializer_list<value_type> il)
+ {
+ this->clear();
+ insert(il.begin(), il.end());
+ return *this;
+ }
+#endif
- //! <b>Effects</b>: Returns the comparison object out
- //! of which a was constructed.
+ #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.
- key_compare key_comp() const
- { return m_tree.key_comp(); }
+ allocator_type get_allocator() const;
- //! <b>Effects</b>: Returns an object of value_compare constructed out
- //! of the comparison object.
+ //! <b>Effects</b>: Returns a reference to the internal allocator.
+ //!
+ //! <b>Throws</b>: Nothing
//!
//! <b>Complexity</b>: Constant.
- value_compare value_comp() const
- { return m_tree.key_comp(); }
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ stored_allocator_type &get_stored_allocator();
- //! <b>Effects</b>: Returns a copy of the Allocator that
- //! was passed to the object's constructor.
+ //! <b>Effects</b>: Returns a reference to the internal allocator.
+ //!
+ //! <b>Throws</b>: Nothing
//!
//! <b>Complexity</b>: Constant.
- allocator_type get_allocator() const
- { return m_tree.get_allocator(); }
-
- const stored_allocator_type &get_stored_allocator() const
- { return m_tree.get_stored_allocator(); }
-
- stored_allocator_type &get_stored_allocator()
- { return m_tree.get_stored_allocator(); }
+ //!
+ //! <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()
- { return m_tree.begin(); }
+ 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
- { return m_tree.begin(); }
+ const_iterator begin() const;
- //! <b>Effects</b>: Returns an iterator to the end of the container.
+ //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- iterator end()
- { return m_tree.end(); }
+ const_iterator cbegin() const;
- //! <b>Effects</b>: Returns a const_iterator to the end of the container.
+ //! <b>Effects</b>: Returns an iterator to the end of the container.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_iterator end() const
- { return m_tree.end(); }
+ iterator end();
- //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
- //! of the reversed container.
+ //! <b>Effects</b>: Returns a const_iterator to the end of the container.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- reverse_iterator rbegin()
- { return m_tree.rbegin(); }
+ const_iterator end() const;
- //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
- //! of the reversed container.
+ //! <b>Effects</b>: Returns a const_iterator to the end of the container.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reverse_iterator rbegin() const
- { return m_tree.rbegin(); }
+ const_iterator cend() const;
- //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
+ //! <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 rend()
- { return m_tree.rend(); }
+ reverse_iterator rbegin();
- //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the 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.
- const_reverse_iterator rend() const
- { return m_tree.rend(); }
+ const_reverse_iterator rbegin() const;
- //! <b>Effects</b>: Returns a const_iterator to the first element contained in the container.
+ //! <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_iterator cbegin() const
- { return m_tree.cbegin(); }
+ const_reverse_iterator crbegin() const;
- //! <b>Effects</b>: Returns a const_iterator to the end of the container.
+ //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
+ //! of the reversed container.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_iterator cend() const
- { return m_tree.cend(); }
+ reverse_iterator rend();
- //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
+ //! <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 crbegin() const
- { return m_tree.crbegin(); }
+ const_reverse_iterator rend() const;
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
//! of the reversed container.
@@ -304,41 +347,82 @@ class set
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reverse_iterator crend() const
- { return m_tree.crend(); }
+ 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
- { return m_tree.empty(); }
+ 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
- { return m_tree.size(); }
+ 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
- { return m_tree.max_size(); }
+ size_type max_size() const;
+ #endif // #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- //! <b>Effects</b>: Swaps the contents of *this and x.
+ #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || 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>Throws</b>: Nothing.
+ //! <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>: Constant.
- void swap(set& x)
- { m_tree.swap(x.m_tree); }
+ //! <b>Throws</b>: If memory allocation throws or
+ //! Key's in-place constructor throws.
+ //!
+ //! <b>Complexity</b>: Logarithmic.
+ template <class... Args>
+ std::pair<iterator,bool> emplace(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>
+ iterator emplace_hint(const_iterator p, Args&&... args)
+ { return this->base_t::emplace_hint_unique(p, boost::forward<Args>(args)...); }
+
+ #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
+
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
+ std::pair<iterator,bool> emplace(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
+ { return this->base_t::emplace_unique(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); }\
+ \
+ BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
+ iterator emplace_hint(const_iterator p \
+ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
+ { return this->base_t::emplace_hint_unique(p \
+ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _));} \
+ //!
+ #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
+ #include BOOST_PP_LOCAL_ITERATE()
+ #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
+
+ #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.
//!
@@ -347,18 +431,7 @@ class set
//! points to the element with key equivalent to the key of x.
//!
//! <b>Complexity</b>: Logarithmic.
- std::pair<iterator,bool> insert(insert_const_ref_type x)
- { return priv_insert(x); }
-
- #if defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- std::pair<iterator,bool> insert(T &x)
- { return this->insert(const_cast<const T &>(x)); }
-
- template<class U>
- std::pair<iterator,bool> insert(const U &u
- , typename container_detail::enable_if_c<container_detail::is_same<T, U>::value && !::boost::has_move_emulation_enabled<U>::value >::type* =0)
- { return priv_insert(u); }
- #endif
+ 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.
@@ -368,9 +441,15 @@ class set
//! points to the element with key equivalent to the key of x.
//!
//! <b>Complexity</b>: Logarithmic.
- std::pair<iterator,bool> insert(BOOST_RV_REF(value_type) x)
- { return m_tree.insert_unique(boost::move(x)); }
+ 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.
@@ -380,18 +459,7 @@ class set
//!
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
//! is inserted right before p.
- iterator insert(const_iterator p, insert_const_ref_type x)
- { return priv_insert(p, x); }
-
- #if defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- iterator insert(const_iterator position, T &x)
- { return this->insert(position, const_cast<const T &>(x)); }
-
- template<class U>
- iterator insert( const_iterator position, const U &u
- , typename container_detail::enable_if_c<container_detail::is_same<T, U>::value && !::boost::has_move_emulation_enabled<U>::value >::type* =0)
- { return priv_insert(position, u); }
- #endif
+ 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.
@@ -399,8 +467,10 @@ class set
//! <b>Returns</b>: An iterator pointing to the element with key equivalent to the key of x.
//!
//! <b>Complexity</b>: Logarithmic.
- iterator insert(const_iterator p, BOOST_RV_REF(value_type) x)
- { return m_tree.insert_unique(p, boost::move(x)); }
+ 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.
//!
@@ -410,58 +480,18 @@ class set
//! <b>Complexity</b>: At most N log(size()+N) (N is the distance from first to last)
template <class InputIterator>
void insert(InputIterator first, InputIterator last)
- { m_tree.insert_unique(first, last); }
-
- #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || 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 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
- //! T's in-place constructor throws.
- //!
- //! <b>Complexity</b>: Logarithmic.
- template <class... Args>
- std::pair<iterator,bool> emplace(Args&&... args)
- { return m_tree.emplace_unique(boost::forward<Args>(args)...); }
-
- //! <b>Effects</b>: Inserts an object of type T 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>
- iterator emplace_hint(const_iterator hint, Args&&... args)
- { return m_tree.emplace_hint_unique(hint, boost::forward<Args>(args)...); }
-
- #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
+ { this->base_t::insert_unique(first, last); }
- #define BOOST_PP_LOCAL_MACRO(n) \
- BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
- std::pair<iterator,bool> emplace(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
- { return m_tree.emplace_unique(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); } \
- \
- BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
- iterator emplace_hint(const_iterator hint \
- BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
- { return m_tree.emplace_hint_unique(hint \
- BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _));} \
+#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.
//!
- #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
- #include BOOST_PP_LOCAL_ITERATE()
+ //! <b>Complexity</b>: At most N log(size()+N) (N is the distance from il.begin() to il.end())
+ void insert(std::initializer_list<value_type> il)
+ { this->base_t::insert_unique(il.begin(), il.end()); }
+#endif
- #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! <b>Effects</b>: Erases the element pointed to by p.
//!
@@ -470,170 +500,197 @@ class set
//! returns end().
//!
//! <b>Complexity</b>: Amortized constant time
- iterator erase(const_iterator p)
- { return m_tree.erase(p); }
+ 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)
- { return m_tree.erase(x); }
+ 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)
- { return m_tree.erase(first, last); }
+ 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(set& x);
//! <b>Effects</b>: erase(a.begin(),a.end()).
//!
//! <b>Postcondition</b>: size() == 0.
//!
//! <b>Complexity</b>: linear in size().
- void clear()
- { m_tree.clear(); }
+ 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)
- { return m_tree.find(x); }
+ iterator find(const key_type& x);
- //! <b>Returns</b>: A const_iterator pointing to an element with the key
+ //! <b>Returns</b>: Allocator 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
- { return m_tree.find(x); }
+ const_iterator find(const key_type& 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)
size_type count(const key_type& x) const
- { return m_tree.find(x) == m_tree.end() ? 0 : 1; }
+ { return static_cast<size_type>(this->base_t::find(x) != this->base_t::cend()); }
+
+ //! <b>Returns</b>: The number of elements with key equivalent to x.
+ //!
+ //! <b>Complexity</b>: log(size())+count(k)
+ size_type count(const key_type& x)
+ { 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)
- { return m_tree.lower_bound(x); }
+ iterator lower_bound(const key_type& x);
- //! <b>Returns</b>: A const iterator pointing to the first element with key not
+ //! <b>Returns</b>: Allocator 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
- { return m_tree.lower_bound(x); }
+ const_iterator lower_bound(const key_type& 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)
- { return m_tree.upper_bound(x); }
+ iterator upper_bound(const key_type& x);
- //! <b>Returns</b>: A const iterator pointing to the first element with key not
+ //! <b>Returns</b>: Allocator 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
- { return m_tree.upper_bound(x); }
+ const_iterator upper_bound(const key_type& 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
- std::pair<iterator,iterator>
- equal_range(const key_type& x)
- { return m_tree.equal_range(x); }
+ std::pair<iterator,iterator> equal_range(const key_type& x)
+ { return this->base_t::lower_bound_range(x); }
//! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
//!
//! <b>Complexity</b>: Logarithmic
- std::pair<const_iterator, const_iterator>
- equal_range(const key_type& x) const
- { return m_tree.equal_range(x); }
+ std::pair<const_iterator, const_iterator> equal_range(const key_type& x) const
+ { return this->base_t::lower_bound_range(x); }
- /// @cond
- template <class K1, class C1, class A1>
- friend bool operator== (const set<K1,C1,A1>&, const set<K1,C1,A1>&);
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- template <class K1, class C1, class A1>
- friend bool operator< (const set<K1,C1,A1>&, const set<K1,C1,A1>&);
+ //! <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);
- private:
- std::pair<iterator, bool> priv_insert(const T &x)
- { return m_tree.insert_unique(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;
- iterator priv_insert(const_iterator p, const T &x)
- { return m_tree.insert_unique(p, x); }
+ //! <b>Effects</b>: Rebalances the tree. It's a no-op for Red-Black and AVL trees.
+ //!
+ //! <b>Complexity</b>: Linear
+ void rebalance();
- /// @endcond
-};
+ //! <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);
-template <class T, class Pred, class A>
-inline bool operator==(const set<T,Pred,A>& x,
- const set<T,Pred,A>& y)
-{ return x.m_tree == y.m_tree; }
+ //! <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);
-template <class T, class Pred, class A>
-inline bool operator<(const set<T,Pred,A>& x,
- const set<T,Pred,A>& y)
-{ return x.m_tree < y.m_tree; }
+ //! <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);
-template <class T, class Pred, class A>
-inline bool operator!=(const set<T,Pred,A>& x,
- const set<T,Pred,A>& y)
-{ return !(x == 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);
-template <class T, class Pred, class A>
-inline bool operator>(const set<T,Pred,A>& x,
- const set<T,Pred,A>& 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 set& x, const set& y);
-template <class T, class Pred, class A>
-inline bool operator<=(const set<T,Pred,A>& x,
- const set<T,Pred,A>& 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 set& x, const set& y);
-template <class T, class Pred, class A>
-inline bool operator>=(const set<T,Pred,A>& x,
- const set<T,Pred,A>& y)
-{ return !(x < y); }
+ //! <b>Effects</b>: x.swap(y)
+ //!
+ //! <b>Complexity</b>: Constant.
+ friend void swap(set& x, set& y);
-template <class T, class Pred, class A>
-inline void swap(set<T,Pred,A>& x, set<T,Pred,A>& y)
-{ x.swap(y); }
+ #endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ private:
+ template <class KeyType>
+ std::pair<iterator, bool> priv_insert(BOOST_FWD_REF(KeyType) x)
+ { return this->base_t::insert_unique(::boost::forward<KeyType>(x)); }
+
+ template <class KeyType>
+ iterator priv_insert(const_iterator p, BOOST_FWD_REF(KeyType) x)
+ { return this->base_t::insert_unique(p, ::boost::forward<KeyType>(x)); }
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+};
-/// @cond
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
} //namespace container {
-/*
+
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
-template <class T, class C, class A>
-struct has_trivial_destructor_after_move<boost::container::set<T, C, A> >
+template <class Key, class C, class SetOptions, class Allocator>
+struct has_trivial_destructor_after_move<boost::container::set<Key, C, Allocator, SetOptions> >
{
- static const bool value = has_trivial_destructor<A>::value && has_trivial_destructor<C>::value;
+ static const bool value = has_trivial_destructor_after_move<Allocator>::value && has_trivial_destructor_after_move<C>::value;
};
-*/
-namespace container {
-// Forward declaration of operators < and ==, needed for friend declaration.
+namespace container {
-template <class T, class Pred, class A>
-inline bool operator==(const multiset<T,Pred,A>& x,
- const multiset<T,Pred,A>& y);
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
-template <class T, class Pred, class A>
-inline bool operator<(const multiset<T,Pred,A>& x,
- const multiset<T,Pred,A>& y);
-/// @endcond
+#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
@@ -642,70 +699,81 @@ inline bool operator<(const multiset<T,Pred,A>& x,
//! 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.
-#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
-template <class T, class Pred = std::less<T>, class A = std::allocator<T> >
+//!
+//! \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 MultiSetOptions is an packed option type generated using using boost::container::tree_assoc_options.
+template <class Key, class Compare = std::less<Key>, class Allocator = std::allocator<Key>, class MultiSetOptions = tree_assoc_defaults >
#else
-template <class T, class Pred, class A>
+template <class Key, class Compare, class Allocator, class MultiSetOptions>
#endif
class multiset
-{
/// @cond
+ : public container_detail::tree
+ <Key, Key,container_detail::identity<Key>, Compare, Allocator, MultiSetOptions>
+ /// @endcond
+{
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
BOOST_COPYABLE_AND_MOVABLE(multiset)
- typedef container_detail::rbtree<T, T,
- container_detail::identity<T>, Pred, A> tree_t;
- tree_t m_tree; // red-black tree representing multiset
- typedef typename container_detail::
- move_const_ref_type<T>::type insert_const_ref_type;
- /// @endcond
+ typedef container_detail::tree
+ <Key, Key,container_detail::identity<Key>, Compare, Allocator, MultiSetOptions> base_t;
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public:
- // typedefs:
- typedef typename tree_t::key_type key_type;
- typedef typename tree_t::value_type value_type;
- typedef typename tree_t::pointer pointer;
- typedef typename tree_t::const_pointer const_pointer;
- typedef typename tree_t::reference reference;
- typedef typename tree_t::const_reference const_reference;
- typedef Pred key_compare;
- typedef Pred value_compare;
- typedef typename tree_t::iterator iterator;
- typedef typename tree_t::const_iterator const_iterator;
- typedef typename tree_t::reverse_iterator reverse_iterator;
- typedef typename tree_t::const_reverse_iterator const_reverse_iterator;
- typedef typename tree_t::size_type size_type;
- typedef typename tree_t::difference_type difference_type;
- typedef typename tree_t::allocator_type allocator_type;
- typedef typename tree_t::stored_allocator_type stored_allocator_type;
-
- //! <b>Effects</b>: Constructs an empty multiset using the specified comparison
- //! object and allocator.
- //!
- //! <b>Complexity</b>: Constant.
+ //////////////////////////////////////////////
+ //
+ // 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;
+
+ //////////////////////////////////////////////
+ //
+ // construct/copy/destroy
+ //
+ //////////////////////////////////////////////
+
+ //! @copydoc ::boost::container::set::set()
multiset()
- : m_tree()
+ : base_t()
{}
- //! <b>Effects</b>: Constructs an empty multiset using the specified comparison
- //! object and allocator.
- //!
- //! <b>Complexity</b>: Constant.
- explicit multiset(const Pred& comp,
+ //! @copydoc ::boost::container::set::set(const Compare&, const allocator_type&)
+ explicit multiset(const Compare& comp,
const allocator_type& a = allocator_type())
- : m_tree(comp, a)
+ : base_t(comp, a)
{}
- //! <b>Effects</b>: Constructs an empty multiset 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.
+ //! @copydoc ::boost::container::set::set(const allocator_type&)
+ explicit multiset(const allocator_type& a)
+ : base_t(a)
+ {}
+
+ //! @copydoc ::boost::container::set::set(InputIterator, InputIterator, const Compare& comp, const allocator_type&)
template <class InputIterator>
multiset(InputIterator first, InputIterator last,
- const Pred& comp = Pred(),
+ const Compare& comp = Compare(),
const allocator_type& a = allocator_type())
- : m_tree(first, last, comp, a, false)
+ : base_t(false, first, last, comp, a)
{}
//! <b>Effects</b>: Constructs an empty multiset using the specified comparison object and
@@ -715,235 +783,170 @@ class multiset
//! <b>Requires</b>: [first ,last) must be ordered according to the predicate.
//!
//! <b>Complexity</b>: Linear in N.
+ //!
+ //! <b>Note</b>: Non-standard extension.
template <class InputIterator>
- multiset( ordered_range_t ordered_range, InputIterator first, InputIterator last
- , const Pred& comp = Pred()
+ multiset( ordered_range_t, InputIterator first, InputIterator last
+ , const Compare& comp = Compare()
, const allocator_type& a = allocator_type())
- : m_tree(ordered_range, first, last, comp, a)
+ : base_t(ordered_range, first, last, comp, a)
{}
- //! <b>Effects</b>: Copy constructs a multiset.
- //!
- //! <b>Complexity</b>: Linear in x.size().
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! @copydoc ::boost::container::set::set(std::initializer_list<value_type>, const Compare& comp, const allocator_type&)
+ multiset(std::initializer_list<value_type> il, const Compare& comp = Compare(), const allocator_type& a = allocator_type())
+ : base_t(false, il.begin(), il.end(), comp, a)
+ {}
+
+ //! @copydoc ::boost::container::set::set(ordered_unique_range_t, std::initializer_list<value_type>, const Compare& comp, const allocator_type&)
+ multiset(ordered_unique_range_t, std::initializer_list<value_type> il, const Compare& comp = Compare(), const allocator_type& a = allocator_type())
+ : base_t(ordered_range, il.begin(), il.end(), comp, a)
+ {}
+#endif
+
+
+ //! @copydoc ::boost::container::set::set(const set &)
multiset(const multiset& x)
- : m_tree(x.m_tree)
+ : base_t(static_cast<const base_t&>(x))
{}
- //! <b>Effects</b>: Move constructs a multiset. Constructs *this using x's resources.
- //!
- //! <b>Complexity</b>: Constant.
- //!
- //! <b>Postcondition</b>: x is emptied.
+ //! @copydoc ::boost::container::set(set &&)
multiset(BOOST_RV_REF(multiset) x)
- : m_tree(boost::move(x.m_tree))
+ : base_t(boost::move(static_cast<base_t&>(x)))
{}
- //! <b>Effects</b>: Copy constructs a multiset using the specified allocator.
- //!
- //! <b>Complexity</b>: Linear in x.size().
+ //! @copydoc ::boost::container::set(const set &, const allocator_type &)
multiset(const multiset& x, const allocator_type &a)
- : m_tree(x.m_tree, a)
+ : base_t(static_cast<const base_t&>(x), a)
{}
- //! <b>Effects</b>: Move constructs a multiset 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.
+ //! @copydoc ::boost::container::set(set &&, const allocator_type &)
multiset(BOOST_RV_REF(multiset) x, const allocator_type &a)
- : m_tree(boost::move(x.m_tree), a)
+ : base_t(boost::move(static_cast<base_t&>(x)), a)
{}
- //! <b>Effects</b>: Makes *this a copy of x.
- //!
- //! <b>Complexity</b>: Linear in x.size().
+ //! @copydoc ::boost::container::set::operator=(const set &)
multiset& operator=(BOOST_COPY_ASSIGN_REF(multiset) x)
- { m_tree = x.m_tree; return *this; }
+ { return static_cast<multiset&>(this->base_t::operator=(static_cast<const base_t&>(x))); }
- //! <b>Effects</b>: this->swap(x.get()).
- //!
- //! <b>Complexity</b>: Constant.
+ //! @copydoc ::boost::container::set::operator=(set &&)
multiset& operator=(BOOST_RV_REF(multiset) x)
- { m_tree = boost::move(x.m_tree); return *this; }
+ { return static_cast<multiset&>(this->base_t::operator=(boost::move(static_cast<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)
- //! <b>Effects</b>: Returns the comparison object out
- //! of which a was constructed.
- //!
- //! <b>Complexity</b>: Constant.
- key_compare key_comp() const
- { return m_tree.key_comp(); }
+ //! @copydoc ::boost::container::set::get_allocator()
+ allocator_type get_allocator() 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
- { return m_tree.key_comp(); }
+ //! @copydoc ::boost::container::set::get_stored_allocator()
+ stored_allocator_type &get_stored_allocator();
- //! <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
- { return m_tree.get_allocator(); }
+ //! @copydoc ::boost::container::set::get_stored_allocator() const
+ const stored_allocator_type &get_stored_allocator() const;
- const stored_allocator_type &get_stored_allocator() const
- { return m_tree.get_stored_allocator(); }
+ //! @copydoc ::boost::container::set::begin()
+ iterator begin();
- stored_allocator_type &get_stored_allocator()
- { return m_tree.get_stored_allocator(); }
+ //! @copydoc ::boost::container::set::begin() const
+ const_iterator begin() 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()
- { return m_tree.begin(); }
+ //! @copydoc ::boost::container::set::cbegin() const
+ const_iterator cbegin() 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 begin() const
- { return m_tree.begin(); }
+ //! @copydoc ::boost::container::set::end()
+ iterator end() BOOST_CONTAINER_NOEXCEPT;
- //! <b>Effects</b>: Returns an iterator to the end of the container.
- //!
- //! <b>Throws</b>: Nothing.
- //!
- //! <b>Complexity</b>: Constant.
- iterator end()
- { return m_tree.end(); }
+ //! @copydoc ::boost::container::set::end() const
+ const_iterator end() const BOOST_CONTAINER_NOEXCEPT;
- //! <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
- { return m_tree.end(); }
+ //! @copydoc ::boost::container::set::cend() const
+ const_iterator cend() const BOOST_CONTAINER_NOEXCEPT;
- //! <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()
- { return m_tree.rbegin(); }
+ //! @copydoc ::boost::container::set::rbegin()
+ reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT;
- //! <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
- { return m_tree.rbegin(); }
+ //! @copydoc ::boost::container::set::rbegin() const
+ const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT;
- //! <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()
- { return m_tree.rend(); }
+ //! @copydoc ::boost::container::set::crbegin() const
+ const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT;
- //! <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
- { return m_tree.rend(); }
+ //! @copydoc ::boost::container::set::rend()
+ reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT;
- //! <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
- { return m_tree.cbegin(); }
+ //! @copydoc ::boost::container::set::rend() const
+ const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT;
- //! <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
- { return m_tree.cend(); }
+ //! @copydoc ::boost::container::set::crend() const
+ const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT;
- //! <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
- { return m_tree.crbegin(); }
+ //! @copydoc ::boost::container::set::empty() const
+ bool empty() 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
- { return m_tree.crend(); }
+ //! @copydoc ::boost::container::set::size() const
+ size_type size() const;
- //! <b>Effects</b>: Returns true if the container contains no elements.
- //!
- //! <b>Throws</b>: Nothing.
- //!
- //! <b>Complexity</b>: Constant.
- bool empty() const
- { return m_tree.empty(); }
+ //! @copydoc ::boost::container::set::max_size() const
+ size_type max_size() const;
- //! <b>Effects</b>: Returns the number of the elements contained in the container.
- //!
- //! <b>Throws</b>: Nothing.
+ #endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || 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>: Constant.
- size_type size() const
- { return m_tree.size(); }
+ //! <b>Complexity</b>: Logarithmic.
+ template <class... Args>
+ iterator emplace(Args&&... args)
+ { return this->base_t::emplace_equal(boost::forward<Args>(args)...); }
- //! <b>Effects</b>: Returns the largest possible size of the container.
+ //! <b>Effects</b>: Inserts an object of type Key constructed with
+ //! std::forward<Args>(args)...
//!
- //! <b>Throws</b>: Nothing.
+ //! <b>Returns</b>: An iterator pointing to the element with key equivalent
+ //! to the key of x.
//!
- //! <b>Complexity</b>: Constant.
- size_type max_size() const
- { return m_tree.max_size(); }
+ //! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
+ //! is inserted right before p.
+ template <class... Args>
+ iterator emplace_hint(const_iterator p, Args&&... args)
+ { return this->base_t::emplace_hint_equal(p, boost::forward<Args>(args)...); }
- //! <b>Effects</b>: Swaps the contents of *this and x.
- //!
- //! <b>Throws</b>: Nothing.
+ #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
+
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
+ iterator emplace(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
+ { return this->base_t::emplace_equal(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); } \
+ \
+ BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
+ iterator emplace_hint(const_iterator p \
+ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
+ { return this->base_t::emplace_hint_equal(p \
+ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _));} \
//!
- //! <b>Complexity</b>: Constant.
- void swap(multiset& x)
- { m_tree.swap(x.m_tree); }
+ #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
+ #include BOOST_PP_LOCAL_ITERATE()
+ #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
+
+ #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(insert_const_ref_type x)
- { return priv_insert(x); }
-
- #if defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- iterator insert(T &x)
- { return this->insert(const_cast<const T &>(x)); }
-
- template<class U>
- iterator insert(const U &u
- , typename container_detail::enable_if_c<container_detail::is_same<T, U>::value && !::boost::has_move_emulation_enabled<U>::value >::type* =0)
- { return priv_insert(u); }
- #endif
+ iterator insert(const value_type &x);
//! <b>Effects</b>: Inserts a copy of x in the container.
//!
@@ -952,9 +955,12 @@ class multiset
//!
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
//! is inserted right before p.
- iterator insert(BOOST_RV_REF(value_type) x)
- { return m_tree.insert_equal(boost::move(x)); }
+ 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.
//!
@@ -963,18 +969,7 @@ class multiset
//!
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
//! is inserted right before p.
- iterator insert(const_iterator p, insert_const_ref_type x)
- { return priv_insert(p, x); }
-
- #if defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- iterator insert(const_iterator position, T &x)
- { return this->insert(position, const_cast<const T &>(x)); }
-
- template<class U>
- iterator insert( const_iterator position, const U &u
- , typename container_detail::enable_if_c<container_detail::is_same<T, U>::value && !::boost::has_move_emulation_enabled<U>::value >::type* =0)
- { return priv_insert(position, u); }
- #endif
+ 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.
@@ -984,8 +979,10 @@ class multiset
//!
//! <b>Complexity</b>: Logarithmic in general, but amortized constant if t
//! is inserted right before p.
- iterator insert(const_iterator p, BOOST_RV_REF(value_type) x)
- { return m_tree.insert_equal(p, boost::move(x)); }
+ 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.
//!
@@ -994,211 +991,132 @@ class multiset
//! <b>Complexity</b>: At most N log(size()+N) (N is the distance from first to last)
template <class InputIterator>
void insert(InputIterator first, InputIterator last)
- { m_tree.insert_equal(first, last); }
+ { this->base_t::insert_equal(first, last); }
- #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! @copydoc ::boost::container::set::insert(std::initializer_list<value_type>)
+ void insert(std::initializer_list<value_type> il)
+ { this->base_t::insert_unique(il.begin(), il.end()); }
+#endif
- //! <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.
- template <class... Args>
- iterator emplace(Args&&... args)
- { return m_tree.emplace_equal(boost::forward<Args>(args)...); }
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- //! <b>Effects</b>: Inserts an object of type T 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>
- iterator emplace_hint(const_iterator hint, Args&&... args)
- { return m_tree.emplace_hint_equal(hint, boost::forward<Args>(args)...); }
+ //! @copydoc ::boost::container::set::erase(const_iterator)
+ iterator erase(const_iterator p);
- #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
+ //! @copydoc ::boost::container::set::erase(const key_type&)
+ size_type erase(const key_type& x);
- #define BOOST_PP_LOCAL_MACRO(n) \
- BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
- iterator emplace(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
- { return m_tree.emplace_equal(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); } \
- \
- BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
- iterator emplace_hint(const_iterator hint \
- BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
- { return m_tree.emplace_hint_equal(hint \
- BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _));} \
- //!
- #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
- #include BOOST_PP_LOCAL_ITERATE()
+ //! @copydoc ::boost::container::set::erase(const_iterator,const_iterator)
+ iterator erase(const_iterator first, const_iterator last);
- #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
+ //! @copydoc ::boost::container::set::swap
+ void swap(flat_multiset& x);
- //! <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)
- { return m_tree.erase(p); }
+ //! @copydoc ::boost::container::set::clear
+ void clear() BOOST_CONTAINER_NOEXCEPT;
- //! <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)
- { return m_tree.erase(x); }
+ //! @copydoc ::boost::container::set::key_comp
+ key_compare key_comp() const;
- //! <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)
- { return m_tree.erase(first, last); }
+ //! @copydoc ::boost::container::set::value_comp
+ value_compare value_comp() const;
- //! <b>Effects</b>: erase(a.begin(),a.end()).
- //!
- //! <b>Postcondition</b>: size() == 0.
- //!
- //! <b>Complexity</b>: linear in size().
- void clear()
- { m_tree.clear(); }
+ //! @copydoc ::boost::container::set::find(const key_type& )
+ iterator find(const key_type& x);
- //! <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)
- { return m_tree.find(x); }
+ //! @copydoc ::boost::container::set::find(const key_type& ) const
+ const_iterator find(const key_type& x) const;
- //! <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
- { return m_tree.find(x); }
+ //! @copydoc ::boost::container::set::count(const key_type& ) const
+ size_type count(const key_type& x) const;
- //! <b>Returns</b>: The number of elements with key equivalent to x.
+ //! @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::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::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::rebalance()
+ void rebalance();
+
+ //! <b>Effects</b>: Returns true if x and y are equal
//!
- //! <b>Complexity</b>: log(size())+count(k)
- size_type count(const key_type& x) const
- { return m_tree.count(x); }
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator==(const multiset& x, const multiset& y);
- //! <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>Effects</b>: Returns true if x and y are unequal
//!
- //! <b>Complexity</b>: Logarithmic
- iterator lower_bound(const key_type& x)
- { return m_tree.lower_bound(x); }
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator!=(const multiset& x, const multiset& y);
- //! <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>Effects</b>: Returns true if x is less than y
//!
- //! <b>Complexity</b>: Logarithmic
- const_iterator lower_bound(const key_type& x) const
- { return m_tree.lower_bound(x); }
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator<(const multiset& x, const multiset& y);
- //! <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>Effects</b>: Returns true if x is greater than y
//!
- //! <b>Complexity</b>: Logarithmic
- iterator upper_bound(const key_type& x)
- { return m_tree.upper_bound(x); }
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator>(const multiset& x, const multiset& y);
- //! <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>Effects</b>: Returns true if x is equal or less than y
//!
- //! <b>Complexity</b>: Logarithmic
- const_iterator upper_bound(const key_type& x) const
- { return m_tree.upper_bound(x); }
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator<=(const multiset& x, const multiset& y);
- //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
+ //! <b>Effects</b>: Returns true if x is equal or greater than y
//!
- //! <b>Complexity</b>: Logarithmic
- std::pair<iterator,iterator>
- equal_range(const key_type& x)
- { return m_tree.equal_range(x); }
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator>=(const multiset& x, const multiset& y);
- //! <b>Effects</b>: Equivalent to std::make_pair(this->lower_bound(k), this->upper_bound(k)).
+ //! <b>Effects</b>: x.swap(y)
//!
- //! <b>Complexity</b>: Logarithmic
- std::pair<const_iterator, const_iterator>
- equal_range(const key_type& x) const
- { return m_tree.equal_range(x); }
+ //! <b>Complexity</b>: Constant.
+ friend void swap(multiset& x, multiset& y);
- /// @cond
- template <class K1, class C1, class A1>
- friend bool operator== (const multiset<K1,C1,A1>&,
- const multiset<K1,C1,A1>&);
- template <class K1, class C1, class A1>
- friend bool operator< (const multiset<K1,C1,A1>&,
- const multiset<K1,C1,A1>&);
+ #endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
- iterator priv_insert(const T &x)
- { return m_tree.insert_equal(x); }
+ template <class KeyType>
+ iterator priv_insert(BOOST_FWD_REF(KeyType) x)
+ { return this->base_t::insert_equal(::boost::forward<KeyType>(x)); }
- iterator priv_insert(const_iterator p, const T &x)
- { return m_tree.insert_equal(p, x); }
+ template <class KeyType>
+ iterator priv_insert(const_iterator p, BOOST_FWD_REF(KeyType) x)
+ { return this->base_t::insert_equal(p, ::boost::forward<KeyType>(x)); }
- /// @endcond
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
};
-template <class T, class Pred, class A>
-inline bool operator==(const multiset<T,Pred,A>& x,
- const multiset<T,Pred,A>& y)
-{ return x.m_tree == y.m_tree; }
-
-template <class T, class Pred, class A>
-inline bool operator<(const multiset<T,Pred,A>& x,
- const multiset<T,Pred,A>& y)
-{ return x.m_tree < y.m_tree; }
-
-template <class T, class Pred, class A>
-inline bool operator!=(const multiset<T,Pred,A>& x,
- const multiset<T,Pred,A>& y)
-{ return !(x == y); }
-
-template <class T, class Pred, class A>
-inline bool operator>(const multiset<T,Pred,A>& x,
- const multiset<T,Pred,A>& y)
-{ return y < x; }
-
-template <class T, class Pred, class A>
-inline bool operator<=(const multiset<T,Pred,A>& x,
- const multiset<T,Pred,A>& y)
-{ return !(y < x); }
-
-template <class T, class Pred, class A>
-inline bool operator>=(const multiset<T,Pred,A>& x,
- const multiset<T,Pred,A>& y)
-{ return !(x < y); }
-
-template <class T, class Pred, class A>
-inline void swap(multiset<T,Pred,A>& x, multiset<T,Pred,A>& y)
-{ x.swap(y); }
-
-/// @cond
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
} //namespace container {
-/*
+
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
-template <class T, class C, class A>
-struct has_trivial_destructor_after_move<boost::container::multiset<T, C, A> >
+template <class Key, class C, class Allocator, class MultiSetOptions>
+struct has_trivial_destructor_after_move<boost::container::multiset<Key, C, Allocator, MultiSetOptions> >
{
- static const bool value = has_trivial_destructor<A>::value && has_trivial_destructor<C>::value;
+ static const bool value = has_trivial_destructor_after_move<Allocator>::value && has_trivial_destructor_after_move<C>::value;
};
-*/
+
namespace container {
-/// @endcond
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
}}
diff --git a/boost/container/slist.hpp b/boost/container/slist.hpp
index 57719357fc..b6b4c388a2 100644
--- a/boost/container/slist.hpp
+++ b/boost/container/slist.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2004-2012. Distributed under the Boost
+// (C) Copyright Ion Gaztanaga 2004-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)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_CONTAINER_SLIST_HPP
#define BOOST_CONTAINER_SLIST_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -19,14 +19,19 @@
#include <boost/container/detail/workaround.hpp>
#include <boost/container/container_fwd.hpp>
-#include <boost/move/move.hpp>
+#include <boost/container/throw_exception.hpp>
+#include <boost/move/utility_core.hpp>
+#include <boost/move/detail/move_helpers.hpp>
+#include <boost/move/traits.hpp>
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/container/detail/utilities.hpp>
+#include <boost/container/detail/iterators.hpp>
#include <boost/container/detail/mpl.hpp>
-#include <boost/type_traits/has_trivial_destructor.hpp>
-#include <boost/detail/no_exceptions_support.hpp>
+#include <boost/container/detail/type_traits.hpp>
+#include <boost/core/no_exceptions_support.hpp>
#include <boost/container/detail/node_alloc_holder.hpp>
#include <boost/intrusive/slist.hpp>
+#include <iterator>
#if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
@@ -35,22 +40,24 @@
#include <boost/container/detail/preprocessor.hpp>
#endif
-#include <stdexcept>
#include <iterator>
#include <utility>
#include <memory>
#include <functional>
#include <algorithm>
-#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
-namespace boost {
-namespace container {
-#else
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+#include <initializer_list>
+#endif
+
+
namespace boost {
namespace container {
-#endif
-/// @cond
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+template <class T, class Allocator>
+class slist;
namespace container_detail {
@@ -69,14 +76,27 @@ struct slist_node
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 A>
+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<A> allocator_traits_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
@@ -97,7 +117,7 @@ struct intrusive_slist_type
} //namespace container_detail {
-/// @endcond
+#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
@@ -131,23 +151,23 @@ struct intrusive_slist_type
//! 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 A = std::allocator<T> >
+template <class T, class Allocator = std::allocator<T> >
#else
-template <class T, class A>
+template <class T, class Allocator>
#endif
class slist
: protected container_detail::node_alloc_holder
- <A, typename container_detail::intrusive_slist_type<A>::type>
+ <Allocator, typename container_detail::intrusive_slist_type<Allocator>::type>
{
- /// @cond
- typedef typename container_detail::
- move_const_ref_type<T>::type insert_const_ref_type;
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
typedef typename
- container_detail::intrusive_slist_type<A>::type Icont;
- typedef container_detail::node_alloc_holder<A, Icont> AllocHolder;
+ container_detail::intrusive_slist_type<Allocator>::type Icont;
+ typedef container_detail::node_alloc_holder<Allocator, Icont> AllocHolder;
typedef typename AllocHolder::NodePtr NodePtr;
- typedef slist <T, A> ThisType;
typedef typename AllocHolder::NodeAlloc NodeAlloc;
typedef typename AllocHolder::ValAlloc ValAlloc;
typedef typename AllocHolder::Node Node;
@@ -155,7 +175,7 @@ class slist
typedef typename AllocHolder::allocator_v1 allocator_v1;
typedef typename AllocHolder::allocator_v2 allocator_v2;
typedef typename AllocHolder::alloc_version alloc_version;
- typedef boost::container::allocator_traits<A> allocator_traits_type;
+ typedef boost::container::allocator_traits<Allocator> allocator_traits_type;
class equal_to_value
{
@@ -185,126 +205,39 @@ class slist
bool operator()(const Node &a) const
{ return static_cast<const Pred&>(*this)(a.m_data); }
};
- /// @endcond
- public:
- //! The type of object, T, stored in the list
- typedef T value_type;
- //! Pointer to T
- typedef typename allocator_traits_type::pointer pointer;
- //! Const pointer to T
- typedef typename allocator_traits_type::const_pointer const_pointer;
- //! Reference to T
- typedef typename allocator_traits_type::reference reference;
- //! Const reference to T
- typedef typename allocator_traits_type::const_reference const_reference;
- //! An unsigned integral type
- typedef typename allocator_traits_type::size_type size_type;
- //! A signed integral type
- typedef typename allocator_traits_type::difference_type difference_type;
- //! The allocator type
- typedef A allocator_type;
- //! Non-standard extension: the stored allocator type
- typedef NodeAlloc stored_allocator_type;
-
- /// @cond
- private:
+
BOOST_COPYABLE_AND_MOVABLE(slist)
- typedef difference_type list_difference_type;
- typedef pointer list_pointer;
- typedef const_pointer list_const_pointer;
- typedef reference list_reference;
- typedef const_reference list_const_reference;
- /// @endcond
+ typedef container_detail::iterator<typename Icont::iterator, false> iterator_impl;
+ typedef container_detail::iterator<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;
- //! Const iterator used to iterate through a list.
- class const_iterator
- /// @cond
- : public std::iterator<std::forward_iterator_tag,
- value_type, list_difference_type,
- list_const_pointer, list_const_reference>
- {
-
- protected:
- typename Icont::iterator m_it;
- explicit const_iterator(typename Icont::iterator it) : m_it(it){}
- void prot_incr(){ ++m_it; }
-
- private:
- typename Icont::iterator get()
- { return this->m_it; }
-
- public:
- friend class slist<T, A>;
- typedef list_difference_type difference_type;
-
- //Constructors
- const_iterator()
- : m_it()
- {}
-
- //Pointer like operators
- const_reference operator*() const
- { return m_it->m_data; }
-
- const_pointer operator->() const
- { return const_pointer(&m_it->m_data); }
-
- //Increment / Decrement
- const_iterator& operator++()
- { prot_incr(); return *this; }
-
- const_iterator operator++(int)
- { typename Icont::iterator tmp = m_it; ++*this; return const_iterator(tmp); }
-
- //Comparison operators
- bool operator== (const const_iterator& r) const
- { return m_it == r.m_it; }
-
- bool operator!= (const const_iterator& r) const
- { return m_it != r.m_it; }
- }
- /// @endcond
- ;
-
- //! Iterator used to iterate through a list
- class iterator
- /// @cond
- : public const_iterator
- {
-
- private:
- explicit iterator(typename Icont::iterator it)
- : const_iterator(it)
- {}
-
- typename Icont::iterator get()
- { return this->m_it; }
-
- public:
- friend class slist<T, A>;
- typedef list_pointer pointer;
- typedef list_reference reference;
-
- //Constructors
- iterator(){}
-
- //Pointer like operators
- reference operator*() const { return this->m_it->m_data; }
- pointer operator->() const { return pointer(&this->m_it->m_data); }
-
- //Increment / Decrement
- iterator& operator++()
- { this->prot_incr(); return *this; }
+ public:
- iterator operator++(int)
- { typename Icont::iterator tmp = this->m_it; ++*this; return iterator(tmp); }
- }
- /// @endcond
- ;
+ //////////////////////////////////////////////
+ //
+ // construct/copy/destroy
+ //
+ //////////////////////////////////////////////
- public:
//! <b>Effects</b>: Constructs a list taking the allocator as parameter.
//!
//! <b>Throws</b>: If allocator_type's copy constructor throws.
@@ -316,10 +249,10 @@ class slist
//! <b>Effects</b>: Constructs a list taking the allocator as parameter.
//!
- //! <b>Throws</b>: If allocator_type's copy constructor throws.
+ //! <b>Throws</b>: Nothing
//!
//! <b>Complexity</b>: Constant.
- explicit slist(const allocator_type& a)
+ explicit slist(const allocator_type& a) BOOST_CONTAINER_NOEXCEPT
: AllocHolder(a)
{}
@@ -330,37 +263,49 @@ class slist
//! <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 or copy constructor
+ //! <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->priv_create_and_insert_nodes(this->before_begin(), n, x); }
+ { 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 or copy constructor
- //! throws or T's constructor taking an dereferenced InIt throws.
+ //! <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())
+ slist(InpIt first, InpIt last, const allocator_type& a = allocator_type())
: AllocHolder(a)
- { this->insert_after(this->before_begin(), first, last); }
+ { this->insert_after(this->cbefore_begin(), first, last); }
- //! <b>Effects</b>: Copy constructs a list.
+#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 or copy constructor throws.
+ //! <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->before_begin(), x.begin(), x.end()); }
+ { this->insert_after(this->cbefore_begin(), x.begin(), x.end()); }
//! <b>Effects</b>: Move constructor. Moves mx's resources to *this.
//!
@@ -375,12 +320,12 @@ class slist
//!
//! <b>Postcondition</b>: x == *this.
//!
- //! <b>Throws</b>: If allocator_type's default constructor or copy constructor throws.
+ //! <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->before_begin(), x.begin(), x.end()); }
+ { 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.
@@ -395,10 +340,19 @@ class slist
this->icont().swap(x.icont());
}
else{
- this->insert(this->cbegin(), x.begin(), x.end());
+ this->insert_after(this->cbefore_begin(), x.begin(), 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_CONTAINER_NOEXCEPT
+ {} //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
@@ -428,85 +382,168 @@ class slist
//! <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>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>: Linear to the number of elements in x.
+ //! <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_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value)
{
- if (&x != this){
- NodeAlloc &this_alloc = this->node_alloc();
- NodeAlloc &x_alloc = x.node_alloc();
- //If allocators a re equal we can just swap pointers
- if(this_alloc == x_alloc){
- //Destroy and swap pointers
- this->clear();
- this->icont() = boost::move(x.icont());
- //Move allocator if needed
- this->AllocHolder::move_assign_alloc(x);
- }
- //If unequal allocators, then do a one by one move
- else{
- typedef typename std::iterator_traits<iterator>::iterator_category ItCat;
- this->assign( boost::make_move_iterator(x.begin())
- , boost::make_move_iterator(x.end()));
- }
+ 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;
}
- //! <b>Effects</b>: Destroys the list. All stored values are destroyed
- //! and used memory is deallocated.
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Makes *this contain the same elements as in il.
//!
- //! <b>Throws</b>: Nothing.
+ //! <b>Postcondition</b>: this->size() == il.size(). *this contains a copy
+ //! of each of il's elements.
//!
- //! <b>Complexity</b>: Linear to the number of elements.
- ~slist()
- {} //AllocHolder clears the slist
+ //! <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 container_detail::enable_if_c
+ < !container_detail::is_convertible<InpIt, size_type>::value
+ >::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
+ allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT
{ return allocator_type(this->node_alloc()); }
- const stored_allocator_type &get_stored_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_CONTAINER_NOEXCEPT
{ return this->node_alloc(); }
- 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 BOOST_CONTAINER_NOEXCEPT
{ return this->node_alloc(); }
- public:
+ //////////////////////////////////////////////
+ //
+ // iterators
+ //
+ //////////////////////////////////////////////
- //! <b>Effects</b>: Assigns the n copies of val to *this.
+ //! <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>: If memory allocation throws or T's copy constructor throws.
+ //! <b>Throws</b>: Nothing.
//!
- //! <b>Complexity</b>: Linear to n.
- void assign(size_type n, const T& val)
- { this->priv_fill_assign(n, val); }
+ //! <b>Complexity</b>: Constant.
+ iterator before_begin() BOOST_CONTAINER_NOEXCEPT
+ { return iterator(end()); }
- //! <b>Effects</b>: Assigns the range [first, last) to *this.
+ //! <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>: If memory allocation throws or
- //! T's constructor from dereferencing InpIt throws.
+ //! <b>Throws</b>: Nothing.
//!
- //! <b>Complexity</b>: Linear to n.
- template <class InpIt>
- void assign(InpIt first, InpIt last)
- {
- const bool aux_boolean = container_detail::is_convertible<InpIt, size_type>::value;
- typedef container_detail::bool_<aux_boolean> Result;
- this->priv_assign_dispatch(first, last, Result());
- }
+ //! <b>Complexity</b>: Constant.
+ const_iterator before_begin() const BOOST_CONTAINER_NOEXCEPT
+ { 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()
+ iterator begin() BOOST_CONTAINER_NOEXCEPT
{ return iterator(this->icont().begin()); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the list.
@@ -514,7 +551,7 @@ class slist
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_iterator begin() const
+ const_iterator begin() const BOOST_CONTAINER_NOEXCEPT
{ return this->cbegin(); }
//! <b>Effects</b>: Returns an iterator to the end of the list.
@@ -522,7 +559,7 @@ class slist
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- iterator end()
+ iterator end() BOOST_CONTAINER_NOEXCEPT
{ return iterator(this->icont().end()); }
//! <b>Effects</b>: Returns a const_iterator to the end of the list.
@@ -530,35 +567,25 @@ class slist
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_iterator end() const
+ const_iterator end() const BOOST_CONTAINER_NOEXCEPT
{ return this->cend(); }
- //! <b>Effects</b>: Returns a non-dereferenceable iterator that,
- //! when incremented, yields begin(). This iterator may be used
- //! as the argument toinsert_after, erase_after, etc.
- //!
- //! <b>Throws</b>: Nothing.
- //!
- //! <b>Complexity</b>: Constant.
- iterator before_begin()
- { 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 toinsert_after, erase_after, etc.
+ //! as the argument to insert_after, erase_after, etc.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_iterator before_begin() const
- { return this->cbefore_begin(); }
+ const_iterator cbefore_begin() const BOOST_CONTAINER_NOEXCEPT
+ { 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
+ const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT
{ return const_iterator(this->non_const_icont().begin()); }
//! <b>Effects</b>: Returns a const_iterator to the end of the list.
@@ -566,18 +593,46 @@ class slist
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_iterator cend() const
+ const_iterator cend() const BOOST_CONTAINER_NOEXCEPT
{ return const_iterator(this->non_const_icont().end()); }
- //! <b>Effects</b>: Returns a non-dereferenceable const_iterator
- //! that, when incremented, yields begin(). This iterator may be used
- //! as the argument toinsert_after, erase_after, etc.
+ //! <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_CONTAINER_NOEXCEPT
+ { 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.
- const_iterator cbefore_begin() const
- { return const_iterator(end()); }
+ bool empty() const
+ { return !this->size(); }
//! <b>Effects</b>: Returns the number of the elements contained in the list.
//!
@@ -595,21 +650,40 @@ class slist
size_type max_size() const
{ return AllocHolder::max_size(); }
- //! <b>Effects</b>: Returns true if the list contains no elements.
+ //! <b>Effects</b>: Inserts or erases elements at the end such that
+ //! the size becomes n. New elements are value initialized.
//!
- //! <b>Throws</b>: Nothing.
+ //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
//!
- //! <b>Complexity</b>: Constant.
- bool empty() const
- { return !this->size(); }
+ //! <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>: Swaps the contents of *this and x.
+ //! <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>: Nothing.
+ //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
//!
- //! <b>Complexity</b>: Linear to the number of elements on *this and x.
- void swap(slist& x)
- { AllocHolder::swap(x); }
+ //! <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()
//!
@@ -633,65 +707,88 @@ class slist
const_reference front() const
{ return *this->begin(); }
- //! <b>Effects</b>: Inserts a copy of t in the beginning of the list.
+ //////////////////////////////////////////////
+ //
+ // modifiers
+ //
+ //////////////////////////////////////////////
+
+ #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... in the front 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(insert_const_ref_type x)
- { return priv_push_front(x); }
+ template <class... Args>
+ void emplace_front(Args&&... args)
+ { this->emplace_after(this->cbefore_begin(), boost::forward<Args>(args)...); }
- #if defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- void push_front(T &x) { push_front(const_cast<const T &>(x)); }
+ //! <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, Args&&... args)
+ {
+ NodePtr pnode(AllocHolder::create_node(boost::forward<Args>(args)...));
+ return iterator(this->icont().insert_after(prev.get(), *pnode));
+ }
- template<class U>
- void push_front(const U &u
- , typename container_detail::enable_if_c<container_detail::is_same<T, U>::value && !::boost::has_move_emulation_enabled<U>::value >::type* =0)
- { return priv_push_front(u); }
- #endif
+ #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
- //! <b>Effects</b>: Constructs a new element in the beginning of the list
- //! and moves the resources of t to this new element.
- //!
- //! <b>Throws</b>: If memory allocation throws.
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
+ void emplace_front(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
+ { \
+ this->emplace(this->cbegin() \
+ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
+ } \
+ \
+ BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
+ iterator emplace_after(const_iterator prev \
+ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
+ { \
+ NodePtr pnode (AllocHolder::create_node \
+ (BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \
+ return iterator(this->icont().insert_after(prev.get(), *pnode)); \
+ } \
//!
- //! <b>Complexity</b>: Amortized constant time.
- void push_front(BOOST_RV_REF(T) x)
- { this->icont().push_front(*this->create_node(boost::move(x))); }
+ #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
+ #include BOOST_PP_LOCAL_ITERATE()
- //! <b>Effects</b>: Removes the first element from the list.
+ #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
+
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ //! <b>Effects</b>: Inserts a copy of x at the beginning of the list.
//!
- //! <b>Throws</b>: Nothing.
+ //! <b>Throws</b>: If memory allocation throws or
+ //! T's copy constructor throws.
//!
//! <b>Complexity</b>: Amortized constant time.
- void pop_front()
- { this->icont().pop_front_and_dispose(Destroyer(this->node_alloc())); }
+ void push_front(const T &x);
- //! <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>Effects</b>: Constructs a new element in the beginning of the list
+ //! and moves the resources of mx to this new element.
//!
- //! <b>Throws</b>: Nothing.
+ //! <b>Throws</b>: If memory allocation throws.
//!
- //! <b>Complexity</b>: Linear to the number of elements before i.
- iterator previous(iterator p)
- { return iterator(this->icont().previous(p.get())); }
+ //! <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
- //! <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.
- const_iterator previous(const_iterator p)
- { return const_iterator(this->icont().previous(p.get())); }
+ #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 the p pointed
- //! by prev_p.
+ //! <b>Effects</b>: Inserts a copy of the value after prev_p.
//!
//! <b>Returns</b>: An iterator to the inserted element.
//!
@@ -701,23 +798,12 @@ class slist
//!
//! <b>Note</b>: Does not affect the validity of iterators and references of
//! previous values.
- iterator insert_after(const_iterator prev_pos, insert_const_ref_type x)
- { return this->priv_insert_after(prev_pos, x); }
-
- #if defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- iterator insert_after(const_iterator position, T &x)
- { return this->insert_after(position, const_cast<const T &>(x)); }
+ iterator insert_after(const_iterator prev_p, const T &x);
- template<class U>
- iterator insert_after( const_iterator position, const U &u
- , typename container_detail::enable_if_c<container_detail::is_same<T, U>::value && !::boost::has_move_emulation_enabled<U>::value >::type* =0)
- { return this->priv_insert_after(position, u); }
- #endif
-
- //! <b>Requires</b>: prev_pos must be a valid iterator of *this.
+ //! <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
- //! p pointed by prev_pos.
+ //! p pointed by prev_p.
//!
//! <b>Returns</b>: An iterator to the inserted element.
//!
@@ -727,26 +813,35 @@ class slist
//!
//! <b>Note</b>: Does not affect the validity of iterators and references of
//! previous values.
- iterator insert_after(const_iterator prev_pos, BOOST_RV_REF(value_type) x)
- { return iterator(this->icont().insert_after(prev_pos.get(), *this->create_node(boost::move(x)))); }
+ 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_pos must be a valid iterator of *this.
+ //! <b>Requires</b>: prev_p must be a valid iterator of *this.
+ //!
+ //! <b>Effects</b>: Inserts n copies of x after prev_p.
//!
- //! <b>Effects</b>: Inserts n copies of x after prev_pos.
+ //! <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.
- void insert_after(const_iterator prev_pos, size_type n, const value_type& x)
- { this->priv_create_and_insert_nodes(prev_pos, n, x); }
+ 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_pos must be a valid iterator of *this.
+ //! <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>Effects</b>: Inserts the range pointed by [first, last)
- //! after the p prev_pos.
+ //! <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.
@@ -755,139 +850,71 @@ class slist
//!
//! <b>Note</b>: Does not affect the validity of iterators and references of
//! previous values.
- template <class InIter>
- void insert_after(const_iterator prev_pos, InIter first, InIter last)
+ template <class InpIt>
+ iterator insert_after(const_iterator prev_p, InpIt first, InpIt last
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename container_detail::enable_if_c
+ < !container_detail::is_convertible<InpIt, size_type>::value
+ && (container_detail::is_input_iterator<InpIt>::value
+ || container_detail::is_same<alloc_version, allocator_v1>::value
+ )
+ >::type * = 0
+ #endif
+ )
{
- const bool aux_boolean = container_detail::is_convertible<InIter, size_type>::value;
- typedef container_detail::bool_<aux_boolean> Result;
- this->priv_insert_after_range_dispatch(prev_pos, first, last, Result());
+ 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;
}
- //! <b>Requires</b>: p must be a valid iterator of *this.
- //!
- //! <b>Effects</b>: Insert a copy of x before p.
- //!
- //! <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 position, insert_const_ref_type x)
- { return this->priv_insert(position, x); }
-
- #if defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- iterator insert(const_iterator position, T &x)
- { return this->insert(position, const_cast<const T &>(x)); }
-
- template<class U>
- iterator insert( const_iterator position, const U &u
- , typename container_detail::enable_if_c<container_detail::is_same<T, U>::value && !::boost::has_move_emulation_enabled<U>::value >::type* =0)
- { return this->priv_insert(position, u); }
- #endif
-
- //! <b>Requires</b>: p must be a valid iterator of *this.
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Requires</b>: prev_p must be a valid iterator of *this.
//!
- //! <b>Effects</b>: Insert a new element before p with mx's resources.
+ //! <b>Effects</b>: Inserts the range pointed by [il.begin(), il.end()) after prev_p.
//!
- //! <b>Throws</b>: If memory allocation throws.
- //!
- //! <b>Complexity</b>: Linear to the elements before p.
- iterator insert(const_iterator p, BOOST_RV_REF(value_type) x)
- { return this->insert_after(previous(p), boost::move(x)); }
-
- //! <b>Requires</b>: p must be a valid iterator of *this.
- //!
- //! <b>Effects</b>: Inserts n copies of x before p.
- //!
- //! <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.
- void insert(const_iterator p, size_type n, const value_type& x)
- { return this->insert_after(previous(p), n, x); }
-
- //! <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 last inserted element or prev_p if il.begin() == il.end().
//!
//! <b>Throws</b>: If memory allocation throws, T's constructor from a
- //! dereferenced InpIt throws.
- //!
- //! <b>Complexity</b>: Linear to std::distance [first, last) plus
- //! linear to the elements before p.
- template <class InIter>
- void insert(const_iterator p, InIter first, InIter last)
- { return this->insert_after(previous(p), first, last); }
-
- #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
-
- //! <b>Effects</b>: Inserts an object of type T constructed with
- //! std::forward<Args>(args)... in the front of the list
+ //! dereferenced std::initializer_list iterator throws.
//!
- //! <b>Throws</b>: If memory allocation throws or
- //! T's copy constructor throws.
- //!
- //! <b>Complexity</b>: Amortized constant time.
- template <class... Args>
- void emplace_front(Args&&... args)
- { 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)... 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, Args&&... args)
- { return this->emplace_after(this->previous(p), 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>: Linear to the number of elements inserted.
//!
- //! <b>Complexity</b>: Constant
- template <class... Args>
- iterator emplace_after(const_iterator prev, Args&&... args)
+ //! <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)
{
- NodePtr pnode(AllocHolder::create_node(boost::forward<Args>(args)...));
- return iterator(this->icont().insert_after(prev.get(), *pnode));
+ 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 container_detail::enable_if_c
+ < !container_detail::is_convertible<FwdIt, size_type>::value
+ && !(container_detail::is_input_iterator<FwdIt>::value
+ || container_detail::is_same<alloc_version, allocator_v1>::value
+ )
+ >::type * = 0
+ )
+ {
+ //Optimized allocation and construction
+ insertion_functor func(this->icont(), prev.get());
+ this->allocate_many_and_construct(first, std::distance(first, last), func);
+ return iterator(func.inserted_first());
+ }
+ #endif
- #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
-
- #define BOOST_PP_LOCAL_MACRO(n) \
- BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
- void emplace_front(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
- { \
- this->emplace(this->cbegin() \
- BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
- } \
- \
- BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
- iterator emplace (const_iterator p \
- BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
- { \
- return this->emplace_after \
- (this->previous(p) \
- BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
- } \
- \
- BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
- iterator emplace_after(const_iterator prev \
- BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
- { \
- NodePtr pnode (AllocHolder::create_node \
- (BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _))); \
- return iterator(this->icont().insert_after(prev.get(), *pnode)); \
- } \
+ //! <b>Effects</b>: Removes the first element from the list.
//!
- #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
- #include BOOST_PP_LOCAL_ITERATE()
-
- #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Amortized constant time.
+ void pop_front()
+ { this->icont().pop_front_and_dispose(Destroyer(this->node_alloc())); }
- //! <b>Effects</b>: Erases the element after the element pointed by prev_pos
+ //! <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,
@@ -898,9 +925,9 @@ class slist
//! <b>Complexity</b>: Constant.
//!
//! <b>Note</b>: Does not invalidate iterators or references to non erased elements.
- iterator erase_after(const_iterator prev_pos)
+ iterator erase_after(const_iterator prev_p)
{
- return iterator(this->icont().erase_after_and_dispose(prev_pos.get(), Destroyer(this->node_alloc())));
+ 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
@@ -919,78 +946,48 @@ class slist
return iterator(this->icont().erase_after_and_dispose(before_first.get(), last.get(), Destroyer(this->node_alloc())));
}
- //! <b>Requires</b>: p must be a valid iterator of *this.
- //!
- //! <b>Effects</b>: Erases the element at p p.
+ //! <b>Effects</b>: Swaps the contents of *this and x.
//!
//! <b>Throws</b>: Nothing.
//!
- //! <b>Complexity</b>: Linear to the number of elements before p.
- iterator erase(const_iterator p)
- { return iterator(this->erase_after(previous(p))); }
+ //! <b>Complexity</b>: Linear to the number of elements on *this and x.
+ void swap(slist& x)
+ { AllocHolder::swap(x); }
- //! <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>Effects</b>: Erases all the elements of the list.
//!
//! <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)
- { return iterator(this->erase_after(previous(first), last)); }
+ //! <b>Complexity</b>: Linear to the number of elements in the list.
+ void clear()
+ { this->icont().clear_and_dispose(Destroyer(this->node_alloc())); }
- //! <b>Effects</b>: Inserts or erases elements at the end such that
- //! the size becomes n. New elements are copy constructed from x.
+ //////////////////////////////////////////////
+ //
+ // slist operations
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Requires</b>: p must point to an element contained
+ //! by the list. x != *this
//!
- //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
+ //! <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>Complexity</b>: Linear to the difference between size() and new_size.
- void resize(size_type new_size, const T& x)
- {
- 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;
- }
- if (cur_next != end_n)
- this->erase_after(const_iterator(cur), const_iterator(end_n));
- else
- this->insert_after(const_iterator(cur), new_size, x);
- }
-
- //! <b>Effects</b>: Inserts or erases elements at the end such that
- //! the size becomes n. New elements are default constructed.
+ //! <b>Throws</b>: std::runtime_error if this' allocator and x's allocator
+ //! are not equal.
//!
- //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
+ //! <b>Complexity</b>: Linear to the elements in x.
//!
- //! <b>Complexity</b>: Linear to the difference between size() and new_size.
- void resize(size_type new_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_after(const_iterator prev_p, slist& x) BOOST_CONTAINER_NOEXCEPT
{
- typename Icont::iterator end_n(this->icont().end()), cur(this->icont().before_begin()), cur_next;
- size_type len = this->size();
- size_type left = new_size;
-
- while (++(cur_next = cur) != end_n && left > 0){
- --left;
- cur = cur_next;
- }
- if (cur_next != end_n){
- this->erase_after(const_iterator(cur), const_iterator(end_n));
- }
- else{
- this->priv_create_and_insert_nodes(const_iterator(cur), new_size - len);
- }
+ BOOST_ASSERT(this != &x);
+ BOOST_ASSERT(this->node_alloc() == x.node_alloc());
+ this->icont().splice_after(prev_p.get(), x.icont());
}
- //! <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())); }
-
//! <b>Requires</b>: p must point to an element contained
//! by the list. x != *this
//!
@@ -1004,153 +1001,129 @@ class slist
//!
//! <b>Note</b>: Iterators of values obtained from list x now point to elements of
//! this list. Iterators of this list and all the references are not invalidated.
- void splice_after(const_iterator prev_pos, slist& x)
- {
- if((NodeAlloc&)*this == (NodeAlloc&)x){
- this->icont().splice_after(prev_pos.get(), x.icont());
- }
- else{
- throw std::runtime_error("slist::splice called with unequal allocators");
- }
- }
+ void splice_after(const_iterator prev_p, BOOST_RV_REF(slist) x) BOOST_CONTAINER_NOEXCEPT
+ { this->splice_after(prev_p, static_cast<slist&>(x)); }
- //! <b>Requires</b>: prev_pos must be a valid iterator of this.
+ //! <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_pos.
- //! If prev_pos == prev or prev_pos == ++prev, this function is a null operation.
+ //! after the element pointed by prev_p.
+ //! If prev_p == prev or prev_p == ++prev, this function is a null operation.
//!
- //! <b>Throws</b>: std::runtime_error if this' allocator and x's allocator
- //! are not equal.
+ //! <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_pos, slist& x, const_iterator prev)
+ void splice_after(const_iterator prev_p, slist& x, const_iterator prev) BOOST_CONTAINER_NOEXCEPT
{
- if((NodeAlloc&)*this == (NodeAlloc&)x){
- this->icont().splice_after(prev_pos.get(), x.icont(), prev.get());
- }
- else{
- throw std::runtime_error("slist::splice called with unequal allocators");
- }
+ BOOST_ASSERT(this->node_alloc() == x.node_alloc());
+ this->icont().splice_after(prev_p.get(), x.icont(), prev.get());
}
- //! <b>Requires</b>: prev_pos must be a valid iterator of this.
- //! before_first and before_last must be valid iterators of x.
- //! prev_pos must not be contained in [before_first, before_last) range.
+ //! <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 range [before_first + 1, before_last + 1)
- //! from list x to this list, after the element pointed by prev_pos.
+ //! <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>: std::runtime_error if this' allocator and x's allocator
- //! are not equal.
+ //! <b>Throws</b>: Nothing
//!
- //! <b>Complexity</b>: Linear to the number of transferred elements.
+ //! <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_pos, slist& x,
- const_iterator before_first, const_iterator before_last)
- {
- if((NodeAlloc&)*this == (NodeAlloc&)x){
- this->icont().splice_after
- (prev_pos.get(), x.icont(), before_first.get(), before_last.get());
- }
- else{
- throw std::runtime_error("slist::splice called with unequal allocators");
- }
- }
+ void splice_after(const_iterator prev_p, BOOST_RV_REF(slist) x, const_iterator prev) BOOST_CONTAINER_NOEXCEPT
+ { this->splice_after(prev_p, static_cast<slist&>(x), prev); }
- //! <b>Requires</b>: prev_pos must be a valid iterator of this.
+ //! <b>Requires</b>: prev_p must be a valid iterator of this.
//! before_first and before_last must be valid iterators of x.
- //! prev_pos must not be contained in [before_first, before_last) range.
- //! n == std::distance(before_first, before_last)
+ //! 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_pos.
+ //! from list x to this list, after the element pointed by prev_p.
//!
- //! <b>Throws</b>: std::runtime_error if this' allocator and x's allocator
- //! are not equal.
+ //! <b>Throws</b>: Nothing
//!
- //! <b>Complexity</b>: Constant.
+ //! <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_pos, slist& x,
- const_iterator before_first, const_iterator before_last,
- size_type n)
+ void splice_after(const_iterator prev_p, slist& x,
+ const_iterator before_first, const_iterator before_last) BOOST_CONTAINER_NOEXCEPT
{
- if((NodeAlloc&)*this == (NodeAlloc&)x){
- this->icont().splice_after
- (prev_pos.get(), x.icont(), before_first.get(), before_last.get(), n);
- }
- else{
- throw std::runtime_error("slist::splice called with unequal allocators");
- }
+ 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>: p must point to an element contained
- //! by the list. x != *this
+ //! <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 all the elements of list x to this list, before the
- //! the element pointed by p. No destructors or copy constructors are called.
+ //! <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>: std::runtime_error if this' allocator and x's allocator
- //! are not equal.
+ //! <b>Throws</b>: Nothing
//!
- //! <b>Complexity</b>: Linear in distance(begin(), p), and linear in x.size().
+ //! <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(const_iterator p, ThisType& x)
- { this->splice_after(this->previous(p), 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,
+ const_iterator before_first, const_iterator before_last) BOOST_CONTAINER_NOEXCEPT
+ { this->splice_after(prev_p, static_cast<slist&>(x), before_first, before_last); }
- //! <b>Requires</b>: p must point to an element contained
- //! by this list. i must point to an element contained in list x.
+ //! <b>Requires</b>: prev_p must be a valid iterator of this.
+ //! before_first and before_last must be valid iterators of x.
+ //! prev_p must not be contained in [before_first, before_last) range.
+ //! n == std::distance(before_first, before_last).
+ //! 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 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>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>: std::runtime_error if this' allocator and x's allocator
- //! are not equal.
+ //! <b>Throws</b>: Nothing
//!
- //! <b>Complexity</b>: Linear in distance(begin(), p), and in distance(x.begin(), i).
+ //! <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, slist& x, const_iterator i)
- { this->splice_after(previous(p), x, i); }
+ void splice_after(const_iterator prev_p, slist& x,
+ const_iterator before_first, const_iterator before_last,
+ size_type n) BOOST_CONTAINER_NOEXCEPT
+ {
+ 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>: p must point to an element contained
- //! by this list. first and last must point to elements contained in list x.
+ //! <b>Requires</b>: prev_p must be a valid iterator of this.
+ //! before_first and before_last must be valid iterators of x.
+ //! prev_p must not be contained in [before_first, before_last) range.
+ //! n == std::distance(before_first, before_last).
+ //! this' allocator and x's allocator shall compare equal.
//!
- //! <b>Effects</b>: Transfers the range pointed by first and last from list x to this list,
- //! before the the element pointed by p. No destructors or copy constructors are called.
+ //! <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>: std::runtime_error if this' allocator and x's allocator
- //! are not equal.
+ //! <b>Throws</b>: Nothing
//!
- //! <b>Complexity</b>: Linear in distance(begin(), p), in distance(x.begin(), first),
- //! and in distance(first, last).
+ //! <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, slist& x, const_iterator first, const_iterator last)
- { this->splice_after(previous(p), x, previous(first), previous(last)); }
-
- //! <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()
- { this->icont().reverse(); }
+ void splice_after(const_iterator prev_p, BOOST_RV_REF(slist) x,
+ const_iterator before_first, const_iterator before_last,
+ size_type n) BOOST_CONTAINER_NOEXCEPT
+ { 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.
//!
@@ -1161,7 +1134,7 @@ class slist
//! <b>Note</b>: The relative order of elements that are not removed is unchanged,
//! and iterators to elements that are not removed remain valid.
void remove(const T& value)
- { remove_if(equal_to_value(value)); }
+ { this->remove_if(equal_to_value(value)); }
//! <b>Effects</b>: Removes all the elements for which a specified
//! predicate is satisfied.
@@ -1182,9 +1155,9 @@ class slist
//! <b>Effects</b>: Removes adjacent duplicate elements or adjacent
//! elements that are equal from the list.
//!
- //! <b>Throws</b>: Nothing.
+ //! <b>Throws</b>: If comparison throws.
//!
- //! <b>Complexity</b>: Linear time (size()-1 comparisons calls to pred()).
+ //! <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.
@@ -1196,7 +1169,7 @@ class slist
//!
//! <b>Throws</b>: If pred throws.
//!
- //! <b>Complexity</b>: Linear time (size()-1 comparisons equality comparisons).
+ //! <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.
@@ -1214,13 +1187,27 @@ class slist
//! 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>: Nothing.
+ //! <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()); }
+ //! <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.
@@ -1229,7 +1216,7 @@ class slist
//! 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>: Nothing.
+ //! <b>Throws</b>: If comp throws.
//!
//! <b>Complexity</b>: This function is linear time: it performs at most
//! size() + x.size() - 1 comparisons.
@@ -1238,19 +1225,33 @@ class slist
template <class StrictWeakOrdering>
void merge(slist& x, StrictWeakOrdering comp)
{
- if((NodeAlloc&)*this == (NodeAlloc&)x){
- this->icont().merge(x.icont(),
- ValueCompareToNodeCompare<StrictWeakOrdering>(comp));
- }
- else{
- throw std::runtime_error("list::merge called with unequal allocators");
- }
+ BOOST_ASSERT(this->node_alloc() == x.node_alloc());
+ this->icont().merge(x.icont(),
+ ValueCompareToNodeCompare<StrictWeakOrdering>(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>: Nothing.
+ //! <b>Throws</b>: If comparison throws.
//!
//! <b>Notes</b>: Iterators and references are not invalidated.
//!
@@ -1262,7 +1263,7 @@ class slist
//! <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>: Nothing.
+ //! <b>Throws</b>: If comp throws.
//!
//! <b>Notes</b>: Iterators and references are not invalidated.
//!
@@ -1277,139 +1278,363 @@ class slist
this->icont().sort(ValueCompareToNodeCompare<StrictWeakOrdering>(comp));
}
- /// @cond
- private:
- iterator priv_insert(const_iterator p, const value_type& x)
- { return this->insert_after(previous(p), x); }
+ //! <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_CONTAINER_NOEXCEPT
+ { this->icont().reverse(); }
- iterator priv_insert_after(const_iterator prev_pos, const value_type& x)
- { return iterator(this->icont().insert_after(prev_pos.get(), *this->create_node(x))); }
+ //////////////////////////////////////////////
+ //
+ // list compatibility interface
+ //
+ //////////////////////////////////////////////
- void priv_push_front(const value_type &x)
- { this->icont().push_front(*this->create_node(x)); }
+ #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- //Iterator range version
- template<class InpIterator>
- void priv_create_and_insert_nodes
- (const_iterator prev, InpIterator beg, InpIterator end)
+ //! <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, Args&&... args)
+ { return this->emplace_after(this->previous(p), boost::forward<Args>(args)...); }
+
+ #else //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
+
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
+ iterator emplace (const_iterator p \
+ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
+ { \
+ return this->emplace_after \
+ (this->previous(p) \
+ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
+ } \
+ //!
+ #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
+ #include BOOST_PP_LOCAL_ITERATE()
+ #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
+
+ #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 mx'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)
{
- typedef typename std::iterator_traits<InpIterator>::iterator_category ItCat;
- priv_create_and_insert_nodes(prev, beg, end, alloc_version(), ItCat());
+ const_iterator prev(this->previous(p));
+ this->insert_after(prev, n, x);
+ return ++iterator(prev.get());
}
- template<class InpIterator>
- void priv_create_and_insert_nodes
- (const_iterator prev, InpIterator beg, InpIterator end, allocator_v1, std::input_iterator_tag)
+ //! <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 std::distance [first, last) plus
+ //! linear to the elements before p.
+ template <class InIter>
+ iterator insert(const_iterator p, InIter first, InIter last)
{
- for (; beg != end; ++beg){
- this->icont().insert_after(prev.get(), *this->create_node_from_it(beg));
- ++prev;
- }
+ const_iterator prev(this->previous(p));
+ this->insert_after(prev, first, last);
+ return ++iterator(prev.get());
}
- template<class InpIterator>
- void priv_create_and_insert_nodes
- (const_iterator prev, InpIterator beg, InpIterator end, allocator_v2, std::input_iterator_tag)
- { //Just forward to the default one
- priv_create_and_insert_nodes(prev, beg, end, allocator_v1(), std::input_iterator_tag());
+#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
- class insertion_functor;
- friend class insertion_functor;
+ //! <b>Requires</b>: p must be a valid iterator of *this.
+ //!
+ //! <b>Effects</b>: Erases the element at p p.
+ //!
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements before p.
+ iterator erase(const_iterator p) BOOST_CONTAINER_NOEXCEPT
+ { return iterator(this->erase_after(previous(p))); }
- class insertion_functor
- {
- Icont &icont_;
- typename Icont::const_iterator prev_;
+ //! <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_CONTAINER_NOEXCEPT
+ { return iterator(this->erase_after(previous(first), last)); }
- public:
- insertion_functor(Icont &icont, typename Icont::const_iterator prev)
- : icont_(icont), prev_(prev)
- {}
+ //! <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_CONTAINER_NOEXCEPT
+ { this->splice_after(this->previous(p), x); }
- void operator()(Node &n)
- { prev_ = this->icont_.insert_after(prev_, n); }
- };
+ //! <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_CONTAINER_NOEXCEPT
+ { this->splice(p, static_cast<slist&>(x)); }
- template<class FwdIterator>
- void priv_create_and_insert_nodes
- (const_iterator prev, FwdIterator beg, FwdIterator end, allocator_v2, std::forward_iterator_tag)
- {
- //Optimized allocation and construction
- this->allocate_many_and_construct
- (beg, std::distance(beg, end), insertion_functor(this->icont(), prev.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 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_CONTAINER_NOEXCEPT
+ { this->splice_after(this->previous(p), x, this->previous(i)); }
- //Default constructed version
- void priv_create_and_insert_nodes(const_iterator prev, size_type n)
- {
- typedef default_construct_iterator<value_type, difference_type> default_iterator;
- this->priv_create_and_insert_nodes(prev, default_iterator(n), default_iterator());
- }
+ //! <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 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_CONTAINER_NOEXCEPT
+ { this->splice(p, static_cast<slist&>(x), i); }
- //Copy constructed version
- void priv_create_and_insert_nodes(const_iterator prev, size_type n, const T& x)
+ //! <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 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_CONTAINER_NOEXCEPT
+ { this->splice_after(this->previous(p), x, this->previous(first), this->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 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_CONTAINER_NOEXCEPT
+ { 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)
{
- typedef constant_iterator<value_type, difference_type> cvalue_iterator;
- this->priv_create_and_insert_nodes(prev, cvalue_iterator(x, n), cvalue_iterator());
+ if(x.size() != y.size()){
+ return false;
+ }
+ typedef typename slist<T,Allocator>::const_iterator const_iterator;
+ const_iterator end1 = x.end();
+
+ const_iterator i1 = x.begin();
+ const_iterator i2 = y.begin();
+ while (i1 != end1 && *i1 == *i2){
+ ++i1;
+ ++i2;
+ }
+ return i1 == end1;
}
- //Dispatch to detect iterator range or integer overloads
- template <class InputIter>
- void priv_insert_dispatch(const_iterator prev,
- InputIter first, InputIter last,
- container_detail::false_)
- { this->priv_create_and_insert_nodes(prev, first, last); }
+ //! <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 std::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); }
- template<class Integer>
- void priv_insert_dispatch(const_iterator prev, Integer n, Integer x, container_detail::true_)
- { this->priv_create_and_insert_nodes(prev, (size_type)n, 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); }
- void priv_fill_assign(size_type n, const T& val)
+ //! <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)
{
- iterator end_n(this->end());
- iterator prev(this->before_begin());
- iterator node(this->begin());
- for ( ; node != end_n && n > 0 ; --n){
- *node = val;
- prev = node;
- ++node;
+ 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;
}
- if (n > 0)
- this->priv_create_and_insert_nodes(prev, n, val);
- else
- this->erase_after(prev, end_n);
}
- template <class Int>
- void priv_assign_dispatch(Int n, Int val, container_detail::true_)
- { this->priv_fill_assign((size_type) n, (T)val); }
+ 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 InpIt>
- void priv_assign_dispatch(InpIt first, InpIt last, container_detail::false_)
+ 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
{
- 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->priv_create_and_insert_nodes(prev, first, last);
- else
- this->erase_after(prev, end_n);
- }
+ Icont &icont_;
+ typedef typename Icont::iterator iiterator;
+ typedef typename Icont::const_iterator iconst_iterator;
+ const iconst_iterator prev_;
+ iiterator ret_;
- template <class Int>
- void priv_insert_after_range_dispatch(const_iterator prev_pos, Int n, Int x, container_detail::true_)
- { this->priv_create_and_insert_nodes(prev_pos, (size_type)n, x); }
+ public:
+ insertion_functor(Icont &icont, typename Icont::const_iterator prev)
+ : icont_(icont), prev_(prev), ret_(prev.unconst())
+ {}
- template <class InIter>
- void priv_insert_after_range_dispatch(const_iterator prev_pos, InIter first, InIter last, container_detail::false_)
- { this->priv_create_and_insert_nodes(prev_pos, first, last); }
+ void operator()(Node &n)
+ {
+ ret_ = this->icont_.insert_after(prev_, n);
+ }
+
+ iiterator inserted_first() const
+ { return ret_; }
+ };
//Functors for member algorithm defaults
struct value_less
@@ -1434,94 +1659,42 @@ class slist
const value_type &m_ref;
};
- /// @endcond
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
};
-template <class T, class A>
-inline bool
-operator==(const slist<T,A>& x, const slist<T,A>& y)
-{
- if(x.size() != y.size()){
- return false;
- }
- typedef typename slist<T,A>::const_iterator const_iterator;
- const_iterator end1 = x.end();
-
- const_iterator i1 = x.begin();
- const_iterator i2 = y.begin();
- while (i1 != end1 && *i1 == *i2){
- ++i1;
- ++i2;
- }
- return i1 == end1;
-}
-
-template <class T, class A>
-inline bool
-operator<(const slist<T,A>& sL1, const slist<T,A>& sL2)
-{
- return std::lexicographical_compare
- (sL1.begin(), sL1.end(), sL2.begin(), sL2.end());
-}
-
-template <class T, class A>
-inline bool
-operator!=(const slist<T,A>& sL1, const slist<T,A>& sL2)
- { return !(sL1 == sL2); }
-
-template <class T, class A>
-inline bool
-operator>(const slist<T,A>& sL1, const slist<T,A>& sL2)
- { return sL2 < sL1; }
-
-template <class T, class A>
-inline bool
-operator<=(const slist<T,A>& sL1, const slist<T,A>& sL2)
- { return !(sL2 < sL1); }
-
-template <class T, class A>
-inline bool
-operator>=(const slist<T,A>& sL1, const slist<T,A>& sL2)
- { return !(sL1 < sL2); }
-
-template <class T, class A>
-inline void swap(slist<T,A>& x, slist<T,A>& y)
- { x.swap(y); }
-
}}
-/// @cond
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
namespace boost {
-/*
+
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
-template <class T, class A>
-struct has_trivial_destructor_after_move<boost::container::slist<T, A> >
-{
- static const bool value = has_trivial_destructor<A>::value;
-};
-*/
+template <class T, class Allocator>
+struct has_trivial_destructor_after_move<boost::container::slist<T, Allocator> >
+ : public ::boost::has_trivial_destructor_after_move<Allocator>
+{};
+
namespace container {
-/// @endcond
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
}} //namespace boost{ namespace container {
// Specialization of insert_iterator so that insertions will be constant
// time rather than linear time.
-///@cond
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//Ummm, I don't like to define things in namespace std, but
//there is no other way
namespace std {
-template <class T, class A>
-class insert_iterator<boost::container::slist<T, A> >
+template <class T, class Allocator>
+class insert_iterator<boost::container::slist<T, Allocator> >
{
protected:
- typedef boost::container::slist<T, A> Container;
+ typedef boost::container::slist<T, Allocator> Container;
Container* container;
typename Container::iterator iter;
public:
@@ -1550,8 +1723,8 @@ class insert_iterator<boost::container::slist<T, A> >
} //namespace std;
-///@endcond
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
#include <boost/container/detail/config_end.hpp>
-#endif /* BOOST_CONTAINER_SLIST_HPP */
+#endif // BOOST_CONTAINER_SLIST_HPP
diff --git a/boost/container/stable_vector.hpp b/boost/container/stable_vector.hpp
index d91eccd16e..b8b415758e 100644
--- a/boost/container/stable_vector.hpp
+++ b/boost/container/stable_vector.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2008-2012. Distributed under the Boost
+// (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)
//
@@ -19,64 +19,51 @@
#ifndef BOOST_CONTAINER_STABLE_VECTOR_HPP
#define BOOST_CONTAINER_STABLE_VECTOR_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
#include <boost/container/container_fwd.hpp>
-#include <boost/mpl/bool.hpp>
-#include <boost/mpl/not.hpp>
-#include <boost/type_traits/is_integral.hpp>
-#include <boost/container/detail/version_type.hpp>
-#include <boost/container/detail/multiallocation_chain.hpp>
+#include <boost/assert.hpp>
+#include <boost/container/throw_exception.hpp>
+#include <boost/container/detail/allocator_version_traits.hpp>
#include <boost/container/detail/utilities.hpp>
#include <boost/container/detail/iterators.hpp>
#include <boost/container/detail/algorithms.hpp>
#include <boost/container/allocator_traits.hpp>
+#include <boost/container/throw_exception.hpp>
#include <boost/intrusive/pointer_traits.hpp>
-
+#include <boost/core/no_exceptions_support.hpp>
+#include <boost/aligned_storage.hpp>
+#include <boost/move/utility_core.hpp>
+#include <boost/move/iterator.hpp>
+#include <boost/move/detail/move_helpers.hpp>
+#include <boost/container/detail/placement_new.hpp>
#include <algorithm>
-#include <stdexcept>
+
+
#include <memory>
-///@cond
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
#include <boost/container/vector.hpp>
//#define STABLE_VECTOR_ENABLE_INVARIANT_CHECKING
-#if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING)
-#include <boost/assert.hpp>
-#endif
-
-///@endcond
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
namespace boost {
namespace container {
-///@cond
-
-namespace stable_vector_detail{
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+#include <initializer_list>
+#endif
-template<class SmartPtr>
-struct smart_ptr_type
-{
- typedef typename SmartPtr::value_type value_type;
- typedef value_type *pointer;
- static pointer get (const SmartPtr &smartptr)
- { return smartptr.get();}
-};
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
-template<class T>
-struct smart_ptr_type<T*>
-{
- typedef T value_type;
- typedef value_type *pointer;
- static pointer get (pointer ptr)
- { return ptr;}
-};
+namespace stable_vector_detail{
template <class C>
class clear_on_destroy
@@ -93,7 +80,7 @@ class clear_on_destroy
{
if(do_clear_){
c_.clear();
- c_.clear_pool();
+ c_.priv_clear_pool();
}
}
@@ -104,239 +91,304 @@ class clear_on_destroy
bool do_clear_;
};
+template<typename Pointer>
+struct node;
+
template<class VoidPtr>
-struct node_type_base
+struct node_base
{
- node_type_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)
{}
- void set_pointer(const VoidPtr &p)
- { up = p; }
- VoidPtr up;
+ node_base()
+ : up()
+ {}
+
+ node_base_ptr_ptr up;
};
-template<typename VoidPointer, typename T>
-struct node_type
- : public node_type_base<VoidPointer>
+template<typename Pointer>
+struct node
+ : public node_base
+ <typename ::boost::intrusive::pointer_traits<Pointer>::template
+ rebind_pointer<void>::type
+ >
{
private:
- node_type();
+ node();
public:
- T value;
+ typename ::boost::intrusive::pointer_traits<Pointer>::element_type value;
};
-template<typename T, typename Reference, typename Pointer>
-class iterator
- : public std::iterator< std::random_access_iterator_tag
- , T
- , typename boost::intrusive::
- pointer_traits<Pointer>::difference_type
- , Pointer
- , Reference>
+template<class VoidPtr, class VoidAllocator>
+struct index_traits
{
- typedef typename boost::intrusive::
- pointer_traits<Pointer>::template
- rebind_pointer<void>::type void_ptr;
- typedef typename boost::intrusive::
- pointer_traits<Pointer>::template
- rebind_pointer<const void>::type const_void_ptr;
- typedef node_type<void_ptr, T> node_type_t;
- typedef typename boost::intrusive::
- pointer_traits<Pointer>::template
- rebind_pointer<node_type_t>::type node_type_ptr_t;
- typedef typename boost::intrusive::
- pointer_traits<Pointer>::template
- rebind_pointer<const node_type_t>::type const_node_type_ptr_t;
- typedef typename boost::intrusive::
- pointer_traits<Pointer>::template
- rebind_pointer<void_ptr>::type void_ptr_ptr;
+ 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;
- friend class iterator<T, const T, typename boost::intrusive::pointer_traits<Pointer>::template rebind_pointer<T>::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();
- public:
- typedef std::random_access_iterator_tag iterator_category;
- typedef T value_type;
- typedef typename boost::intrusive::
- pointer_traits<Pointer>::difference_type difference_type;
- typedef Pointer pointer;
- typedef Reference reference;
+ static node_base_ptr_ptr ptr_to_node_base_ptr(node_base_ptr &n)
+ { return node_base_ptr_ptr_traits::pointer_to(n); }
- iterator()
- {}
+ 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;
+ }
+ }
- explicit iterator(node_type_ptr_t pn)
- : pn(pn)
- {}
+ static index_iterator get_fix_up_end(index_type &index)
+ { return index.end() - (ExtraPointers - 1); }
- iterator(const iterator<T, T&, typename boost::intrusive::pointer_traits<Pointer>::template rebind_pointer<T>::type>& x)
- : pn(x.pn)
- {}
-
- private:
- static node_type_ptr_t node_ptr_cast(const void_ptr &p)
+ 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)
{
- return node_type_ptr_t(static_cast<node_type_t*>(container_detail::to_raw_pointer(p)));
+ 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 const_node_type_ptr_t node_ptr_cast(const const_void_ptr &p)
+ static void initialize_end_node(index_type &index, node_base_type &end_node, const size_type index_capacity_if_empty)
{
- return const_node_type_ptr_t(static_cast<const node_type_t*>(container_detail::to_raw_pointer(p)));
+ 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);
+ }
}
- static void_ptr_ptr void_ptr_ptr_cast(const void_ptr &p)
+ #ifdef STABLE_VECTOR_ENABLE_INVARIANT_CHECKING
+ static bool invariants(index_type &index)
{
- return void_ptr_ptr(static_cast<void_ptr*>(container_detail::to_raw_pointer(p)));
+ 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
- reference dereference() const
- { return pn->value; }
- bool equal(const iterator& x) const
- { return pn==x.pn; }
- void increment()
- { pn = node_ptr_cast(*(void_ptr_ptr_cast(pn->up)+1)); }
- void decrement()
- { pn = node_ptr_cast(*(void_ptr_ptr_cast(pn->up)-1)); }
- void advance(difference_type n)
- { pn = node_ptr_cast(*(void_ptr_ptr_cast(pn->up)+n)); }
- difference_type distance_to(const iterator& x)const
- { return void_ptr_ptr_cast(x.pn->up) - void_ptr_ptr_cast(pn->up); }
+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::container_detail::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:
- //Pointer like operators
- reference operator*() const { return this->dereference(); }
- pointer operator->() const { return pointer(&this->dereference()); }
- //Increment / Decrement
- iterator& operator++()
- { this->increment(); return *this; }
+ explicit stable_vector_iterator(node_base_ptr p) BOOST_CONTAINER_NOEXCEPT
+ : m_pn(p)
+ {}
- iterator operator++(int)
- { iterator tmp(*this); ++*this; return iterator(tmp); }
+ stable_vector_iterator() BOOST_CONTAINER_NOEXCEPT
+ : m_pn() //Value initialization to achieve "null iterators" (N3644)
+ {}
- iterator& operator--()
- { this->decrement(); return *this; }
+ stable_vector_iterator(stable_vector_iterator<Pointer, false> const& other) BOOST_CONTAINER_NOEXCEPT
+ : m_pn(other.node_pointer())
+ {}
- iterator operator--(int)
- { iterator tmp(*this); --*this; return iterator(tmp); }
+ node_ptr node_pointer() const BOOST_CONTAINER_NOEXCEPT
+ { return node_ptr_traits::static_cast_from(m_pn); }
- reference operator[](difference_type off) const
+ public:
+ //Pointer like operators
+ reference operator*() const BOOST_CONTAINER_NOEXCEPT
+ { return node_pointer()->value; }
+
+ pointer operator->() const BOOST_CONTAINER_NOEXCEPT
+ { return ptr_traits::pointer_to(this->operator*()); }
+
+ //Increment / Decrement
+ stable_vector_iterator& operator++() BOOST_CONTAINER_NOEXCEPT
{
- iterator tmp(*this);
- tmp += off;
- return *tmp;
+ node_base_ptr_ptr p(this->m_pn->up);
+ this->m_pn = *(++p);
+ return *this;
}
- iterator& operator+=(difference_type off)
+ stable_vector_iterator operator++(int) BOOST_CONTAINER_NOEXCEPT
+ { stable_vector_iterator tmp(*this); ++*this; return stable_vector_iterator(tmp); }
+
+ stable_vector_iterator& operator--() BOOST_CONTAINER_NOEXCEPT
{
- pn = node_ptr_cast(*(void_ptr_ptr_cast(pn->up)+off));
+ node_base_ptr_ptr p(this->m_pn->up);
+ this->m_pn = *(--p);
return *this;
}
- friend iterator operator+(const iterator &left, difference_type off)
+ stable_vector_iterator operator--(int) BOOST_CONTAINER_NOEXCEPT
+ { stable_vector_iterator tmp(*this); --*this; return stable_vector_iterator(tmp); }
+
+ reference operator[](difference_type off) const BOOST_CONTAINER_NOEXCEPT
+ { return node_ptr_traits::static_cast_from(this->m_pn->up[off])->value; }
+
+ stable_vector_iterator& operator+=(difference_type off) BOOST_CONTAINER_NOEXCEPT
{
- iterator tmp(left);
+ if(off) this->m_pn = this->m_pn->up[off];
+ return *this;
+ }
+
+ friend stable_vector_iterator operator+(const stable_vector_iterator &left, difference_type off) BOOST_CONTAINER_NOEXCEPT
+ {
+ stable_vector_iterator tmp(left);
tmp += off;
return tmp;
}
- friend iterator operator+(difference_type off, const iterator& right)
+ friend stable_vector_iterator operator+(difference_type off, const stable_vector_iterator& right) BOOST_CONTAINER_NOEXCEPT
{
- iterator tmp(right);
+ stable_vector_iterator tmp(right);
tmp += off;
return tmp;
}
- iterator& operator-=(difference_type off)
+ stable_vector_iterator& operator-=(difference_type off) BOOST_CONTAINER_NOEXCEPT
{ *this += -off; return *this; }
- friend iterator operator-(const iterator &left, difference_type off)
+ friend stable_vector_iterator operator-(const stable_vector_iterator &left, difference_type off) BOOST_CONTAINER_NOEXCEPT
{
- iterator tmp(left);
+ stable_vector_iterator tmp(left);
tmp -= off;
return tmp;
}
- friend difference_type operator-(const iterator& left, const iterator& right)
- {
- return void_ptr_ptr_cast(left.pn->up) - void_ptr_ptr_cast(right.pn->up);
- }
+ friend difference_type operator-(const stable_vector_iterator& left, const stable_vector_iterator& right) BOOST_CONTAINER_NOEXCEPT
+ { return left.m_pn->up - right.m_pn->up; }
//Comparison operators
- friend bool operator== (const iterator& l, const iterator& r)
- { return l.pn == r.pn; }
-
- friend bool operator!= (const iterator& l, const iterator& r)
- { return l.pn != r.pn; }
-
- friend bool operator< (const iterator& l, const iterator& r)
- { return void_ptr_ptr_cast(l.pn->up) < void_ptr_ptr_cast(r.pn->up); }
-
- friend bool operator<= (const iterator& l, const iterator& r)
- { return void_ptr_ptr_cast(l.pn->up) <= void_ptr_ptr_cast(r.pn->up); }
+ friend bool operator== (const stable_vector_iterator& l, const stable_vector_iterator& r) BOOST_CONTAINER_NOEXCEPT
+ { return l.m_pn == r.m_pn; }
- friend bool operator> (const iterator& l, const iterator& r)
- { return void_ptr_ptr_cast(l.pn->up) > void_ptr_ptr_cast(r.pn->up); }
+ friend bool operator!= (const stable_vector_iterator& l, const stable_vector_iterator& r) BOOST_CONTAINER_NOEXCEPT
+ { return l.m_pn != r.m_pn; }
- friend bool operator>= (const iterator& l, const iterator& r)
- { return void_ptr_ptr_cast(l.pn->up) >= void_ptr_ptr_cast(r.pn->up); }
+ friend bool operator< (const stable_vector_iterator& l, const stable_vector_iterator& r) BOOST_CONTAINER_NOEXCEPT
+ { return l.m_pn->up < r.m_pn->up; }
- node_type_ptr_t pn;
-};
+ friend bool operator<= (const stable_vector_iterator& l, const stable_vector_iterator& r) BOOST_CONTAINER_NOEXCEPT
+ { return l.m_pn->up <= r.m_pn->up; }
-template<class A, unsigned int Version>
-struct select_multiallocation_chain
-{
- typedef typename A::multiallocation_chain type;
-};
+ friend bool operator> (const stable_vector_iterator& l, const stable_vector_iterator& r) BOOST_CONTAINER_NOEXCEPT
+ { return l.m_pn->up > r.m_pn->up; }
-template<class A>
-struct select_multiallocation_chain<A, 1>
-{
- typedef typename boost::intrusive::pointer_traits
- <typename allocator_traits<A>::pointer>::
- template rebind_pointer<void>::type void_ptr;
- typedef container_detail::basic_multiallocation_chain
- <void_ptr> multialloc_cached_counted;
- typedef boost::container::container_detail::
- transform_multiallocation_chain
- < multialloc_cached_counted
- , typename allocator_traits<A>::value_type> type;
+ friend bool operator>= (const stable_vector_iterator& l, const stable_vector_iterator& r) BOOST_CONTAINER_NOEXCEPT
+ { return l.m_pn->up >= r.m_pn->up; }
};
-} //namespace stable_vector_detail
-
-#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ #if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING)
-#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();
-#define STABLE_VECTOR_CHECK_INVARIANT \
-invariant_checker BOOST_JOIN(check_invariant_,__LINE__)(*this); \
-BOOST_JOIN(check_invariant_,__LINE__).touch();
-#else
+ #else //STABLE_VECTOR_ENABLE_INVARIANT_CHECKING
-#define STABLE_VECTOR_CHECK_INVARIANT
+ #define STABLE_VECTOR_CHECK_INVARIANT
-#endif //#if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING)
+ #endif //#if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING)
-#endif //#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
-/// @endcond
-
-//! Originally developed by Joaquin M. Lopez Munoz, stable_vector is std::vector
+//! 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.
//!
-//! More details taken the author's blog:
+//! 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>)
+//! 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.
+//! 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
@@ -353,46 +405,53 @@ BOOST_JOIN(check_invariant_,__LINE__).touch();
//! 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:
+//! 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 A = std::allocator<T> >
+template <class T, class Allocator = std::allocator<T> >
#else
-template <class T, class A>
+template <class T, class Allocator>
#endif
class stable_vector
{
- ///@cond
- typedef allocator_traits<A> allocator_traits_type;
- typedef typename container_detail::
- move_const_ref_type<T>::type insert_const_ref_type;
- typedef typename boost::intrusive::pointer_traits
- <typename allocator_traits_type::pointer>::
+ #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 boost::intrusive::pointer_traits
- <void_ptr>::template
- rebind_pointer<const void>::type const_void_ptr;
- typedef typename boost::intrusive::pointer_traits
- <void_ptr>::template
- rebind_pointer<void_ptr>::type void_ptr_ptr;
- typedef typename boost::intrusive::pointer_traits
- <void_ptr>::template
- rebind_pointer<const void_ptr>::type const_void_ptr_ptr;
- typedef stable_vector_detail::node_type
- <void_ptr, T> node_type_t;
- typedef typename boost::intrusive::pointer_traits
- <void_ptr>::template
- rebind_pointer<node_type_t>::type node_type_ptr_t;
- typedef stable_vector_detail::node_type_base
- <void_ptr> node_type_base_t;
- typedef typename boost::intrusive::pointer_traits
- <void_ptr>::template
- rebind_pointer<node_type_base_t>::type node_type_base_ptr_t;
- typedef ::boost::container::vector<void_ptr,
- typename allocator_traits_type::
- template portable_rebind_alloc
- <void_ptr>::type> impl_type;
- typedef typename impl_type::iterator impl_iterator;
- typedef typename impl_type::const_iterator const_impl_iterator;
+ 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::container_detail::
integral_constant<unsigned, 1> allocator_v1;
@@ -400,85 +459,74 @@ class stable_vector
integral_constant<unsigned, 2> allocator_v2;
typedef ::boost::container::container_detail::integral_constant
<unsigned, boost::container::container_detail::
- version<A>::value> alloc_version;
+ version<Allocator>::value> alloc_version;
typedef typename allocator_traits_type::
template portable_rebind_alloc
- <node_type_t>::type node_allocator_type;
-
- node_type_ptr_t allocate_one()
- { return this->allocate_one(alloc_version()); }
-
- template<class AllocatorVersion>
- node_type_ptr_t allocate_one(AllocatorVersion,
- typename boost::container::container_detail::enable_if_c
- <boost::container::container_detail::is_same<AllocatorVersion, allocator_v1>
- ::value>::type * = 0)
- { return node_alloc().allocate(1); }
-
- template<class AllocatorVersion>
- node_type_ptr_t allocate_one(AllocatorVersion,
- typename boost::container::container_detail::enable_if_c
- <!boost::container::container_detail::is_same<AllocatorVersion, allocator_v1>
- ::value>::type * = 0)
- { return node_alloc().allocate_one(); }
-
- void deallocate_one(node_type_ptr_t p)
- { return this->deallocate_one(p, alloc_version()); }
-
- template<class AllocatorVersion>
- void deallocate_one(node_type_ptr_t p, AllocatorVersion,
- typename boost::container::container_detail::enable_if_c
- <boost::container::container_detail::is_same<AllocatorVersion, allocator_v1>
- ::value>::type * = 0)
- { node_alloc().deallocate(p, 1); }
-
- template<class AllocatorVersion>
- void deallocate_one(node_type_ptr_t p, AllocatorVersion,
- typename boost::container::container_detail::enable_if_c
- <!boost::container::container_detail::is_same<AllocatorVersion, allocator_v1>
- ::value>::type * = 0)
- { node_alloc().deallocate_one(p); }
+ <node_type>::type node_allocator_type;
+
+ typedef ::boost::container::container_detail::
+ 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>;
- ///@endcond
+ typedef stable_vector_iterator
+ < typename allocator_traits<Allocator>::pointer
+ , false> iterator_impl;
+ typedef stable_vector_iterator
+ < typename allocator_traits<Allocator>::pointer
+ , false> const_iterator_impl;
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public:
-
- // types:
-
- typedef typename allocator_traits_type::reference reference;
- typedef typename allocator_traits_type::const_reference const_reference;
- typedef typename allocator_traits_type::pointer pointer;
- typedef typename allocator_traits_type::const_pointer const_pointer;
- typedef stable_vector_detail::iterator
- <T,T&, pointer> iterator;
- typedef stable_vector_detail::iterator
- <T,const T&, const_pointer> const_iterator;
- typedef typename impl_type::size_type size_type;
- typedef typename iterator::difference_type difference_type;
- typedef T value_type;
- typedef A allocator_type;
- typedef std::reverse_iterator<iterator> reverse_iterator;
- typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
- typedef node_allocator_type stored_allocator_type;
-
- ///@cond
+ //////////////////////////////////////////////
+ //
+ // 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(container_detail::reverse_iterator<iterator>) reverse_iterator;
+ typedef BOOST_CONTAINER_IMPDEF(container_detail::reverse_iterator<const_iterator>) const_reverse_iterator;
+
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
BOOST_COPYABLE_AND_MOVABLE(stable_vector)
- static const size_type ExtraPointers = 3;
- //This container stores metadata at the end of the void_ptr vector with additional 3 pointers:
- // back() is impl.back() - ExtraPointers;
- // end node index is impl.end()[-3]
- // Node cache first is impl.end()[-2];
- // Node cache last is *impl.back();
-
- typedef typename stable_vector_detail::
- select_multiallocation_chain
- < node_allocator_type
- , alloc_version::value
- >::type multiallocation_chain;
- ///@endcond
+ 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.
//!
@@ -486,31 +534,31 @@ class stable_vector
//!
//! <b>Complexity</b>: Constant.
stable_vector()
- : internal_data(), impl()
+ : internal_data(), index()
{
STABLE_VECTOR_CHECK_INVARIANT;
}
//! <b>Effects</b>: Constructs a stable_vector taking the allocator as parameter.
//!
- //! <b>Throws</b>: If allocator_type's copy constructor throws.
+ //! <b>Throws</b>: Nothing
//!
//! <b>Complexity</b>: Constant.
- explicit stable_vector(const allocator_type& al)
- : internal_data(al),impl(al)
+ explicit stable_vector(const allocator_type& al) BOOST_CONTAINER_NOEXCEPT
+ : internal_data(al), index(al)
{
STABLE_VECTOR_CHECK_INVARIANT;
}
//! <b>Effects</b>: Constructs a stable_vector that will use a copy of allocator a
- //! and inserts n default contructed values.
+ //! and inserts n value initialized values.
//!
- //! <b>Throws</b>: If allocator_type's default constructor or copy constructor
+ //! <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(),impl()
+ : internal_data(), index()
{
stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
this->resize(n);
@@ -519,17 +567,35 @@ class stable_vector
}
//! <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)
+ : 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 copies of value.
//!
- //! <b>Throws</b>: If allocator_type's default constructor or copy constructor
+ //! <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),impl(al)
+ : internal_data(al), index(al)
{
stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
- this->insert(this->cbegin(), n, t);
+ this->insert(this->cend(), n, t);
STABLE_VECTOR_CHECK_INVARIANT;
cod.release();
}
@@ -537,16 +603,16 @@ class stable_vector
//! <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 or copy constructor
- //! throws or T's constructor taking an dereferenced InIt throws.
+ //! <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),impl(al)
+ : internal_data(al), index(al)
{
stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
- this->insert(this->cbegin(), first, last);
+ this->insert(this->cend(), first, last);
STABLE_VECTOR_CHECK_INVARIANT;
cod.release();
}
@@ -558,15 +624,33 @@ class stable_vector
//! <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.node_alloc()))
- , impl(allocator_traits<allocator_type>::
- select_on_container_copy_construction(x.impl.get_stored_allocator()))
+ 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);
- this->insert(this->cbegin(), x.begin(), x.end());
+ insert(cend(), il.begin(), il.end())
STABLE_VECTOR_CHECK_INVARIANT;
cod.release();
}
+#endif
//! <b>Effects</b>: Move constructor. Moves mx's resources to *this.
//!
@@ -574,7 +658,7 @@ class stable_vector
//!
//! <b>Complexity</b>: Constant.
stable_vector(BOOST_RV_REF(stable_vector) x)
- : internal_data(boost::move(x.node_alloc())), impl(boost::move(x.impl))
+ : internal_data(boost::move(x.priv_node_alloc())), index(boost::move(x.index))
{
this->priv_swap_members(x);
}
@@ -585,10 +669,10 @@ class stable_vector
//!
//! <b>Complexity</b>: Linear to the elements x contains.
stable_vector(const stable_vector& x, const allocator_type &a)
- : internal_data(a), impl(a)
+ : internal_data(a), index(a)
{
stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
- this->insert(this->cbegin(), x.begin(), x.end());
+ this->insert(this->cend(), x.begin(), x.end());
STABLE_VECTOR_CHECK_INVARIANT;
cod.release();
}
@@ -600,14 +684,14 @@ class stable_vector
//!
//! <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), impl(a)
+ : internal_data(a), index(a)
{
- if(this->node_alloc() == x.node_alloc()){
+ if(this->priv_node_alloc() == x.priv_node_alloc()){
this->priv_swap_members(x);
}
else{
stable_vector_detail::clear_on_destroy<stable_vector> cod(*this);
- this->insert(this->cbegin(), x.begin(), x.end());
+ this->insert(this->cend(), x.begin(), x.end());
STABLE_VECTOR_CHECK_INVARIANT;
cod.release();
}
@@ -622,7 +706,7 @@ class stable_vector
~stable_vector()
{
this->clear();
- clear_pool();
+ this->priv_clear_pool();
}
//! <b>Effects</b>: Makes *this contain the same elements as x.
@@ -637,16 +721,16 @@ class stable_vector
{
STABLE_VECTOR_CHECK_INVARIANT;
if (&x != this){
- node_allocator_type &this_alloc = this->node_alloc();
- const node_allocator_type &x_alloc = x.node_alloc();
+ node_allocator_type &this_alloc = this->priv_node_alloc();
+ const node_allocator_type &x_alloc = x.priv_node_alloc();
container_detail::bool_<allocator_traits_type::
propagate_on_container_copy_assignment::value> flag;
if(flag && this_alloc != x_alloc){
this->clear();
this->shrink_to_fit();
}
- container_detail::assign_alloc(this->node_alloc(), x.node_alloc(), flag);
- container_detail::assign_alloc(this->impl.get_stored_allocator(), x.impl.get_stored_allocator(), flag);
+ container_detail::assign_alloc(this->priv_node_alloc(), x.priv_node_alloc(), flag);
+ container_detail::assign_alloc(this->index.get_stored_allocator(), x.index.get_stored_allocator(), flag);
this->assign(x.begin(), x.end());
}
return *this;
@@ -657,35 +741,65 @@ class stable_vector
//! <b>Postcondition</b>: x.empty(). *this contains a the elements x had
//! before the function.
//!
- //! <b>Throws</b>: If allocator_type's copy constructor throws.
+ //! <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>: Linear.
+ //! <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)
- {
- if (&x != this){
- node_allocator_type &this_alloc = this->node_alloc();
- node_allocator_type &x_alloc = x.node_alloc();
- //If allocators are equal we can just swap pointers
- if(this_alloc == x_alloc){
- //Destroy objects but retain memory
- this->clear();
- this->impl = boost::move(x.impl);
- this->priv_swap_members(x);
- //Move allocator if needed
- container_detail::bool_<allocator_traits_type::
- propagate_on_container_move_assignment::value> flag;
- container_detail::move_alloc(this->node_alloc(), x.node_alloc(), flag);
- }
- //If unequal allocators, then do a one by one move
- else{
- typedef typename std::iterator_traits<iterator>::iterator_category ItCat;
- this->assign( boost::make_move_iterator(x.begin())
- , boost::make_move_iterator(x.end()));
- }
+ BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::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;
+ container_detail::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
+ container_detail::move_alloc(this_alloc, x_alloc, flag);
+ //Take resources
+ this->index = boost::move(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
@@ -693,29 +807,47 @@ class stable_vector
//!
//! <b>Complexity</b>: Linear to n.
template<typename InputIterator>
- void assign(InputIterator first,InputIterator last)
+ void assign(InputIterator first,InputIterator last
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename container_detail::enable_if_c
+ < !container_detail::is_convertible<InputIterator, size_type>::value
+ >::type * = 0
+ #endif
+ )
{
- assign_dispatch(first, last, boost::is_integral<InputIterator>());
+ 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);
+ }
}
-
- //! <b>Effects</b>: Assigns the n copies of val to *this.
+#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 copy constructor throws.
+ //! <b>Throws</b>: If memory allocation throws or
+ //! T's constructor from dereferencing initializer_list iterator throws.
//!
- //! <b>Complexity</b>: Linear to n.
- void assign(size_type n,const T& t)
+ void assign(std::initializer_list<value_type> il)
{
- typedef constant_iterator<value_type, difference_type> cvalue_iterator;
- return assign_dispatch(cvalue_iterator(t, n), cvalue_iterator(), boost::mpl::false_());
+ 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->node_alloc();}
+ allocator_type get_allocator() const
+ { return this->priv_node_alloc(); }
//! <b>Effects</b>: Returns a reference to the internal allocator.
//!
@@ -725,7 +857,7 @@ class stable_vector
//!
//! <b>Note</b>: Non-standard extension.
const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT
- { return node_alloc(); }
+ { return this->priv_node_alloc(); }
//! <b>Effects</b>: Returns a reference to the internal allocator.
//!
@@ -735,38 +867,45 @@ class stable_vector
//!
//! <b>Note</b>: Non-standard extension.
stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT
- { return node_alloc(); }
+ { 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()
- { return (impl.empty()) ? end(): iterator(node_ptr_cast(impl.front())) ; }
+ iterator begin() BOOST_CONTAINER_NOEXCEPT
+ { 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
- { return (impl.empty()) ? cend() : const_iterator(node_ptr_cast(impl.front())) ; }
+ const_iterator begin() const BOOST_CONTAINER_NOEXCEPT
+ { 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() {return iterator(get_end_node());}
+ iterator end() BOOST_CONTAINER_NOEXCEPT
+ { 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 {return const_iterator(get_end_node());}
+ const_iterator end() const BOOST_CONTAINER_NOEXCEPT
+ { return const_iterator(this->priv_get_end_node()); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
//! of the reversed stable_vector.
@@ -774,7 +913,8 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- reverse_iterator rbegin() {return reverse_iterator(this->end());}
+ reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT
+ { return reverse_iterator(this->end()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
//! of the reversed stable_vector.
@@ -782,7 +922,8 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reverse_iterator rbegin()const {return const_reverse_iterator(this->end());}
+ const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT
+ { return const_reverse_iterator(this->end()); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the end
//! of the reversed stable_vector.
@@ -790,7 +931,8 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- reverse_iterator rend() {return reverse_iterator(this->begin());}
+ reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT
+ { return reverse_iterator(this->begin()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
//! of the reversed stable_vector.
@@ -798,21 +940,24 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reverse_iterator rend()const {return const_reverse_iterator(this->begin());}
+ const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT
+ { 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 {return this->begin();}
+ const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT
+ { 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 {return this->end();}
+ const_iterator cend() const BOOST_CONTAINER_NOEXCEPT
+ { return this->end(); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
//! of the reversed stable_vector.
@@ -820,7 +965,8 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reverse_iterator crbegin()const{return this->rbegin();}
+ const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT
+ { return this->rbegin(); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
//! of the reversed stable_vector.
@@ -828,81 +974,110 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reverse_iterator crend()const {return this->rend();}
+ const_reverse_iterator crend()const BOOST_CONTAINER_NOEXCEPT
+ { return this->rend(); }
- //! <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
- { return impl.empty() ? 0 : (impl.size() - ExtraPointers); }
+ //////////////////////////////////////////////
+ //
+ // capacity
+ //
+ //////////////////////////////////////////////
- //! <b>Effects</b>: Returns the largest possible size of the stable_vector.
+ //! <b>Effects</b>: Returns true if the stable_vector contains no elements.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- size_type max_size() const
- { return impl.max_size() - ExtraPointers; }
+ bool empty() const BOOST_CONTAINER_NOEXCEPT
+ { return this->index.size() <= ExtraPointers; }
- //! <b>Effects</b>: Number of elements for which memory has been allocated.
- //! capacity() is always greater than or equal to size().
+ //! <b>Effects</b>: Returns the number of the elements contained in the stable_vector.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- size_type capacity() const
+ size_type size() const BOOST_CONTAINER_NOEXCEPT
{
- if(!impl.capacity()){
- return 0;
- }
- else{
- const size_type num_nodes = this->impl.size() + this->internal_data.pool_size;
- const size_type num_buck = this->impl.capacity();
- return (num_nodes < num_buck) ? num_nodes : num_buck;
- }
+ const size_type index_size = this->index.size();
+ return (index_size - ExtraPointers) & (std::size_t(0u) -std::size_t(index_size != 0));
}
- //! <b>Effects</b>: Returns true if the stable_vector contains no elements.
+ //! <b>Effects</b>: Returns the largest possible size of the stable_vector.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- bool empty() const
- { return impl.empty() || impl.size() == ExtraPointers; }
+ size_type max_size() const BOOST_CONTAINER_NOEXCEPT
+ { 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 copy constructed from x.
+ //! the size becomes n. New elements are value initialized.
//!
- //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
+ //! <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, const T& t)
+ void resize(size_type n)
{
+ typedef value_init_construct_iterator<value_type, difference_type> value_init_iterator;
STABLE_VECTOR_CHECK_INVARIANT;
- if(n > size())
- this->insert(this->cend(), n - this->size(), t);
+ 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 default constructed.
+ //! 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)
+ void resize(size_type n, const T& t)
{
- typedef default_construct_iterator<value_type, difference_type> default_iterator;
STABLE_VECTOR_CHECK_INVARIANT;
- if(n > size())
- this->insert(this->cend(), default_iterator(n - this->size()), default_iterator());
+ 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_CONTAINER_NOEXCEPT
+ {
+ const size_type index_size = this->index.size();
+ BOOST_ASSERT(!index_size || index_size >= ExtraPointers);
+ const size_type bucket_extra_capacity = this->index.capacity()- index_size;
+ const size_type node_extra_capacity = this->internal_data.pool_size;
+ const size_type extra_capacity = (bucket_extra_capacity < node_extra_capacity)
+ ? bucket_extra_capacity : node_extra_capacity;
+ const size_type index_offset =
+ (ExtraPointers + extra_capacity) & (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
@@ -912,76 +1087,63 @@ class stable_vector
void reserve(size_type n)
{
STABLE_VECTOR_CHECK_INVARIANT;
- if(n > this->max_size())
- throw std::bad_alloc();
+ if(n > this->max_size()){
+ throw_length_error("stable_vector::reserve max_size() exceeded");
+ }
- size_type size = this->size();
+ size_type sz = this->size();
size_type old_capacity = this->capacity();
if(n > old_capacity){
- this->initialize_end_node(n);
- const void * old_ptr = &impl[0];
- impl.reserve(n + ExtraPointers);
- bool realloced = &impl[0] != old_ptr;
+ 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){
- this->align_nodes(impl.begin(), impl.begin()+size+1);
+ index_traits_type::fix_up_pointers_from(this->index, this->index.begin());
}
//Now fill pool if data is not enough
- if((n - size) > this->internal_data.pool_size){
- this->add_to_pool((n - size) - this->internal_data.pool_size);
+ if((n - sz) > this->internal_data.pool_size){
+ this->priv_increase_pool((n - sz) - this->internal_data.pool_size);
}
}
}
- //! <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){return value(impl[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{return value(impl[n]);}
-
- //! <b>Requires</b>: size() > n.
- //!
- //! <b>Effects</b>: Returns a reference to the nth element
- //! from the beginning of the container.
+ //! <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>: std::range_error if n >= size()
+ //! <b>Throws</b>: If memory allocation throws.
//!
- //! <b>Complexity</b>: Constant.
- reference at(size_type n)
+ //! <b>Complexity</b>: Linear to size().
+ void shrink_to_fit()
{
- if(n>=size())
- throw std::out_of_range("invalid subscript at stable_vector::at");
- return operator[](n);
+ 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());
+ }
+ }
+ }
}
- //! <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>=size())
- throw std::out_of_range("invalid subscript at stable_vector::at");
- return operator[](n);
- }
+ //////////////////////////////////////////////
+ //
+ // element access
+ //
+ //////////////////////////////////////////////
//! <b>Requires</b>: !empty()
//!
@@ -991,8 +1153,8 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- reference front()
- { return value(impl.front()); }
+ reference front() BOOST_CONTAINER_NOEXCEPT
+ { return static_cast<node_reference>(*this->index.front()).value; }
//! <b>Requires</b>: !empty()
//!
@@ -1002,8 +1164,8 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reference front()const
- { return value(impl.front()); }
+ const_reference front() const BOOST_CONTAINER_NOEXCEPT
+ { return static_cast<const_node_reference>(*this->index.front()).value; }
//! <b>Requires</b>: !empty()
//!
@@ -1013,8 +1175,8 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- reference back()
- { return value(*(&impl.back() - ExtraPointers)); }
+ reference back() BOOST_CONTAINER_NOEXCEPT
+ { return static_cast<node_reference>(*this->index[this->size()-1u]).value; }
//! <b>Requires</b>: !empty()
//!
@@ -1024,113 +1186,75 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reference back()const
- { return value(*(&impl.back() - ExtraPointers)); }
+ const_reference back() const BOOST_CONTAINER_NOEXCEPT
+ { return static_cast<const_node_reference>(*this->index[this->size()-1u]).value; }
- //! <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(insert_const_ref_type x)
- { return priv_push_back(x); }
-
- #if defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- void push_back(T &x) { push_back(const_cast<const T &>(x)); }
-
- template<class U>
- void push_back(const U &u, typename container_detail::enable_if_c
- <container_detail::is_same<T, U>::value && !::boost::has_move_emulation_enabled<U>::value >::type* =0)
- { return priv_push_back(u); }
- #endif
-
- //! <b>Effects</b>: Constructs a new element in the end of the stable_vector
- //! and moves the resources of mx to this new element.
- //!
- //! <b>Throws</b>: If memory allocation throws.
+ //! <b>Requires</b>: size() > n.
//!
- //! <b>Complexity</b>: Amortized constant time.
- void push_back(BOOST_RV_REF(T) t)
- { this->insert(end(), boost::move(t)); }
-
- //! <b>Effects</b>: Removes the last element from the stable_vector.
+ //! <b>Effects</b>: Returns a reference to the nth element
+ //! from the beginning of the container.
//!
//! <b>Throws</b>: Nothing.
//!
- //! <b>Complexity</b>: Constant time.
- void pop_back()
- { this->erase(this->end()-1); }
-
- //! <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 x's copy constructor throws.
- //!
- //! <b>Complexity</b>: If position is end(), amortized constant time
- //! Linear time otherwise.
- iterator insert(const_iterator position, insert_const_ref_type x)
- { return this->priv_insert(position, x); }
-
- #if defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
- iterator insert(const_iterator position, T &x) { return this->insert(position, const_cast<const T &>(x)); }
-
- template<class U>
- iterator insert(const_iterator position, const U &u, typename container_detail::enable_if_c
- <container_detail::is_same<T, U>::value && !::boost::has_move_emulation_enabled<U>::value >::type* =0)
- { return this->priv_insert(position, u); }
- #endif
+ //! <b>Complexity</b>: Constant.
+ reference operator[](size_type n) BOOST_CONTAINER_NOEXCEPT
+ {
+ BOOST_ASSERT(n < this->size());
+ return static_cast<node_reference>(*this->index[n]).value;
+ }
- //! <b>Requires</b>: position must be a valid iterator of *this.
+ //! <b>Requires</b>: size() > n.
//!
- //! <b>Effects</b>: Insert a new element before position with mx's resources.
+ //! <b>Effects</b>: Returns a const reference to the nth element
+ //! from the beginning of the container.
//!
- //! <b>Throws</b>: If memory allocation throws.
+ //! <b>Throws</b>: Nothing.
//!
- //! <b>Complexity</b>: If position is end(), amortized constant time
- //! Linear time otherwise.
- iterator insert(const_iterator position, BOOST_RV_REF(T) x)
- {
- typedef repeat_iterator<T, difference_type> repeat_it;
- typedef boost::move_iterator<repeat_it> repeat_move_it;
- //Just call more general insert(pos, size, value) and return iterator
- size_type pos_n = position - cbegin();
- this->insert(position
- ,repeat_move_it(repeat_it(x, 1))
- ,repeat_move_it(repeat_it()));
- return iterator(this->begin() + pos_n);
+ //! <b>Complexity</b>: Constant.
+ const_reference operator[](size_type n) const BOOST_CONTAINER_NOEXCEPT
+ {
+ BOOST_ASSERT(n < this->size());
+ return static_cast<const_node_reference>(*this->index[n]).value;
}
- //! <b>Requires</b>: pos must be a valid iterator of *this.
+ //! <b>Requires</b>: size() > n.
//!
- //! <b>Effects</b>: Insert n copies of x before pos.
+ //! <b>Effects</b>: Returns a reference to the nth element
+ //! from the beginning of the container.
//!
- //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
+ //! <b>Throws</b>: std::range_error if n >= size()
//!
- //! <b>Complexity</b>: Linear to n.
- void insert(const_iterator position, size_type n, const T& t)
+ //! <b>Complexity</b>: Constant.
+ reference at(size_type n)
{
- STABLE_VECTOR_CHECK_INVARIANT;
- this->insert_not_iter(position, n, t);
+ if(n >= this->size()){
+ throw_out_of_range("vector::at invalid subscript");
+ }
+ return operator[](n);
}
- //! <b>Requires</b>: pos must be a valid iterator of *this.
+ //! <b>Requires</b>: size() > n.
//!
- //! <b>Effects</b>: Insert a copy of the [first, last) range before pos.
+ //! <b>Effects</b>: Returns a const reference to the nth element
+ //! from the beginning of the container.
//!
- //! <b>Throws</b>: If memory allocation throws, T's constructor from a
- //! dereferenced InpIt throws or T's copy constructor throws.
+ //! <b>Throws</b>: std::range_error if n >= size()
//!
- //! <b>Complexity</b>: Linear to std::distance [first, last).
- template <class InputIterator>
- void insert(const_iterator position,InputIterator first, InputIterator last)
+ //! <b>Complexity</b>: Constant.
+ const_reference at(size_type n)const
{
- STABLE_VECTOR_CHECK_INVARIANT;
- this->insert_iter(position,first,last,
- boost::mpl::not_<boost::is_integral<InputIterator> >());
+ if(n >= this->size()){
+ throw_out_of_range("vector::at invalid subscript");
+ }
+ return operator[](n);
}
+ //////////////////////////////////////////////
+ //
+ // modifiers
+ //
+ //////////////////////////////////////////////
+
#if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! <b>Effects</b>: Inserts an object of type T constructed with
@@ -1148,24 +1272,23 @@ class stable_vector
this->insert(this->cend(), EmplaceIterator(ef), EmplaceIterator());
}
- //! <b>Requires</b>: position must be a valid iterator of *this.
+ //! <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 position
+ //! std::forward<Args>(args)... before p
//!
//! <b>Throws</b>: If memory allocation throws or the in-place constructor throws.
//!
- //! <b>Complexity</b>: If position is end(), amortized constant time
+ //! <b>Complexity</b>: If p is end(), amortized constant time
//! Linear time otherwise.
template<class ...Args>
- iterator emplace(const_iterator position, Args && ...args)
+ iterator emplace(const_iterator p, Args && ...args)
{
- //Just call more general insert(pos, size, value) and return iterator
- size_type pos_n = position - cbegin();
+ 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(position, EmplaceIterator(ef), EmplaceIterator());
+ this->insert(p, EmplaceIterator(ef), EmplaceIterator());
return iterator(this->begin() + pos_n);
}
@@ -1186,7 +1309,7 @@ class stable_vector
} \
\
BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
- iterator emplace(const_iterator pos \
+ iterator emplace(const_iterator p \
BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
{ \
typedef BOOST_PP_CAT(BOOST_PP_CAT(emplace_functor, n), arg) \
@@ -1196,8 +1319,8 @@ class stable_vector
EmplaceFunctor ef BOOST_PP_LPAREN_IF(n) \
BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) \
BOOST_PP_RPAREN_IF(n); \
- size_type pos_n = pos - this->cbegin(); \
- this->insert(pos, EmplaceIterator(ef), EmplaceIterator()); \
+ size_type pos_n = p - this->cbegin(); \
+ this->insert(p, EmplaceIterator(ef), EmplaceIterator()); \
return iterator(this->begin() + pos_n); \
} \
//!
@@ -1206,21 +1329,178 @@ class stable_vector
#endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
- //! <b>Effects</b>: Erases the element at position pos.
+ #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 mx 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 mx'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)
+ {
+ 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 std::distance [il.begin(), il.end()).
+ iterator insert(const_iterator p, std::initializer_list<value_type> il)
+ {
+ 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 std::distance [first, last).
+ template <class InputIterator>
+ iterator insert(const_iterator p, InputIterator first, InputIterator last
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename container_detail::enable_if_c
+ < !container_detail::is_convertible<InputIterator, size_type>::value
+ && container_detail::is_input_iterator<InputIterator>::value
+ >::type * = 0
+ #endif
+ )
+ {
+ 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>
+ iterator insert(const_iterator p, FwdIt first, FwdIt last
+ , typename container_detail::enable_if_c
+ < !container_detail::is_convertible<FwdIt, size_type>::value
+ && !container_detail::is_input_iterator<FwdIt>::value
+ >::type * = 0
+ )
+ {
+ const size_type num_new = static_cast<size_type>(std::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 p = this->priv_get_from_pool();
+ BOOST_ASSERT(!!p);
+ //Put it in the index so rollback can return it in pool if construct_in_place throws
+ *it_past_newly_constructed = p;
+ //Constructs and fixes up pointers This can throw
+ this->priv_build_node_from_it(p, 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_CONTAINER_NOEXCEPT
+ { this->erase(--this->cend()); }
+
+ //! <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. Constant if pos is the last element.
- iterator erase(const_iterator position)
+ //! <b>Complexity</b>: Linear to the elements between p and the
+ //! last element. Constant if p is the last element.
+ iterator erase(const_iterator p) BOOST_CONTAINER_NOEXCEPT
{
STABLE_VECTOR_CHECK_INVARIANT;
- difference_type d = position - this->cbegin();
- impl_iterator it = impl.begin() + d;
- this->delete_node(*it);
- it = impl.erase(it);
- this->align_nodes(it, get_last_align());
- return this->begin()+d;
+ 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).
@@ -1228,9 +1508,32 @@ class stable_vector
//! <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)
- { return priv_erase(first, last, alloc_version()); }
+ //! plus linear to the elements between p and the last element.
+ iterator erase(const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT
+ {
+ 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.
//!
@@ -1241,9 +1544,9 @@ class stable_vector
{
STABLE_VECTOR_CHECK_INVARIANT;
container_detail::bool_<allocator_traits_type::propagate_on_container_swap::value> flag;
- container_detail::swap_alloc(this->node_alloc(), x.node_alloc(), flag);
+ container_detail::swap_alloc(this->priv_node_alloc(), x.priv_node_alloc(), flag);
//vector's allocator is swapped here
- this->impl.swap(x.impl);
+ this->index.swap(x.index);
this->priv_swap_members(x);
}
@@ -1252,459 +1555,330 @@ class stable_vector
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Linear to the number of elements in the stable_vector.
- void clear()
+ void clear() BOOST_CONTAINER_NOEXCEPT
{ this->erase(this->cbegin(),this->cend()); }
- //! <b>Effects</b>: Tries to deallocate the excess of memory created
- //! with previous allocations. The size of the stable_vector is unchanged
+ //! <b>Effects</b>: Returns true if x and y are equal
//!
- //! <b>Throws</b>: If memory allocation throws.
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator==(const stable_vector& x, const stable_vector& y)
+ { return x.size() == y.size() && std::equal(x.begin(), x.end(), y.begin()); }
+
+ //! <b>Effects</b>: Returns true if x and y are unequal
//!
- //! <b>Complexity</b>: Linear to size().
- void shrink_to_fit()
- {
- if(this->capacity()){
- //First empty allocated node pool
- this->clear_pool();
- //If empty completely destroy the index, let's recover default-constructed state
- if(this->empty()){
- this->impl.clear();
- this->impl.shrink_to_fit();
- this->internal_data.set_end_pointer_to_default_constructed();
- }
- //Otherwise, try to shrink-to-fit the index and readjust pointers if necessary
- else{
- const size_type size = this->size();
- const void* old_ptr = &impl[0];
- this->impl.shrink_to_fit();
- bool realloced = &impl[0] != old_ptr;
- //Fix the pointers for the newly allocated buffer
- if(realloced){
- this->align_nodes(impl.begin(), impl.begin()+size+1);
- }
- }
- }
- }
+ //! <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); }
- /// @cond
+ //! <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 std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
- iterator priv_insert(const_iterator position, const value_type &t)
- {
- typedef constant_iterator<value_type, difference_type> cvalue_iterator;
- return this->insert_iter(position, cvalue_iterator(t, 1), cvalue_iterator(), std::forward_iterator_tag());
- }
+ //! <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; }
- void priv_push_back(const value_type &t)
- { this->insert(end(), t); }
+ //! <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); }
- template<class AllocatorVersion>
- void clear_pool(AllocatorVersion,
- typename boost::container::container_detail::enable_if_c
- <boost::container::container_detail::is_same<AllocatorVersion, allocator_v1>
- ::value>::type * = 0)
- {
- if(!impl.empty() && impl.back()){
- void_ptr &pool_first_ref = impl.end()[-2];
- void_ptr &pool_last_ref = impl.back();
+ //! <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); }
- multiallocation_chain holder;
- holder.incorporate_after(holder.before_begin(), pool_first_ref, pool_last_ref, this->internal_data.pool_size);
- while(!holder.empty()){
- node_type_ptr_t n = holder.front();
- holder.pop_front();
- this->deallocate_one(n);
- }
- pool_first_ref = pool_last_ref = 0;
- this->internal_data.pool_size = 0;
- }
- }
+ //! <b>Effects</b>: x.swap(y)
+ //!
+ //! <b>Complexity</b>: Constant.
+ friend void swap(stable_vector& x, stable_vector& y)
+ { x.swap(y); }
- template<class AllocatorVersion>
- void clear_pool(AllocatorVersion,
- typename boost::container::container_detail::enable_if_c
- <!boost::container::container_detail::is_same<AllocatorVersion, allocator_v1>
- ::value>::type * = 0)
- {
- if(!impl.empty() && impl.back()){
- void_ptr &pool_first_ref = impl.end()[-2];
- void_ptr &pool_last_ref = impl.back();
- multiallocation_chain holder;
- holder.incorporate_after(holder.before_begin(), pool_first_ref, pool_last_ref, internal_data.pool_size);
- node_alloc().deallocate_individual(boost::move(holder));
- pool_first_ref = pool_last_ref = 0;
- this->internal_data.pool_size = 0;
- }
- }
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ private:
- void clear_pool()
+ class insert_rollback
{
- this->clear_pool(alloc_version());
- }
+ public:
- void add_to_pool(size_type n)
- {
- this->add_to_pool(n, alloc_version());
- }
+ 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)
+ {}
- template<class AllocatorVersion>
- void add_to_pool(size_type n, AllocatorVersion,
- typename boost::container::container_detail::enable_if_c
- <boost::container::container_detail::is_same<AllocatorVersion, allocator_v1>
- ::value>::type * = 0)
- {
- size_type remaining = n;
- while(remaining--){
- this->put_in_pool(this->allocate_one());
+ ~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);
+ }
}
- }
- template<class AllocatorVersion>
- void add_to_pool(size_type n, AllocatorVersion,
- typename boost::container::container_detail::enable_if_c
- <!boost::container::container_detail::is_same<AllocatorVersion, allocator_v1>
- ::value>::type * = 0)
- {
- void_ptr &pool_first_ref = impl.end()[-2];
- void_ptr &pool_last_ref = impl.back();
- multiallocation_chain holder;
- holder.incorporate_after(holder.before_begin(), pool_first_ref, pool_last_ref, internal_data.pool_size);
- //BOOST_STATIC_ASSERT((::boost::has_move_emulation_enabled<multiallocation_chain>::value == true));
- multiallocation_chain m (node_alloc().allocate_individual(n));
- holder.splice_after(holder.before_begin(), m, m.before_begin(), m.last(), n);
- this->internal_data.pool_size += n;
- std::pair<void_ptr, void_ptr> data(holder.extract_data());
- pool_first_ref = data.first;
- pool_last_ref = data.second;
- }
+ private:
+ stable_vector &m_sv;
+ index_iterator &m_it_past_constructed;
+ const index_iterator &m_it_past_new;
+ };
- void put_in_pool(node_type_ptr_t p)
+ class push_back_rollback
{
- void_ptr &pool_first_ref = impl.end()[-2];
- void_ptr &pool_last_ref = impl.back();
- multiallocation_chain holder;
- holder.incorporate_after(holder.before_begin(), pool_first_ref, pool_last_ref, internal_data.pool_size);
- holder.push_front(p);
- ++this->internal_data.pool_size;
- std::pair<void_ptr, void_ptr> ret(holder.extract_data());
- pool_first_ref = ret.first;
- pool_last_ref = ret.second;
- }
+ public:
+ push_back_rollback(stable_vector &sv, const node_ptr &p)
+ : m_sv(sv), m_p(p)
+ {}
- node_type_ptr_t get_from_pool()
- {
- if(!impl.back()){
- return node_type_ptr_t(0);
- }
- else{
- void_ptr &pool_first_ref = impl.end()[-2];
- void_ptr &pool_last_ref = impl.back();
- multiallocation_chain holder;
- holder.incorporate_after(holder.before_begin(), pool_first_ref, pool_last_ref, internal_data.pool_size);
- node_type_ptr_t ret = holder.front();
- holder.pop_front();
- --this->internal_data.pool_size;
- if(!internal_data.pool_size){
- pool_first_ref = pool_last_ref = void_ptr(0);
- }
- else{
- std::pair<void_ptr, void_ptr> data(holder.extract_data());
- pool_first_ref = data.first;
- pool_last_ref = data.second;
+ ~push_back_rollback()
+ {
+ if(m_p){
+ m_sv.priv_put_in_pool(m_p);
}
- return ret;
}
- }
- void insert_iter_prolog(size_type n, difference_type d)
- {
- initialize_end_node(n);
- const void* old_ptr = &impl[0];
- //size_type old_capacity = capacity();
- //size_type old_size = size();
- impl.insert(impl.begin()+d, n, 0);
- bool realloced = &impl[0] != old_ptr;
- //Fix the pointers for the newly allocated buffer
- if(realloced){
- align_nodes(impl.begin(), impl.begin()+d);
- }
- }
+ void release()
+ { m_p = node_ptr(); }
- template<typename InputIterator>
- void assign_dispatch(InputIterator first, InputIterator last, boost::mpl::false_)
+ private:
+ stable_vector &m_sv;
+ node_ptr m_p;
+ };
+
+ index_iterator priv_insert_forward_non_templated(size_type idx, size_type num_new)
{
- 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);
+ 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);
}
- else{
- this->insert(last1, first, last);
+
+ //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;
}
- template<typename Integer>
- void assign_dispatch(Integer n, Integer t, boost::mpl::true_)
+ bool priv_capacity_bigger_than_size() const
{
- typedef constant_iterator<value_type, difference_type> cvalue_iterator;
- this->assign_dispatch(cvalue_iterator(t, n), cvalue_iterator(), boost::mpl::false_());
+ return this->index.capacity() > this->index.size() &&
+ this->internal_data.pool_size > 0;
}
- iterator priv_erase(const_iterator first, const_iterator last, allocator_v1)
+ template <class U>
+ void priv_push_back(BOOST_MOVE_CATCH_FWD(U) x)
{
- STABLE_VECTOR_CHECK_INVARIANT;
- difference_type d1 = first - this->cbegin(), d2 = last - this->cbegin();
- if(d1 != d2){
- impl_iterator it1(impl.begin() + d1), it2(impl.begin() + d2);
- for(impl_iterator it = it1; it != it2; ++it)
- this->delete_node(*it);
- impl_iterator e = impl.erase(it1, it2);
- this->align_nodes(e, get_last_align());
+ if(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));
}
- return iterator(this->begin() + d1);
}
- impl_iterator get_last_align()
+ iterator priv_insert(const_iterator p, const value_type &t)
{
- return impl.end() - (ExtraPointers - 1);
+ typedef constant_iterator<value_type, difference_type> cvalue_iterator;
+ return this->insert(p, cvalue_iterator(t, 1), cvalue_iterator());
}
- const_impl_iterator get_last_align() const
+ iterator priv_insert(const_iterator p, BOOST_RV_REF(T) x)
{
- return impl.cend() - (ExtraPointers - 1);
+ 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()));
}
- template<class AllocatorVersion>
- iterator priv_erase(const_iterator first, const_iterator last, AllocatorVersion,
- typename boost::container::container_detail::enable_if_c
- <!boost::container::container_detail::is_same<AllocatorVersion, allocator_v1>
- ::value>::type * = 0)
+ void priv_clear_pool()
{
- STABLE_VECTOR_CHECK_INVARIANT;
- return priv_erase(first, last, allocator_v1());
- }
+ 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();
- static node_type_ptr_t node_ptr_cast(const void_ptr &p)
- {
- return node_type_ptr_t(static_cast<node_type_t*>(container_detail::to_raw_pointer(p)));
+ 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;
+ }
}
- static node_type_base_ptr_t node_base_ptr_cast(const void_ptr &p)
+ void priv_increase_pool(size_type n)
{
- return node_type_base_ptr_t(static_cast<node_type_base_t*>(container_detail::to_raw_pointer(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);
+ 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;
}
- static value_type& value(const void_ptr &p)
+ void priv_put_in_pool(const node_ptr &p)
{
- return node_ptr_cast(p)->value;
+ 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 initialize_end_node(size_type impl_capacity = 0)
+ void priv_put_in_pool(multiallocation_chain &ch)
{
- if(impl.empty()){
- impl.reserve(impl_capacity + ExtraPointers);
- impl.resize (ExtraPointers, void_ptr(0));
- impl[0] = &this->internal_data.end_node;
- this->internal_data.end_node.up = &impl[0];
- }
+ 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;
}
- void readjust_end_node()
+ node_ptr priv_get_from_pool()
{
- if(!this->impl.empty()){
- void_ptr &end_node_ref = *(this->get_last_align()-1);
- end_node_ref = this->get_end_node();
- this->internal_data.end_node.up = &end_node_ref;
+ //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{
- this->internal_data.end_node.up = void_ptr(&this->internal_data.end_node.up);
+ const std::pair<node_ptr, node_ptr> data(holder.extract_data());
+ pool_first_ref = data.first;
+ pool_last_ref = data.second;
}
+ return ret;
}
- node_type_ptr_t get_end_node() const
- {
- const node_type_base_t* cp = &this->internal_data.end_node;
- node_type_base_t* p = const_cast<node_type_base_t*>(cp);
- return node_ptr_cast(p);
- }
+ 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)); }
- template<class Iter>
- void_ptr new_node(const void_ptr &up, Iter it)
+ void priv_destroy_node(const node_type &n)
{
- node_type_ptr_t p = this->allocate_one();
- try{
- boost::container::construct_in_place(this->node_alloc(), container_detail::addressof(p->value), it);
- //This does not throw
- ::new(static_cast<node_type_base_t*>(container_detail::to_raw_pointer(p))) node_type_base_t;
- p->set_pointer(up);
- }
- catch(...){
- this->deallocate_one(p);
- throw;
- }
- return p;
- }
-
- void delete_node(const void_ptr &p)
- {
- node_type_ptr_t n(node_ptr_cast(p));
allocator_traits<node_allocator_type>::
- destroy(this->node_alloc(), container_detail::to_raw_pointer(n));
- this->put_in_pool(n);
+ destroy(this->priv_node_alloc(), container_detail::addressof(n.value));
+ static_cast<const node_base_type*>(&n)->~node_base_type();
}
- static void align_nodes(impl_iterator first, impl_iterator last)
+ void priv_delete_node(const node_ptr &n)
{
- while(first!=last){
- node_ptr_cast(*first)->up = void_ptr(&*first);
- ++first;
- }
+ this->priv_destroy_node(*n);
+ this->priv_put_in_pool(n);
}
- void insert_not_iter(const_iterator position, size_type n, const T& t)
+ template<class Iterator>
+ void priv_build_node_from_it(const node_ptr &p, const index_iterator &up_index, const Iterator &it)
{
- typedef constant_iterator<value_type, difference_type> cvalue_iterator;
- this->insert_iter(position, cvalue_iterator(t, n), cvalue_iterator(), std::forward_iterator_tag());
+ //This can throw
+ boost::container::construct_in_place
+ ( this->priv_node_alloc()
+ , container_detail::addressof(p->value)
+ , it);
+ //This does not throw
+ ::new(static_cast<node_base_type*>(container_detail::to_raw_pointer(p)), boost_container_new_t())
+ node_base_type(index_traits_type::ptr_to_node_base_ptr(*up_index));
}
- template <class InputIterator>
- void insert_iter(const_iterator position,InputIterator first,InputIterator last, boost::mpl::true_)
+ template<class ValueConvertible>
+ void priv_build_node_from_convertible(const node_ptr &p, BOOST_FWD_REF(ValueConvertible) value_convertible)
{
- typedef typename std::iterator_traits<InputIterator>::iterator_category category;
- this->insert_iter(position, first, last, category());
+ //This can throw
+ boost::container::allocator_traits<node_allocator_type>::construct
+ ( this->priv_node_alloc()
+ , container_detail::addressof(p->value)
+ , ::boost::forward<ValueConvertible>(value_convertible));
+ //This does not throw
+ ::new(static_cast<node_base_type*>(container_detail::to_raw_pointer(p)), boost_container_new_t()) node_base_type;
}
- template <class InputIterator>
- void insert_iter(const_iterator position,InputIterator first,InputIterator last,std::input_iterator_tag)
+ void priv_swap_members(stable_vector &x)
{
- for(; first!=last; ++first){
- this->insert(position, *first);
- }
- }
-
- template <class InputIterator>
- iterator insert_iter(const_iterator position, InputIterator first, InputIterator last, std::forward_iterator_tag)
- {
- size_type n = (size_type)std::distance(first,last);
- difference_type d = position-this->cbegin();
- if(n){
- this->insert_iter_prolog(n, d);
- const impl_iterator it(impl.begin() + d);
- this->insert_iter_fwd(it, first, last, n);
- //Fix the pointers for the newly allocated buffer
- this->align_nodes(it + n, get_last_align());
- }
- return this->begin() + d;
+ boost::container::swap_dispatch(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);
}
- template <class FwdIterator>
- void insert_iter_fwd_alloc(const impl_iterator it, FwdIterator first, FwdIterator last, difference_type n, allocator_v1)
+ #if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING)
+ bool priv_invariant()const
{
- size_type i=0;
- try{
- while(first!=last){
- it[i] = this->new_node(void_ptr_ptr(&it[i]), first);
- ++first;
- ++i;
- }
- }
- catch(...){
- impl_iterator e = impl.erase(it + i, it + n);
- this->align_nodes(e, get_last_align());
- throw;
- }
- }
-
- template <class FwdIterator>
- void insert_iter_fwd_alloc(const impl_iterator it, FwdIterator first, FwdIterator last, difference_type n, allocator_v2)
- {
- multiallocation_chain mem(node_alloc().allocate_individual(n));
-
- size_type i = 0;
- node_type_ptr_t p = 0;
- try{
- while(first != last){
- p = mem.front();
- mem.pop_front();
- //This can throw
- boost::container::construct_in_place(this->node_alloc(), container_detail::addressof(p->value), first);
- //This does not throw
- ::new(static_cast<node_type_base_t*>(container_detail::to_raw_pointer(p))) node_type_base_t;
- p->set_pointer(void_ptr_ptr(&it[i]));
- ++first;
- it[i] = p;
- ++i;
- }
- }
- catch(...){
- node_alloc().deallocate_one(p);
- node_alloc().deallocate_many(boost::move(mem));
- impl_iterator e = impl.erase(it+i, it+n);
- this->align_nodes(e, get_last_align());
- throw;
- }
- }
+ index_type & index_ref = const_cast<index_type&>(this->index);
- template <class FwdIterator>
- void insert_iter_fwd(const impl_iterator it, FwdIterator first, FwdIterator last, difference_type n)
- {
- size_type i = 0;
- node_type_ptr_t p = 0;
- try{
- while(first != last){
- p = this->get_from_pool();
- if(!p){
- insert_iter_fwd_alloc(it+i, first, last, n-i, alloc_version());
- break;
- }
- //This can throw
- boost::container::construct_in_place(this->node_alloc(), container_detail::addressof(p->value), first);
- //This does not throw
- ::new(static_cast<node_type_base_t*>(container_detail::to_raw_pointer(p))) node_type_base_t;
- p->set_pointer(void_ptr_ptr(&it[i]));
- ++first;
- it[i]=p;
- ++i;
- }
- }
- catch(...){
- put_in_pool(p);
- impl_iterator e = impl.erase(it+i, it+n);
- this->align_nodes(e, get_last_align());
- throw;
+ if(index.empty())
+ return !this->capacity() && !this->size();
+ if(this->priv_get_end_node() != *(index.end() - ExtraPointers)){
+ return false;
}
- }
- template <class InputIterator>
- void insert_iter(const_iterator position, InputIterator first, InputIterator last, boost::mpl::false_)
- {
- this->insert_not_iter(position, first, last);
- }
-
- #if defined(STABLE_VECTOR_ENABLE_INVARIANT_CHECKING)
- bool invariant()const
- {
- if(impl.empty())
- return !capacity() && !size();
- if(get_end_node() != *(impl.end() - ExtraPointers)){
+ if(!index_traits_type::invariants(index_ref)){
return false;
}
- for(const_impl_iterator it = impl.begin(), it_end = get_last_align(); it != it_end; ++it){
- if(const_void_ptr(node_ptr_cast(*it)->up) !=
- const_void_ptr(const_void_ptr_ptr(&*it)))
- return false;
- }
- size_type n = capacity()-size();
- const void_ptr &pool_head = impl.back();
+
+ 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;
- node_type_ptr_t p = node_ptr_cast(pool_head);
- while(p){
+ while(beg != end){
++num_pool;
- p = node_ptr_cast(p->up);
+ ++beg;
}
- return n >= num_pool;
+ return n >= num_pool && num_pool == internal_data.pool_size;
}
class invariant_checker
@@ -1715,7 +1889,7 @@ class stable_vector
public:
invariant_checker(const stable_vector& v):p(&v){}
- ~invariant_checker(){BOOST_ASSERT(p->invariant());}
+ ~invariant_checker(){BOOST_ASSERT(p->priv_invariant());}
void touch(){}
};
#endif
@@ -1725,103 +1899,48 @@ class stable_vector
{
private:
BOOST_MOVABLE_BUT_NOT_COPYABLE(ebo_holder)
+
public:
-/*
- explicit ebo_holder(BOOST_RV_REF(ebo_holder) x)
- : node_allocator_type(boost::move(static_cast<node_allocator_type&>(x)))
- , pool_size(0)
- , end_node()
- {}
-*/
template<class AllocatorRLValue>
explicit ebo_holder(BOOST_FWD_REF(AllocatorRLValue) a)
: node_allocator_type(boost::forward<AllocatorRLValue>(a))
, pool_size(0)
, end_node()
- {
- this->set_end_pointer_to_default_constructed();
- }
+ {}
ebo_holder()
: node_allocator_type()
, pool_size(0)
, end_node()
- {
- this->set_end_pointer_to_default_constructed();
- }
-
- void set_end_pointer_to_default_constructed()
- {
- end_node.set_pointer(void_ptr(&end_node.up));
- }
+ {}
size_type pool_size;
- node_type_base_t end_node;
+ node_base_type end_node;
} internal_data;
- void priv_swap_members(stable_vector &x)
- {
- container_detail::do_swap(this->internal_data.pool_size, x.internal_data.pool_size);
- this->readjust_end_node();
- x.readjust_end_node();
- }
-
- node_allocator_type &node_alloc() { return internal_data; }
- const node_allocator_type &node_alloc() const { return internal_data; }
+ node_allocator_type &priv_node_alloc() { return internal_data; }
+ const node_allocator_type &priv_node_alloc() const { return internal_data; }
- impl_type impl;
- /// @endcond
+ index_type index;
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
};
-template <typename T,typename A>
-bool operator==(const stable_vector<T,A>& x,const stable_vector<T,A>& y)
-{
- return x.size()==y.size()&&std::equal(x.begin(),x.end(),y.begin());
-}
-
-template <typename T,typename A>
-bool operator< (const stable_vector<T,A>& x,const stable_vector<T,A>& y)
-{
- return std::lexicographical_compare(x.begin(),x.end(),y.begin(),y.end());
-}
-
-template <typename T,typename A>
-bool operator!=(const stable_vector<T,A>& x,const stable_vector<T,A>& y)
-{
- return !(x==y);
-}
-
-template <typename T,typename A>
-bool operator> (const stable_vector<T,A>& x,const stable_vector<T,A>& y)
-{
- return y<x;
-}
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
-template <typename T,typename A>
-bool operator>=(const stable_vector<T,A>& x,const stable_vector<T,A>& y)
-{
- return !(x<y);
-}
-
-template <typename T,typename A>
-bool operator<=(const stable_vector<T,A>& x,const stable_vector<T,A>& y)
-{
- return !(x>y);
-}
+#undef STABLE_VECTOR_CHECK_INVARIANT
-// specialized algorithms:
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
-template <typename T, typename A>
-void swap(stable_vector<T,A>& x,stable_vector<T,A>& y)
-{
- x.swap(y);
-}
-
-/// @cond
+/*
-#undef STABLE_VECTOR_CHECK_INVARIANT
+//!has_trivial_destructor_after_move<> == true_type
+//!specialization for optimizations
+template <class T, class Allocator>
+struct has_trivial_destructor_after_move<boost::container::stable_vector<T, Allocator> >
+ : public has_trivial_destructor_after_move<Allocator>::value
+{};
-/// @endcond
+*/
}}
diff --git a/boost/container/static_vector.hpp b/boost/container/static_vector.hpp
new file mode 100644
index 0000000000..1ae80114b3
--- /dev/null
+++ b/boost/container/static_vector.hpp
@@ -0,0 +1,1156 @@
+// 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
+
+#if defined(_MSC_VER)
+# pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+
+#include <boost/container/vector.hpp>
+#include <boost/aligned_storage.hpp>
+
+namespace boost { namespace container {
+
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+namespace container_detail {
+
+template<class T, std::size_t N>
+class static_storage_allocator
+{
+ public:
+ typedef T value_type;
+
+ static_storage_allocator() BOOST_CONTAINER_NOEXCEPT
+ {}
+
+ static_storage_allocator(const static_storage_allocator &) BOOST_CONTAINER_NOEXCEPT
+ {}
+
+ static_storage_allocator & operator=(const static_storage_allocator &) BOOST_CONTAINER_NOEXCEPT
+ {}
+
+ T* internal_storage() const BOOST_CONTAINER_NOEXCEPT
+ { return const_cast<T*>(static_cast<const T*>(static_cast<const void*>(&storage))); }
+
+ T* internal_storage() BOOST_CONTAINER_NOEXCEPT
+ { return static_cast<T*>(static_cast<void*>(&storage)); }
+
+ static const std::size_t internal_capacity = N;
+
+ typedef boost::container::container_detail::version_type<static_storage_allocator, 0> version;
+
+ friend bool operator==(const static_storage_allocator &, const static_storage_allocator &) BOOST_CONTAINER_NOEXCEPT
+ { return false; }
+
+ friend bool operator!=(const static_storage_allocator &, const static_storage_allocator &) BOOST_CONTAINER_NOEXCEPT
+ { return true; }
+
+ private:
+ typename boost::aligned_storage
+ <sizeof(T)*N, boost::alignment_of<T>::value>::type storage;
+};
+
+} //namespace container_detail {
+
+#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, container_detail::static_storage_allocator<Value, Capacity> >
+{
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+ typedef vector<Value, container_detail::static_storage_allocator<Value, Capacity> > base_t;
+
+ BOOST_COPYABLE_AND_MOVABLE(static_vector)
+
+ template<class U, std::size_t OtherCapacity>
+ friend class static_vector;
+
+ #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 Constructs an empty static_vector.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ static_vector() BOOST_CONTAINER_NOEXCEPT
+ : 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).
+ 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
+ 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).
+ 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>
+ 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).
+ 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).
+ static_vector(static_vector const& other)
+ : base_t(other)
+ {}
+
+ //! @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>
+ 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 boost::has_nothrow_move<Value>::value is \c true and Value's move constructor throws.
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c false and Value's copy constructor throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ static_vector(BOOST_RV_REF(static_vector) other)
+ : base_t(boost::move(static_cast<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 boost::has_nothrow_move<Value>::value is \c true and Value's move constructor throws.
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c false and Value's copy constructor throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ template <std::size_t C>
+ static_vector(BOOST_RV_REF_BEG static_vector<value_type, C> BOOST_RV_REF_END other)
+ : base_t(boost::move(static_cast<typename static_vector<value_type, C>::base_t&>(other)))
+ {}
+
+ //! @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).
+ 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).
+ 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>
+ 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 boost::has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws.
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ static_vector & operator=(BOOST_RV_REF(static_vector) other)
+ {
+ return static_cast<static_vector&>(base_t::operator=(boost::move(static_cast<base_t&>(other))));
+ }
+
+ //! @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 boost::has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws.
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ template <std::size_t C>
+ static_vector & operator=(BOOST_RV_REF_BEG static_vector<value_type, C> BOOST_RV_REF_END other)
+ {
+ return static_cast<static_vector&>(base_t::operator=
+ (boost::move(static_cast<typename static_vector<value_type, C>::base_t&>(other))));
+ }
+
+#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 boost::has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws,
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws,
+ //!
+ //! @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 boost::has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws,
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws,
+ //!
+ //! @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_CONTAINER_NOEXCEPT;
+
+ //! @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);
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! @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);
+#endif
+
+ //! @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);
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! @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 first 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);
+#endif
+
+ //! @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.
+ //!
+ //! @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>
+ void 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_CONTAINER_NOEXCEPT;
+
+ //! @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 \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_CONTAINER_NOEXCEPT;
+
+ //! @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_CONTAINER_NOEXCEPT;
+
+ //! @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_CONTAINER_NOEXCEPT;
+
+ //! @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_CONTAINER_NOEXCEPT;
+
+ //! @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_CONTAINER_NOEXCEPT;
+
+ //! @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_CONTAINER_NOEXCEPT;
+
+ //! @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_CONTAINER_NOEXCEPT;
+
+ //! @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_CONTAINER_NOEXCEPT;
+
+ //! @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_CONTAINER_NOEXCEPT;
+
+ //! @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_CONTAINER_NOEXCEPT;
+
+ //! @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_CONTAINER_NOEXCEPT;
+
+ //! @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_CONTAINER_NOEXCEPT;
+
+ //! @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_CONTAINER_NOEXCEPT;
+
+ //! @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_CONTAINER_NOEXCEPT;
+
+ //! @brief Returns container's capacity.
+ //!
+ //! @return container's capacity.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ static size_type capacity() BOOST_CONTAINER_NOEXCEPT;
+
+ //! @brief Returns container's capacity.
+ //!
+ //! @return container's capacity.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ static size_type max_size() BOOST_CONTAINER_NOEXCEPT;
+
+ //! @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_CONTAINER_NOEXCEPT;
+
+ //! @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_CONTAINER_NOEXCEPT;
+#else
+
+ 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 container_detail::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/boost/container/string.hpp b/boost/container/string.hpp
index 2a64cec428..1c3cf3bbc8 100644
--- a/boost/container/string.hpp
+++ b/boost/container/string.hpp
@@ -1,58 +1,43 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
+// (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.
//
//////////////////////////////////////////////////////////////////////////////
-// Copyright (c) 1996,1997
-// Silicon Graphics Computer Systems, Inc.
-//
-// Permission to use, copy, modify, distribute and sell this software
-// and its documentation for any purpose is hereby granted without fee,
-// provided that the above copyright notice appear in all copies and
-// that both that copyright notice and this permission notice appear
-// in supporting documentation. Silicon Graphics makes no
-// representations about the suitability of this software for any
-// purpose. It is provided "as is" without express or implied warranty.
-//
-//
-// Copyright (c) 1994
-// Hewlett-Packard Company
-//
-// Permission to use, copy, modify, distribute and sell this software
-// and its documentation for any purpose is hereby granted without fee,
-// provided that the above copyright notice appear in all copies and
-// that both that copyright notice and this permission notice appear
-// in supporting documentation. Hewlett-Packard Company makes no
-// representations about the suitability of this software for any
-// purpose. It is provided "as is" without express or implied warranty.
#ifndef BOOST_CONTAINER_STRING_HPP
#define BOOST_CONTAINER_STRING_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/workaround.hpp>
#include <boost/container/container_fwd.hpp>
+#include <boost/container/throw_exception.hpp>
#include <boost/container/detail/utilities.hpp>
#include <boost/container/detail/iterators.hpp>
#include <boost/container/detail/algorithms.hpp>
#include <boost/container/detail/version_type.hpp>
#include <boost/container/detail/allocation_type.hpp>
#include <boost/container/allocator_traits.hpp>
+#include <boost/container/detail/allocator_version_traits.hpp>
#include <boost/container/detail/mpl.hpp>
-#include <boost/move/move.hpp>
+#include <boost/move/utility_core.hpp>
#include <boost/static_assert.hpp>
#include <boost/functional/hash.hpp>
+#include <boost/intrusive/pointer_traits.hpp>
+#include <boost/core/no_exceptions_support.hpp>
#include <functional>
#include <string>
-#include <stdexcept>
-#include <utility>
+#include <utility>
#include <iterator>
#include <memory>
#include <algorithm>
@@ -64,43 +49,39 @@
#include <cstddef>
#include <climits>
#include <boost/container/detail/type_traits.hpp>
-#include <boost/detail/no_exceptions_support.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp>
#include <boost/aligned_storage.hpp>
+#include <boost/move/traits.hpp>
-#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
-namespace boost {
-namespace container {
-#else
namespace boost {
namespace container {
-#endif
-/// @cond
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
namespace container_detail {
// ------------------------------------------------------------
-// Class basic_string_base.
+// 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
+// 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 A>
+template <class Allocator>
class basic_string_base
{
- BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_string_base)
+ basic_string_base & operator=(const basic_string_base &);
+ basic_string_base(const basic_string_base &);
- typedef allocator_traits<A> allocator_traits_type;
+ typedef allocator_traits<Allocator> allocator_traits_type;
public:
- typedef A allocator_type;
- //! The stored allocator type
- typedef allocator_type stored_allocator_type;
+ 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_()
@@ -110,28 +91,22 @@ class basic_string_base
: members_(a)
{ init(); }
+ 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);
}
- basic_string_base(BOOST_RV_REF(basic_string_base) b)
- : members_(boost::move(b.alloc()))
- {
- this->init();
- this->swap_data(b);
- }
-
~basic_string_base()
- {
+ {
if(!this->is_short()){
this->deallocate_block();
- allocator_traits_type::destroy
- ( this->alloc()
- , static_cast<long_t*>(static_cast<void*>(&this->members_.m_repr.r))
- );
+ this->is_short(true);
}
}
@@ -176,7 +151,7 @@ class basic_string_base
//This type has the same alignment and size as long_t but it's POD
//so, unlike long_t, it can be placed in a union
-
+
typedef typename boost::aligned_storage< sizeof(long_t),
container_detail::alignment_of<long_t>::value>::type long_raw_t;
@@ -203,32 +178,38 @@ class basic_string_base
long_raw_t r;
short_t s;
- short_t &short_repr() const
- { return *const_cast<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)); }
- long_t &long_repr() const
- { return *const_cast<long_t*>(reinterpret_cast<const long_t*>(&r)); }
+ short_t &short_repr()
+ { return s; }
+
+ long_t &long_repr()
+ { return *static_cast<long_t*>(static_cast<void*>(&r)); }
};
struct members_holder
- : public A
+ : public Allocator
{
members_holder()
- : A()
+ : Allocator()
{}
template<class AllocatorConvertible>
explicit members_holder(BOOST_FWD_REF(AllocatorConvertible) a)
- : A(boost::forward<AllocatorConvertible>(a))
+ : Allocator(boost::forward<AllocatorConvertible>(a))
{}
repr_t m_repr;
} members_;
- const A &alloc() const
+ const Allocator &alloc() const
{ return members_; }
- A &alloc()
+ Allocator &alloc()
{ return members_; }
static const size_type InternalBufferChars = (sizeof(repr_t) - ShortDataOffset)/sizeof(value_type);
@@ -242,20 +223,22 @@ class basic_string_base
{ return static_cast<bool>(this->members_.m_repr.s.h.is_short != 0); }
void is_short(bool yes)
- {
- if(yes && !this->is_short()){
+ {
+ 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{
+ 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;
}
- this->members_.m_repr.s.h.is_short = yes;
}
private:
@@ -270,7 +253,7 @@ class basic_string_base
typedef container_detail::integral_constant<unsigned, 1> allocator_v1;
typedef container_detail::integral_constant<unsigned, 2> allocator_v2;
typedef container_detail::integral_constant<unsigned,
- boost::container::container_detail::version<A>::value> alloc_version;
+ boost::container::container_detail::version<Allocator>::value> alloc_version;
std::pair<pointer, bool>
allocation_command(allocation_type command,
@@ -279,46 +262,23 @@ class basic_string_base
size_type &received_size, pointer reuse = 0)
{
if(this->is_short() && (command & (expand_fwd | expand_bwd)) ){
- reuse = pointer(0);
+ reuse = pointer();
command &= ~(expand_fwd | expand_bwd);
}
- return this->allocation_command
- (command, limit_size, preferred_size, received_size, reuse, alloc_version());
- }
-
- std::pair<pointer, bool>
- allocation_command(allocation_type command,
- size_type limit_size,
- size_type preferred_size,
- size_type &received_size,
- const pointer &reuse,
- allocator_v1)
- {
- (void)limit_size;
- (void)reuse;
- if(!(command & allocate_new))
- return std::pair<pointer, bool>(pointer(0), false);
- received_size = preferred_size;
- return std::make_pair(this->alloc().allocate(received_size), false);
+ return container_detail::allocator_version_traits<Allocator>::allocation_command
+ (this->alloc(), command, limit_size, preferred_size, received_size, reuse);
}
- std::pair<pointer, bool>
- allocation_command(allocation_type command,
- size_type limit_size,
- size_type preferred_size,
- size_type &received_size,
- pointer reuse,
- allocator_v2)
+ size_type next_capacity(size_type additional_objects) const
{
- return this->alloc().allocation_command(command, limit_size, preferred_size,
- received_size, reuse);
+ return next_capacity_calculator
+ <size_type, NextCapacityDouble /*NextCapacity60Percent*/>::
+ get( allocator_traits_type::max_size(this->alloc())
+ , this->priv_storage(), additional_objects );
}
- size_type next_capacity(size_type additional_objects) const
- { return get_next_capacity(allocator_traits_type::max_size(this->alloc()), this->priv_storage(), additional_objects); }
-
void deallocate(pointer p, size_type n)
- {
+ {
if (p && (n > InternalBufferChars))
this->alloc().deallocate(p, n);
}
@@ -334,11 +294,9 @@ class basic_string_base
void destroy(pointer p, size_type n)
{
- for(; n--; ++p){
- allocator_traits_type::destroy
- ( this->alloc()
- , container_detail::to_raw_pointer(p)
- );
+ value_type *raw_p = container_detail::to_raw_pointer(p);
+ for(; n--; ++raw_p){
+ allocator_traits_type::destroy( this->alloc(), raw_p);
}
}
@@ -358,39 +316,46 @@ class basic_string_base
pointer p = this->allocation_command(allocate_new, n, new_cap, new_cap).first;
this->is_short(false);
this->priv_long_addr(p);
- this->priv_size(0);
+ this->priv_long_size(0);
this->priv_storage(new_cap);
}
}
- else
- throw_length_error();
+ 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; }
- // Helper functions for exception handling.
- void throw_length_error() const
- { throw(std::length_error("basic_string")); }
-
- void throw_out_of_range() const
- { throw(std::out_of_range("basic_string")); }
-
protected:
size_type priv_capacity() const
{ return this->priv_storage() - 1; }
pointer priv_short_addr() const
- { return pointer(&this->members_.m_repr.short_repr().data[0]); }
+ { 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() ? pointer(&this->members_.m_repr.short_repr().data[0]) : this->members_.m_repr.long_repr().start; }
+ {
+ 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; }
@@ -405,18 +370,18 @@ class basic_string_base
{ 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() ? priv_short_size() : priv_long_size(); }
+ { 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; }
@@ -425,7 +390,7 @@ class basic_string_base
{ return this->members_.m_repr.long_repr().length; }
void priv_size(size_type sz)
- {
+ {
if(this->is_short())
this->priv_short_size(sz);
else
@@ -433,35 +398,41 @@ class basic_string_base
}
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 = static_cast<typename allocator_traits_type::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()){
- container_detail::do_swap(this->members_.m_repr, other.members_.m_repr);
+ std::swap(this->members_.m_repr, other.members_.m_repr);
}
else{
- repr_t copied(this->members_.m_repr);
- this->members_.m_repr.long_repr() = other.members_.m_repr.long_repr();
- other.members_.m_repr = copied;
+ short_t short_backup(this->members_.m_repr.short_repr());
+ long_t long_backup (other.members_.m_repr.long_repr());
+ other.members_.m_repr.long_repr().~long_t();
+ ::new(&this->members_.m_repr.long_repr()) long_t;
+ this->members_.m_repr.long_repr() = long_backup;
+ other.members_.m_repr.short_repr() = short_backup;
}
}
else{
if(other.is_short()){
- repr_t copied(other.members_.m_repr);
- other.members_.m_repr.long_repr() = this->members_.m_repr.long_repr();
- this->members_.m_repr = copied;
+ short_t short_backup(other.members_.m_repr.short_repr());
+ long_t long_backup (this->members_.m_repr.long_repr());
+ this->members_.m_repr.long_repr().~long_t();
+ ::new(&other.members_.m_repr.long_repr()) long_t;
+ other.members_.m_repr.long_repr() = long_backup;
+ this->members_.m_repr.short_repr() = short_backup;
}
else{
- container_detail::do_swap(this->members_.m_repr.long_repr(), other.members_.m_repr.long_repr());
+ boost::container::swap_dispatch(this->members_.m_repr.long_repr(), other.members_.m_repr.long_repr());
}
}
}
@@ -469,7 +440,7 @@ class basic_string_base
} //namespace container_detail {
-/// @endcond
+#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
@@ -499,39 +470,46 @@ class basic_string_base
//! 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 A = std::allocator<CharT> >
+template <class CharT, class Traits = std::char_traits<CharT>, class Allocator = std::allocator<CharT> >
#else
-template <class CharT, class Traits, class A>
+template <class CharT, class Traits, class Allocator>
#endif
class basic_string
- : private container_detail::basic_string_base<A>
+ : private container_detail::basic_string_base<Allocator>
{
- /// @cond
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
- typedef allocator_traits<A> allocator_traits_type;
+ typedef allocator_traits<Allocator> allocator_traits_type;
BOOST_COPYABLE_AND_MOVABLE(basic_string)
- typedef container_detail::basic_string_base<A> base_t;
+ typedef container_detail::basic_string_base<Allocator> base_t;
static const typename base_t::size_type InternalBufferChars = base_t::InternalBufferChars;
protected:
- // A helper class to use a char_traits as a function object.
+ // Allocator helper class to use a char_traits as a function object.
template <class Tr>
struct Eq_traits
- : public std::binary_function<typename Tr::char_type,
- typename Tr::char_type,
- bool>
{
- bool operator()(const typename Tr::char_type& x,
- const typename Tr::char_type& y) const
+ //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
- : public std::unary_function<typename Tr::char_type, bool>
{
+ 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;
@@ -545,51 +523,46 @@ class basic_string
std::bind1st(Eq_traits<Tr>(), x)) == m_last;
}
};
- /// @endcond
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public:
-
- //! The allocator type
- typedef A allocator_type;
- //! The stored allocator type
- typedef allocator_type stored_allocator_type;
- //! The type of object, CharT, stored in the string
- typedef CharT value_type;
- //! The second template parameter Traits
- typedef Traits traits_type;
- //! Pointer to CharT
- typedef typename allocator_traits_type::pointer pointer;
- //! Const pointer to CharT
- typedef typename allocator_traits_type::const_pointer const_pointer;
- //! Reference to CharT
- typedef typename allocator_traits_type::reference reference;
- //! Const reference to CharT
- typedef typename allocator_traits_type::const_reference const_reference;
- //! An unsigned integral type
- typedef typename allocator_traits_type::size_type size_type;
- //! A signed integral type
- typedef typename allocator_traits_type::difference_type difference_type;
- //! Iterator used to iterate through a string. It's a Random Access Iterator
- typedef pointer iterator;
- //! Const iterator used to iterate through a string. It's a Random Access Iterator
- typedef const_pointer const_iterator;
- //! Iterator used to iterate backwards through a string
- typedef std::reverse_iterator<iterator> reverse_iterator;
- //! Const iterator used to iterate backwards through a string
- typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
- //! The largest possible value of type size_type. That is, size_type(-1).
- static const size_type npos;
-
- /// @cond
+ //////////////////////////////////////////////
+ //
+ // 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(container_detail::reverse_iterator<iterator>) reverse_iterator;
+ typedef BOOST_CONTAINER_IMPDEF(container_detail::reverse_iterator<const_iterator>) const_reverse_iterator;
+ static const size_type npos = size_type(-1);
+
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
typedef constant_iterator<CharT, difference_type> cvalue_iterator;
typedef typename base_t::allocator_v1 allocator_v1;
typedef typename base_t::allocator_v2 allocator_v2;
typedef typename base_t::alloc_version alloc_version;
- /// @endcond
+ typedef ::boost::intrusive::pointer_traits<pointer> pointer_traits;
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public: // Constructor, destructor, assignment.
- /// @cond
+ //////////////////////////////////////////////
+ //
+ // construct/copy/destroy
+ //
+ //////////////////////////////////////////////
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
struct reserve_t {};
basic_string(reserve_t, size_type n,
@@ -600,7 +573,7 @@ class basic_string
, n + 1)
{ this->priv_terminate_string(); }
- /// @endcond
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
//! <b>Effects</b>: Default constructs a basic_string.
//!
@@ -612,8 +585,8 @@ class basic_string
//! <b>Effects</b>: Constructs a basic_string taking the allocator as parameter.
//!
- //! <b>Throws</b>: If allocator_type's copy constructor throws.
- explicit basic_string(const allocator_type& a)
+ //! <b>Throws</b>: Nothing
+ explicit basic_string(const allocator_type& a) BOOST_CONTAINER_NOEXCEPT
: base_t(a)
{ this->priv_terminate_string(); }
@@ -621,19 +594,29 @@ class basic_string
//!
//! <b>Postcondition</b>: x == *this.
//!
- //! <b>Throws</b>: If allocator_type's default constructor throws.
+ //! <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_range_initialize(s.begin(), s.end()); }
+ {
+ this->priv_terminate_string();
+ this->assign(s.begin(), s.end());
+ }
//! <b>Effects</b>: Move constructor. Moves s's resources to *this.
//!
- //! <b>Throws</b>: If allocator_type's copy constructor throws.
+ //! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- basic_string(BOOST_RV_REF(basic_string) s)
- : base_t(boost::move((base_t&)s))
- {}
+ basic_string(BOOST_RV_REF(basic_string) s) BOOST_CONTAINER_NOEXCEPT
+ : 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.
//!
@@ -642,7 +625,10 @@ class basic_string
//! <b>Throws</b>: If allocation throws.
basic_string(const basic_string& s, const allocator_type &a)
: base_t(a)
- { this->priv_range_initialize(s.begin(), s.end()); }
+ {
+ 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.
@@ -653,62 +639,73 @@ class basic_string
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->priv_range_initialize(s.begin(), s.end());
+ this->assign(s.begin(), s.end());
}
}
//! <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 = npos,
- const allocator_type& a = allocator_type())
+ const allocator_type& a = allocator_type())
: base_t(a)
{
+ this->priv_terminate_string();
if (pos > s.size())
- this->throw_out_of_range();
+ throw_out_of_range("basic_string::basic_string out of range position");
else
- this->priv_range_initialize
+ this->assign
(s.begin() + pos, s.begin() + pos + container_detail::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 c-string.
- basic_string(const CharT* s, size_type n,
- const allocator_type& a = allocator_type())
+ basic_string(const CharT* s, size_type n, const allocator_type& a = allocator_type())
: base_t(a)
- { this->priv_range_initialize(s, s + n); }
+ {
+ 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 the null-terminated s c-string.
- basic_string(const CharT* s,
- const allocator_type& a = allocator_type())
+ basic_string(const CharT* s, const allocator_type& a = allocator_type())
: base_t(a)
- { this->priv_range_initialize(s, s + Traits::length(s)); }
+ {
+ 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 n copies of c.
- basic_string(size_type n, CharT c,
- const allocator_type& a = allocator_type())
+ basic_string(size_type n, CharT c, const allocator_type& a = allocator_type())
: base_t(a)
- {
- this->priv_range_initialize(cvalue_iterator(c, n),
- cvalue_iterator());
+ {
+ 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 default-initialized characters.
+ basic_string(size_type n, default_init_t, const allocator_type& a = allocator_type())
+ : base_t(a, n + 1)
+ {
+ this->priv_size(n);
+ this->priv_terminate_string();
}
//! <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 = allocator_type())
+ basic_string(InputIterator f, InputIterator l, const allocator_type& a = allocator_type())
: base_t(a)
{
- //Dispatch depending on integer/iterator
- const bool aux_boolean = container_detail::is_convertible<InputIterator, size_type>::value;
- typedef container_detail::bool_<aux_boolean> Result;
- this->priv_initialize_dispatch(f, l, Result());
+ this->priv_terminate_string();
+ this->assign(f, l);
}
//! <b>Effects</b>: Destroys the basic_string. All used memory is deallocated.
@@ -716,9 +713,9 @@ class basic_string
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- ~basic_string()
+ ~basic_string() BOOST_CONTAINER_NOEXCEPT
{}
-
+
//! <b>Effects</b>: Copy constructs a string.
//!
//! <b>Postcondition</b>: x == *this.
@@ -735,8 +732,8 @@ class basic_string
if(!this->is_short()){
this->deallocate_block();
this->is_short(true);
- Traits::assign(*this->priv_addr(), this->priv_null());
- this->priv_size(0);
+ Traits::assign(*this->priv_addr(), CharT(0));
+ this->priv_short_size(0);
}
}
container_detail::assign_alloc(this->alloc(), x.alloc(), flag);
@@ -745,30 +742,38 @@ class basic_string
return *this;
}
- //! <b>Effects</b>: Move constructor. Moves mx's resources to *this.
+ //! <b>Effects</b>: Move constructor. Moves x's resources to *this.
//!
- //! <b>Throws</b>: If allocator_type's copy constructor throws.
+ //! <b>Throws</b>: If allocator_traits_type::propagate_on_container_move_assignment
+ //! is false and allocation throws
//!
- //! <b>Complexity</b>: Constant.
+ //! <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)
- {
- if (&x != this){
- allocator_type &this_alloc = this->alloc();
- allocator_type &x_alloc = x.alloc();
- //If allocators are equal we can just swap pointers
- if(this_alloc == x_alloc){
- //Destroy objects but retain memory in case x reuses it in the future
- this->clear();
- this->swap_data(x);
- //Move allocator if needed
- container_detail::bool_<allocator_traits_type::
- propagate_on_container_move_assignment::value> flag;
- container_detail::move_alloc(this_alloc, x_alloc, flag);
- }
- //If unequal allocators, then do a one by one move
- else{
- this->assign( x.begin(), x.end());
- }
+ BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::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;
+ container_detail::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
+ container_detail::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;
}
@@ -781,71 +786,80 @@ class basic_string
basic_string& operator=(CharT c)
{ return this->assign(static_cast<size_type>(1), c); }
- //! <b>Effects</b>: Returns an iterator to the first element contained in the vector.
+ //! <b>Effects</b>: Returns a copy of the internal allocator.
//!
- //! <b>Throws</b>: Nothing.
+ //! <b>Throws</b>: If allocator's copy constructor throws.
//!
//! <b>Complexity</b>: Constant.
- iterator begin()
- { return this->priv_addr(); }
+ allocator_type get_allocator() const BOOST_CONTAINER_NOEXCEPT
+ { return this->alloc(); }
- //! <b>Effects</b>: Returns a const_iterator to the first element contained in the vector.
+ //! <b>Effects</b>: Returns a reference to the internal allocator.
//!
- //! <b>Throws</b>: Nothing.
+ //! <b>Throws</b>: Nothing
//!
//! <b>Complexity</b>: Constant.
- const_iterator begin() const
- { return this->priv_addr(); }
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT
+ { return this->alloc(); }
- //! <b>Effects</b>: Returns a const_iterator to the first element contained in the vector.
+ //! <b>Effects</b>: Returns a reference to the internal allocator.
//!
- //! <b>Throws</b>: Nothing.
+ //! <b>Throws</b>: Nothing
//!
//! <b>Complexity</b>: Constant.
- const_iterator cbegin() const
- { return this->priv_addr(); }
+ //!
+ //! <b>Note</b>: Non-standard extension.
+ const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT
+ { return this->alloc(); }
- //! <b>Effects</b>: Returns an iterator to the end of the vector.
+ //////////////////////////////////////////////
+ //
+ // iterators
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Returns an iterator to the first element contained in the vector.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- iterator end()
- { return this->priv_addr() + this->priv_size(); }
+ iterator begin() BOOST_CONTAINER_NOEXCEPT
+ { return this->priv_addr(); }
- //! <b>Effects</b>: Returns a const_iterator to the end of the vector.
+ //! <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 end() const
- { return this->priv_addr() + this->priv_size(); }
+ const_iterator begin() const BOOST_CONTAINER_NOEXCEPT
+ { return this->priv_addr(); }
- //! <b>Effects</b>: Returns a const_iterator to the end of the vector.
+ //! <b>Effects</b>: Returns an iterator to the end of the vector.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_iterator cend() const
- { return this->priv_addr() + this->priv_size(); }
+ iterator end() BOOST_CONTAINER_NOEXCEPT
+ { return this->priv_end_addr(); }
- //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
- //! of the reversed vector.
+ //! <b>Effects</b>: Returns a const_iterator to the end of the vector.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- reverse_iterator rbegin()
- { return reverse_iterator(this->priv_addr() + this->priv_size()); }
+ const_iterator end() const BOOST_CONTAINER_NOEXCEPT
+ { return this->priv_end_addr(); }
- //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
+ //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
//! of the reversed vector.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reverse_iterator rbegin() const
- { return this->crbegin(); }
+ reverse_iterator rbegin() BOOST_CONTAINER_NOEXCEPT
+ { return reverse_iterator(this->priv_end_addr()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
//! of the reversed vector.
@@ -853,8 +867,8 @@ class basic_string
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reverse_iterator crbegin() const
- { return const_reverse_iterator(this->priv_addr() + this->priv_size()); }
+ const_reverse_iterator rbegin() const BOOST_CONTAINER_NOEXCEPT
+ { return this->crbegin(); }
//! <b>Effects</b>: Returns a reverse_iterator pointing to the end
//! of the reversed vector.
@@ -862,7 +876,7 @@ class basic_string
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- reverse_iterator rend()
+ reverse_iterator rend() BOOST_CONTAINER_NOEXCEPT
{ return reverse_iterator(this->priv_addr()); }
//! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
@@ -871,52 +885,63 @@ class basic_string
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reverse_iterator rend() const
+ const_reverse_iterator rend() const BOOST_CONTAINER_NOEXCEPT
{ return this->crend(); }
- //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
- //! of the reversed vector.
+ //! <b>Effects</b>: Returns a const_iterator to the first element contained in the vector.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reverse_iterator crend() const
- { return const_reverse_iterator(this->priv_addr()); }
+ const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT
+ { return this->priv_addr(); }
- //! <b>Effects</b>: Returns a copy of the internal allocator.
+ //! <b>Effects</b>: Returns a const_iterator to the end of the vector.
//!
- //! <b>Throws</b>: If allocator's copy constructor throws.
+ //! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- allocator_type get_allocator() const
- { return this->alloc(); }
+ const_iterator cend() const BOOST_CONTAINER_NOEXCEPT
+ { return this->priv_end_addr(); }
- //! <b>Effects</b>: Returns a reference to the internal allocator.
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
+ //! of the reversed vector.
//!
- //! <b>Throws</b>: Nothing
+ //! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- //!
- //! <b>Note</b>: Non-standard extension.
- const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT
- { return this->alloc(); }
+ const_reverse_iterator crbegin() const BOOST_CONTAINER_NOEXCEPT
+ { return const_reverse_iterator(this->priv_end_addr()); }
- //! <b>Effects</b>: Returns a reference to the internal allocator.
+ //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
+ //! of the reversed vector.
//!
- //! <b>Throws</b>: Nothing
+ //! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
+ const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT
+ { return const_reverse_iterator(this->priv_addr()); }
+
+ //////////////////////////////////////////////
+ //
+ // capacity
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Returns true if the vector contains no elements.
//!
- //! <b>Note</b>: Non-standard extension.
- stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT
- { return this->alloc(); }
+ //! <b>Throws</b>: Nothing.
+ //!
+ //! <b>Complexity</b>: Constant.
+ bool empty() const BOOST_CONTAINER_NOEXCEPT
+ { 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
+ size_type size() const BOOST_CONTAINER_NOEXCEPT
{ return this->priv_size(); }
//! <b>Effects</b>: Returns the number of the elements contained in the vector.
@@ -924,7 +949,7 @@ class basic_string
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- size_type length() const
+ size_type length() const BOOST_CONTAINER_NOEXCEPT
{ return this->size(); }
//! <b>Effects</b>: Returns the largest possible size of the vector.
@@ -932,7 +957,7 @@ class basic_string
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- size_type max_size() const
+ size_type max_size() const BOOST_CONTAINER_NOEXCEPT
{ return base_t::max_size(); }
//! <b>Effects</b>: Inserts or erases elements at the end such that
@@ -943,47 +968,38 @@ class basic_string
//! <b>Complexity</b>: Linear to the difference between size() and new_size.
void resize(size_type n, CharT c)
{
- if (n <= size())
+ 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 default constructed.
+ //! 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, this->priv_null()); }
+ { resize(n, CharT()); }
- //! <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>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 allocation throws
- void reserve(size_type res_arg)
+ //! <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 (res_arg > this->max_size())
- this->throw_length_error();
-
- if (this->capacity() < res_arg){
- size_type n = container_detail::max_value(res_arg, this->size()) + 1;
- size_type new_cap = this->next_capacity(n);
- pointer new_start = this->allocation_command
- (allocate_new, n, new_cap, new_cap).first;
- size_type new_length = 0;
-
- new_length += priv_uninitialized_copy
- (this->priv_addr(), this->priv_addr() + this->priv_size(), new_start);
- this->priv_construct_null(new_start + new_length);
- this->deallocate_block();
- this->is_short(false);
- this->priv_long_addr(new_start);
- this->priv_size(new_length);
- this->priv_storage(new_cap);
+ 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();
}
}
@@ -993,21 +1009,17 @@ class basic_string
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- size_type capacity() const
+ size_type capacity() const BOOST_CONTAINER_NOEXCEPT
{ return this->priv_capacity(); }
- //! <b>Effects</b>: Erases all the elements of the vector.
- //!
- //! <b>Throws</b>: Nothing.
+ //! <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>Complexity</b>: Linear to the number of elements in the vector.
- void clear()
- {
- if (!empty()) {
- Traits::assign(*this->priv_addr(), this->priv_null());
- this->priv_size(0);
- }
- }
+ //! <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
@@ -1021,7 +1033,7 @@ class basic_string
if(this->priv_storage() > InternalBufferChars){
//Check if we should pass from dynamically allocated buffer
//to the internal storage
- if(this->priv_size() < (InternalBufferChars)){
+ if(this->priv_size() < InternalBufferChars){
//Dynamically allocated buffer attributes
pointer long_addr = this->priv_long_addr();
size_type long_storage = this->priv_long_storage();
@@ -1040,13 +1052,11 @@ class basic_string
}
}
- //! <b>Effects</b>: Returns true if the vector contains no elements.
- //!
- //! <b>Throws</b>: Nothing.
- //!
- //! <b>Complexity</b>: Constant.
- bool empty() const
- { return !this->priv_size(); }
+ //////////////////////////////////////////////
+ //
+ // element access
+ //
+ //////////////////////////////////////////////
//! <b>Requires</b>: size() > n.
//!
@@ -1056,7 +1066,7 @@ class basic_string
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- reference operator[](size_type n)
+ reference operator[](size_type n) BOOST_CONTAINER_NOEXCEPT
{ return *(this->priv_addr() + n); }
//! <b>Requires</b>: size() > n.
@@ -1067,7 +1077,7 @@ class basic_string
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reference operator[](size_type n) const
+ const_reference operator[](size_type n) const BOOST_CONTAINER_NOEXCEPT
{ return *(this->priv_addr() + n); }
//! <b>Requires</b>: size() > n.
@@ -1078,9 +1088,10 @@ class basic_string
//! <b>Throws</b>: std::range_error if n >= size()
//!
//! <b>Complexity</b>: Constant.
- reference at(size_type n) {
- if (n >= size())
- this->throw_out_of_range();
+ reference at(size_type n)
+ {
+ if (n >= this->size())
+ throw_out_of_range("basic_string::at invalid subscript");
return *(this->priv_addr() + n);
}
@@ -1093,11 +1104,17 @@ class basic_string
//!
//! <b>Complexity</b>: Constant.
const_reference at(size_type n) const {
- if (n >= size())
- this->throw_out_of_range();
+ 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
@@ -1133,7 +1150,7 @@ class basic_string
basic_string& append(const basic_string& s, size_type pos, size_type n)
{
if (pos > s.size())
- this->throw_out_of_range();
+ throw_out_of_range("basic_string::append out of range position");
return this->append(s.begin() + pos,
s.begin() + pos + container_detail::min_value(n, s.size() - pos));
}
@@ -1177,14 +1194,16 @@ class basic_string
//! <b>Effects</b>: Equivalent to append(static_cast<size_type>(1), c).
void push_back(CharT c)
{
- if (this->priv_size() < this->capacity()){
- this->priv_construct_null(this->priv_addr() + (this->priv_size() + 1));
- Traits::assign(this->priv_addr()[this->priv_size()], c);
- this->priv_size(this->priv_size()+1);
+ 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);
+ this->append(size_type(1), c);
}
}
@@ -1201,7 +1220,7 @@ class basic_string
//! <b>Throws</b>: Nothing
//!
//! <b>Returns</b>: *this
- basic_string& assign(BOOST_RV_REF(basic_string) ms)
+ basic_string& assign(BOOST_RV_REF(basic_string) ms) BOOST_CONTAINER_NOEXCEPT
{ return this->swap_data(ms), *this; }
//! <b>Requires</b>: pos <= str.size()
@@ -1212,10 +1231,10 @@ class basic_string
//! <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) {
+ basic_string& assign(const basic_string& s, size_type pos, size_type n)
+ {
if (pos > s.size())
- this->throw_out_of_range();
+ throw_out_of_range("basic_string::assign out of range position");
return this->assign(s.begin() + pos,
s.begin() + pos + container_detail::min_value(n, s.size() - pos));
}
@@ -1226,7 +1245,7 @@ class basic_string
//! 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); }
@@ -1246,15 +1265,46 @@ class basic_string
{ 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 = container_detail::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)
+ basic_string& assign(InputIter first, InputIter last
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename container_detail::enable_if_c
+ < !container_detail::is_convertible<InputIter, size_type>::value
+ >::type * = 0
+ #endif
+ )
{
- //Dispatch depending on integer/iterator
- const bool aux_boolean = container_detail::is_convertible<InputIter, size_type>::value;
- typedef container_detail::bool_<aux_boolean> Result;
- return this->priv_assign_dispatch(first, last, Result());
+ size_type cur = 0;
+ const pointer addr = this->priv_addr();
+ CharT *ptr = container_detail::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;
}
//! <b>Requires</b>: pos <= size().
@@ -1266,10 +1316,11 @@ class basic_string
//! <b>Returns</b>: *this
basic_string& insert(size_type pos, const basic_string& s)
{
- if (pos > size())
- this->throw_out_of_range();
- if (this->size() > this->max_size() - s.size())
- this->throw_length_error();
+ 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;
}
@@ -1282,14 +1333,15 @@ class basic_string
//! <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)
- {
- if (pos1 > this->size() || pos2 > s.size())
- this->throw_out_of_range();
- size_type len = container_detail::min_value(n, s.size() - pos2);
- if (this->size() > this->max_size() - len)
- this->throw_length_error();
+ basic_string& insert(size_type pos1, const basic_string& s, size_type pos2, size_type n)
+ {
+ 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 = container_detail::min_value(n, str_size - pos2);
+ if (sz > this->max_size() - len)
+ throw_length_error("basic_string::insert max_size() exceeded");
const CharT *beg_ptr = container_detail::to_raw_pointer(s.begin()) + pos2;
const CharT *end_ptr = beg_ptr + len;
this->insert(this->priv_addr() + pos1, beg_ptr, end_ptr);
@@ -1310,9 +1362,9 @@ class basic_string
basic_string& insert(size_type pos, const CharT* s, size_type n)
{
if (pos > this->size())
- this->throw_out_of_range();
+ throw_out_of_range("basic_string::insert out of range position");
if (this->size() > this->max_size() - n)
- this->throw_length_error();
+ throw_length_error("basic_string::insert max_size() exceeded");
this->insert(this->priv_addr() + pos, s, s + n);
return *this;
}
@@ -1327,11 +1379,11 @@ class basic_string
//! <b>Returns</b>: *this
basic_string& insert(size_type pos, const CharT* s)
{
- if (pos > size())
- this->throw_out_of_range();
+ 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)
- this->throw_length_error();
+ throw_length_error("basic_string::insert max_size() exceeded");
this->insert(this->priv_addr() + pos, s, s + len);
return *this;
}
@@ -1345,9 +1397,9 @@ class basic_string
basic_string& insert(size_type pos, size_type n, CharT c)
{
if (pos > this->size())
- this->throw_out_of_range();
+ throw_out_of_range("basic_string::insert out of range position");
if (this->size() > this->max_size() - n)
- this->throw_length_error();
+ throw_length_error("basic_string::insert max_size() exceeded");
this->insert(const_iterator(this->priv_addr() + pos), n, c);
return *this;
}
@@ -1359,7 +1411,7 @@ class basic_string
//! <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() + 1;
+ size_type new_offset = p - this->priv_addr();
this->insert(p, cvalue_iterator(c, 1), cvalue_iterator());
return this->priv_addr() + new_offset;
}
@@ -1369,27 +1421,143 @@ class basic_string
//!
//! <b>Effects</b>: Inserts n copies of c before the character referred to by p.
//!
- //! <b>Returns</b>: An iterator which refers to the copy of the first
- //! inserted character, or p if n == 0.
- void insert(const_iterator p, size_type n, CharT c)
- {
- this->insert(p, cvalue_iterator(c, n), cvalue_iterator());
- }
+ //! <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 which refers to the copy of the first
- //! inserted character, or p if first == last.
+ //! <b>Returns</b>: an iterator to the first inserted element or p if first == last.
template <class InputIter>
- void insert(const_iterator p, InputIter first, InputIter last)
- {
- //Dispatch depending on integer/iterator
- const bool aux_boolean = container_detail::is_convertible<InputIter, size_type>::value;
- typedef container_detail::bool_<aux_boolean> Result;
- this->priv_insert_dispatch(p, first, last, Result());
+ iterator insert(const_iterator p, InputIter first, InputIter last
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename container_detail::enable_if_c
+ < !container_detail::is_convertible<InputIter, size_type>::value
+ && container_detail::is_input_iterator<InputIter>::value
+ >::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 container_detail::enable_if_c
+ < !container_detail::is_convertible<ForwardIter, size_type>::value
+ && !container_detail::is_input_iterator<ForwardIter>::value
+ >::type * = 0
+ )
+ {
+ const size_type n_pos = p - this->cbegin();
+ if (first != last) {
+ const size_type n = std::distance(first, last);
+ const size_type old_size = this->priv_size();
+ const size_type remaining = this->capacity() - old_size;
+ const pointer old_start = this->priv_addr();
+ bool enough_capacity = false;
+ std::pair<pointer, bool> allocation_ret;
+ size_type new_cap = 0;
+
+ //Check if we have enough capacity
+ if (remaining >= n){
+ enough_capacity = true;
+ }
+ else {
+ //Otherwise expand current buffer or allocate new storage
+ new_cap = this->next_capacity(n);
+ allocation_ret = this->allocation_command
+ (allocate_new | expand_fwd | expand_bwd, old_size + n + 1,
+ new_cap, new_cap, old_start);
+
+ //Check forward expansion
+ if(old_start == allocation_ret.first){
+ 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*>(container_detail::to_raw_pointer(p + n)),
+ container_detail::to_raw_pointer(p),
+ (elems_after - n) + 1);
+ this->priv_copy(first, last, const_cast<CharT*>(container_detail::to_raw_pointer(p)));
+ }
+ else {
+ ForwardIter mid = first;
+ std::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*>(container_detail::to_raw_pointer(p)));
+ }
+ }
+ else{
+ pointer new_start = allocation_ret.first;
+ if(!allocation_ret.second){
+ //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 = container_detail::to_raw_pointer(old_start);
+ value_type * const newbuf = container_detail::to_raw_pointer(new_start);
+ const value_type *const pos = container_detail::to_raw_pointer(p);
+ 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
//! <b>Requires</b>: pos <= size()
//!
@@ -1404,11 +1572,12 @@ class basic_string
//! <b>Returns</b>: *this
basic_string& erase(size_type pos = 0, size_type n = npos)
{
- if (pos > size())
- this->throw_out_of_range();
- erase(this->priv_addr() + pos, this->priv_addr() + pos + container_detail::min_value(n, size() - pos));
+ 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 + container_detail::min_value(n, this->size() - pos));
return *this;
- }
+ }
//! <b>Effects</b>: Removes the character referred to by p.
//!
@@ -1416,14 +1585,15 @@ class basic_string
//!
//! <b>Returns</b>: An iterator which points to the element immediately following p prior to the element being
//! erased. If no such element exists, end() is returned.
- iterator erase(const_iterator p)
+ iterator erase(const_iterator p) BOOST_CONTAINER_NOEXCEPT
{
// The move includes the terminating null.
- CharT *ptr = const_cast<CharT*>(container_detail::to_raw_pointer(p));
+ CharT * const ptr = const_cast<CharT*>(container_detail::to_raw_pointer(p));
+ const size_type old_size = this->priv_size();
Traits::move(ptr,
container_detail::to_raw_pointer(p + 1),
- this->priv_size() - (p - this->priv_addr()));
- this->priv_size(this->priv_size()-1);
+ old_size - (p - this->priv_addr()));
+ this->priv_size(old_size-1);
return iterator(ptr);
}
@@ -1435,15 +1605,16 @@ class basic_string
//!
//! <b>Returns</b>: An iterator which points to the element pointed to by last prior to
//! the other elements being erased. If no such element exists, end() is returned.
- iterator erase(const_iterator first, const_iterator last)
+ iterator erase(const_iterator first, const_iterator last) BOOST_CONTAINER_NOEXCEPT
{
CharT * f = const_cast<CharT*>(container_detail::to_raw_pointer(first));
if (first != last) { // The move includes the terminating null.
- size_type num_erased = last - first;
+ const size_type num_erased = last - first;
+ const size_type old_size = this->priv_size();
Traits::move(f,
container_detail::to_raw_pointer(last),
- (this->priv_size() + 1)-(last - this->priv_addr()));
- size_type new_length = this->priv_size() - num_erased;
+ (old_size + 1)-(last - this->priv_addr()));
+ const size_type new_length = old_size - num_erased;
this->priv_size(new_length);
}
return iterator(f);
@@ -1454,10 +1625,24 @@ class basic_string
//! <b>Throws</b>: Nothing
//!
//! <b>Effects</b>: Equivalent to erase(size() - 1, 1).
- void pop_back()
+ void pop_back() BOOST_CONTAINER_NOEXCEPT
+ {
+ const size_type old_size = this->priv_size();
+ Traits::assign(this->priv_addr()[old_size-1], CharT(0));
+ this->priv_size(old_size-1);;
+ }
+
+ //! <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_CONTAINER_NOEXCEPT
{
- Traits::assign(this->priv_addr()[this->priv_size()-1], this->priv_null());
- this->priv_size(this->priv_size()-1);;
+ if (!this->empty()) {
+ Traits::assign(*this->priv_addr(), CharT(0));
+ this->priv_size(0);
+ }
}
//! <b>Requires</b>: pos1 <= size().
@@ -1469,13 +1654,15 @@ class basic_string
//! <b>Returns</b>: *this
basic_string& replace(size_type pos1, size_type n1, const basic_string& str)
{
- if (pos1 > size())
- this->throw_out_of_range();
- const size_type len = container_detail::min_value(n1, size() - pos1);
+ if (pos1 > this->size())
+ throw_out_of_range("basic_string::replace out of range position");
+ const size_type len = container_detail::min_value(n1, this->size() - pos1);
if (this->size() - len >= this->max_size() - str.size())
- this->throw_length_error();
- return this->replace(this->priv_addr() + pos1, this->priv_addr() + pos1 + len,
- str.begin(), str.end());
+ 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>Requires</b>: pos1 <= size() and pos2 <= str.size().
@@ -1490,14 +1677,16 @@ class basic_string
basic_string& replace(size_type pos1, size_type n1,
const basic_string& str, size_type pos2, size_type n2)
{
- if (pos1 > size() || pos2 > str.size())
- this->throw_out_of_range();
- const size_type len1 = container_detail::min_value(n1, size() - pos1);
+ if (pos1 > this->size() || pos2 > str.size())
+ throw_out_of_range("basic_string::replace out of range position");
+ const size_type len1 = container_detail::min_value(n1, this->size() - pos1);
const size_type len2 = container_detail::min_value(n2, str.size() - pos2);
if (this->size() - len1 >= this->max_size() - len2)
- this->throw_length_error();
- return this->replace(this->priv_addr() + pos1, this->priv_addr() + pos1 + len1,
- str.priv_addr() + pos2, str.priv_addr() + pos2 + len2);
+ throw_length_error("basic_string::replace max_size() exceeded");
+ const pointer addr = this->priv_addr();
+ const pointer straddr = str.priv_addr();
+ return this->replace(addr + pos1, addr + pos1 + len1,
+ straddr + pos2, straddr + pos2 + len2);
}
//! <b>Requires</b>: pos1 <= size() and s points to an array of at least n2 elements of CharT.
@@ -1514,16 +1703,15 @@ class basic_string
//! 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)
+ basic_string& replace(size_type pos1, size_type n1, const CharT* s, size_type n2)
{
- if (pos1 > size())
- this->throw_out_of_range();
- const size_type len = container_detail::min_value(n1, size() - pos1);
+ if (pos1 > this->size())
+ throw_out_of_range("basic_string::replace out of range position");
+ const size_type len = container_detail::min_value(n1, this->size() - pos1);
if (n2 > this->max_size() || size() - len >= this->max_size() - n2)
- this->throw_length_error();
- return this->replace(this->priv_addr() + pos1, this->priv_addr() + pos1 + len,
- s, s + n2);
+ throw_length_error("basic_string::replace max_size() exceeded");
+ const pointer addr = this->priv_addr();
+ return this->replace(addr + pos1, addr + pos1 + len, s, s + n2);
}
//! <b>Requires</b>: pos1 <= size() and s points to an array of at least n2 elements of CharT.
@@ -1542,13 +1730,14 @@ class basic_string
//! <b>Returns</b>: *this
basic_string& replace(size_type pos, size_type n1, const CharT* s)
{
- if (pos > size())
- this->throw_out_of_range();
- const size_type len = container_detail::min_value(n1, size() - pos);
+ if (pos > this->size())
+ throw_out_of_range("basic_string::replace out of range position");
+ const size_type len = container_detail::min_value(n1, this->size() - pos);
const size_type n2 = Traits::length(s);
- if (n2 > this->max_size() || size() - len >= this->max_size() - n2)
- this->throw_length_error();
- return this->replace(this->priv_addr() + pos, this->priv_addr() + pos + len,
+ 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 + pos, addr + pos + len,
s, s + Traits::length(s));
}
@@ -1562,12 +1751,13 @@ class basic_string
//! <b>Returns</b>: *this
basic_string& replace(size_type pos1, size_type n1, size_type n2, CharT c)
{
- if (pos1 > size())
- this->throw_out_of_range();
- const size_type len = container_detail::min_value(n1, size() - pos1);
- if (n2 > this->max_size() || size() - len >= this->max_size() - n2)
- this->throw_length_error();
- return this->replace(this->priv_addr() + pos1, this->priv_addr() + pos1 + len, n2, c);
+ if (pos1 > this->size())
+ throw_out_of_range("basic_string::replace out of range position");
+ const size_type len = container_detail::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.
@@ -1631,13 +1821,50 @@ class basic_string
//!
//! <b>Returns</b>: *this
template <class InputIter>
- basic_string& replace(const_iterator i1, const_iterator i2, InputIter j1, InputIter j2)
- {
- //Dispatch depending on integer/iterator
- const bool aux_boolean = container_detail::is_convertible<InputIter, size_type>::value;
- typedef container_detail::bool_<aux_boolean> Result;
- return this->priv_replace_dispatch(i1, i2, j1, j2, Result());
+ basic_string& replace(const_iterator i1, const_iterator i2, InputIter j1, InputIter j2
+ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ , typename container_detail::enable_if_c
+ < !container_detail::is_convertible<InputIter, size_type>::value
+ && container_detail::is_input_iterator<InputIter>::value
+ >::type * = 0
+ #endif
+ )
+ {
+ for ( ; i1 != i2 && j1 != j2; ++i1, ++j1){
+ Traits::assign(*const_cast<CharT*>(container_detail::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 container_detail::enable_if_c
+ < !container_detail::is_convertible<ForwardIter, size_type>::value
+ && !container_detail::is_input_iterator<ForwardIter>::value
+ >::type * = 0
+ )
+ {
+ difference_type n = std::distance(j1, j2);
+ const difference_type len = i2 - i1;
+ if (len >= n) {
+ this->priv_copy(j1, j2, const_cast<CharT*>(container_detail::to_raw_pointer(i1)));
+ this->erase(i1 + n, i2);
+ }
+ else {
+ ForwardIter m = j1;
+ std::advance(m, len);
+ this->priv_copy(j1, m, const_cast<CharT*>(container_detail::to_raw_pointer(i1)));
+ this->insert(i2, m, j2);
+ }
+ return *this;
}
+ #endif
//! <b>Requires</b>: pos <= size()
//!
@@ -1652,9 +1879,9 @@ class basic_string
//! <b>Returns</b>: rlen
size_type copy(CharT* s, size_type n, size_type pos = 0) const
{
- if (pos > size())
- this->throw_out_of_range();
- const size_type len = container_detail::min_value(n, size() - pos);
+ if (pos > this->size())
+ throw_out_of_range("basic_string::copy out of range position");
+ const size_type len = container_detail::min_value(n, this->size() - pos);
Traits::copy(s, container_detail::to_raw_pointer(this->priv_addr() + pos), len);
return len;
}
@@ -1670,22 +1897,34 @@ class basic_string
container_detail::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>Returns</b>: Allocator pointer p such that p + i == &operator[](i) for each i in [0,size()].
//!
//! <b>Complexity</b>: constant time.
- const CharT* c_str() const
+ const CharT* c_str() const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::to_raw_pointer(this->priv_addr()); }
//! <b>Requires</b>: The program shall not alter any of the values stored in the character array.
//!
- //! <b>Returns</b>: A pointer p such that p + i == &operator[](i) for each i in [0,size()].
+ //! <b>Returns</b>: Allocator pointer p such that p + i == &operator[](i) for each i in [0,size()].
//!
//! <b>Complexity</b>: constant time.
- const CharT* data() const
+ const CharT* data() const BOOST_CONTAINER_NOEXCEPT
{ return container_detail::to_raw_pointer(this->priv_addr()); }
+ //////////////////////////////////////////////
+ //
+ // string operations
+ //
+ //////////////////////////////////////////////
+
//! <b>Effects</b>: Determines the lowest position xpos, if possible, such that both
//! of the following conditions obtain: 19 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.
@@ -1703,12 +1942,13 @@ class basic_string
//! <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 > size())
+ if (pos + n > this->size())
return npos;
else {
- pointer finish = this->priv_addr() + this->priv_size();
+ const pointer addr = this->priv_addr();
+ pointer finish = addr + this->priv_size();
const const_iterator result =
- std::search(container_detail::to_raw_pointer(this->priv_addr() + pos),
+ std::search(container_detail::to_raw_pointer(addr + pos),
container_detail::to_raw_pointer(finish),
s, s + n, Eq_traits<Traits>());
return result != finish ? result - begin() : npos;
@@ -1721,19 +1961,21 @@ class basic_string
//!
//! <b>Returns</b>: find(basic_string(s), pos).
size_type find(const CharT* s, size_type pos = 0) const
- { return find(s, pos, Traits::length(s)); }
+ { 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
{
- if (pos >= size())
+ const size_type sz = this->size();
+ if (pos >= sz)
return npos;
else {
- pointer finish = this->priv_addr() + this->priv_size();
+ const pointer addr = this->priv_addr();
+ pointer finish = addr + sz;
const const_iterator result =
- std::find_if(this->priv_addr() + pos, finish,
+ std::find_if(addr + pos, finish,
std::bind2nd(Eq_traits<Traits>(), c));
return result != finish ? result - begin() : npos;
}
@@ -1757,7 +1999,7 @@ class basic_string
//! <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 = size();
+ const size_type len = this->size();
if (n > len)
return npos;
@@ -1786,7 +2028,7 @@ class basic_string
//! <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 = size();
+ const size_type len = this->size();
if (len < 1)
return npos;
@@ -1816,14 +2058,15 @@ class basic_string
//! <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
{
- if (pos >= size())
+ const size_type sz = this->size();
+ if (pos >= sz)
return npos;
else {
- pointer finish = this->priv_addr() + this->priv_size();
- const_iterator result = std::find_first_of(this->priv_addr() + pos, finish,
- s, s + n,
- Eq_traits<Traits>());
- return result != finish ? result - begin() : npos;
+ const pointer addr = this->priv_addr();
+ pointer finish = addr + sz;
+ const_iterator result = std::find_first_of
+ (addr + pos, finish, s, s + n, Eq_traits<Traits>());
+ return result != finish ? result - this->begin() : npos;
}
}
@@ -1860,17 +2103,17 @@ class basic_string
//! <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 = size();
+ const size_type len = this->size();
if (len < 1)
return npos;
else {
- const const_iterator last = this->priv_addr() + container_detail::min_value(len - 1, pos) + 1;
+ const pointer addr = this->priv_addr();
+ const const_iterator last = addr + container_detail::min_value(len - 1, pos) + 1;
const const_reverse_iterator rresult =
std::find_first_of(const_reverse_iterator(last), rend(),
- s, s + n,
- Eq_traits<Traits>());
- return rresult != rend() ? (rresult.base() - 1) - this->priv_addr() : npos;
+ s, s + n, Eq_traits<Traits>());
+ return rresult != rend() ? (rresult.base() - 1) - addr : npos;
}
}
@@ -1906,13 +2149,14 @@ class basic_string
//! <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 > size())
+ if (pos > this->size())
return npos;
else {
- pointer finish = this->priv_addr() + this->priv_size();
- const_iterator result = std::find_if(this->priv_addr() + pos, finish,
- Not_within_traits<Traits>(s, s + n));
- return result != finish ? result - this->priv_addr() : npos;
+ const pointer addr = this->priv_addr();
+ const pointer finish = addr + this->priv_size();
+ const const_iterator result = std::find_if
+ (addr + pos, finish, Not_within_traits<Traits>(s, s + n));
+ return result != finish ? result - addr : npos;
}
}
@@ -1929,12 +2173,13 @@ class basic_string
//! <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 > size())
+ if (pos > this->size())
return npos;
else {
- pointer finish = this->priv_addr() + this->priv_size();
- const_iterator result
- = std::find_if(this->priv_addr() + pos, finish,
+ const pointer addr = this->priv_addr();
+ const pointer finish = addr + this->priv_size();
+ const const_iterator result
+ = std::find_if(addr + pos, finish,
std::not1(std::bind2nd(Eq_traits<Traits>(), c)));
return result != finish ? result - begin() : npos;
}
@@ -1957,7 +2202,7 @@ class basic_string
//! <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 = size();
+ const size_type len = this->size();
if (len < 1)
return npos;
@@ -1983,13 +2228,13 @@ class basic_string
//! <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 = size();
+ const size_type len = this->size();
if (len < 1)
return npos;
else {
const const_iterator last = begin() + container_detail::min_value(len - 1, pos) + 1;
- const_reverse_iterator rresult =
+ const const_reverse_iterator rresult =
std::find_if(const_reverse_iterator(last), rend(),
std::not1(std::bind2nd(Eq_traits<Traits>(), c)));
return rresult != rend() ? (rresult.base() - 1) - begin() : npos;
@@ -2006,10 +2251,11 @@ class basic_string
//! <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 > size())
- this->throw_out_of_range();
- return basic_string(this->priv_addr() + pos,
- this->priv_addr() + pos + container_detail::min_value(n, size() - pos), this->alloc());
+ 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 + container_detail::min_value(n, size() - pos), this->alloc());
}
//! <b>Effects</b>: Determines the effective length rlen of the string to copy as
@@ -2022,7 +2268,11 @@ class basic_string
//! 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
- { return s_compare(this->priv_addr(), this->priv_addr() + this->priv_size(), str.priv_addr(), str.priv_addr() + str.priv_size()); }
+ {
+ 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>Requires</b>: pos1 <= size()
//!
@@ -2034,11 +2284,13 @@ class basic_string
//! <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 > size())
- this->throw_out_of_range();
- return s_compare(this->priv_addr() + pos1,
- this->priv_addr() + pos1 + container_detail::min_value(n1, size() - pos1),
- str.priv_addr(), str.priv_addr() + str.priv_size());
+ 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 + container_detail::min_value(n1, this->size() - pos1),
+ str_addr, str_addr + str.priv_size());
}
//! <b>Requires</b>: pos1 <= size() and pos2 <= str.size()
@@ -2049,21 +2301,26 @@ class basic_string
//! <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) const {
- if (pos1 > size() || pos2 > str.size())
- this->throw_out_of_range();
- return s_compare(this->priv_addr() + pos1,
- this->priv_addr() + pos1 + container_detail::min_value(n1, size() - pos1),
- str.priv_addr() + pos2,
- str.priv_addr() + pos2 + container_detail::min_value(n2, size() - pos2));
+ int compare(size_type pos1, size_type n1, const basic_string& str, size_type pos2, size_type n2) 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();
+ const pointer str_addr = str.priv_addr();
+ return s_compare(addr + pos1,
+ addr + pos1 + container_detail::min_value(n1, this->size() - pos1),
+ str_addr + pos2,
+ str_addr + pos2 + container_detail::min_value(n2, str.size() - pos2));
}
//! <b>Throws</b>: Nothing
//!
//! <b>Returns</b>: compare(basic_string(s)).
int compare(const CharT* s) const
- { return s_compare(this->priv_addr(), this->priv_addr() + this->priv_size(), s, s + Traits::length(s)); }
+ {
+ 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.
@@ -2071,13 +2328,13 @@ class basic_string
//! <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
+ int compare(size_type pos1, size_type n1, const CharT* s, size_type n2) const
{
- if (pos1 > size())
- this->throw_out_of_range();
- return s_compare(this->priv_addr() + pos1,
- this->priv_addr() + pos1 + container_detail::min_value(n1, size() - pos1),
+ 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 + container_detail::min_value(n1, this->size() - pos1),
s, s + n2);
}
@@ -2089,8 +2346,35 @@ class basic_string
int compare(size_type pos1, size_type n1, const CharT* s) const
{ return this->compare(pos1, n1, s, Traits::length(s)); }
- /// @cond
+ #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 = container_detail::max_value(res_arg, this->size()) + 1;
+ size_type new_cap = this->next_capacity(n);
+ pointer new_start = this->allocation_command
+ (allocate_new, n, new_cap, new_cap).first;
+ 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);
+ }
+ }
+
static int s_compare(const_pointer f1, const_pointer l1,
const_pointer f2, const_pointer l2)
{
@@ -2109,12 +2393,12 @@ class basic_string
{
//Allocate a new buffer.
size_type real_cap = 0;
- pointer long_addr = this->priv_long_addr();
- size_type long_size = this->priv_long_size();
- size_type long_storage = this->priv_long_storage();
+ 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
- try{
- std::pair<pointer, bool> ret = this->allocation_command
+ BOOST_TRY{
+ const std::pair<pointer, bool> ret = this->allocation_command
(allocate_new, long_size+1, long_size+1, real_cap, long_addr);
//Copy and update
Traits::copy( container_detail::to_raw_pointer(ret.first)
@@ -2125,9 +2409,10 @@ class basic_string
//And release old buffer
this->alloc().deallocate(long_addr, long_storage);
}
- catch(...){
+ BOOST_CATCH(...){
return;
}
+ BOOST_CATCH_END
}
template<class AllocVersion>
@@ -2145,55 +2430,12 @@ class basic_string
}
void priv_construct_null(pointer p)
- { this->construct(p, 0); }
-
- static CharT priv_null()
- { return (CharT) 0; }
+ { 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_addr() + this->priv_size()); }
-
- template <class InputIter>
- void priv_range_initialize(InputIter f, InputIter l,
- std::input_iterator_tag)
- {
- this->allocate_initial_block(InternalBufferChars);
- this->priv_construct_null(this->priv_addr() + this->priv_size());
- this->append(f, l);
- }
-
- template <class ForwardIter>
- void priv_range_initialize(ForwardIter f, ForwardIter l,
- std::forward_iterator_tag)
- {
- difference_type n = std::distance(f, l);
- this->allocate_initial_block(container_detail::max_value<difference_type>(n+1, InternalBufferChars));
- priv_uninitialized_copy(f, l, this->priv_addr());
- this->priv_size(n);
- this->priv_terminate_string();
- }
-
- template <class InputIter>
- void priv_range_initialize(InputIter f, InputIter l)
- {
- typedef typename std::iterator_traits<InputIter>::iterator_category Category;
- this->priv_range_initialize(f, l, Category());
- }
-
- template <class Integer>
- void priv_initialize_dispatch(Integer n, Integer x, container_detail::true_)
- {
- this->allocate_initial_block(container_detail::max_value<difference_type>(n+1, InternalBufferChars));
- priv_uninitialized_fill_n(this->priv_addr(), n, x);
- this->priv_size(n);
- this->priv_terminate_string();
- }
-
- template <class InputIter>
- void priv_initialize_dispatch(InputIter f, InputIter l, container_detail::false_)
- { this->priv_range_initialize(f, l); }
+ { 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)
@@ -2241,154 +2483,6 @@ class basic_string
return (constructed);
}
- template <class Integer>
- basic_string& priv_assign_dispatch(Integer n, Integer x, container_detail::true_)
- { return this->assign((size_type) n, (CharT) x); }
-
- template <class InputIter>
- basic_string& priv_assign_dispatch(InputIter f, InputIter l,
- container_detail::false_)
- {
- size_type cur = 0;
- CharT *ptr = container_detail::to_raw_pointer(this->priv_addr());
- while (f != l && cur != this->priv_size()) {
- Traits::assign(*ptr, *f);
- ++f;
- ++cur;
- ++ptr;
- }
- if (f == l)
- this->erase(this->priv_addr() + cur, this->priv_addr() + this->priv_size());
- else
- this->append(f, l);
- return *this;
- }
-
- template <class InputIter>
- void priv_insert(const_iterator p, InputIter first, InputIter last, std::input_iterator_tag)
- {
- for ( ; first != last; ++first, ++p) {
- p = this->insert(p, *first);
- }
- }
-
- template <class ForwardIter>
- void priv_insert(const_iterator position, ForwardIter first,
- ForwardIter last, std::forward_iterator_tag)
- {
- if (first != last) {
- size_type n = std::distance(first, last);
- size_type remaining = this->capacity() - this->priv_size();
- const size_type old_size = this->size();
- pointer old_start = this->priv_addr();
- bool enough_capacity = false;
- std::pair<pointer, bool> allocation_ret;
- size_type new_cap = 0;
-
- //Check if we have enough capacity
- if (remaining >= n){
- enough_capacity = true;
- }
- else {
- //Otherwise expand current buffer or allocate new storage
- new_cap = this->next_capacity(n);
- allocation_ret = this->allocation_command
- (allocate_new | expand_fwd | expand_bwd, old_size + n + 1,
- new_cap, new_cap, old_start);
-
- //Check forward expansion
- if(old_start == allocation_ret.first){
- enough_capacity = true;
- this->priv_storage(new_cap);
- }
- }
-
- //Reuse same buffer
- if(enough_capacity){
- const size_type elems_after =
- this->priv_size() - (position - this->priv_addr());
- size_type old_length = this->priv_size();
- if (elems_after >= n) {
- pointer pointer_past_last = this->priv_addr() + this->priv_size() + 1;
- priv_uninitialized_copy(this->priv_addr() + (this->priv_size() - n + 1),
- pointer_past_last, pointer_past_last);
-
- this->priv_size(this->priv_size()+n);
- Traits::move(const_cast<CharT*>(container_detail::to_raw_pointer(position + n)),
- container_detail::to_raw_pointer(position),
- (elems_after - n) + 1);
- this->priv_copy(first, last, const_cast<CharT*>(container_detail::to_raw_pointer(position)));
- }
- else {
- ForwardIter mid = first;
- std::advance(mid, elems_after + 1);
-
- priv_uninitialized_copy(mid, last, this->priv_addr() + this->priv_size() + 1);
- this->priv_size(this->priv_size() + (n - elems_after));
- priv_uninitialized_copy
- (position, const_iterator(this->priv_addr() + old_length + 1),
- this->priv_addr() + this->priv_size());
- this->priv_size(this->priv_size() + elems_after);
- this->priv_copy(first, mid, const_cast<CharT*>(container_detail::to_raw_pointer(position)));
- }
- }
- else{
- pointer new_start = allocation_ret.first;
- if(!allocation_ret.second){
- //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(this->priv_addr()), position, new_start);
- new_length += priv_uninitialized_copy
- (first, last, new_start + new_length);
- new_length += priv_uninitialized_copy
- (position, const_iterator(this->priv_addr() + this->priv_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 *oldbuf = container_detail::to_raw_pointer(old_start);
- value_type *newbuf = container_detail::to_raw_pointer(new_start);
- const value_type *pos = container_detail::to_raw_pointer(position);
- 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);
- }
- }
- }
- }
-
- template <class Integer>
- void priv_insert_dispatch(const_iterator p, Integer n, Integer x,
- container_detail::true_)
- { insert(p, (size_type) n, (CharT) x); }
-
- template <class InputIter>
- void priv_insert_dispatch(const_iterator p, InputIter first, InputIter last,
- container_detail::false_)
- {
- typedef typename std::iterator_traits<InputIter>::iterator_category Category;
- priv_insert(p, first, last, Category());
- }
-
template <class InputIterator, class OutIterator>
void priv_copy(InputIterator first, InputIterator last, OutIterator result)
{
@@ -2414,43 +2508,11 @@ class basic_string
return this->priv_replace(first, last, f, l, Category());
}
-
- template <class InputIter>
- basic_string& priv_replace(const_iterator first, const_iterator last,
- InputIter f, InputIter l, std::input_iterator_tag)
- {
- for ( ; first != last && f != l; ++first, ++f)
- Traits::assign(*first, *f);
-
- if (f == l)
- this->erase(first, last);
- else
- this->insert(last, f, l);
- return *this;
- }
-
- template <class ForwardIter>
- basic_string& priv_replace(const_iterator first, const_iterator last,
- ForwardIter f, ForwardIter l,
- std::forward_iterator_tag)
- {
- difference_type n = std::distance(f, l);
- const difference_type len = last - first;
- if (len >= n) {
- this->priv_copy(f, l, const_cast<CharT*>(container_detail::to_raw_pointer(first)));
- this->erase(first + n, last);
- }
- else {
- ForwardIter m = f;
- std::advance(m, len);
- this->priv_copy(f, m, const_cast<CharT*>(container_detail::to_raw_pointer(first)));
- this->insert(last, m, l);
- }
- return *this;
- }
- /// @endcond
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
};
+#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
+
//!Typedef for a basic_string of
//!narrow characters
typedef basic_string
@@ -2467,291 +2529,223 @@ typedef basic_string
,std::allocator<wchar_t> >
wstring;
-/// @cond
-
-template <class CharT, class Traits, class A>
-const typename basic_string<CharT,Traits,A>::size_type
-basic_string<CharT,Traits,A>::npos
- = (typename basic_string<CharT,Traits,A>::size_type) -1;
-
-/// @endcond
+#endif
// ------------------------------------------------------------
// Non-member functions.
// Operator+
-template <class CharT, class Traits, class A>
-inline basic_string<CharT,Traits,A>
-operator+(const basic_string<CharT,Traits,A>& x,
- const basic_string<CharT,Traits,A>& y)
+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,A> str_t;
+ 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 boost::move(result);
+ return result;
}
-template <class CharT, class Traits, class A> inline
-BOOST_RV_REF_3_TEMPL_ARGS(basic_string, CharT, Traits, A)
- operator+(
- BOOST_RV_REF_3_TEMPL_ARGS(basic_string, CharT, Traits, A) mx
- , BOOST_RV_REF_3_TEMPL_ARGS(basic_string, CharT, Traits, A) my)
+template <class CharT, class Traits, class Allocator> inline
+ basic_string<CharT, Traits, Allocator> operator+
+ ( BOOST_RV_REF_BEG basic_string<CharT, Traits, Allocator> BOOST_RV_REF_END mx
+ , BOOST_RV_REF_BEG basic_string<CharT, Traits, Allocator> BOOST_RV_REF_END my)
{
mx += my;
return boost::move(mx);
}
-template <class CharT, class Traits, class A> inline
-BOOST_RV_REF_3_TEMPL_ARGS(basic_string, CharT, Traits, A)
- operator+(
- BOOST_RV_REF_3_TEMPL_ARGS(basic_string, CharT, Traits, A) mx
- , const basic_string<CharT,Traits,A>& y)
+template <class CharT, class Traits, class Allocator> inline
+ basic_string<CharT, Traits, Allocator> operator+
+ ( BOOST_RV_REF_BEG basic_string<CharT, Traits, Allocator> BOOST_RV_REF_END mx
+ , const basic_string<CharT,Traits,Allocator>& y)
{
mx += y;
return boost::move(mx);
}
-template <class CharT, class Traits, class A> inline
-BOOST_RV_REF_3_TEMPL_ARGS(basic_string, CharT, Traits, A)
- operator+(const basic_string<CharT,Traits,A>& x,
- BOOST_RV_REF_3_TEMPL_ARGS(basic_string, CharT, Traits, A) my)
+template <class CharT, class Traits, class Allocator> inline
+ basic_string<CharT, Traits, Allocator> operator+
+ (const basic_string<CharT,Traits,Allocator>& x
+ ,BOOST_RV_REF_BEG basic_string<CharT, Traits, Allocator> BOOST_RV_REF_END my)
{
- typedef typename basic_string<CharT,Traits,A>::size_type size_type;
- my.replace(size_type(0), size_type(0), x);
+ my.insert(my.begin(), x.begin(), x.end());
return boost::move(my);
}
-template <class CharT, class Traits, class A>
-inline basic_string<CharT,Traits,A>
-operator+(const CharT* s, const basic_string<CharT,Traits,A>& y)
-{
- typedef basic_string<CharT, Traits, A> str_t;
- typedef typename str_t::reserve_t reserve_t;
- reserve_t reserve;
- const typename str_t::size_type n = Traits::length(s);
- str_t result(reserve, n + y.size());
- result.append(s, s + n);
- result.append(y);
- return boost::move(result);
-}
-
-template <class CharT, class Traits, class A> inline
-BOOST_RV_REF_3_TEMPL_ARGS(basic_string, CharT, Traits, A)
-operator+(const CharT* s,
- BOOST_RV_REF_3_TEMPL_ARGS(basic_string, CharT, Traits, A) my)
-{
- typedef typename basic_string<CharT,Traits,A>::size_type size_type;
- return boost::move(my.replace(size_type(0), size_type(0), s));
-}
-
-template <class CharT, class Traits, class A>
-inline basic_string<CharT,Traits,A>
-operator+(CharT c, const basic_string<CharT,Traits,A>& y)
-{
- typedef basic_string<CharT,Traits,A> str_t;
- typedef typename str_t::reserve_t reserve_t;
- reserve_t reserve;
- str_t result(reserve, 1 + y.size());
- result.push_back(c);
- result.append(y);
- return boost::move(result);
-}
-
-template <class CharT, class Traits, class A> inline
-BOOST_RV_REF_3_TEMPL_ARGS(basic_string, CharT, Traits, A)
-operator+(CharT c,
- BOOST_RV_REF_3_TEMPL_ARGS(basic_string, CharT, Traits, A) my)
+template <class CharT, class Traits, class Allocator> inline
+ basic_string<CharT, Traits, Allocator> operator+
+ (const CharT* s, basic_string<CharT, Traits, Allocator> y)
{
- typedef typename basic_string<CharT,Traits,A>::size_type size_type;
- return boost::move(my.replace(size_type(0), size_type(0), &c, &c + 1));
+ y.insert(y.begin(), s, s + Traits::length(s));
+ return y;
}
-template <class CharT, class Traits, class A>
-inline basic_string<CharT,Traits,A>
-operator+(const basic_string<CharT,Traits,A>& x, const CharT* s)
+template <class CharT, class Traits, class Allocator> inline
+ basic_string<CharT,Traits,Allocator> operator+
+ (basic_string<CharT,Traits,Allocator> x, const CharT* s)
{
- typedef basic_string<CharT,Traits,A> str_t;
- typedef typename str_t::reserve_t reserve_t;
- reserve_t reserve;
- const typename str_t::size_type n = Traits::length(s);
- str_t result(reserve, x.size() + n, x.get_stored_allocator());
- result.append(x);
- result.append(s, s + n);
- return boost::move(result);
+ x += s;
+ return x;
}
-template <class CharT, class Traits, class A>
-BOOST_RV_REF_3_TEMPL_ARGS(basic_string, CharT, Traits, A)
-operator+(BOOST_RV_REF_3_TEMPL_ARGS(basic_string, CharT, Traits, A) mx
- , const CharT* s)
+template <class CharT, class Traits, class Allocator> inline
+ basic_string<CharT,Traits,Allocator> operator+
+ (CharT c, basic_string<CharT,Traits,Allocator> y)
{
- mx += s;
- return boost::move(mx);
-}
-
-template <class CharT, class Traits, class A>
-inline basic_string<CharT,Traits,A>
-operator+(const basic_string<CharT,Traits,A>& x, const CharT c)
-{
- typedef basic_string<CharT,Traits,A> str_t;
- typedef typename str_t::reserve_t reserve_t;
- reserve_t reserve;
- str_t result(reserve, x.size() + 1, x.get_stored_allocator());
- result.append(x);
- result.push_back(c);
- return boost::move(result);
+ y.insert(y.begin(), c);
+ return y;
}
-template <class CharT, class Traits, class A>
-BOOST_RV_REF_3_TEMPL_ARGS(basic_string, CharT, Traits, A)
-operator+( BOOST_RV_REF_3_TEMPL_ARGS(basic_string, CharT, Traits, A) mx
- , const CharT c)
+template <class CharT, class Traits, class Allocator> inline
+ basic_string<CharT,Traits,Allocator> operator+
+ (basic_string<CharT,Traits,Allocator> x, const CharT c)
{
- mx += c;
- return boost::move(mx);
+ x += c;
+ return x;
}
// Operator== and operator!=
-template <class CharT, class Traits, class A>
+template <class CharT, class Traits, class Allocator>
inline bool
-operator==(const basic_string<CharT,Traits,A>& x,
- const basic_string<CharT,Traits,A>& y)
+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 A>
+template <class CharT, class Traits, class Allocator>
inline bool
-operator==(const CharT* s, const basic_string<CharT,Traits,A>& y)
+operator==(const CharT* s, const basic_string<CharT,Traits,Allocator>& y)
{
- typename basic_string<CharT,Traits,A>::size_type n = Traits::length(s);
+ 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 A>
+template <class CharT, class Traits, class Allocator>
inline bool
-operator==(const basic_string<CharT,Traits,A>& x, const CharT* s)
+operator==(const basic_string<CharT,Traits,Allocator>& x, const CharT* s)
{
- typename basic_string<CharT,Traits,A>::size_type n = Traits::length(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 A>
+template <class CharT, class Traits, class Allocator>
inline bool
-operator!=(const basic_string<CharT,Traits,A>& x,
- const basic_string<CharT,Traits,A>& y)
+operator!=(const basic_string<CharT,Traits,Allocator>& x,
+ const basic_string<CharT,Traits,Allocator>& y)
{ return !(x == y); }
-template <class CharT, class Traits, class A>
+template <class CharT, class Traits, class Allocator>
inline bool
-operator!=(const CharT* s, const basic_string<CharT,Traits,A>& y)
+operator!=(const CharT* s, const basic_string<CharT,Traits,Allocator>& y)
{ return !(s == y); }
-template <class CharT, class Traits, class A>
+template <class CharT, class Traits, class Allocator>
inline bool
-operator!=(const basic_string<CharT,Traits,A>& x, const CharT* s)
+operator!=(const basic_string<CharT,Traits,Allocator>& x, const CharT* s)
{ return !(x == s); }
// Operator< (and also >, <=, and >=).
-template <class CharT, class Traits, class A>
+template <class CharT, class Traits, class Allocator>
inline bool
-operator<(const basic_string<CharT,Traits,A>& x, const basic_string<CharT,Traits,A>& y)
+operator<(const basic_string<CharT,Traits,Allocator>& x, const basic_string<CharT,Traits,Allocator>& y)
{
return x.compare(y) < 0;
-// return basic_string<CharT,Traits,A>
+// return basic_string<CharT,Traits,Allocator>
// ::s_compare(x.begin(), x.end(), y.begin(), y.end()) < 0;
}
-template <class CharT, class Traits, class A>
+template <class CharT, class Traits, class Allocator>
inline bool
-operator<(const CharT* s, const basic_string<CharT,Traits,A>& y)
+operator<(const CharT* s, const basic_string<CharT,Traits,Allocator>& y)
{
return y.compare(s) > 0;
-// basic_string<CharT,Traits,A>::size_type n = Traits::length(s);
-// return basic_string<CharT,Traits,A>
+// basic_string<CharT,Traits,Allocator>::size_type n = Traits::length(s);
+// return basic_string<CharT,Traits,Allocator>
// ::s_compare(s, s + n, y.begin(), y.end()) < 0;
}
-template <class CharT, class Traits, class A>
+template <class CharT, class Traits, class Allocator>
inline bool
-operator<(const basic_string<CharT,Traits,A>& x,
+operator<(const basic_string<CharT,Traits,Allocator>& x,
const CharT* s)
{
return x.compare(s) < 0;
-// basic_string<CharT,Traits,A>::size_type n = Traits::length(s);
-// return basic_string<CharT,Traits,A>
+// basic_string<CharT,Traits,Allocator>::size_type n = Traits::length(s);
+// return basic_string<CharT,Traits,Allocator>
// ::s_compare(x.begin(), x.end(), s, s + n) < 0;
}
-template <class CharT, class Traits, class A>
+template <class CharT, class Traits, class Allocator>
inline bool
-operator>(const basic_string<CharT,Traits,A>& x,
- const basic_string<CharT,Traits,A>& y) {
+operator>(const basic_string<CharT,Traits,Allocator>& x,
+ const basic_string<CharT,Traits,Allocator>& y) {
return y < x;
}
-template <class CharT, class Traits, class A>
+template <class CharT, class Traits, class Allocator>
inline bool
-operator>(const CharT* s, const basic_string<CharT,Traits,A>& y) {
+operator>(const CharT* s, const basic_string<CharT,Traits,Allocator>& y) {
return y < s;
}
-template <class CharT, class Traits, class A>
+template <class CharT, class Traits, class Allocator>
inline bool
-operator>(const basic_string<CharT,Traits,A>& x, const CharT* s)
+operator>(const basic_string<CharT,Traits,Allocator>& x, const CharT* s)
{
return s < x;
}
-template <class CharT, class Traits, class A>
+template <class CharT, class Traits, class Allocator>
inline bool
-operator<=(const basic_string<CharT,Traits,A>& x,
- const basic_string<CharT,Traits,A>& y)
+operator<=(const basic_string<CharT,Traits,Allocator>& x,
+ const basic_string<CharT,Traits,Allocator>& y)
{
return !(y < x);
}
-template <class CharT, class Traits, class A>
+template <class CharT, class Traits, class Allocator>
inline bool
-operator<=(const CharT* s, const basic_string<CharT,Traits,A>& y)
+operator<=(const CharT* s, const basic_string<CharT,Traits,Allocator>& y)
{ return !(y < s); }
-template <class CharT, class Traits, class A>
+template <class CharT, class Traits, class Allocator>
inline bool
-operator<=(const basic_string<CharT,Traits,A>& x, const CharT* s)
+operator<=(const basic_string<CharT,Traits,Allocator>& x, const CharT* s)
{ return !(s < x); }
-template <class CharT, class Traits, class A>
+template <class CharT, class Traits, class Allocator>
inline bool
-operator>=(const basic_string<CharT,Traits,A>& x,
- const basic_string<CharT,Traits,A>& y)
+operator>=(const basic_string<CharT,Traits,Allocator>& x,
+ const basic_string<CharT,Traits,Allocator>& y)
{ return !(x < y); }
-template <class CharT, class Traits, class A>
+template <class CharT, class Traits, class Allocator>
inline bool
-operator>=(const CharT* s, const basic_string<CharT,Traits,A>& y)
+operator>=(const CharT* s, const basic_string<CharT,Traits,Allocator>& y)
{ return !(s < y); }
-template <class CharT, class Traits, class A>
+template <class CharT, class Traits, class Allocator>
inline bool
-operator>=(const basic_string<CharT,Traits,A>& x, const CharT* s)
+operator>=(const basic_string<CharT,Traits,Allocator>& x, const CharT* s)
{ return !(x < s); }
// Swap.
-template <class CharT, class Traits, class A>
-inline void swap(basic_string<CharT,Traits,A>& x, basic_string<CharT,Traits,A>& y)
+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); }
-/// @cond
-// I/O.
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+// I/O.
namespace container_detail {
template <class CharT, class Traits>
@@ -2770,28 +2764,28 @@ string_fill(std::basic_ostream<CharT, Traits>& os,
}
} //namespace container_detail {
-/// @endcond
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
-template <class CharT, class Traits, class A>
+template <class CharT, class Traits, class Allocator>
std::basic_ostream<CharT, Traits>&
-operator<<(std::basic_ostream<CharT, Traits>& os, const basic_string<CharT,Traits,A>& s)
+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,A>::size_type n = s.size();
- typename basic_string<CharT,Traits,A>::size_type pad_len = 0;
+ 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 = container_detail::string_fill(os, buf, pad_len);
+ ok = container_detail::string_fill(os, buf, pad_len);
ok = ok &&
buf->sputn(s.data(), std::streamsize(n)) == std::streamsize(n);
@@ -2807,9 +2801,9 @@ operator<<(std::basic_ostream<CharT, Traits>& os, const basic_string<CharT,Trait
}
-template <class CharT, class Traits, class A>
+template <class CharT, class Traits, class Allocator>
std::basic_istream<CharT, Traits>&
-operator>>(std::basic_istream<CharT, Traits>& is, basic_string<CharT,Traits,A>& s)
+operator>>(std::basic_istream<CharT, Traits>& is, basic_string<CharT,Traits,Allocator>& s)
{
typename std::basic_istream<CharT, Traits>::sentry sentry(is);
@@ -2843,7 +2837,7 @@ operator>>(std::basic_istream<CharT, Traits>& is, basic_string<CharT,Traits,A>&
s.push_back(c);
}
}
-
+
// If we have read no characters, then set failbit.
if (s.size() == 0)
is.setstate(std::ios_base::failbit);
@@ -2854,11 +2848,11 @@ operator>>(std::basic_istream<CharT, Traits>& is, basic_string<CharT,Traits,A>&
return is;
}
-template <class CharT, class Traits, class A>
+template <class CharT, class Traits, class Allocator>
std::basic_istream<CharT, Traits>&
-getline(std::istream& is, basic_string<CharT,Traits,A>& s,CharT delim)
+getline(std::istream& is, basic_string<CharT,Traits,Allocator>& s,CharT delim)
{
- typename basic_string<CharT,Traits,A>::size_type nread = 0;
+ 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();
@@ -2886,36 +2880,38 @@ getline(std::istream& is, basic_string<CharT,Traits,A>& s,CharT delim)
return is;
}
-template <class CharT, class Traits, class A>
+template <class CharT, class Traits, class Allocator>
inline std::basic_istream<CharT, Traits>&
-getline(std::basic_istream<CharT, Traits>& is, basic_string<CharT,Traits,A>& s)
+getline(std::basic_istream<CharT, Traits>& is, basic_string<CharT,Traits,Allocator>& s)
{
return getline(is, s, '\n');
}
-template <class Ch, class A>
-inline std::size_t hash_value(basic_string<Ch, std::char_traits<Ch>, A> const& v)
+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());
}
}}
-/// @cond
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
namespace boost {
-/*
+
+template <class T>
+struct has_trivial_destructor_after_move;
+
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
-template <class C, class T, class A>
-struct has_trivial_destructor_after_move<boost::container::basic_string<C, T, A> >
-{
- static const bool value = has_trivial_destructor<A>::value;
-};
-*/
+template <class C, class T, class Allocator>
+struct has_trivial_destructor_after_move<boost::container::basic_string<C, T, Allocator> >
+ : public ::boost::has_trivial_destructor_after_move<Allocator>
+{};
+
}
-/// @endcond
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
#include <boost/container/detail/config_end.hpp>
diff --git a/boost/container/throw_exception.hpp b/boost/container/throw_exception.hpp
new file mode 100644
index 0000000000..02768856e5
--- /dev/null
+++ b/boost/container/throw_exception.hpp
@@ -0,0 +1,166 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (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
+
+#if defined(_MSC_VER)
+# 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 <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()
+ {
+ BOOST_ASSERT(!"boost::container bad_alloc thrown");
+ std::abort();
+ }
+
+ inline void throw_out_of_range(const char* str)
+ {
+ BOOST_ASSERT_MSG(!"boost::container out_of_range thrown", str);
+ std::abort();
+ }
+
+ inline void throw_length_error(const char* str)
+ {
+ BOOST_ASSERT_MSG(!"boost::container length_error thrown", str);
+ std::abort();
+ }
+
+ inline void throw_logic_error(const char* str)
+ {
+ BOOST_ASSERT_MSG(!"boost::container logic_error thrown", str);
+ std::abort();
+ }
+
+ inline void throw_runtime_error(const char* str)
+ {
+ BOOST_ASSERT_MSG(!"boost::container runtime_error thrown", 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/boost/container/vector.hpp b/boost/container/vector.hpp
index c6e5b51c30..765a2c6861 100644
--- a/boost/container/vector.hpp
+++ b/boost/container/vector.hpp
@@ -1,6 +1,6 @@
//////////////////////////////////////////////////////////////////////////////
//
-// (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
+// (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)
//
@@ -11,7 +11,7 @@
#ifndef BOOST_CONTAINER_CONTAINER_VECTOR_HPP
#define BOOST_CONTAINER_CONTAINER_VECTOR_HPP
-#if (defined _MSC_VER) && (_MSC_VER >= 1200)
+#if defined(_MSC_VER)
# pragma once
#endif
@@ -19,19 +19,22 @@
#include <boost/container/detail/workaround.hpp>
#include <boost/container/container_fwd.hpp>
-#include <cstddef>
-#include <memory>
-#include <algorithm>
-#include <stdexcept>
-#include <iterator>
-#include <utility>
-#include <boost/detail/no_exceptions_support.hpp>
-#include <boost/type_traits/has_trivial_destructor.hpp>
-#include <boost/type_traits/has_trivial_copy.hpp>
-#include <boost/type_traits/has_trivial_assign.hpp>
-#include <boost/type_traits/has_nothrow_copy.hpp>
-#include <boost/type_traits/has_nothrow_assign.hpp>
-#include <boost/type_traits/has_nothrow_constructor.hpp>
+//#include <cstddef> //Already included by container_fwd.hpp
+#include <memory> //for std::allocator
+#include <iterator> //for std::random_access_iterator_tag
+#include <utility> //for std::pair,std::distance
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+#include <initializer_list> //for std::initializer_list
+#endif
+
+#include <boost/core/no_exceptions_support.hpp>
+#include <boost/assert.hpp>
+#include <boost/move/utility_core.hpp>
+#include <boost/move/iterator.hpp>
+#include <boost/move/algorithm.hpp>
+#include <boost/move/detail/move_helpers.hpp>
+#include <boost/move/traits.hpp>
+
#include <boost/container/detail/version_type.hpp>
#include <boost/container/detail/allocation_type.hpp>
#include <boost/container/detail/utilities.hpp>
@@ -39,426 +42,557 @@
#include <boost/container/detail/algorithms.hpp>
#include <boost/container/detail/destroyers.hpp>
#include <boost/container/allocator_traits.hpp>
-#include <boost/container/container_fwd.hpp>
-#include <boost/move/move.hpp>
-#include <boost/move/move_helpers.hpp>
-#include <boost/intrusive/pointer_traits.hpp>
+#include <boost/container/detail/allocator_version_traits.hpp>
+#include <boost/container/throw_exception.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/container/detail/type_traits.hpp>
#include <boost/container/detail/advanced_insert_int.hpp>
-#include <boost/assert.hpp>
+
+#include <boost/intrusive/pointer_traits.hpp>
+
+#include <boost/type_traits/has_trivial_destructor.hpp>
+#include <boost/type_traits/has_trivial_copy.hpp>
+#include <boost/type_traits/has_trivial_assign.hpp>
+#include <boost/type_traits/has_nothrow_copy.hpp>
+#include <boost/type_traits/has_nothrow_assign.hpp>
+#include <boost/type_traits/has_nothrow_constructor.hpp>
namespace boost {
namespace container {
-/// @cond
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+//#define BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
namespace container_detail {
-//! Const vector_iterator used to iterate through a vector.
-template <class Pointer>
-class vector_const_iterator
+#ifndef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
+
+template <class Pointer, bool IsConst>
+class vec_iterator
{
public:
- typedef std::random_access_iterator_tag iterator_category;
+ 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 boost::intrusive::pointer_traits<Pointer>::template
- rebind_pointer<const value_type>::type pointer;
- typedef const value_type& reference;
-
- /// @cond
- protected:
+ typedef typename 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:
- Pointer get_ptr() const { return m_ptr; }
- explicit vector_const_iterator(Pointer ptr) : m_ptr(ptr){}
- /// @endcond
+ const Pointer &get_ptr() const BOOST_CONTAINER_NOEXCEPT
+ { return m_ptr; }
+
+ Pointer &get_ptr() BOOST_CONTAINER_NOEXCEPT
+ { return m_ptr; }
+
+ explicit vec_iterator(Pointer ptr) BOOST_CONTAINER_NOEXCEPT
+ : m_ptr(ptr)
+ {}
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public:
//Constructors
- vector_const_iterator() : m_ptr(0){}
+ vec_iterator() BOOST_CONTAINER_NOEXCEPT
+ : m_ptr() //Value initialization to achieve "null iterators" (N3644)
+ {}
+
+ vec_iterator(vec_iterator<Pointer, false> const& other) BOOST_CONTAINER_NOEXCEPT
+ : m_ptr(other.get_ptr())
+ {}
//Pointer like operators
- reference operator*() const
+ reference operator*() const BOOST_CONTAINER_NOEXCEPT
{ return *m_ptr; }
- const value_type * operator->() const
- { return container_detail::to_raw_pointer(m_ptr); }
+ pointer operator->() const BOOST_CONTAINER_NOEXCEPT
+ { return ::boost::intrusive::pointer_traits<pointer>::pointer_to(this->operator*()); }
- reference operator[](difference_type off) const
+ reference operator[](difference_type off) const BOOST_CONTAINER_NOEXCEPT
{ return m_ptr[off]; }
//Increment / Decrement
- vector_const_iterator& operator++()
+ vec_iterator& operator++() BOOST_CONTAINER_NOEXCEPT
{ ++m_ptr; return *this; }
- vector_const_iterator operator++(int)
- { Pointer tmp = m_ptr; ++*this; return vector_const_iterator(tmp); }
+ vec_iterator operator++(int) BOOST_CONTAINER_NOEXCEPT
+ { return vec_iterator(m_ptr++); }
- vector_const_iterator& operator--()
+ vec_iterator& operator--() BOOST_CONTAINER_NOEXCEPT
{ --m_ptr; return *this; }
- vector_const_iterator operator--(int)
- { Pointer tmp = m_ptr; --*this; return vector_const_iterator(tmp); }
+ vec_iterator operator--(int) BOOST_CONTAINER_NOEXCEPT
+ { return vec_iterator(m_ptr--); }
//Arithmetic
- vector_const_iterator& operator+=(difference_type off)
+ vec_iterator& operator+=(difference_type off) BOOST_CONTAINER_NOEXCEPT
{ m_ptr += off; return *this; }
- vector_const_iterator operator+(difference_type off) const
- { return vector_const_iterator(m_ptr+off); }
+ vec_iterator& operator-=(difference_type off) BOOST_CONTAINER_NOEXCEPT
+ { m_ptr -= off; return *this; }
- friend vector_const_iterator operator+(difference_type off, const vector_const_iterator& right)
- { return vector_const_iterator(off + right.m_ptr); }
+ friend vec_iterator operator+(const vec_iterator &x, difference_type off) BOOST_CONTAINER_NOEXCEPT
+ { return vec_iterator(x.m_ptr+off); }
- vector_const_iterator& operator-=(difference_type off)
- { m_ptr -= off; return *this; }
+ friend vec_iterator operator+(difference_type off, vec_iterator right) BOOST_CONTAINER_NOEXCEPT
+ { right.m_ptr += off; return right; }
- vector_const_iterator operator-(difference_type off) const
- { return vector_const_iterator(m_ptr-off); }
+ friend vec_iterator operator-(vec_iterator left, difference_type off) BOOST_CONTAINER_NOEXCEPT
+ { left.m_ptr -= off; return left; }
- difference_type operator-(const vector_const_iterator& right) const
- { return m_ptr - right.m_ptr; }
+ friend difference_type operator-(const vec_iterator &left, const vec_iterator& right) BOOST_CONTAINER_NOEXCEPT
+ { return left.m_ptr - right.m_ptr; }
//Comparison operators
- bool operator== (const vector_const_iterator& r) const
- { return m_ptr == r.m_ptr; }
+ friend bool operator== (const vec_iterator& l, const vec_iterator& r) BOOST_CONTAINER_NOEXCEPT
+ { return l.m_ptr == r.m_ptr; }
- bool operator!= (const vector_const_iterator& r) const
- { return m_ptr != r.m_ptr; }
+ friend bool operator!= (const vec_iterator& l, const vec_iterator& r) BOOST_CONTAINER_NOEXCEPT
+ { return l.m_ptr != r.m_ptr; }
- bool operator< (const vector_const_iterator& r) const
- { return m_ptr < r.m_ptr; }
+ friend bool operator< (const vec_iterator& l, const vec_iterator& r) BOOST_CONTAINER_NOEXCEPT
+ { return l.m_ptr < r.m_ptr; }
- bool operator<= (const vector_const_iterator& r) const
- { return m_ptr <= r.m_ptr; }
+ friend bool operator<= (const vec_iterator& l, const vec_iterator& r) BOOST_CONTAINER_NOEXCEPT
+ { return l.m_ptr <= r.m_ptr; }
- bool operator> (const vector_const_iterator& r) const
- { return m_ptr > r.m_ptr; }
+ friend bool operator> (const vec_iterator& l, const vec_iterator& r) BOOST_CONTAINER_NOEXCEPT
+ { return l.m_ptr > r.m_ptr; }
- bool operator>= (const vector_const_iterator& r) const
- { return m_ptr >= r.m_ptr; }
+ friend bool operator>= (const vec_iterator& l, const vec_iterator& r) BOOST_CONTAINER_NOEXCEPT
+ { return l.m_ptr >= r.m_ptr; }
};
-//! Iterator used to iterate through a vector
-template <class Pointer>
-class vector_iterator
- : public vector_const_iterator<Pointer>
-{
- public:
- explicit vector_iterator(Pointer ptr)
- : vector_const_iterator<Pointer>(ptr)
- {}
-
- 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 Pointer pointer;
- typedef value_type& reference;
+} //namespace container_detail {
- //Constructors
- vector_iterator()
- {}
+template<class Pointer, bool IsConst>
+const Pointer &vector_iterator_get_ptr(const container_detail::vec_iterator<Pointer, IsConst> &it) BOOST_CONTAINER_NOEXCEPT
+{ return it.get_ptr(); }
- //Pointer like operators
- reference operator*() const
- { return *this->m_ptr; }
+template<class Pointer, bool IsConst>
+Pointer &get_ptr(container_detail::vec_iterator<Pointer, IsConst> &it) BOOST_CONTAINER_NOEXCEPT
+{ return it.get_ptr(); }
- value_type* operator->() const
- { return container_detail::to_raw_pointer(this->m_ptr); }
-
- reference operator[](difference_type off) const
- { return this->m_ptr[off]; }
+namespace container_detail {
- //Increment / Decrement
- vector_iterator& operator++()
- { ++this->m_ptr; return *this; }
+#else //ifndef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
- vector_iterator operator++(int)
- { pointer tmp = this->m_ptr; ++*this; return vector_iterator(tmp); }
-
- vector_iterator& operator--()
- { --this->m_ptr; return *this; }
+template< class MaybeConstPointer
+ , bool ElementTypeIsConst
+ = is_const< typename boost::intrusive::pointer_traits<MaybeConstPointer>::element_type>::value >
+struct vector_get_ptr_pointer_to_non_const
+{
+ typedef MaybeConstPointer const_pointer;
+ typedef boost::intrusive::pointer_traits<const_pointer> pointer_traits_t;
+ typedef typename pointer_traits_t::element_type element_type;
+ typedef typename remove_const<element_type>::type non_const_element_type;
+ typedef typename pointer_traits_t
+ ::template rebind_pointer<non_const_element_type>::type return_type;
+
+ static return_type get_ptr(const const_pointer &ptr) BOOST_CONTAINER_NOEXCEPT
+ { return boost::intrusive::pointer_traits<return_type>::const_cast_from(ptr); }
+};
- vector_iterator operator--(int)
- { vector_iterator tmp = *this; --*this; return vector_iterator(tmp); }
+template<class Pointer>
+struct vector_get_ptr_pointer_to_non_const<Pointer, false>
+{
+ typedef const Pointer & return_type;
+ static return_type get_ptr(const Pointer &ptr) BOOST_CONTAINER_NOEXCEPT
+ { return ptr; }
+};
- // Arithmetic
- vector_iterator& operator+=(difference_type off)
- { this->m_ptr += off; return *this; }
+} //namespace container_detail {
- vector_iterator operator+(difference_type off) const
- { return vector_iterator(this->m_ptr+off); }
+template<class MaybeConstPointer>
+typename container_detail::vector_get_ptr_pointer_to_non_const<MaybeConstPointer>::return_type
+ vector_iterator_get_ptr(const MaybeConstPointer &ptr) BOOST_CONTAINER_NOEXCEPT
+{
+ return container_detail::vector_get_ptr_pointer_to_non_const<MaybeConstPointer>::get_ptr(ptr);
+}
- friend vector_iterator operator+(difference_type off, const vector_iterator& right)
- { return vector_iterator(off + right.m_ptr); }
+namespace container_detail {
- vector_iterator& operator-=(difference_type off)
- { this->m_ptr -= off; return *this; }
+#endif //#ifndef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
- vector_iterator operator-(difference_type off) const
- { return vector_iterator(this->m_ptr-off); }
+struct uninitialized_size_t {};
+static const uninitialized_size_t uninitialized_size = uninitialized_size_t();
- difference_type operator-(const vector_const_iterator<Pointer>& right) const
- { return static_cast<const vector_const_iterator<Pointer>&>(*this) - right; }
+template <class T>
+struct vector_value_traits_base
+{
+ static const bool trivial_dctr = boost::has_trivial_destructor<T>::value;
+ static const bool trivial_dctr_after_move = ::boost::has_trivial_destructor_after_move<T>::value;
+ static const bool trivial_copy = has_trivial_copy<T>::value;
+ static const bool nothrow_copy = has_nothrow_copy<T>::value || trivial_copy;
+ static const bool trivial_assign = has_trivial_assign<T>::value;
+ static const bool nothrow_assign = has_nothrow_assign<T>::value || trivial_assign;
};
-template <class T, class A>
+
+template <class Allocator>
struct vector_value_traits
+ : public vector_value_traits_base<typename Allocator::value_type>
{
- typedef T value_type;
- typedef A allocator_type;
- static const bool trivial_dctr = boost::has_trivial_destructor<value_type>::value;
- static const bool trivial_dctr_after_move = trivial_dctr;
- //::boost::has_trivial_destructor_after_move<value_type>::value || trivial_dctr;
- //static const bool trivial_copy = has_trivial_copy<value_type>::value;
- //static const bool nothrow_copy = has_nothrow_copy<value_type>::value;
- //static const bool trivial_assign = has_trivial_assign<value_type>::value;
- //static const bool nothrow_assign = has_nothrow_assign<value_type>::value;
-
- static const bool trivial_copy = has_trivial_copy<value_type>::value;
- static const bool nothrow_copy = has_nothrow_copy<value_type>::value;
- static const bool trivial_assign = has_trivial_assign<value_type>::value;
- static const bool nothrow_assign = false;
-
+ 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 container_detail::if_c
- <trivial_dctr
- ,container_detail::null_scoped_destructor_n<A>
- ,container_detail::scoped_destructor_n<A>
- >::type OldArrayDestructor;
- //This is the anti-exception array destructor
- //to destroy objects created with copy construction
- typedef typename container_detail::if_c
- <nothrow_copy
- ,container_detail::null_scoped_destructor_n<A>
- ,container_detail::scoped_destructor_n<A>
+ <base_t::trivial_dctr
+ ,container_detail::null_scoped_destructor_n<Allocator>
+ ,container_detail::scoped_destructor_n<Allocator>
>::type ArrayDestructor;
//This is the anti-exception array deallocator
- typedef typename container_detail::if_c
- <nothrow_copy
- ,container_detail::null_scoped_array_deallocator<A>
- ,container_detail::scoped_array_deallocator<A>
- >::type ArrayDeallocator;
+ typedef container_detail::scoped_array_deallocator<Allocator> ArrayDeallocator;
};
//!This struct deallocates and allocated memory
-template <class A>
+template < class Allocator
+ , class AllocatorVersion = typename container_detail::version<Allocator>::type
+ >
struct vector_alloc_holder
+ : public Allocator
{
- typedef boost::container::allocator_traits<A> allocator_traits_type;
+ 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 vector_value_traits<value_type, A> value_traits;
//Constructor, does not throw
vector_alloc_holder()
- BOOST_CONTAINER_NOEXCEPT_IF(::boost::has_nothrow_default_constructor<A>::value)
- : members_()
+ BOOST_CONTAINER_NOEXCEPT_IF(::boost::has_nothrow_default_constructor<Allocator>::value)
+ : Allocator(), m_start(), m_size(), m_capacity()
{}
//Constructor, does not throw
template<class AllocConvertible>
explicit vector_alloc_holder(BOOST_FWD_REF(AllocConvertible) a) BOOST_CONTAINER_NOEXCEPT
- : members_(boost::forward<AllocConvertible>(a))
+ : Allocator(boost::forward<AllocConvertible>(a)), m_start(), m_size(), m_capacity()
{}
- //Destructor
- ~vector_alloc_holder()
+ //Constructor, does not throw
+ template<class AllocConvertible>
+ vector_alloc_holder(uninitialized_size_t, BOOST_FWD_REF(AllocConvertible) a, size_type initial_size)
+ : Allocator(boost::forward<AllocConvertible>(a))
+ , m_start()
+ , m_size(initial_size) //Size is initialized here so vector should only call uninitialized_xxx after this
+ , m_capacity()
{
- this->prot_destroy_all();
- this->prot_deallocate();
+ if(initial_size){
+ m_start = this->allocation_command(allocate_new, initial_size, initial_size, m_capacity, m_start).first;
+ }
}
- typedef container_detail::integral_constant<unsigned, 1> allocator_v1;
- typedef container_detail::integral_constant<unsigned, 2> allocator_v2;
- typedef container_detail::integral_constant<unsigned,
- boost::container::container_detail::version<A>::value> alloc_version;
- std::pair<pointer, bool>
- allocation_command(allocation_type command,
- size_type limit_size,
- size_type preferred_size,
- size_type &received_size, const pointer &reuse = 0)
+ //Constructor, does not throw
+ vector_alloc_holder(uninitialized_size_t, size_type initial_size)
+ : Allocator()
+ , m_start()
+ , m_size(initial_size) //Size is initialized here so vector should only call uninitialized_xxx after this
+ , m_capacity()
{
- return allocation_command(command, limit_size, preferred_size,
- received_size, reuse, alloc_version());
+ if(initial_size){
+ m_start = this->allocation_command
+ (allocate_new, initial_size, initial_size, m_capacity, m_start).first;
+ }
}
- std::pair<pointer, bool>
- allocation_command(allocation_type command,
- size_type limit_size,
- size_type preferred_size,
- size_type &received_size,
- const pointer &reuse,
- allocator_v1)
+ vector_alloc_holder(BOOST_RV_REF(vector_alloc_holder) holder) BOOST_CONTAINER_NOEXCEPT
+ : Allocator(boost::move(static_cast<Allocator&>(holder)))
+ , m_start(holder.m_start)
+ , m_size(holder.m_size)
+ , m_capacity(holder.m_capacity)
{
- (void)limit_size;
- (void)reuse;
- if(!(command & allocate_new))
- return std::pair<pointer, bool>(pointer(0), false);
- received_size = preferred_size;
- return std::make_pair(this->alloc().allocate(received_size), false);
+ holder.m_start = pointer();
+ holder.m_size = holder.m_capacity = 0;
+ }
+
+ void first_allocation(size_type cap)
+ {
+ if(cap){
+ m_start = this->allocation_command
+ (allocate_new, cap, cap, m_capacity, m_start).first;
+ #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
+ ++this->num_alloc;
+ #endif
+ }
+ }
+
+ void first_allocation_same_allocator_type(size_type cap)
+ { this->first_allocation(cap); }
+
+ ~vector_alloc_holder() BOOST_CONTAINER_NOEXCEPT
+ {
+ if(this->m_capacity){
+ this->alloc().deallocate(this->m_start, this->m_capacity);
+ }
}
std::pair<pointer, bool>
- allocation_command(allocation_type command,
+ allocation_command(boost::container::allocation_type command,
size_type limit_size,
size_type preferred_size,
- size_type &received_size,
- const pointer &reuse,
- allocator_v2)
+ size_type &received_size, const pointer &reuse = pointer())
{
- return this->alloc().allocation_command
- (command, limit_size, preferred_size, received_size, reuse);
+ return allocator_version_traits<Allocator>::allocation_command
+ (this->alloc(), command, limit_size, preferred_size, received_size, reuse);
}
size_type next_capacity(size_type additional_objects) const
{
- return get_next_capacity( allocator_traits_type::max_size(this->alloc())
- , this->members_.m_capacity, additional_objects);
+ return next_capacity_calculator
+ <size_type, NextCapacityDouble //NextCapacity60Percent
+ >::get( allocator_traits_type::max_size(this->alloc())
+ , this->m_capacity, additional_objects );
+ }
+
+ pointer m_start;
+ size_type m_size;
+ size_type m_capacity;
+
+ void swap(vector_alloc_holder &x) BOOST_CONTAINER_NOEXCEPT
+ {
+ boost::container::swap_dispatch(this->m_start, x.m_start);
+ boost::container::swap_dispatch(this->m_size, x.m_size);
+ boost::container::swap_dispatch(this->m_capacity, x.m_capacity);
}
- struct members_holder
- : public A
+ void move_from_empty(vector_alloc_holder &x) BOOST_CONTAINER_NOEXCEPT
{
- private:
- members_holder(const members_holder&);
+ //this->m_size was previously initialized
+ this->m_start = x.m_start;
+ this->m_capacity = x.m_capacity;
+ x.m_start = pointer();
+ x.m_size = x.m_capacity = 0;
+ }
+
+ Allocator &alloc() BOOST_CONTAINER_NOEXCEPT
+ { return *this; }
+
+ const Allocator &alloc() const BOOST_CONTAINER_NOEXCEPT
+ { return *this; }
+
+ const pointer &start() const BOOST_CONTAINER_NOEXCEPT { return m_start; }
+ const size_type &capacity() const BOOST_CONTAINER_NOEXCEPT { return m_capacity; }
+ void start(const pointer &p) BOOST_CONTAINER_NOEXCEPT { m_start = p; }
+ void capacity(const size_type &c) BOOST_CONTAINER_NOEXCEPT { m_capacity = c; }
+};
+
+//!This struct deallocates and allocated memory
+template <class Allocator>
+struct vector_alloc_holder<Allocator, container_detail::integral_constant<unsigned, 0> >
+ : public Allocator
+{
+ private:
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(vector_alloc_holder)
- public:
- template<class Alloc>
- explicit members_holder(BOOST_FWD_REF(Alloc) alloc)
- : A(boost::forward<Alloc>(alloc)), m_start(0), m_size(0), m_capacity(0)
- {}
+ 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;
- members_holder()
- : A(), m_start(0), m_size(0), m_capacity(0)
- {}
+ template <class OtherAllocator, class OtherAllocatorVersion>
+ friend struct vector_alloc_holder;
- pointer m_start;
- size_type m_size;
- size_type m_capacity;
- } members_;
+ //Constructor, does not throw
+ vector_alloc_holder()
+ BOOST_CONTAINER_NOEXCEPT_IF(::boost::has_nothrow_default_constructor<Allocator>::value)
+ : Allocator(), m_size()
+ {}
- void swap_members(vector_alloc_holder &x)
+ //Constructor, does not throw
+ template<class AllocConvertible>
+ explicit vector_alloc_holder(BOOST_FWD_REF(AllocConvertible) a) BOOST_CONTAINER_NOEXCEPT
+ : Allocator(boost::forward<AllocConvertible>(a)), m_size()
+ {}
+
+ //Constructor, does not throw
+ template<class AllocConvertible>
+ vector_alloc_holder(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...
{
- container_detail::do_swap(this->members_.m_start, x.members_.m_start);
- container_detail::do_swap(this->members_.m_size, x.members_.m_size);
- container_detail::do_swap(this->members_.m_capacity, x.members_.m_capacity);
+ //... and capacity here, so vector, must call uninitialized_xxx in the derived constructor
+ this->first_allocation(initial_size);
}
- A &alloc()
- { return members_; }
+ //Constructor, does not throw
+ vector_alloc_holder(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->first_allocation(initial_size);
+ }
- const A &alloc() const
- { return members_; }
+ vector_alloc_holder(BOOST_RV_REF(vector_alloc_holder) holder)
+ : Allocator(boost::move(static_cast<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(), container_detail::to_raw_pointer(holder.start()), m_size, container_detail::to_raw_pointer(this->start()));
+ }
+
+ template<class OtherAllocator, class OtherAllocatorVersion>
+ vector_alloc_holder(BOOST_RV_REF_BEG vector_alloc_holder<OtherAllocator, 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->first_allocation(n);
+ ::boost::container::uninitialized_move_alloc_n
+ (this->alloc(), container_detail::to_raw_pointer(holder.start()), n, container_detail::to_raw_pointer(this->start()));
+ }
- protected:
- void prot_deallocate()
+ void first_allocation(size_type cap)
{
- if(!this->members_.m_capacity) return;
- this->alloc().deallocate(this->members_.m_start, this->members_.m_capacity);
- this->members_.m_start = 0;
- this->members_.m_size = 0;
- this->members_.m_capacity = 0;
+ if(cap > Allocator::internal_capacity){
+ throw_bad_alloc();
+ }
}
- void destroy(value_type* p)
+ void first_allocation_same_allocator_type(size_type) BOOST_CONTAINER_NOEXCEPT
+ {}
+
+ //Destructor
+ ~vector_alloc_holder() BOOST_CONTAINER_NOEXCEPT
+ {}
+
+ void swap(vector_alloc_holder &x)
{
- if(!value_traits::trivial_dctr)
- allocator_traits_type::destroy(this->alloc(), p);
+ this->priv_swap_members_impl(x);
}
- void destroy_n(value_type* p, size_type n)
+ template<class OtherAllocator, class OtherAllocatorVersion>
+ void swap(vector_alloc_holder<OtherAllocator, OtherAllocatorVersion> &x)
{
- if(!value_traits::trivial_dctr){
- for(; n--; ++p){
- allocator_traits_type::destroy(this->alloc(), p);
- }
+ if(this->m_size > OtherAllocator::internal_capacity || x.m_size > Allocator::internal_capacity){
+ throw_bad_alloc();
}
+ this->priv_swap_members_impl(x);
+ }
+
+ void move_from_empty(vector_alloc_holder &)
+ { //Containers with version 0 allocators can't be moved without move elements one by one
+ throw_bad_alloc();
}
- void prot_destroy_all()
+ Allocator &alloc() BOOST_CONTAINER_NOEXCEPT
+ { return *this; }
+
+ const Allocator &alloc() const BOOST_CONTAINER_NOEXCEPT
+ { return *this; }
+
+ pointer start() const BOOST_CONTAINER_NOEXCEPT { return Allocator::internal_storage(); }
+ size_type capacity() const BOOST_CONTAINER_NOEXCEPT { return Allocator::internal_capacity; }
+ size_type m_size;
+
+ private:
+
+ template<class OtherAllocator, class OtherAllocatorVersion>
+ void priv_swap_members_impl(vector_alloc_holder<OtherAllocator, OtherAllocatorVersion> &x)
{
- this->destroy_n(container_detail::to_raw_pointer(this->members_.m_start), this->members_.m_size);
- this->members_.m_size = 0;
+ const std::size_t MaxTmpStorage = sizeof(value_type)*Allocator::internal_capacity;
+ value_type *const first_this = container_detail::to_raw_pointer(this->start());
+ value_type *const first_x = container_detail::to_raw_pointer(x.start());
+
+ 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::container::swap_dispatch(this->m_size, x.m_size);
}
};
} //namespace container_detail {
-/// @endcond
-//! \class vector
+#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.
-//! boost::container::vector is similar to std::vector but it's compatible
-//! with shared memory and memory mapped files.
-#ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
-template <class T, class A = std::allocator<T> >
-#else
-template <class T, class A>
-#endif
-class vector : private container_detail::vector_alloc_holder<A>
+//!
+//! \tparam T The type of object that is stored in the vector
+//! \tparam Allocator The allocator used for all internal memory management
+template <class T, class Allocator BOOST_CONTAINER_DOCONLY(= std::allocator<T>) >
+class vector
{
- /// @cond
- typedef vector<T, A> self_t;
- typedef container_detail::vector_alloc_holder<A> base_t;
- typedef allocator_traits<A> allocator_traits_type;
- /// @endcond
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ typedef typename container_detail::version<Allocator>::type alloc_version;
+ boost::container::container_detail::vector_alloc_holder
+ <Allocator, alloc_version> m_holder;
+ typedef allocator_traits<Allocator> allocator_traits_type;
+ template <class U, class UAllocator>
+ friend class vector;
+
+ typedef typename ::boost::container::allocator_traits
+ <Allocator>::pointer pointer_impl;
+ typedef container_detail::vec_iterator<pointer_impl, false> iterator_impl;
+ typedef container_detail::vec_iterator<pointer_impl, true > const_iterator_impl;
+
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public:
- //! The type of object, T, stored in the vector
- typedef T value_type;
- //! Pointer to T
- typedef typename allocator_traits_type::pointer pointer;
- //! Const pointer to T
- typedef typename allocator_traits_type::const_pointer const_pointer;
- //! Reference to T
- typedef typename allocator_traits_type::reference reference;
- //! Const reference to T
- typedef typename allocator_traits_type::const_reference const_reference;
- //! An unsigned integral type
- typedef typename allocator_traits_type::size_type size_type;
- //! A signed integral type
- typedef typename allocator_traits_type::difference_type difference_type;
- //! The allocator type
- typedef A allocator_type;
- //! The random access iterator
- typedef container_detail::vector_iterator<pointer> iterator;
- //! The random access const_iterator
- typedef container_detail::vector_const_iterator<pointer> const_iterator;
-
- //! Iterator used to iterate backwards through a vector.
- typedef std::reverse_iterator<iterator>
- reverse_iterator;
- //! Const iterator used to iterate backwards through a vector.
- typedef std::reverse_iterator<const_iterator>
- const_reverse_iterator;
- //! The stored allocator type
- typedef allocator_type stored_allocator_type;
-
- /// @cond
+ //////////////////////////////////////////////
+ //
+ // 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;
+ #if defined BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER
+ typedef BOOST_CONTAINER_IMPDEF(pointer) iterator;
+ typedef BOOST_CONTAINER_IMPDEF(const_pointer) const_iterator;
+ #else
+ typedef BOOST_CONTAINER_IMPDEF(iterator_impl) iterator;
+ typedef BOOST_CONTAINER_IMPDEF(const_iterator_impl) const_iterator;
+ #endif
+ typedef BOOST_CONTAINER_IMPDEF(container_detail::reverse_iterator<iterator>) reverse_iterator;
+ typedef BOOST_CONTAINER_IMPDEF(container_detail::reverse_iterator<const_iterator>) const_reverse_iterator;
+
+ #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
private:
BOOST_COPYABLE_AND_MOVABLE(vector)
- typedef container_detail::advanced_insert_aux_int<T*> advanced_insert_aux_int_t;
- typedef container_detail::vector_value_traits<value_type, A> value_traits;
+ typedef container_detail::vector_value_traits<Allocator> value_traits;
- typedef typename base_t::allocator_v1 allocator_v1;
- typedef typename base_t::allocator_v2 allocator_v2;
- typedef typename base_t::alloc_version alloc_version;
+ typedef container_detail::integral_constant<unsigned, 0> allocator_v0;
+ typedef container_detail::integral_constant<unsigned, 1> allocator_v1;
+ typedef container_detail::integral_constant<unsigned, 2> allocator_v2;
- typedef constant_iterator<T, difference_type> cvalue_iterator;
- typedef repeat_iterator<T, difference_type> repeat_it;
- typedef boost::move_iterator<repeat_it> repeat_move_it;
- /// @endcond
+ typedef constant_iterator<T, difference_type> cvalue_iterator;
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
public:
+ //////////////////////////////////////////////
+ //
+ // construct/copy/destroy
+ //
+ //////////////////////////////////////////////
//! <b>Effects</b>: Constructs a vector taking the allocator as parameter.
//!
@@ -466,8 +600,8 @@ class vector : private container_detail::vector_alloc_holder<A>
//!
//! <b>Complexity</b>: Constant.
vector()
- BOOST_CONTAINER_NOEXCEPT_IF(::boost::has_nothrow_default_constructor<A>::value)
- : base_t()
+ BOOST_CONTAINER_NOEXCEPT_IF(::boost::has_nothrow_default_constructor<Allocator>::value)
+ : m_holder()
{}
//! <b>Effects</b>: Constructs a vector taking the allocator as parameter.
@@ -475,47 +609,103 @@ class vector : private container_detail::vector_alloc_holder<A>
//! <b>Throws</b>: Nothing
//!
//! <b>Complexity</b>: Constant.
- explicit vector(const A& a) BOOST_CONTAINER_NOEXCEPT
- : base_t(a)
+ explicit vector(const Allocator& a) BOOST_CONTAINER_NOEXCEPT
+ : m_holder(a)
{}
//! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
- //! and inserts n default contructed values.
+ //! and inserts n value initialized values.
//!
//! <b>Throws</b>: If allocator_type's default constructor or allocation
- //! throws or T's default constructor throws.
+ //! throws or T's value initialization throws.
//!
//! <b>Complexity</b>: Linear to n.
explicit vector(size_type n)
- : base_t()
- {
- //Allocate
- size_type real_cap;
- std::pair<pointer, bool> ret =
- this->allocation_command(allocate_new, n, n, real_cap, this->members_.m_start);
- T *new_mem = container_detail::to_raw_pointer(ret.first);
- //Anti-exception rollback
- typename value_traits::ArrayDeallocator scoped_alloc(new_mem, this->alloc(), real_cap);
- //Default constructor
- container_detail::default_construct_aux_proxy<A, T*> proxy(this->alloc(), n);
- proxy.uninitialized_copy_remaining_to(new_mem);
- //All ok, commit
- this->members_.m_start = ret.first;
- this->members_.m_size = n;
- this->members_.m_capacity = real_cap;
- scoped_alloc.release();
+ : m_holder(container_detail::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, container_detail::to_raw_pointer(this->m_holder.start()));
}
//! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
+ //! and inserts n default initialized values.
+ //!
+ //! <b>Throws</b>: If allocator_type's default constructor or 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(container_detail::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, container_detail::to_raw_pointer(this->m_holder.start()));
+ }
+
+ //! <b>Effects</b>: Constructs a vector
//! and inserts n copies of value.
//!
//! <b>Throws</b>: If allocator_type's default constructor or allocation
//! throws or T's copy constructor throws.
//!
//! <b>Complexity</b>: Linear to n.
- vector(size_type n, const T& value, const allocator_type& a = allocator_type())
- : base_t(a)
- { this->insert(this->cend(), n, value); }
+ vector(size_type n, const T& value)
+ : m_holder(container_detail::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, container_detail::to_raw_pointer(this->m_holder.start()));
+ }
+
+ //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
+ //! and inserts n 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(container_detail::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, container_detail::to_raw_pointer(this->m_holder.start()));
+ }
+
+ //! <b>Effects</b>: Constructs a vector
+ //! and inserts a copy of the range [first, last) in the vector.
+ //!
+ //! <b>Throws</b>: If allocator_type's default constructor or allocation
+ //! throws or T's constructor taking a dereferenced InIt throws.
+ //!
+ //! <b>Complexity</b>: Linear to the range [first, last).
+ template <class InIt>
+ vector(InIt first, InIt last)
+ : m_holder()
+ { this->insert(this->cend(), first, last); }
+
+ //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
+ //! and inserts a copy of the range [first, last) in the vector.
+ //!
+ //! <b>Throws</b>: If allocator_type's default constructor or allocation
+ //! throws or T's constructor taking a dereferenced InIt throws.
+ //!
+ //! <b>Complexity</b>: Linear to the range [first, last).
+ template <class InIt>
+ vector(InIt first, InIt last, const allocator_type& a)
+ : m_holder(a)
+ { this->insert(this->cend(), first, last); }
//! <b>Effects</b>: Copy constructs a vector.
//!
@@ -526,20 +716,61 @@ class vector : private container_detail::vector_alloc_holder<A>
//!
//! <b>Complexity</b>: Linear to the elements x contains.
vector(const vector &x)
- : base_t(allocator_traits_type::select_on_container_copy_construction(x.alloc()))
+ : m_holder( container_detail::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(), container_detail::to_raw_pointer(x.m_holder.start())
+ , x.size(), container_detail::to_raw_pointer(this->m_holder.start()));
+ }
+
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
+ //! and inserts a copy of the range [il.begin(), il.last()) in the vector
+ //!
+ //! <b>Throws</b>: If allocator_type's default constructor
+ //! throws or T's constructor taking a dereferenced initializer_list iterator throws.
+ //!
+ //! <b>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( container_detail::to_raw_pointer(x.members_.m_start)
- , container_detail::to_raw_pointer(x.members_.m_start + x.members_.m_size));
+ insert(cend(), il.begin(), il.end());
}
+#endif
+
- //! <b>Effects</b>: Move constructor. Moves mx's resources to *this.
+ //! <b>Effects</b>: Move constructor. Moves x's resources to *this.
//!
//! <b>Throws</b>: Nothing
//!
//! <b>Complexity</b>: Constant.
- vector(BOOST_RV_REF(vector) mx) BOOST_CONTAINER_NOEXCEPT
- : base_t(boost::move(mx.alloc()))
- { this->swap_members(mx); }
+ vector(BOOST_RV_REF(vector) x) BOOST_CONTAINER_NOEXCEPT
+ : m_holder(boost::move(x.m_holder))
+ {}
+
+ #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 container_detail::enable_if_c
+ < container_detail::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.
//!
@@ -550,43 +781,41 @@ class vector : private container_detail::vector_alloc_holder<A>
//!
//! <b>Complexity</b>: Linear to the elements x contains.
vector(const vector &x, const allocator_type &a)
- : base_t(a)
+ : m_holder(container_detail::uninitialized_size, a, x.size())
{
- this->assign( container_detail::to_raw_pointer(x.members_.m_start)
- , container_detail::to_raw_pointer(x.members_.m_start + x.members_.m_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(), container_detail::to_raw_pointer(x.m_holder.start())
+ , x.size(), container_detail::to_raw_pointer(this->m_holder.start()));
}
//! <b>Effects</b>: Move constructor using the specified allocator.
- //! Moves mx's resources to *this if a == allocator_type().
+ //! Moves x's resources to *this if a == allocator_type().
//! Otherwise copies values from x to *this.
//!
//! <b>Throws</b>: If allocation or T's copy constructor throws.
//!
- //! <b>Complexity</b>: Constant if a == mx.get_allocator(), linear otherwise.
- vector(BOOST_RV_REF(vector) mx, const allocator_type &a)
- : base_t(a)
+ //! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise.
+ vector(BOOST_RV_REF(vector) x, const allocator_type &a)
+ : m_holder(container_detail::uninitialized_size, a, x.size())
{
- if(mx.alloc() == a){
- this->swap_members(mx);
+ #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
+ this->num_alloc += x.size() != 0;
+ #endif
+ if(x.m_holder.alloc() == a){
+ this->m_holder.move_from_empty(x.m_holder);
}
else{
- this->assign( container_detail::to_raw_pointer(mx.members_.m_start)
- , container_detail::to_raw_pointer(mx.members_.m_start + mx.members_.m_size));
+ const size_type n = x.size();
+ this->m_holder.first_allocation_same_allocator_type(n);
+ ::boost::container::uninitialized_move_alloc_n_source
+ ( this->m_holder.alloc(), container_detail::to_raw_pointer(x.m_holder.start())
+ , n, container_detail::to_raw_pointer(this->m_holder.start()));
}
}
- //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
- //! and inserts a copy of the range [first, last) in the vector.
- //!
- //! <b>Throws</b>: If allocator_type's default constructor or allocation
- //! throws or T's constructor taking an dereferenced InIt throws.
- //!
- //! <b>Complexity</b>: Linear to the range [first, last).
- template <class InIt>
- vector(InIt first, InIt last, const allocator_type& a = allocator_type())
- : base_t(a)
- { this->assign(first, last); }
-
//! <b>Effects</b>: Destroys the vector. All stored values are destroyed
//! and used memory is deallocated.
//!
@@ -594,7 +823,253 @@ class vector : private container_detail::vector_alloc_holder<A>
//!
//! <b>Complexity</b>: Linear to the number of elements.
~vector() BOOST_CONTAINER_NOEXCEPT
- {} //vector_alloc_holder clears the data
+ {
+ boost::container::destroy_alloc_n
+ (this->get_stored_allocator(), container_detail::to_raw_pointer(this->m_holder.start()), 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.
+ 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()).
+ vector& operator=(std::initializer_list<value_type> il)
+ {
+ 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.
+ vector& operator=(BOOST_RV_REF(vector) x)
+ BOOST_CONTAINER_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value)
+ {
+ 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>
+ typename container_detail::enable_if_c
+ < container_detail::is_version<OtherAllocator, 0>::value &&
+ !container_detail::is_same<OtherAllocator, allocator_type>::value
+ , vector& >::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>
+ typename container_detail::enable_if_c
+ < container_detail::is_version<OtherAllocator, 0>::value &&
+ !container_detail::is_same<OtherAllocator, allocator_type>::value
+ , vector& >::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
+ BOOST_CONTAINER_DOCIGN(BOOST_CONTAINER_I typename container_detail::enable_if_c
+ < !container_detail::is_convertible<InIt BOOST_CONTAINER_I size_type>::value &&
+ ( container_detail::is_input_iterator<InIt>::value ||
+ container_detail::is_same<alloc_version BOOST_CONTAINER_I allocator_v0>::value )
+ >::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 = container_detail::to_raw_pointer(this->m_holder.start()) + this->m_holder.m_size;
+ const size_type n = static_cast<size_type>(end_pos - container_detail::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.
+ //!
+ void assign(std::initializer_list<T> il)
+ {
+ 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
+ BOOST_CONTAINER_DOCIGN(BOOST_CONTAINER_I typename container_detail::enable_if_c
+ < !container_detail::is_convertible<FwdIt BOOST_CONTAINER_I size_type>::value &&
+ ( !container_detail::is_input_iterator<FwdIt>::value &&
+ !container_detail::is_same<alloc_version BOOST_CONTAINER_I allocator_v0>::value )
+ >::type * = 0)
+ )
+ {
+ //For Fwd iterators the standard only requires EmplaceConstructible and assignable from *first
+ //so we can't do any backwards allocation
+ const size_type input_sz = static_cast<size_type>(std::distance(first, last));
+ const size_type old_capacity = this->capacity();
+ if(input_sz > old_capacity){ //If input range is too big, we need to reallocate
+ size_type real_cap = 0;
+ std::pair<pointer, bool> ret =
+ this->m_holder.allocation_command(allocate_new|expand_fwd, input_sz, input_sz, real_cap, this->m_holder.start());
+ if(!ret.second){ //New allocation, just emplace new values
+ #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.alloc().deallocate(old_p, old_capacity);
+ }
+ this->m_holder.start(ret.first);
+ 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
+ }
+ }
+ //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
+ this->priv_destroy_last_n(this->size() - input_sz);
+ }
+ else{
+ //Uninitialized construct at end the remaining range
+ this->priv_uninitialized_construct_at_end(first, last);
+ }
+ }
+
+ //! <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.
+ 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_CONTAINER_NOEXCEPT
+ { 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.
+ stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT
+ { 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.
+ const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT
+ { return this->m_holder.alloc(); }
+
+ //////////////////////////////////////////////
+ //
+ // iterators
+ //
+ //////////////////////////////////////////////
//! <b>Effects</b>: Returns an iterator to the first element contained in the vector.
//!
@@ -602,7 +1077,7 @@ class vector : private container_detail::vector_alloc_holder<A>
//!
//! <b>Complexity</b>: Constant.
iterator begin() BOOST_CONTAINER_NOEXCEPT
- { return iterator(this->members_.m_start); }
+ { return iterator(this->m_holder.start()); }
//! <b>Effects</b>: Returns a const_iterator to the first element contained in the vector.
//!
@@ -610,7 +1085,7 @@ class vector : private container_detail::vector_alloc_holder<A>
//!
//! <b>Complexity</b>: Constant.
const_iterator begin() const BOOST_CONTAINER_NOEXCEPT
- { return const_iterator(this->members_.m_start); }
+ { return const_iterator(this->m_holder.start()); }
//! <b>Effects</b>: Returns an iterator to the end of the vector.
//!
@@ -618,7 +1093,7 @@ class vector : private container_detail::vector_alloc_holder<A>
//!
//! <b>Complexity</b>: Constant.
iterator end() BOOST_CONTAINER_NOEXCEPT
- { return iterator(this->members_.m_start + this->members_.m_size); }
+ { return iterator(this->m_holder.start() + this->m_holder.m_size); }
//! <b>Effects</b>: Returns a const_iterator to the end of the vector.
//!
@@ -670,7 +1145,7 @@ class vector : private container_detail::vector_alloc_holder<A>
//!
//! <b>Complexity</b>: Constant.
const_iterator cbegin() const BOOST_CONTAINER_NOEXCEPT
- { return const_iterator(this->members_.m_start); }
+ { return const_iterator(this->m_holder.start()); }
//! <b>Effects</b>: Returns a const_iterator to the end of the vector.
//!
@@ -678,7 +1153,7 @@ class vector : private container_detail::vector_alloc_holder<A>
//!
//! <b>Complexity</b>: Constant.
const_iterator cend() const BOOST_CONTAINER_NOEXCEPT
- { return const_iterator(this->members_.m_start + this->members_.m_size); }
+ { 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.
@@ -698,100 +1173,145 @@ class vector : private container_detail::vector_alloc_holder<A>
const_reverse_iterator crend() const BOOST_CONTAINER_NOEXCEPT
{ return const_reverse_iterator(this->begin()); }
- //! <b>Requires</b>: !empty()
- //!
- //! <b>Effects</b>: Returns a reference to the first
- //! element of the container.
+ //////////////////////////////////////////////
+ //
+ // capacity
+ //
+ //////////////////////////////////////////////
+
+ //! <b>Effects</b>: Returns true if the vector contains no elements.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- reference front() BOOST_CONTAINER_NOEXCEPT
- { return *this->members_.m_start; }
+ bool empty() const BOOST_CONTAINER_NOEXCEPT
+ { return !this->m_holder.m_size; }
- //! <b>Requires</b>: !empty()
- //!
- //! <b>Effects</b>: Returns a const reference to the first
- //! element of the container.
+ //! <b>Effects</b>: Returns the number of the elements contained in the vector.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- const_reference front() const BOOST_CONTAINER_NOEXCEPT
- { return *this->members_.m_start; }
+ size_type size() const BOOST_CONTAINER_NOEXCEPT
+ { return this->m_holder.m_size; }
- //! <b>Requires</b>: !empty()
- //!
- //! <b>Effects</b>: Returns a reference to the last
- //! element of the container.
+ //! <b>Effects</b>: Returns the largest possible size of the vector.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- reference back() BOOST_CONTAINER_NOEXCEPT
- { return this->members_.m_start[this->members_.m_size - 1]; }
+ size_type max_size() const BOOST_CONTAINER_NOEXCEPT
+ { return allocator_traits_type::max_size(this->m_holder.alloc()); }
- //! <b>Requires</b>: !empty()
+ //! <b>Effects</b>: Inserts or erases elements at the end such that
+ //! the size becomes n. New elements are value initialized.
//!
- //! <b>Effects</b>: Returns a const reference to the last
- //! element of the container.
+ //! <b>Throws</b>: If memory allocation throws, or T's copy/move or value initialization throws.
//!
- //! <b>Throws</b>: Nothing.
+ //! <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>Complexity</b>: Constant.
- const_reference back() const BOOST_CONTAINER_NOEXCEPT
- { return this->members_.m_start[this->members_.m_size - 1]; }
+ //! <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>Returns</b>: A pointer such that [data(),data() + size()) is a valid range.
- //! For a non-empty vector, data() == &front().
+ //! <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>: Nothing.
+ //! <b>Throws</b>: If memory allocation throws, or T's copy/move constructor throws.
//!
- //! <b>Complexity</b>: Constant.
- pointer data() BOOST_CONTAINER_NOEXCEPT
- { return this->members_.m_start; }
+ //! <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>Returns</b>: A pointer such that [data(),data() + size()) is a valid range.
- //! For a non-empty vector, data() == &front().
+ //! <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.
- const_pointer data() const BOOST_CONTAINER_NOEXCEPT
- { return this->members_.m_start; }
+ size_type capacity() const BOOST_CONTAINER_NOEXCEPT
+ { return this->m_holder.capacity(); }
- //! <b>Effects</b>: Returns the number of the elements contained in the vector.
+ //! <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.
+ void reserve(size_type new_cap)
+ {
+ if (this->capacity() < new_cap){
+ this->priv_reserve(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().
+ 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.
- size_type size() const BOOST_CONTAINER_NOEXCEPT
- { return this->members_.m_size; }
+ reference front() BOOST_CONTAINER_NOEXCEPT
+ { return *this->m_holder.start(); }
- //! <b>Effects</b>: Returns the largest possible size of the vector.
+ //! <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.
- size_type max_size() const BOOST_CONTAINER_NOEXCEPT
- { return allocator_traits_type::max_size(this->alloc()); }
+ const_reference front() const BOOST_CONTAINER_NOEXCEPT
+ { return *this->m_holder.start(); }
- //! <b>Effects</b>: Number of elements for which memory has been allocated.
- //! capacity() is always greater than or equal to size().
+ //! <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.
- size_type capacity() const BOOST_CONTAINER_NOEXCEPT
- { return this->members_.m_capacity; }
+ reference back() BOOST_CONTAINER_NOEXCEPT
+ { return this->m_holder.start()[this->m_holder.m_size - 1]; }
- //! <b>Effects</b>: Returns true if the vector contains no elements.
+ //! <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.
- bool empty() const BOOST_CONTAINER_NOEXCEPT
- { return !this->members_.m_size; }
+ const_reference back() const BOOST_CONTAINER_NOEXCEPT
+ { return this->m_holder.start()[this->m_holder.m_size - 1]; }
//! <b>Requires</b>: size() > n.
//!
@@ -801,8 +1321,8 @@ class vector : private container_detail::vector_alloc_holder<A>
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- reference operator[](size_type n)
- { return this->members_.m_start[n]; }
+ reference operator[](size_type n) BOOST_CONTAINER_NOEXCEPT
+ { return this->m_holder.start()[n]; }
//! <b>Requires</b>: size() > n.
//!
@@ -813,7 +1333,7 @@ class vector : private container_detail::vector_alloc_holder<A>
//!
//! <b>Complexity</b>: Constant.
const_reference operator[](size_type n) const BOOST_CONTAINER_NOEXCEPT
- { return this->members_.m_start[n]; }
+ { return this->m_holder.start()[n]; }
//! <b>Requires</b>: size() > n.
//!
@@ -824,7 +1344,7 @@ class vector : private container_detail::vector_alloc_holder<A>
//!
//! <b>Complexity</b>: Constant.
reference at(size_type n)
- { this->priv_check_range(n); return this->members_.m_start[n]; }
+ { this->priv_check_range(n); return this->m_holder.start()[n]; }
//! <b>Requires</b>: size() > n.
//!
@@ -835,223 +1355,59 @@ class vector : private container_detail::vector_alloc_holder<A>
//!
//! <b>Complexity</b>: Constant.
const_reference at(size_type n) const
- { this->priv_check_range(n); return this->members_.m_start[n]; }
+ { this->priv_check_range(n); return this->m_holder.start()[n]; }
- //! <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_CONTAINER_NOEXCEPT
- { return this->alloc(); }
+ //////////////////////////////////////////////
+ //
+ // data access
+ //
+ //////////////////////////////////////////////
- //! <b>Effects</b>: Returns a reference to the internal allocator.
+ //! <b>Returns</b>: Allocator pointer such that [data(),data() + size()) is a valid range.
+ //! For a non-empty vector, data() == &front().
//!
- //! <b>Throws</b>: Nothing
+ //! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- //!
- //! <b>Note</b>: Non-standard extension.
- const stored_allocator_type &get_stored_allocator() const BOOST_CONTAINER_NOEXCEPT
- { return this->alloc(); }
+ T* data() BOOST_CONTAINER_NOEXCEPT
+ { return container_detail::to_raw_pointer(this->m_holder.start()); }
- //! <b>Effects</b>: Returns a reference to the internal allocator.
+ //! <b>Returns</b>: Allocator pointer such that [data(),data() + size()) is a valid range.
+ //! For a non-empty vector, data() == &front().
//!
- //! <b>Throws</b>: Nothing
+ //! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant.
- //!
- //! <b>Note</b>: Non-standard extension.
- stored_allocator_type &get_stored_allocator() BOOST_CONTAINER_NOEXCEPT
- { return this->alloc(); }
-
- //! <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.
- void reserve(size_type new_cap)
- {
- if (this->capacity() < new_cap){
- //There is not enough memory, allocate a new
- //buffer or expand the old one.
- bool same_buffer_start;
- size_type real_cap = 0;
- std::pair<pointer, bool> ret =
- this->allocation_command
- (allocate_new | expand_fwd | expand_bwd,
- new_cap, new_cap, real_cap, this->members_.m_start);
+ const T * data() const BOOST_CONTAINER_NOEXCEPT
+ { return container_detail::to_raw_pointer(this->m_holder.start()); }
- //Check for forward expansion
- same_buffer_start = ret.second && this->members_.m_start == ret.first;
- if(same_buffer_start){
- #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
- ++this->num_expand_fwd;
- #endif
- this->members_.m_capacity = real_cap;
- }
-
- //If there is no forward expansion, move objects
- else{
- //We will reuse insert code, so create a dummy input iterator
- T *dummy_it(container_detail::to_raw_pointer(this->members_.m_start));
- container_detail::advanced_insert_aux_proxy<A, boost::move_iterator<T*>, T*>
- proxy(this->alloc(), ::boost::make_move_iterator(dummy_it), ::boost::make_move_iterator(dummy_it));
- //Backwards (and possibly forward) expansion
- if(ret.second){
- #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
- ++this->num_expand_bwd;
- #endif
- this->priv_range_insert_expand_backwards
- ( container_detail::to_raw_pointer(ret.first)
- , real_cap
- , container_detail::to_raw_pointer(this->members_.m_start)
- , 0
- , proxy);
- }
- //New buffer
- else{
- #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
- ++this->num_alloc;
- #endif
- this->priv_range_insert_new_allocation
- ( container_detail::to_raw_pointer(ret.first)
- , real_cap
- , container_detail::to_raw_pointer(this->members_.m_start)
- , 0
- , proxy);
- }
- }
- }
- }
-
- //! <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.
- vector& operator=(BOOST_COPY_ASSIGN_REF(vector) x)
- {
- if (&x != this){
- allocator_type &this_alloc = this->alloc();
- const allocator_type &x_alloc = x.alloc();
- container_detail::bool_<allocator_traits_type::
- propagate_on_container_copy_assignment::value> flag;
- if(flag && this_alloc != x_alloc){
- this->clear();
- this->shrink_to_fit();
- }
- container_detail::assign_alloc(this_alloc, x_alloc, flag);
- this->assign( container_detail::to_raw_pointer(x.members_.m_start)
- , container_detail::to_raw_pointer(x.members_.m_start + x.members_.m_size));
- }
- return *this;
- }
-
- //! <b>Effects</b>: Move assignment. All mx's values are transferred to *this.
- //!
- //! <b>Postcondition</b>: x.empty(). *this contains a the elements x had
- //! before the function.
- //!
- //! <b>Throws</b>: Nothing
- //!
- //! <b>Complexity</b>: Linear.
- vector& operator=(BOOST_RV_REF(vector) x)
- //iG BOOST_CONTAINER_NOEXCEPT_IF(!allocator_type::propagate_on_container_move_assignment::value || is_nothrow_move_assignable<allocator_type>::value);)
- BOOST_CONTAINER_NOEXCEPT
- {
- if (&x != this){
- allocator_type &this_alloc = this->alloc();
- allocator_type &x_alloc = x.alloc();
- //If allocators are equal we can just swap pointers
- if(this_alloc == x_alloc){
- //Destroy objects but retain memory in case x reuses it in the future
- this->clear();
- this->swap_members(x);
- //Move allocator if needed
- container_detail::bool_<allocator_traits_type::
- propagate_on_container_move_assignment::value> flag;
- container_detail::move_alloc(this_alloc, x_alloc, flag);
- }
- //If unequal allocators, then do a one by one move
- else{
- this->assign( boost::make_move_iterator(container_detail::to_raw_pointer(x.members_.m_start))
- , boost::make_move_iterator(container_detail::to_raw_pointer(x.members_.m_start + x.members_.m_size)));
- }
- }
- return *this;
- }
-
- //! <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.
- void assign(size_type n, const value_type& val)
- { this->assign(cvalue_iterator(val, n), cvalue_iterator()); }
-
- //! <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)
- {
- //Dispatch depending on integer/iterator
- const bool aux_boolean = container_detail::is_convertible<InIt, size_type>::value;
- typedef container_detail::bool_<aux_boolean> Result;
- this->priv_assign_dispatch(first, last, Result());
- }
-
- #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 mx to this new element.
- //!
- //! <b>Throws</b>: If memory allocation throws or
- //! T's 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
+ //////////////////////////////////////////////
+ //
+ // modifiers
+ //
+ //////////////////////////////////////////////
#if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! <b>Effects</b>: Inserts an object of type T constructed with
//! std::forward<Args>(args)... in the end of the vector.
//!
//! <b>Throws</b>: If memory allocation throws or the in-place constructor throws or
- //! T's move constructor throws.
+ //! T's copy/move constructor throws.
//!
//! <b>Complexity</b>: Amortized constant time.
template<class ...Args>
void emplace_back(Args &&...args)
{
- T* back_pos = container_detail::to_raw_pointer(this->members_.m_start) + this->members_.m_size;
- if (this->members_.m_size < this->members_.m_capacity){
+ if (BOOST_LIKELY(this->m_holder.m_size < this->m_holder.capacity())){
+ T* const back_pos = container_detail::to_raw_pointer(this->m_holder.start()) + this->m_holder.m_size;
//There is more memory, just construct a new object at the end
- allocator_traits_type::construct(this->alloc(), back_pos, ::boost::forward<Args>(args)...);
- ++this->members_.m_size;
+ allocator_traits_type::construct(this->m_holder.alloc(), back_pos, ::boost::forward<Args>(args)...);
+ ++this->m_holder.m_size;
}
else{
- typedef container_detail::advanced_insert_aux_emplace<A, T*, Args...> type;
- type &&proxy = type(this->alloc(), ::boost::forward<Args>(args)...);
- priv_range_insert(back_pos, 1, proxy);
+ typedef container_detail::insert_emplace_proxy<Allocator, T*, Args...> type;
+ this->priv_forward_range_insert_no_capacity
+ (vector_iterator_get_ptr(this->cend()), 1, type(::boost::forward<Args>(args)...), alloc_version());
}
}
@@ -1061,7 +1417,7 @@ class vector : private container_detail::vector_alloc_holder<A>
//! std::forward<Args>(args)... before position
//!
//! <b>Throws</b>: If memory allocation throws or the in-place constructor throws or
- //! T's move constructor/assignment throws.
+ //! T's copy/move constructor/assignment throws.
//!
//! <b>Complexity</b>: If position is end(), amortized constant time
//! Linear time otherwise.
@@ -1069,64 +1425,69 @@ class vector : private container_detail::vector_alloc_holder<A>
iterator emplace(const_iterator position, Args && ...args)
{
//Just call more general insert(pos, size, value) and return iterator
- size_type pos_n = position - cbegin();
- typedef container_detail::advanced_insert_aux_emplace<A, T*, Args...> type;
- type &&proxy = type(this->alloc(), ::boost::forward<Args>(args)...);
- priv_range_insert(position.get_ptr(), 1, proxy);
- return iterator(this->members_.m_start + pos_n);
+ typedef container_detail::insert_emplace_proxy<Allocator, T*, Args...> type;
+ return this->priv_forward_range_insert( vector_iterator_get_ptr(position), 1
+ , type(::boost::forward<Args>(args)...), alloc_version());
}
#else
- #define BOOST_PP_LOCAL_MACRO(n) \
- BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
- void emplace_back(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
- { \
- T* back_pos = container_detail::to_raw_pointer \
- (this->members_.m_start) + this->members_.m_size; \
- if (this->members_.m_size < this->members_.m_capacity){ \
- allocator_traits_type::construct (this->alloc() \
- , back_pos BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \
- ++this->members_.m_size; \
- } \
- else{ \
- container_detail::BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \
- <A, T* BOOST_PP_ENUM_TRAILING_PARAMS(n, P)> proxy \
- (this->alloc() BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
- priv_range_insert(back_pos, 1, proxy); \
- } \
- } \
- \
- BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
- iterator emplace(const_iterator pos \
- BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
- { \
- size_type pos_n = pos - cbegin(); \
- container_detail::BOOST_PP_CAT(BOOST_PP_CAT(advanced_insert_aux_emplace, n), arg) \
- <A, T* BOOST_PP_ENUM_TRAILING_PARAMS(n, P)> proxy \
- (this->alloc() BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
- priv_range_insert(container_detail::to_raw_pointer(pos.get_ptr()), 1, proxy); \
- return iterator(this->members_.m_start + pos_n); \
- } \
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
+ void emplace_back(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
+ { \
+ T* const back_pos = container_detail::to_raw_pointer \
+ (this->m_holder.start()) + this->m_holder.m_size; \
+ if (BOOST_LIKELY(this->m_holder.m_size < this->m_holder.capacity())){ \
+ allocator_traits_type::construct (this->m_holder.alloc() \
+ , back_pos BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \
+ ++this->m_holder.m_size; \
+ } \
+ else{ \
+ typedef container_detail::BOOST_PP_CAT(insert_emplace_proxy_arg, n) \
+ <Allocator, T* BOOST_PP_ENUM_TRAILING_PARAMS(n, P)> type; \
+ this->priv_forward_range_insert_no_capacity \
+ ( vector_iterator_get_ptr(this->cend()), 1 \
+ , type(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)), alloc_version()); \
+ } \
+ } \
+ \
+ BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
+ iterator emplace(const_iterator pos \
+ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
+ { \
+ typedef container_detail::BOOST_PP_CAT(insert_emplace_proxy_arg, n) \
+ <Allocator, T* BOOST_PP_ENUM_TRAILING_PARAMS(n, P)> type; \
+ return this->priv_forward_range_insert \
+ ( container_detail::to_raw_pointer(vector_iterator_get_ptr(pos)), 1 \
+ , type(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)), alloc_version()); \
+ } \
//!
#define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
#include BOOST_PP_LOCAL_ITERATE()
#endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
-
- //! <b>Effects</b>: Swaps the contents of *this and x.
+
+ #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ //! <b>Effects</b>: Inserts a copy of x at the end of the vector.
//!
- //! <b>Throws</b>: Nothing.
+ //! <b>Throws</b>: If memory allocation throws or
+ //! T's copy/move constructor throws.
//!
- //! <b>Complexity</b>: Constant.
- void swap(vector& x)
- {
- //Just swap internals
- this->swap_members(x);
- //And now the allocator
- container_detail::bool_<allocator_traits_type::propagate_on_container_swap::value> flag;
- container_detail::swap_alloc(this->alloc(), x.alloc(), flag);
- }
+ //! <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.
@@ -1141,7 +1502,7 @@ class vector : private container_detail::vector_alloc_holder<A>
//! <b>Requires</b>: position must be a valid iterator of *this.
//!
- //! <b>Effects</b>: Insert a new element before position with mx's resources.
+ //! <b>Effects</b>: Insert a new element before position with x's resources.
//!
//! <b>Throws</b>: If memory allocation throws.
//!
@@ -1149,46 +1510,115 @@ class vector : private container_detail::vector_alloc_holder<A>
//! Linear time otherwise.
iterator insert(const_iterator position, T &&x);
#else
- BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator)
+ 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)
+ {
+ container_detail::insert_n_copies_proxy<Allocator, T*> proxy(x);
+ return this->priv_forward_range_insert(vector_iterator_get_ptr(p), n, proxy, alloc_version());
+ }
+
+ //! <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 std::distance [first, last).
+ template <class InIt>
+ iterator insert(const_iterator pos, InIt first, InIt last
+ BOOST_CONTAINER_DOCIGN(BOOST_CONTAINER_I typename container_detail::enable_if_c
+ < !container_detail::is_convertible<InIt BOOST_CONTAINER_I size_type>::value
+ && container_detail::is_input_iterator<InIt>::value
+ >::type * = 0)
+ )
+ {
+ 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 container_detail::enable_if_c
+ < !container_detail::is_convertible<FwdIt, size_type>::value
+ && !container_detail::is_input_iterator<FwdIt>::value
+ >::type * = 0
+ )
+ {
+ container_detail::insert_range_proxy<Allocator, FwdIt, T*> proxy(first);
+ return this->priv_forward_range_insert(vector_iterator_get_ptr(pos), std::distance(first, last), proxy, alloc_version());
+ }
#endif
- //! <b>Requires</b>: pos must be a valid iterator of *this.
+ //! <b>Requires</b>: p must be a valid iterator of *this. num, must
+ //! be equal to std::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 std::distance [first, last).
+ //!
+ //! <b>Note</b>: This function avoids a linear operation to calculate std::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>
- void insert(const_iterator pos, InIt first, InIt last)
+ iterator insert(const_iterator pos, size_type num, InIt first, InIt last)
{
- //Dispatch depending on integer/iterator
- const bool aux_boolean = container_detail::is_convertible<InIt, size_type>::value;
- typedef container_detail::bool_<aux_boolean> Result;
- this->priv_insert_dispatch(pos, first, last, Result());
+ BOOST_ASSERT(container_detail::is_input_iterator<InIt>::value ||
+ num == static_cast<size_type>(std::distance(first, last)));
+ (void)last;
+ container_detail::insert_range_proxy<Allocator, InIt, T*> proxy(first);
+ return this->priv_forward_range_insert(vector_iterator_get_ptr(pos), num, proxy, alloc_version());
}
+ #endif
- //! <b>Requires</b>: pos must be a valid iterator of *this.
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+ //! <b>Requires</b>: position must be a valid iterator of *this.
//!
- //! <b>Effects</b>: Insert n copies of x before pos.
+ //! <b>Effects</b>: Insert a copy of the [il.begin(), il.end()) range before position.
//!
- //! <b>Throws</b>: If memory allocation throws or T's copy constructor throws.
+ //! <b>Returns</b>: an iterator to the first inserted element or position if first == last.
//!
- //! <b>Complexity</b>: Linear to n.
- void insert(const_iterator p, size_type n, const T& x)
- { this->insert(p, cvalue_iterator(x, n), cvalue_iterator()); }
+ //! <b>Complexity</b>: Linear to the range [il.begin(), il.end()).
+ iterator insert(const_iterator position, std::initializer_list<value_type> il)
+ {
+ return insert(position, il.begin(), il.end());
+ }
+#endif
//! <b>Effects</b>: Removes the last element from the vector.
//!
//! <b>Throws</b>: Nothing.
//!
//! <b>Complexity</b>: Constant time.
- void pop_back()
+ void pop_back() BOOST_CONTAINER_NOEXCEPT
{
//Destroy last element
- --this->members_.m_size;
- this->destroy(container_detail::to_raw_pointer(this->members_.m_start) + this->members_.m_size);
+ this->priv_destroy_last();
}
//! <b>Effects</b>: Erases the element at position pos.
@@ -1199,13 +1629,13 @@ class vector : private container_detail::vector_alloc_holder<A>
//! last element. Constant if pos is the last element.
iterator erase(const_iterator position)
{
- T *pos = container_detail::to_raw_pointer(position.get_ptr());
- T *beg = container_detail::to_raw_pointer(this->members_.m_start);
- ::boost::move(pos + 1, beg + this->members_.m_size, pos);
- --this->members_.m_size;
- //Destroy last element
- base_t::destroy(container_detail::to_raw_pointer(this->members_.m_start) + this->members_.m_size);
- return iterator(position.get_ptr());
+ const pointer p = vector_iterator_get_ptr(position);
+ T *const pos_ptr = container_detail::to_raw_pointer(p);
+ T *const beg_ptr = container_detail::to_raw_pointer(this->m_holder.start());
+ T *const new_end_ptr = ::boost::move(pos_ptr + 1, beg_ptr + this->m_holder.m_size, pos_ptr);
+ //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).
@@ -1216,181 +1646,557 @@ class vector : private container_detail::vector_alloc_holder<A>
//! plus linear to the elements between pos and the last element.
iterator erase(const_iterator first, const_iterator last)
{
- if (first != last){ // worth doing, copy down over hole
- T* end_pos = container_detail::to_raw_pointer(this->members_.m_start) + this->members_.m_size;
- T* ptr = container_detail::to_raw_pointer(boost::move
- (container_detail::to_raw_pointer(last.get_ptr())
- ,end_pos
- ,container_detail::to_raw_pointer(first.get_ptr())
- ));
- size_type destroyed = (end_pos - ptr);
- this->destroy_n(ptr, destroyed);
- this->members_.m_size -= destroyed;
+ if (first != last){
+ T* const old_end_ptr = container_detail::to_raw_pointer(this->m_holder.start()) + this->m_holder.m_size;
+ T* const first_ptr = container_detail::to_raw_pointer(vector_iterator_get_ptr(first));
+ T* const last_ptr = container_detail::to_raw_pointer(vector_iterator_get_ptr(last));
+ T* const ptr = container_detail::to_raw_pointer(boost::move(last_ptr, old_end_ptr, first_ptr));
+ this->priv_destroy_last_n(old_end_ptr - ptr, last_ptr == old_end_ptr);
}
- return iterator(first.get_ptr());
+ return iterator(vector_iterator_get_ptr(first));
}
- //! <b>Effects</b>: Inserts or erases elements at the end such that
- //! the size becomes n. New elements are copy constructed from x.
+ //! <b>Effects</b>: Swaps the contents of *this and x.
//!
- //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
+ //! <b>Throws</b>: Nothing.
//!
- //! <b>Complexity</b>: Linear to the difference between size() and new_size.
- void resize(size_type new_size, const T& x)
+ //! <b>Complexity</b>: Constant.
+ void swap(vector& x) BOOST_CONTAINER_NOEXCEPT_IF((!container_detail::is_version<Allocator, 0>::value))
{
- pointer finish = this->members_.m_start + this->members_.m_size;
- if (new_size < size()){
- //Destroy last elements
- this->erase(const_iterator(this->members_.m_start + new_size), this->end());
+ //Just swap internals in case of !allocator_v0. Otherwise, deep swap
+ this->m_holder.swap(x.m_holder);
+ //And now the allocator
+ container_detail::bool_<allocator_traits_type::propagate_on_container_swap::value> flag;
+ container_detail::swap_alloc(this->m_holder.alloc(), x.m_holder.alloc(), flag);
+ }
+
+ #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>
+ void swap(vector<T, OtherAllocator> & x
+ , typename container_detail::enable_if_c
+ < container_detail::is_version<OtherAllocator, 0>::value &&
+ !container_detail::is_same<OtherAllocator, allocator_type>::value >::type * = 0
+ )
+ { this->m_holder.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.
+ void clear() BOOST_CONTAINER_NOEXCEPT
+ { this->priv_destroy_all(); }
+
+ //! <b>Effects</b>: Returns true if x and y are equal
+ //!
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator==(const vector& x, const vector& y)
+ {
+ if(x.size() != y.size()){
+ return false;
}
else{
- //Insert new elements at the end
- this->insert(const_iterator(finish), new_size - this->size(), x);
+ const_iterator first1(x.cbegin()), first2(y.cbegin());
+ const const_iterator last1(x.cend());
+ for (; first1 != last1; ++first1, ++first2) {
+ if (!(*first1 != *first2)) {
+ return false;
+ }
+ }
+ return true;
}
}
- //! <b>Effects</b>: Inserts or erases elements at the end such that
- //! the size becomes n. New elements are default constructed.
+ //! <b>Effects</b>: Returns true if x and y are unequal
//!
- //! <b>Throws</b>: If memory allocation throws, or T's copy constructor throws.
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ 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 difference between size() and new_size.
- void resize(size_type new_size)
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator<(const vector& x, const vector& y)
{
- if (new_size < this->size()){
- //Destroy last elements
- this->erase(const_iterator(this->members_.m_start + new_size), this->end());
- }
- else{
- size_type n = new_size - this->size();
- this->reserve(new_size);
- container_detail::default_construct_aux_proxy<A, T*> proxy(this->alloc(), n);
- priv_range_insert(this->cend().get_ptr(), n, proxy);
+ 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>: Erases all the elements of the vector.
+ //! <b>Effects</b>: Returns true if x is greater than y
//!
- //! <b>Throws</b>: Nothing.
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ 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 vector.
- void clear() BOOST_CONTAINER_NOEXCEPT
- { this->prot_destroy_all(); }
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator<=(const vector& x, const vector& y)
+ { return !(y < x); }
- //! <b>Effects</b>: Tries to deallocate the excess of memory created
- //! with previous allocations. The size of the vector is unchanged
+ //! <b>Effects</b>: Returns true if x is equal or greater than y
//!
- //! <b>Throws</b>: If memory allocation throws, or T's copy/move constructor throws.
+ //! <b>Complexity</b>: Linear to the number of elements in the container.
+ friend bool operator>=(const vector& x, const vector& y)
+ { return !(x < y); }
+
+ //! <b>Effects</b>: x.swap(y)
//!
- //! <b>Complexity</b>: Linear to size().
- void shrink_to_fit()
- { priv_shrink_to_fit(alloc_version()); }
+ //! <b>Complexity</b>: Constant.
+ friend void swap(vector& x, vector& y)
+ { x.swap(y); }
- /// @cond
+ #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 bool room_enough = this->capacity() < new_cap;
+ if(!room_enough && alloc_version::value < 2){
+ return false;
+ }
+ else{
+ //There is not enough memory, try to expand the old one
+ size_type real_cap = 0;
+ std::pair<pointer, bool> ret = this->m_holder.allocation_command
+ (expand_fwd, new_cap, new_cap, real_cap, this->m_holder.start());
+ //Check for forward expansion
+ if(ret.second){
+ #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
+ ++this->num_expand_fwd;
+ #endif
+ this->m_holder.capacity(real_cap);
+ }
+ return ret.second;
+ }
+ }
//Absolutely experimental. This function might change, disappear or simply crash!
template<class BiDirPosConstIt, class BiDirValueIt>
- void insert_ordered_at(size_type element_count, BiDirPosConstIt last_position_it, BiDirValueIt last_value_it)
+ void insert_ordered_at(const size_type element_count, BiDirPosConstIt last_position_it, BiDirValueIt last_value_it)
{
- const size_type *dummy = 0;
- this->priv_insert_ordered_at(element_count, last_position_it, false, &dummy[0], last_value_it);
+ const size_type old_size_pos = this->size();
+ this->reserve(old_size_pos + element_count);
+ T* const begin_ptr = container_detail::to_raw_pointer(this->m_holder.start());
+ size_type insertions_left = element_count;
+ size_type next_pos = old_size_pos;
+ size_type 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){
+ size_type pos = static_cast<size_type>(*(--last_position_it));
+ while(pos == size_type(-1)){
+ --last_value_it;
+ pos = static_cast<size_type>(*(--last_position_it));
+ }
+
+ BOOST_ASSERT(pos != size_type(-1) && pos <= old_size_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 != next_pos)
+ ? priv_insert_ordered_at_shift_range(pos, next_pos, this->size(), insertions_left)
+ : hole_size
+ ;
+ if(new_hole_size > 0){
+ //The hole was reduced by priv_insert_ordered_at_shift_range so expand exception rollback range backwards
+ past_hole_values_destroyer.increment_size_backwards(next_pos - pos);
+ //Insert the new value in the hole
+ allocator_traits_type::construct(this->m_holder.alloc(), begin_ptr + pos + insertions_left - 1, *(--last_value_it));
+ --new_hole_size;
+ if(new_hole_size == 0){
+ //Hole was just filled, disable exception rollback and change vector size
+ past_hole_values_destroyer.release();
+ this->m_holder.m_size += element_count;
+ }
+ else{
+ //The hole was reduced by the new insertion by one
+ past_hole_values_destroyer.increment_size_backwards(size_type(1u));
+ }
+ }
+ else{
+ if(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] = *(--last_value_it);
+ }
+ --insertions_left;
+ hole_size = new_hole_size;
+ next_pos = pos;
+ }
}
- //Absolutely experimental. This function might change, disappear or simply crash!
- template<class BiDirPosConstIt, class BiDirSkipConstIt, class BiDirValueIt>
- void insert_ordered_at(size_type element_count, BiDirPosConstIt last_position_it, BiDirSkipConstIt last_skip_it, BiDirValueIt last_value_it)
+ #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ //! <b>Effects</b>: Inserts an object of type T constructed with
+ //! std::forward<Args>(args)... in the end of the vector.
+ //!
+ //! <b>Throws</b>: If memory allocation throws or the in-place constructor throws or
+ //! T's copy/move constructor throws.
+ //!
+ //! <b>Complexity</b>: Amortized constant time.
+ template<class ...Args>
+ bool stable_emplace_back(Args &&...args)
{
- this->priv_insert_ordered_at(element_count, last_position_it, true, last_skip_it, last_value_it);
+ const bool room_enough = this->m_holder.m_size < this->m_holder.capacity();
+ if (BOOST_LIKELY(room_enough)){
+ T* const back_pos = container_detail::to_raw_pointer(this->m_holder.start()) + this->m_holder.m_size;
+ //There is more memory, just construct a new object at the end
+ allocator_traits_type::construct(this->m_holder.alloc(), back_pos, ::boost::forward<Args>(args)...);
+ ++this->m_holder.m_size;
+ }
+ return room_enough;
}
+ #else
+
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
+ bool stable_emplace_back(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
+ { \
+ const bool room_enough = this->m_holder.m_size < this->m_holder.capacity(); \
+ if (BOOST_LIKELY(room_enough)){ \
+ T* const back_pos = container_detail::to_raw_pointer \
+ (this->m_holder.start()) + this->m_holder.m_size; \
+ allocator_traits_type::construct (this->m_holder.alloc() \
+ , back_pos BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); \
+ ++this->m_holder.m_size; \
+ } \
+ return room_enough; \
+ } \
+ //!
+ #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
+ #include BOOST_PP_LOCAL_ITERATE()
+
+ #endif //#ifdef BOOST_CONTAINER_PERFECT_FORWARDING
+
private:
- iterator priv_insert(const_iterator position, const T &x)
+
+ template<class OtherAllocator>
+ void priv_move_assign(BOOST_RV_REF_BEG vector<T, OtherAllocator> BOOST_RV_REF_END x
+ , typename container_detail::enable_if_c
+ < container_detail::is_version<OtherAllocator, 0>::value >::type * = 0)
{
- //Just call more general insert(pos, size, value) and return iterator
- size_type pos_n = position - cbegin();
- this->insert(position, (size_type)1, x);
- return iterator(this->members_.m_start + pos_n);
+ if(!container_detail::is_same<OtherAllocator, allocator_type>::value &&
+ this->capacity() < x.size()){
+ throw_bad_alloc();
+ }
+ T* const this_start = container_detail::to_raw_pointer(m_holder.start());
+ T* const other_start = container_detail::to_raw_pointer(x.m_holder.start());
+ 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;
}
- iterator priv_insert(const_iterator position, BOOST_RV_REF(T) x)
+ template<class OtherAllocator>
+ void priv_move_assign(BOOST_RV_REF_BEG vector<T, OtherAllocator> BOOST_RV_REF_END x
+ , typename container_detail::enable_if_c
+ < !container_detail::is_version<OtherAllocator, 0>::value &&
+ container_detail::is_same<OtherAllocator, allocator_type>::value>::type * = 0)
{
- //Just call more general insert(pos, size, value) and return iterator
- size_type pos_n = position - cbegin();
- this->insert(position
- ,repeat_move_it(repeat_it(x, 1))
- ,repeat_move_it(repeat_it()));
- return iterator(this->members_.m_start + pos_n);
+ //for move constructor, 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;
+ container_detail::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
+ container_detail::move_alloc(this_alloc, x_alloc, flag);
+ //Nothrow swap
+ this->m_holder.swap(x.m_holder);
+ }
+ //Else do a one by one move
+ else{
+ this->assign( boost::make_move_iterator(x.begin())
+ , boost::make_move_iterator(x.end()));
+ }
+ }
+
+ template<class OtherAllocator>
+ void priv_copy_assign(const vector<T, OtherAllocator> &x
+ , typename container_detail::enable_if_c
+ < container_detail::is_version<OtherAllocator, 0>::value >::type * = 0)
+ {
+ if(!container_detail::is_same<OtherAllocator, allocator_type>::value &&
+ this->capacity() < x.size()){
+ throw_bad_alloc();
+ }
+ T* const this_start = container_detail::to_raw_pointer(m_holder.start());
+ T* const other_start = container_detail::to_raw_pointer(x.m_holder.start());
+ 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>
+ void priv_copy_assign(const vector<T, OtherAllocator> &x
+ , typename container_detail::enable_if_c
+ < !container_detail::is_version<OtherAllocator, 0>::value &&
+ container_detail::is_same<OtherAllocator, allocator_type>::value >::type * = 0)
+ {
+ allocator_type &this_alloc = this->m_holder.alloc();
+ const allocator_type &x_alloc = x.m_holder.alloc();
+ container_detail::bool_<allocator_traits_type::
+ propagate_on_container_copy_assignment::value> flag;
+ if(flag && this_alloc != x_alloc){
+ this->clear();
+ this->shrink_to_fit();
+ }
+ container_detail::assign_alloc(this_alloc, x_alloc, flag);
+ this->assign( container_detail::to_raw_pointer(x.m_holder.start())
+ , container_detail::to_raw_pointer(x.m_holder.start() + x.m_holder.m_size));
+ }
+
+ void priv_reserve(size_type, allocator_v0)
+ { throw_bad_alloc(); }
+
+ container_detail::insert_range_proxy<Allocator, boost::move_iterator<T*>, T*> priv_dummy_empty_proxy()
+ {
+ return container_detail::insert_range_proxy<Allocator, boost::move_iterator<T*>, T*>
+ (::boost::make_move_iterator((T *)0));
+ }
+
+ void priv_reserve(size_type new_cap, allocator_v1)
+ {
+ //There is not enough memory, allocate a new buffer
+ pointer 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
+ ( container_detail::to_raw_pointer(p), new_cap
+ , container_detail::to_raw_pointer(this->m_holder.start()) + this->m_holder.m_size
+ , 0, this->priv_dummy_empty_proxy());
+ }
+
+ void priv_reserve(size_type new_cap, allocator_v2)
+ {
+ //There is not enough memory, allocate a new
+ //buffer or expand the old one.
+ bool same_buffer_start;
+ size_type real_cap = 0;
+ std::pair<pointer, bool> ret = this->m_holder.allocation_command
+ (allocate_new | expand_fwd | expand_bwd, new_cap, new_cap, real_cap, this->m_holder.start());
+
+ //Check for forward expansion
+ same_buffer_start = ret.second && this->m_holder.start() == ret.first;
+ 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 = container_detail::to_raw_pointer(ret.first);
+ T * const ins_pos = container_detail::to_raw_pointer(this->m_holder.start()) + this->m_holder.m_size;
+ if(ret.second){ //Backwards (and possibly forward) expansion
+ #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() BOOST_CONTAINER_NOEXCEPT
+ {
+ if(!value_traits::trivial_dctr){
+ value_type* const p = container_detail::to_raw_pointer(this->m_holder.start()) + this->m_holder.m_size - 1;
+ allocator_traits_type::destroy(this->get_stored_allocator(), p);
+ }
+ --this->m_holder.m_size;
+ }
+
+ void priv_destroy_last(const bool moved) BOOST_CONTAINER_NOEXCEPT
+ {
+ (void)moved;
+ if(!(value_traits::trivial_dctr || (value_traits::trivial_dctr_after_move && moved))){
+ value_type* const p = container_detail::to_raw_pointer(this->m_holder.start()) + this->m_holder.m_size - 1;
+ allocator_traits_type::destroy(this->get_stored_allocator(), p);
+ }
+ --this->m_holder.m_size;
+ }
+
+ void priv_destroy_last_n(const size_type n) BOOST_CONTAINER_NOEXCEPT
+ {
+ BOOST_ASSERT(n <= this->m_holder.m_size);
+ if(!value_traits::trivial_dctr){
+ T* const destroy_pos = container_detail::to_raw_pointer(this->m_holder.start()) + (this->m_holder.m_size-n);
+ boost::container::destroy_alloc_n(this->get_stored_allocator(), destroy_pos, n);
+ }
+ this->m_holder.m_size -= n;
+ }
+
+ void priv_destroy_last_n(const size_type n, const bool moved) BOOST_CONTAINER_NOEXCEPT
+ {
+ BOOST_ASSERT(n <= this->m_holder.m_size);
+ (void)moved;
+ if(!(value_traits::trivial_dctr || (value_traits::trivial_dctr_after_move && moved))){
+ T* const destroy_pos = container_detail::to_raw_pointer(this->m_holder.start()) + (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 = container_detail::to_raw_pointer(this->m_holder.start()) + this->m_holder.m_size;
+ T* const new_end_pos = boost::container::uninitialized_copy_alloc(this->m_holder.alloc(), first, last, old_end_pos);
+ this->m_holder.m_size += new_end_pos - old_end_pos;
+ }
+
+ void priv_destroy_all() BOOST_CONTAINER_NOEXCEPT
+ {
+ boost::container::destroy_alloc_n
+ (this->get_stored_allocator(), container_detail::to_raw_pointer(this->m_holder.start()), 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)
+ {
+ return this->priv_forward_range_insert
+ ( vector_iterator_get_ptr(p), 1, container_detail::get_insert_value_proxy<T*, Allocator>
+ (::boost::forward<U>(x)), alloc_version());
}
+ container_detail::insert_copy_proxy<Allocator, T*> priv_single_insert_proxy(const T &x)
+ { return container_detail::insert_copy_proxy<Allocator, T*> (x); }
+
+ container_detail::insert_move_proxy<Allocator, T*> priv_single_insert_proxy(BOOST_RV_REF(T) x)
+ { return container_detail::insert_move_proxy<Allocator, T*> (x); }
+
template <class U>
- void priv_push_back(BOOST_MOVE_CATCH_FWD(U) x)
+ void priv_push_back(BOOST_FWD_REF(U) u)
{
- if (this->members_.m_size < this->members_.m_capacity){
+ if (BOOST_LIKELY(this->m_holder.m_size < this->m_holder.capacity())){
//There is more memory, just construct a new object at the end
allocator_traits_type::construct
- ( this->alloc()
- , container_detail::to_raw_pointer(this->members_.m_start + this->members_.m_size)
- , ::boost::forward<U>(x) );
- ++this->members_.m_size;
+ ( this->m_holder.alloc()
+ , container_detail::to_raw_pointer(this->m_holder.start() + this->m_holder.m_size)
+ , ::boost::forward<U>(u) );
+ ++this->m_holder.m_size;
}
else{
- this->insert(this->cend(), ::boost::forward<U>(x));
+ this->priv_forward_range_insert_no_capacity
+ ( vector_iterator_get_ptr(this->cend()), 1
+ , this->priv_single_insert_proxy(::boost::forward<U>(u)), alloc_version());
}
}
- template<class AllocVersion>
- void priv_shrink_to_fit( AllocVersion
- , typename container_detail::enable_if_c<
- container_detail::is_same<AllocVersion, allocator_v1>::value >::type * = 0)
+ container_detail::insert_n_copies_proxy<Allocator, T*> priv_resize_proxy(const T &x)
+ { return container_detail::insert_n_copies_proxy<Allocator, T*>(x); }
+
+ container_detail::insert_default_initialized_n_proxy<Allocator, T*> priv_resize_proxy(default_init_t)
+ { return container_detail::insert_default_initialized_n_proxy<Allocator, T*>(); }
+
+ container_detail::insert_value_initialized_n_proxy<Allocator, T*> priv_resize_proxy(value_init_t)
+ { return container_detail::insert_value_initialized_n_proxy<Allocator, T*>(); }
+
+ template <class U>
+ void priv_resize(size_type new_size, const U& u)
{
- if(this->members_.m_capacity){
- if(!size()){
- this->prot_deallocate();
+ 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());
+ }
+ }
+
+ void priv_shrink_to_fit(allocator_v0) BOOST_CONTAINER_NOEXCEPT
+ {}
+
+ void priv_shrink_to_fit(allocator_v1)
+ {
+ const size_type cp = this->m_holder.capacity();
+ if(cp){
+ const size_type sz = this->size();
+ if(!sz){
+ this->m_holder.alloc().deallocate(this->m_holder.m_start, cp);
+ this->m_holder.m_start = pointer();
+ this->m_holder.m_capacity = 0;
}
- else{
+ else if(sz < cp){
//Allocate a new buffer.
- size_type real_cap = 0;
- std::pair<pointer, bool> ret =
- this->allocation_command
- (allocate_new, this->size(), this->size(), real_cap, this->members_.m_start);
- if(real_cap < this->capacity()){
- //We will reuse insert code, so create a dummy input iterator
- T *dummy_it(container_detail::to_raw_pointer(this->members_.m_start));
- container_detail::advanced_insert_aux_proxy<A, boost::move_iterator<T*>, T*>
- proxy(this->alloc(), ::boost::make_move_iterator(dummy_it), ::boost::make_move_iterator(dummy_it));
- #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
- ++this->num_alloc;
- #endif
- this->priv_range_insert_new_allocation
- ( container_detail::to_raw_pointer(ret.first)
- , real_cap
- , container_detail::to_raw_pointer(this->members_.m_start)
- , 0
- , proxy);
- }
- else{
- this->alloc().deallocate(ret.first, real_cap);
- }
+ pointer 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
+ ( container_detail::to_raw_pointer(p), sz
+ , container_detail::to_raw_pointer(this->m_holder.start())
+ , 0, this->priv_dummy_empty_proxy());
}
}
}
- template<class AllocVersion>
- void priv_shrink_to_fit(AllocVersion
- , typename container_detail::enable_if_c<
- !container_detail::is_same<AllocVersion, allocator_v1>::value >::type * = 0)
+ void priv_shrink_to_fit(allocator_v2) BOOST_CONTAINER_NOEXCEPT
{
- if(this->members_.m_capacity){
- if(!size()){
- this->prot_deallocate();
+ const size_type cp = this->m_holder.capacity();
+ if(cp){
+ const size_type sz = this->size();
+ if(!sz){
+ this->m_holder.alloc().deallocate(this->m_holder.m_start, cp);
+ this->m_holder.m_start = pointer();
+ this->m_holder.m_capacity = 0;
}
else{
size_type received_size;
- if(this->alloc().allocation_command
+ if(this->m_holder.allocation_command
( shrink_in_place | nothrow_allocation
- , this->capacity(), this->size()
- , received_size, this->members_.m_start).first){
- this->members_.m_capacity = received_size;
+ , cp, sz, received_size, this->m_holder.start()).first){
+ this->m_holder.capacity(received_size);
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
++this->num_shrink;
#endif
@@ -1399,85 +2205,166 @@ class vector : private container_detail::vector_alloc_holder<A>
}
}
- template <class FwdIt>
- void priv_range_insert(const_iterator pos, FwdIt first, FwdIt last, std::forward_iterator_tag)
+ template <class InsertionProxy>
+ iterator priv_forward_range_insert_no_capacity
+ (const pointer &pos, const size_type, const InsertionProxy , allocator_v0)
+ {
+ 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, allocator_v1)
+ {
+ //Check if we have enough memory or try to expand current memory
+ const size_type n_pos = pos - this->m_holder.start();
+ T *const raw_pos = container_detail::to_raw_pointer(pos);
+
+ const size_type new_cap = this->m_holder.next_capacity(n);
+ T * new_buf = container_detail::to_raw_pointer(this->m_holder.alloc().allocate(new_cap));
+ #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, allocator_v2)
{
- if(first != last){
- const size_type n = std::distance(first, last);
- container_detail::advanced_insert_aux_proxy<A, FwdIt, T*> proxy(this->alloc(), first, last);
- priv_range_insert(pos.get_ptr(), n, proxy);
+ //Check if we have enough memory or try to expand current memory
+ T *const raw_pos = container_detail::to_raw_pointer(pos);
+ const size_type n_pos = raw_pos - container_detail::to_raw_pointer(this->m_holder.start());
+
+ size_type real_cap = 0;
+ //There is not enough memory, allocate a new
+ //buffer or expand the old one.
+ std::pair<pointer, bool> ret = (this->m_holder.allocation_command
+ (allocate_new | expand_fwd | expand_bwd,
+ this->m_holder.m_size + n, this->m_holder.next_capacity(n), real_cap, this->m_holder.start()));
+
+ //Buffer reallocated
+ if(ret.second){
+ //Forward expansion, delay insertion
+ if(this->m_holder.start() == ret.first){
+ #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
+ ( container_detail::to_raw_pointer(ret.first)
+ , 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
+ ( container_detail::to_raw_pointer(ret.first)
+ , real_cap, raw_pos, n, insert_range_proxy);
+ }
+
+ return iterator(this->m_holder.start() + n_pos);
}
- template <class InIt>
- void priv_range_insert(const_iterator pos, InIt first, InIt last, std::input_iterator_tag)
+ template <class InsertionProxy>
+ iterator priv_forward_range_insert
+ (const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy, allocator_v0)
{
- for(;first != last; ++first){
- this->emplace(pos, *first);
+ //Check if we have enough memory or try to expand current memory
+ const size_type remaining = this->m_holder.capacity() - this->m_holder.m_size;
+
+ if (n > remaining){
+ //This will trigger an error
+ throw_bad_alloc();
}
+ const size_type n_pos = pos - this->m_holder.start();
+ T *const raw_pos = container_detail::to_raw_pointer(pos);
+ this->priv_forward_range_insert_expand_forward(raw_pos, n, insert_range_proxy);
+ return iterator(this->m_holder.start() + n_pos);
}
- void priv_range_insert(pointer pos, const size_type n, advanced_insert_aux_int_t &interf)
+ template <class InsertionProxy>
+ iterator priv_forward_range_insert
+ (const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy, allocator_v1)
{
//Check if we have enough memory or try to expand current memory
- size_type remaining = this->members_.m_capacity - this->members_.m_size;
- bool same_buffer_start;
- std::pair<pointer, bool> ret;
- size_type real_cap = this->members_.m_capacity;
+ const size_type remaining = this->m_holder.capacity() - this->m_holder.m_size;
+ T *const raw_pos = container_detail::to_raw_pointer(pos);
- //Check if we already have room
if (n <= remaining){
- same_buffer_start = true;
+ const size_type n_pos = raw_pos - container_detail::to_raw_pointer(this->m_holder.start());
+ this->priv_forward_range_insert_expand_forward(raw_pos, n, insert_range_proxy);
+ return iterator(this->m_holder.start() + n_pos);
}
else{
- //There is not enough memory, allocate a new
- //buffer or expand the old one.
- size_type new_cap = this->next_capacity(n);
- ret = this->allocation_command
- (allocate_new | expand_fwd | expand_bwd,
- this->members_.m_size + n, new_cap, real_cap, this->members_.m_start);
-
- //Check for forward expansion
- same_buffer_start = ret.second && this->members_.m_start == ret.first;
- if(same_buffer_start){
- this->members_.m_capacity = real_cap;
- }
+ return this->priv_forward_range_insert_no_capacity(pos, n, insert_range_proxy, alloc_version());
}
-
- //If we had room or we have expanded forward
- if (same_buffer_start){
- #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
- ++this->num_expand_fwd;
- #endif
- this->priv_range_insert_expand_forward
- (container_detail::to_raw_pointer(pos), n, interf);
- }
- //Backwards (and possibly forward) expansion
- else if(ret.second){
- #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
- ++this->num_expand_bwd;
- #endif
- this->priv_range_insert_expand_backwards
- ( container_detail::to_raw_pointer(ret.first)
- , real_cap
- , container_detail::to_raw_pointer(pos)
- , n
- , interf);
+ }
+
+ template <class InsertionProxy>
+ iterator priv_forward_range_insert
+ (const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy, allocator_v2)
+ {
+ 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());
}
- //New buffer
else{
- #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
- ++this->num_alloc;
- #endif
- this->priv_range_insert_new_allocation
- ( container_detail::to_raw_pointer(ret.first)
- , real_cap
- , container_detail::to_raw_pointer(pos)
- , n
- , interf);
+ //Expand forward
+ T *const raw_pos = container_detail::to_raw_pointer(pos);
+ const size_type n_pos = raw_pos - container_detail::to_raw_pointer(this->m_holder.start());
+ 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, allocator_v0)
+ {
+ //Check if we have enough memory or try to expand current memory
+ const size_type remaining = this->m_holder.capacity() - this->m_holder.m_size;
+
+ if (n > remaining){
+ //This will trigger an error
+ throw_bad_alloc();
+ }
+ this->priv_forward_range_insert_at_end_expand_forward(n, insert_range_proxy);
+ return this->end();
+ }
+
+ template <class InsertionProxy>
+ iterator priv_forward_range_insert_at_end
+ (const size_type n, const InsertionProxy insert_range_proxy, allocator_v1)
+ {
+ return this->priv_forward_range_insert(vector_iterator_get_ptr(this->cend()), n, insert_range_proxy, allocator_v1());
+ }
+
+ template <class InsertionProxy>
+ iterator priv_forward_range_insert_at_end
+ (const size_type n, const InsertionProxy insert_range_proxy, allocator_v2)
+ {
+ return this->priv_forward_range_insert(vector_iterator_get_ptr(this->cend()), n, insert_range_proxy, allocator_v2());
+ }
+
//Absolutely experimental. This function might change, disappear or simply crash!
template<class BiDirPosConstIt, class BiDirSkipConstIt, class BiDirValueIt>
void priv_insert_ordered_at( size_type element_count, BiDirPosConstIt last_position_it
@@ -1485,7 +2372,7 @@ class vector : private container_detail::vector_alloc_holder<A>
{
const size_type old_size_pos = this->size();
this->reserve(old_size_pos + element_count);
- T* const begin_ptr = container_detail::to_raw_pointer(this->members_.m_start);
+ T* const begin_ptr = container_detail::to_raw_pointer(this->m_holder.start());
size_type insertions_left = element_count;
size_type next_pos = old_size_pos;
size_type hole_size = element_count;
@@ -1493,10 +2380,14 @@ class vector : private container_detail::vector_alloc_holder<A>
//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->alloc(), size_type(0u));
+ (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){
+ if(do_skip){
+ size_type n = *(--last_skip_it);
+ std::advance(last_value_it, -difference_type(n));
+ }
const size_type pos = static_cast<size_type>(*(--last_position_it));
BOOST_ASSERT(pos <= old_size_pos);
//If needed shift the range after the insertion point and the previous insertion point.
@@ -1510,12 +2401,12 @@ class vector : private container_detail::vector_alloc_holder<A>
//The hole was reduced by priv_insert_ordered_at_shift_range so expand exception rollback range backwards
past_hole_values_destroyer.increment_size_backwards(next_pos - pos);
//Insert the new value in the hole
- allocator_traits_type::construct(this->alloc(), begin_ptr + pos + insertions_left - 1, *(--last_value_it));
+ allocator_traits_type::construct(this->m_holder.alloc(), begin_ptr + pos + insertions_left - 1, *(--last_value_it));
--new_hole_size;
if(new_hole_size == 0){
//Hole was just filled, disable exception rollback and change vector size
past_hole_values_destroyer.release();
- this->members_.m_size += element_count;
+ this->m_holder.m_size += element_count;
}
else{
//The hole was reduced by the new insertion by one
@@ -1526,17 +2417,11 @@ class vector : private container_detail::vector_alloc_holder<A>
if(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->members_.m_size += element_count;
+ this->m_holder.m_size += element_count;
}
//Insert the new value in the already constructed range
begin_ptr[pos + insertions_left - 1] = *(--last_value_it);
}
- if(do_skip){
- size_type n = *(--last_skip_it);
- while(n--){
- --last_value_it;
- }
- }
--insertions_left;
hole_size = new_hole_size;
next_pos = pos;
@@ -1556,28 +2441,28 @@ class vector : private container_detail::vector_alloc_holder<A>
//
//Old situation:
// first_pos last_pos old_limit
- // | | |
+ // | | |
// ____________V_______V__________________V_____________
//| prefix | range | suffix |raw_mem ~
//|____________|_______|__________________|_____________~
//
- //New situation in Case A (hole_size == 0):
+ //New situation in Case Allocator (hole_size == 0):
// range is moved through move assignments
//
- // first_pos last_pos old_limit
- // | | |
+ // first_pos last_pos limit_pos
+ // | | |
// ____________V_______V__________________V_____________
//| prefix' | | | range |suffix'|raw_mem ~
//|________________+______|___^___|_______|_____________~
// | |
- // |_>_>_>_>_>^
+ // |_>_>_>_>_>^
//
//
- //New situation in Case B (hole_size >= 0):
+ //New situation in Case B (hole_size > 0):
// range is moved through uninitialized moves
//
- // first_pos last_pos old_limit
- // | | |
+ // first_pos last_pos limit_pos
+ // | | |
// ____________V_______V__________________V________________
//| prefix' | | | [hole] | range |
//|_______________________________________|________|___^___|
@@ -1587,31 +2472,34 @@ class vector : private container_detail::vector_alloc_holder<A>
//New situation in Case C (hole_size == 0):
// range is moved through move assignments and uninitialized moves
//
- // first_pos last_pos old_limit
- // | | |
+ // 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)
+ 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 = container_detail::to_raw_pointer(this->members_.m_start);
+ T* const begin_ptr = container_detail::to_raw_pointer(this->m_holder.start());
+ 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::move_backward(begin_ptr + first_pos, begin_ptr + last_pos, begin_ptr + last_pos + shift_count);
+ boost::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->alloc(), begin_ptr + first_pos, begin_ptr + last_pos, begin_ptr + first_pos + shift_count);
+ (this->m_holder.alloc(), first_ptr, last_ptr, first_ptr + shift_count);
hole_size = last_pos + shift_count - limit_pos;
}
//Case C:
@@ -1619,121 +2507,145 @@ class vector : private container_detail::vector_alloc_holder<A>
//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->alloc(), boundary_ptr, begin_ptr + last_pos, limit_ptr);
+ ::boost::container::uninitialized_move_alloc(this->m_holder.alloc(), boundary_ptr, last_ptr, limit_ptr);
//The rest is move assigned
- boost::move_backward(begin_ptr + first_pos, boundary_ptr, limit_ptr);
+ boost::move_backward(first_ptr, boundary_ptr, limit_ptr);
}
return hole_size;
}
private:
- void priv_range_insert_expand_forward(T* pos, size_type n, advanced_insert_aux_int_t &interf)
+ template <class InsertionProxy>
+ void priv_forward_range_insert_at_end_expand_forward(const size_type n, InsertionProxy insert_range_proxy)
+ {
+ T* const old_finish = container_detail::to_raw_pointer(this->m_holder.start()) + this->m_holder.m_size;
+ 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(!n) return;
//There is enough memory
- T* old_finish = container_detail::to_raw_pointer(this->members_.m_start) + this->members_.m_size;
+ T* const old_finish = container_detail::to_raw_pointer(this->m_holder.start()) + this->m_holder.m_size;
const size_type elems_after = old_finish - pos;
- if (elems_after >= n){
+ 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->alloc(), old_finish - n, old_finish, old_finish);
- this->members_.m_size += n;
+ (this->m_holder.alloc(), old_finish - n, old_finish, old_finish);
+ this->m_holder.m_size += n;
//Copy previous to last objects to the initialized end
boost::move_backward(pos, old_finish - n, old_finish);
//Insert new objects in the pos
- interf.copy_remaining_to(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
- //to the beginning of the unallocated zone the last new elements.
- interf.uninitialized_copy_some_and_update(old_finish, elems_after, false);
- this->members_.m_size += n - elems_after;
- //Copy old [pos, end()) elements to the uninitialized memory
- ::boost::container::uninitialized_move_alloc
- (this->alloc(), pos, old_finish, container_detail::to_raw_pointer(this->members_.m_start) + this->members_.m_size);
- this->members_.m_size += elems_after;
- //Copy first new elements in pos
- interf.copy_remaining_to(pos);
+ //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
}
}
- void priv_range_insert_new_allocation
- (T* new_start, size_type new_cap, T* pos, size_type n, advanced_insert_aux_int_t &interf)
+ 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 scoped_alloc(new_start, this->alloc(), new_cap);
- typename value_traits::ArrayDestructor constructed_values_destroyer(new_start, this->alloc(), 0u);
+ 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 *old_buffer = container_detail::to_raw_pointer(this->members_.m_start);
+ T * const old_buffer = container_detail::to_raw_pointer(this->m_holder.start());
if(old_buffer){
new_finish = ::boost::container::uninitialized_move_alloc
- (this->alloc(), container_detail::to_raw_pointer(this->members_.m_start), pos, old_finish = new_finish);
- constructed_values_destroyer.increment_size(new_finish - old_finish);
+ (this->m_holder.alloc(), container_detail::to_raw_pointer(this->m_holder.start()), pos, old_finish = new_finish);
+ new_values_destroyer.increment_size(new_finish - old_finish);
}
//Initialize new objects, starting from previous point
- interf.uninitialized_copy_remaining_to(old_finish = new_finish);
+ old_finish = new_finish;
+ insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), old_finish, n);
new_finish += n;
- constructed_values_destroyer.increment_size(new_finish - old_finish);
+ 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->alloc(), pos, old_buffer + this->members_.m_size, new_finish);
+ (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)
- this->destroy_n(old_buffer, this->members_.m_size);
- this->alloc().deallocate(this->members_.m_start, this->members_.m_capacity);
+ boost::container::destroy_alloc_n(this->get_stored_allocator(), old_buffer, this->m_holder.m_size);
+ this->m_holder.alloc().deallocate(this->m_holder.start(), this->m_holder.capacity());
}
- this->members_.m_start = new_start;
- this->members_.m_size = new_finish - new_start;
- this->members_.m_capacity = new_cap;
+ this->m_holder.start(new_start);
+ this->m_holder.m_size = new_finish - new_start;
+ this->m_holder.capacity(new_cap);
//All construction successful, disable rollbacks
- constructed_values_destroyer.release();
- scoped_alloc.release();
+ new_values_destroyer.release();
+ new_buffer_deallocator.release();
}
- void priv_range_insert_expand_backwards
- (T* new_start, size_type new_capacity,
- T* pos, const size_type n, advanced_insert_aux_int_t &interf)
+ 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* old_start = container_detail::to_raw_pointer(this->members_.m_start);
- T* old_finish = old_start + this->members_.m_size;
- size_type old_size = this->members_.m_size;
+ T* const old_start = container_detail::to_raw_pointer(this->m_holder.start());
+ 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 = (size_type)(pos - old_start);
- const size_type s_before = (size_type)(old_start - new_start);
+ 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->members_.m_start = new_start;
- this->members_.m_capacity = new_capacity;
- this->members_.m_size = 0;
+ 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::OldArrayDestructor old_values_destroyer(old_start, this->alloc(), old_size);
+ 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(difference_type(s_before) >= difference_type(elemsbefore + n)){
+ if(s_before >= before_plus_new){
//Copy first old values before pos, after that the new objects
- ::boost::container::uninitialized_move_alloc(this->alloc(), old_start, pos, new_start);
- this->members_.m_size = elemsbefore;
- interf.uninitialized_copy_remaining_to(new_start + elemsbefore);
- this->members_.m_size += n;
+ 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 >= (old_size + n)){
+ if(s_before >= new_size){
//Old situation:
// _________________________________________________________
//| raw_mem | old_begin | old_end |
@@ -1745,10 +2657,12 @@ class vector : private container_detail::vector_alloc_holder<A>
//|___________|__________|_________|________________________|
//
//Now initialize the rest of memory with the last old values
- ::boost::container::uninitialized_move_alloc
- (this->alloc(), pos, old_finish, new_start + elemsbefore + n);
- //All new elements correctly constructed, avoid new element destruction
- this->members_.m_size = old_size + n;
+ 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.
@@ -1769,23 +2683,29 @@ class vector : private container_detail::vector_alloc_holder<A>
//
//Now initialize the rest of memory with the last old values
//All new elements correctly constructed, avoid new element destruction
- size_type raw_gap = s_before - (elemsbefore + n);
- //Now initialize the rest of s_before memory with the
- //first of elements after new values
- ::boost::container::uninitialized_move_alloc
- (this->alloc(), pos, pos + raw_gap, new_start + elemsbefore + n);
- //Update size since we have a contiguous buffer
- this->members_.m_size = old_size + s_before;
- //All new elements correctly constructed, avoid old element destruction
- old_values_destroyer.release();
- //Now copy remaining last objects in the old buffer begin
- T *to_destroy = ::boost::move(pos + raw_gap, old_finish, old_start);
- //Now destroy redundant elements except if they were moved and
- //they have trivial destructor after move
- size_type n_destroy = old_finish - to_destroy;
- if(!value_traits::trivial_dctr_after_move)
- this->destroy_n(to_destroy, n_destroy);
- this->members_.m_size -= n_destroy;
+ 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
+ ::boost::move(pos + raw_gap, old_finish, old_start);
+ //Once moved, avoid calling the destructors if trivial after move
+ if(value_traits::trivial_dctr_after_move){
+ old_values_destroyer.release();
+ }
+ }
+ 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, old_finish - pos, new_start + before_plus_new);
+ this->m_holder.m_size = new_size;
+ old_values_destroyer.release();
+ }
}
}
else{
@@ -1808,7 +2728,7 @@ class vector : private container_detail::vector_alloc_holder<A>
//| old_begin + new + old_end | raw_mem |
//|____________________________|____________________|
//
- bool do_after = n > s_before;
+ 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:
@@ -1837,31 +2757,35 @@ class vector : private container_detail::vector_alloc_holder<A>
//|___________|_____|_________|_____________________|
//
//Copy the first part of old_begin to raw_mem
- T *start_n = old_start + difference_type(s_before);
- ::boost::container::uninitialized_move_alloc
- (this->alloc(), old_start, start_n, new_start);
+ ::boost::container::uninitialized_move_alloc_n
+ (this->m_holder.alloc(), old_start, s_before, new_start);
//The buffer is all constructed until old_end,
- //release destroyer and update size
- old_values_destroyer.release();
- this->members_.m_size = old_size + s_before;
- //Now copy the second part of old_begin overwriting himself
- T* next = ::boost::move(start_n, pos, old_start);
+ //so program trailing destruction and assign final size
+ //if !do_after, s_before+n otherwise.
+ size_type new_1st_range;
if(do_after){
- //Now copy the new_beg elements
- interf.copy_some_and_update(next, s_before, true);
+ new_1st_range = s_before;
+ //release destroyer and update size
+ old_values_destroyer.release();
}
else{
- //Now copy the all the new elements
- interf.copy_remaining_to(next);
- T* move_start = next + n;
+ 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::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
- T* move_end = ::boost::move(pos, old_finish, move_start);
- //Destroy remaining moved elements from old_end except if
- //they have trivial destructor after being moved
- difference_type n_destroy = s_before - n;
- if(!value_traits::trivial_dctr_after_move)
- this->destroy_n(move_end, n_destroy);
- this->members_.m_size -= n_destroy;
+ ::boost::move(pos, old_finish, next + new_1st_range);
}
}
else {
@@ -1891,40 +2815,37 @@ class vector : private container_detail::vector_alloc_holder<A>
//|___________|_____|_________|__________________________|
//
//First copy whole old_begin and part of new to raw_mem
- ::boost::container::uninitialized_move_alloc
- (this->alloc(), old_start, pos, new_start);
- this->members_.m_size = elemsbefore;
-
- const size_type mid_n = difference_type(s_before) - elemsbefore;
- interf.uninitialized_copy_some_and_update(new_start + elemsbefore, mid_n, true);
- this->members_.m_size = old_size + s_before;
+ 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 and update size
+ //release destroyer
+ this->m_holder.m_size = old_size + s_before;
old_values_destroyer.release();
if(do_after){
//Copy new_beg part
- interf.copy_some_and_update(old_start, s_before - mid_n, true);
+ insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), old_start, elemsbefore);
}
else{
//Copy all new elements
- interf.copy_remaining_to(old_start);
- T* move_start = old_start + (n-mid_n);
+ 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
- T* move_end = ::boost::move(pos, old_finish, move_start);
+ T* const move_end = ::boost::move(pos, old_finish, move_start);
//Destroy remaining moved elements from old_end except if they
//have trivial destructor after being moved
- difference_type n_destroy = s_before - n;
+ size_type n_destroy = s_before - n;
if(!value_traits::trivial_dctr_after_move)
- this->destroy_n(move_end, n_destroy);
- this->members_.m_size -= n_destroy;
+ 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
- //This can be executed without exception handling since we
- //have to just copy and append in raw memory and
- //old_values_destroyer has been released in phase 1.
if(do_after){
//The raw memory divides the new elements
//
@@ -1943,11 +2864,11 @@ class vector : private container_detail::vector_alloc_holder<A>
//| old_begin + new | old_end |raw |
//|_______________________________________|_________|____|
//
- const size_type n_after = n - s_before;
- const difference_type elemsafter = old_size - elemsbefore;
+ const size_type n_after = n - s_before;
+ const size_type elemsafter = old_size - elemsbefore;
//We can have two situations:
- if (elemsafter > difference_type(n_after)){
+ if (elemsafter >= n_after){
//The raw_mem from end will divide displaced old_end
//
//Old situation:
@@ -1961,15 +2882,15 @@ class vector : private container_detail::vector_alloc_holder<A>
//|__________________________|_________|________|_________|
//
//First copy the part of old_end raw_mem
- T* finish_n = old_finish - difference_type(n_after);
+ T* finish_n = old_finish - n_after;
::boost::container::uninitialized_move_alloc
- (this->alloc(), finish_n, old_finish, old_finish);
- this->members_.m_size += n_after;
+ (this->m_holder.alloc(), finish_n, old_finish, old_finish);
+ this->m_holder.m_size += n_after;
//Displace the rest of old_end to the new position
boost::move_backward(pos, finish_n, old_finish);
//Now overwrite with new_end
//The new_end part is [first + (n - n_after), last)
- interf.copy_remaining_to(pos);
+ 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
@@ -1984,189 +2905,34 @@ class vector : private container_detail::vector_alloc_holder<A>
//| old_begin + new_beg | new_end |old_end | raw_mem |
//|__________________________|_______________|________|_________|
//
- size_type mid_last_dist = n_after - elemsafter;
- //First initialize data in raw memory
- //The new_end part is [first + (n - n_after), last)
- interf.uninitialized_copy_some_and_update(old_finish, elemsafter, false);
- this->members_.m_size += mid_last_dist;
- ::boost::container::uninitialized_move_alloc
- (this->alloc(), pos, old_finish, old_finish + mid_last_dist);
- this->members_.m_size += n_after - mid_last_dist;
- //Now copy the part of new_end over constructed elements
- interf.copy_remaining_to(pos);
- }
- }
- }
- }
- template <class InIt>
- void priv_assign_aux(InIt first, InIt last, std::input_iterator_tag)
- {
- //Overwrite all elements we can from [first, last)
- iterator cur = begin();
- for ( ; first != last && cur != end(); ++cur, ++first){
- *cur = *first;
- }
+ const size_type mid_last_dist = n_after - elemsafter;
+ //First initialize data in raw memory
- if (first == last){
- //There are no more elements in the sequence, erase remaining
- this->erase(cur, cend());
- }
- else{
- //There are more elements in the range, insert the remaining ones
- this->insert(this->cend(), first, last);
- }
- }
+ //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);
- template <class FwdIt>
- void priv_assign_aux(FwdIt first, FwdIt last, std::forward_iterator_tag)
- {
- size_type n = std::distance(first, last);
- if(!n){
- this->prot_destroy_all();
- return;
- }
- //Check if we have enough memory or try to expand current memory
- size_type remaining = this->members_.m_capacity - this->members_.m_size;
- bool same_buffer_start;
- std::pair<pointer, bool> ret;
- size_type real_cap = this->members_.m_capacity;
+ typename value_traits::ArrayDestructor old_end_destroyer
+ (old_finish + mid_last_dist, this->m_holder.alloc(), old_finish - pos);
- if (n <= remaining){
- same_buffer_start = true;
- }
- else{
- //There is not enough memory, allocate a new buffer
- size_type new_cap = this->next_capacity(n);
- ret = this->allocation_command
- (allocate_new | expand_fwd | expand_bwd,
- this->size() + n, new_cap, real_cap, this->members_.m_start);
- same_buffer_start = ret.second && this->members_.m_start == ret.first;
- if(same_buffer_start){
- this->members_.m_capacity = real_cap;
- }
- }
-
- if(same_buffer_start){
- T *start = container_detail::to_raw_pointer(this->members_.m_start);
- if (this->size() >= n){
- //There is memory, but there are more old elements than new ones
- //Overwrite old elements with new ones
- std::copy(first, last, start);
- //Destroy remaining old elements
- this->destroy_n(start + n, this->members_.m_size - n);
- this->members_.m_size = n;
- }
- else{
- //There is memory, but there are less old elements than new ones
- //First overwrite some old elements with new ones
- FwdIt mid = first;
- std::advance(mid, this->size());
- // iG T *end = std::copy(first, mid, start);
- T *end = std::copy(first, mid, start);
- //Initialize the remaining new elements in the uninitialized memory
- ::boost::container::uninitialized_copy_or_move_alloc(this->alloc(), mid, last, end);
- this->members_.m_size = n;
- }
- }
- else if(!ret.second){
- typename value_traits::ArrayDeallocator scoped_alloc(ret.first, this->alloc(), real_cap);
- ::boost::container::uninitialized_copy_or_move_alloc(this->alloc(), first, last, container_detail::to_raw_pointer(ret.first));
- scoped_alloc.release();
- //Destroy and deallocate old buffer
- if(this->members_.m_start != 0){
- this->destroy_n(container_detail::to_raw_pointer(this->members_.m_start), this->members_.m_size);
- this->alloc().deallocate(this->members_.m_start, this->members_.m_capacity);
- }
- this->members_.m_start = ret.first;
- this->members_.m_size = n;
- this->members_.m_capacity = real_cap;
- }
- else{
- //Backwards expansion
- //If anything goes wrong, this object will destroy old objects
- T *old_start = container_detail::to_raw_pointer(this->members_.m_start);
- size_type old_size = this->members_.m_size;
- typename value_traits::OldArrayDestructor old_values_destroyer(old_start, this->alloc(), old_size);
- //If something goes wrong size will be 0
- //but holding the whole buffer
- this->members_.m_size = 0;
- this->members_.m_start = ret.first;
- this->members_.m_capacity = real_cap;
-
- //Backup old buffer data
- size_type old_offset = old_start - container_detail::to_raw_pointer(ret.first);
- size_type first_count = container_detail::min_value(n, old_offset);
-
- FwdIt mid = first;
- std::advance(mid, first_count);
- ::boost::container::uninitialized_copy_or_move_alloc
- (this->alloc(), first, mid, container_detail::to_raw_pointer(ret.first));
-
- if(old_offset > n){
- //All old elements will be destroyed by "old_values_destroyer"
- this->members_.m_size = n;
- }
- else{
- //We have constructed objects from the new begin until
- //the old end so release the rollback destruction
- old_values_destroyer.release();
- this->members_.m_start = ret.first;
- this->members_.m_size = first_count + old_size;
- //Now overwrite the old values
- size_type second_count = container_detail::min_value(old_size, n - first_count);
- FwdIt mid2 = mid;
- std::advance(mid2, second_count);
- // iG std::copy(mid, mid2, old_start);
- std::copy(mid, mid2, old_start);
-
- //Check if we still have to append elements in the
- //uninitialized end
- if(second_count == old_size){
- // iG std::copy(mid2, last, old_start + old_size);
- std::copy(mid2, last, old_start + old_size);
- }
- else{
- //We have to destroy some old values
- this->destroy_n
- (old_start + second_count, old_size - second_count);
- this->members_.m_size = n;
+ //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();
}
- this->members_.m_size = n;
}
}
}
- template <class Integer>
- void priv_assign_dispatch(Integer n, Integer val, container_detail::true_)
- { this->assign((size_type) n, (value_type)val); }
-
- template <class InIt>
- void priv_assign_dispatch(InIt first, InIt last, container_detail::false_)
- {
- //Dispatch depending on integer/iterator
- typedef typename std::iterator_traits<InIt>::iterator_category ItCat;
- this->priv_assign_aux(first, last, ItCat());
- }
-
- template <class Integer>
- void priv_insert_dispatch(const_iterator pos, Integer n, Integer val, container_detail::true_)
- { this->insert(pos, (size_type)n, (T)val); }
-
- template <class InIt>
- void priv_insert_dispatch(const_iterator pos, InIt first,
- InIt last, container_detail::false_)
- {
- //Dispatch depending on integer/iterator
- typedef typename std::iterator_traits<InIt>::iterator_category ItCat;
- this->priv_range_insert(pos, first, last, ItCat());
- }
-
void priv_check_range(size_type n) const
{
//If n is out of range, throw an out_of_range exception
- if (n >= size())
- throw std::out_of_range("vector::at");
+ if (n >= this->size()){
+ throw_out_of_range("vector::at out of range");
+ }
}
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
@@ -2178,59 +2944,41 @@ class vector : private container_detail::vector_alloc_holder<A>
void reset_alloc_stats()
{ num_expand_fwd = num_expand_bwd = num_alloc = 0, num_shrink = 0; }
#endif
- /// @endcond
+ #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
};
-template <class T, class A>
-inline bool
-operator==(const vector<T, A>& x, const vector<T, A>& y)
-{
- //Check first size and each element if needed
- return x.size() == y.size() && std::equal(x.begin(), x.end(), y.begin());
-}
-
-template <class T, class A>
-inline bool
-operator!=(const vector<T, A>& x, const vector<T, A>& y)
-{
- //Check first size and each element if needed
- return x.size() != y.size() || !std::equal(x.begin(), x.end(), y.begin());
-}
-
-template <class T, class A>
-inline bool
-operator<(const vector<T, A>& x, const vector<T, A>& y)
-{
- return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
-}
-
-template <class T, class A>
-inline void swap(vector<T, A>& x, vector<T, A>& y)
-{ x.swap(y); }
-
}}
-/// @cond
+#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
namespace boost {
/*
-
//!has_trivial_destructor_after_move<> == true_type
//!specialization for optimizations
-template <class T, class A>
-struct has_trivial_destructor_after_move<boost::container::vector<T, A> >
-{
- static const bool value = has_trivial_destructor<A>::value;
-};
-
+template <class T, class Allocator>
+struct has_trivial_destructor_after_move<boost::container::vector<T, Allocator> >
+ : public ::boost::has_trivial_destructor_after_move<Allocator>
+{};
*/
-
}
-/// @endcond
+//#define BOOST_CONTAINER_PUT_SWAP_OVERLOAD_IN_NAMESPACE_STD
+
+#ifdef BOOST_CONTAINER_PUT_SWAP_OVERLOAD_IN_NAMESPACE_STD
+
+namespace std {
+
+template <class T, class Allocator>
+inline void swap(boost::container::vector<T, Allocator>& x, boost::container::vector<T, Allocator>& y)
+{ x.swap(y); }
+
+} //namespace std {
+
+#endif
+
+#endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
#include <boost/container/detail/config_end.hpp>
#endif // #ifndef BOOST_CONTAINER_CONTAINER_VECTOR_HPP
-